In preparation for removing the `#include "llvm/ADT/StringExtras.h"` from the header to source file of `llvm/Support/Error.h`, first add in all the missing includes that were previously included transitively through this header.
118 lines
4.3 KiB
C++
118 lines
4.3 KiB
C++
//===-- NVPTXCtorDtorLowering.cpp - Handle global ctors and dtors --------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This pass creates a unified init and fini kernel with the required metadata
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "NVPTXCtorDtorLowering.h"
|
|
#include "NVPTX.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
#include "llvm/IR/IRBuilder.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/Value.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "nvptx-lower-ctor-dtor"
|
|
|
|
static cl::opt<std::string>
|
|
GlobalStr("nvptx-lower-global-ctor-dtor-id",
|
|
cl::desc("Override unique ID of ctor/dtor globals."),
|
|
cl::init(""), cl::Hidden);
|
|
|
|
namespace {
|
|
|
|
static std::string getHash(StringRef Str) {
|
|
llvm::MD5 Hasher;
|
|
llvm::MD5::MD5Result Hash;
|
|
Hasher.update(Str);
|
|
Hasher.final(Hash);
|
|
return llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
|
|
}
|
|
|
|
static bool createInitOrFiniGlobls(Module &M, StringRef GlobalName,
|
|
bool IsCtor) {
|
|
GlobalVariable *GV = M.getGlobalVariable(GlobalName);
|
|
if (!GV || !GV->hasInitializer())
|
|
return false;
|
|
ConstantArray *GA = dyn_cast<ConstantArray>(GV->getInitializer());
|
|
if (!GA || GA->getNumOperands() == 0)
|
|
return false;
|
|
|
|
// NVPTX has no way to emit variables at specific sections or support for
|
|
// the traditional constructor sections. Instead, we emit mangled global
|
|
// names so the runtime can build the list manually.
|
|
for (Value *V : GA->operands()) {
|
|
auto *CS = cast<ConstantStruct>(V);
|
|
auto *F = cast<Constant>(CS->getOperand(1));
|
|
uint64_t Priority = cast<ConstantInt>(CS->getOperand(0))->getSExtValue();
|
|
std::string PriorityStr = "." + std::to_string(Priority);
|
|
// We append a semi-unique hash and the priority to the global name.
|
|
std::string GlobalID =
|
|
!GlobalStr.empty() ? GlobalStr : getHash(M.getSourceFileName());
|
|
std::string NameStr =
|
|
((IsCtor ? "__init_array_object_" : "__fini_array_object_") +
|
|
F->getName() + "_" + GlobalID + "_" + std::to_string(Priority))
|
|
.str();
|
|
// PTX does not support exported names with '.' in them.
|
|
llvm::transform(NameStr, NameStr.begin(),
|
|
[](char c) { return c == '.' ? '_' : c; });
|
|
|
|
auto *GV = new GlobalVariable(M, F->getType(), /*IsConstant=*/true,
|
|
GlobalValue::ExternalLinkage, F, NameStr,
|
|
nullptr, GlobalValue::NotThreadLocal,
|
|
/*AddressSpace=*/4);
|
|
// This isn't respected by Nvidia, simply put here for clarity.
|
|
GV->setSection(IsCtor ? ".init_array" + PriorityStr
|
|
: ".fini_array" + PriorityStr);
|
|
GV->setVisibility(GlobalVariable::ProtectedVisibility);
|
|
appendToUsed(M, {GV});
|
|
}
|
|
|
|
GV->eraseFromParent();
|
|
return true;
|
|
}
|
|
|
|
static bool lowerCtorsAndDtors(Module &M) {
|
|
bool Modified = false;
|
|
Modified |= createInitOrFiniGlobls(M, "llvm.global_ctors", /*IsCtor =*/true);
|
|
Modified |= createInitOrFiniGlobls(M, "llvm.global_dtors", /*IsCtor =*/false);
|
|
return Modified;
|
|
}
|
|
|
|
class NVPTXCtorDtorLoweringLegacy final : public ModulePass {
|
|
public:
|
|
static char ID;
|
|
NVPTXCtorDtorLoweringLegacy() : ModulePass(ID) {}
|
|
bool runOnModule(Module &M) override { return lowerCtorsAndDtors(M); }
|
|
};
|
|
|
|
} // End anonymous namespace
|
|
|
|
PreservedAnalyses NVPTXCtorDtorLoweringPass::run(Module &M,
|
|
ModuleAnalysisManager &AM) {
|
|
return lowerCtorsAndDtors(M) ? PreservedAnalyses::none()
|
|
: PreservedAnalyses::all();
|
|
}
|
|
|
|
char NVPTXCtorDtorLoweringLegacy::ID = 0;
|
|
char &llvm::NVPTXCtorDtorLoweringLegacyPassID = NVPTXCtorDtorLoweringLegacy::ID;
|
|
INITIALIZE_PASS(NVPTXCtorDtorLoweringLegacy, DEBUG_TYPE,
|
|
"Lower ctors and dtors for NVPTX", false, false)
|
|
|
|
ModulePass *llvm::createNVPTXCtorDtorLoweringLegacyPass() {
|
|
return new NVPTXCtorDtorLoweringLegacy();
|
|
}
|