Prepare for LLVM 11

This commit is contained in:
Josh Stone
2020-06-25 18:52:41 -07:00
parent 50fc24d8a1
commit 49f6166ef7
8 changed files with 167 additions and 57 deletions

View File

@@ -49,8 +49,10 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
#if LLVM_VERSION_LT(11, 0)
DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
LLVMPassManagerBuilderRef)
#endif
extern "C" void LLVMInitializePasses() {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
@@ -343,17 +345,17 @@ enum class LLVMRustPassBuilderOptLevel {
static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
switch (Level) {
case LLVMRustPassBuilderOptLevel::O0:
return PassBuilder::O0;
return PassBuilder::OptimizationLevel::O0;
case LLVMRustPassBuilderOptLevel::O1:
return PassBuilder::O1;
return PassBuilder::OptimizationLevel::O1;
case LLVMRustPassBuilderOptLevel::O2:
return PassBuilder::O2;
return PassBuilder::OptimizationLevel::O2;
case LLVMRustPassBuilderOptLevel::O3:
return PassBuilder::O3;
return PassBuilder::OptimizationLevel::O3;
case LLVMRustPassBuilderOptLevel::Os:
return PassBuilder::Os;
return PassBuilder::OptimizationLevel::Os;
case LLVMRustPassBuilderOptLevel::Oz:
return PassBuilder::Oz;
return PassBuilder::OptimizationLevel::Oz;
default:
report_fatal_error("Bad PassBuilderOptLevel.");
}
@@ -796,8 +798,13 @@ LLVMRustOptimizeWithNewPassManager(
// We manually collect pipeline callbacks so we can apply them at O0, where the
// PassBuilder does not create a pipeline.
std::vector<std::function<void(ModulePassManager &)>> PipelineStartEPCallbacks;
#if LLVM_VERSION_GE(11, 0)
std::vector<std::function<void(ModulePassManager &, PassBuilder::OptimizationLevel)>>
OptimizerLastEPCallbacks;
#else
std::vector<std::function<void(FunctionPassManager &, PassBuilder::OptimizationLevel)>>
OptimizerLastEPCallbacks;
#endif
if (VerifyIR) {
PipelineStartEPCallbacks.push_back([VerifyIR](ModulePassManager &MPM) {
@@ -811,6 +818,14 @@ LLVMRustOptimizeWithNewPassManager(
SanitizerOptions->SanitizeMemoryTrackOrigins,
SanitizerOptions->SanitizeMemoryRecover,
/*CompileKernel=*/false);
#if LLVM_VERSION_GE(11, 0)
OptimizerLastEPCallbacks.push_back(
[Options](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
MPM.addPass(MemorySanitizerPass(Options));
MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
}
);
#else
#if LLVM_VERSION_GE(10, 0)
PipelineStartEPCallbacks.push_back([Options](ModulePassManager &MPM) {
MPM.addPass(MemorySanitizerPass(Options));
@@ -821,9 +836,18 @@ LLVMRustOptimizeWithNewPassManager(
FPM.addPass(MemorySanitizerPass(Options));
}
);
#endif
}
if (SanitizerOptions->SanitizeThread) {
#if LLVM_VERSION_GE(11, 0)
OptimizerLastEPCallbacks.push_back(
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
MPM.addPass(ThreadSanitizerPass());
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
}
);
#else
#if LLVM_VERSION_GE(10, 0)
PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM) {
MPM.addPass(ThreadSanitizerPass());
@@ -834,9 +858,22 @@ LLVMRustOptimizeWithNewPassManager(
FPM.addPass(ThreadSanitizerPass());
}
);
#endif
}
if (SanitizerOptions->SanitizeAddress) {
#if LLVM_VERSION_GE(11, 0)
OptimizerLastEPCallbacks.push_back(
[SanitizerOptions](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
MPM.addPass(ModuleAddressSanitizerPass(
/*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
/*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
/*UseAfterScope=*/true)));
}
);
#else
PipelineStartEPCallbacks.push_back([&](ModulePassManager &MPM) {
MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
});
@@ -853,21 +890,27 @@ LLVMRustOptimizeWithNewPassManager(
/*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
}
);
#endif
}
}
ModulePassManager MPM(DebugPassManager);
if (!NoPrepopulatePasses) {
if (OptLevel == PassBuilder::O0) {
if (OptLevel == PassBuilder::OptimizationLevel::O0) {
for (const auto &C : PipelineStartEPCallbacks)
C(MPM);
#if LLVM_VERSION_GE(11, 0)
for (const auto &C : OptimizerLastEPCallbacks)
C(MPM, OptLevel);
#else
if (!OptimizerLastEPCallbacks.empty()) {
FunctionPassManager FPM(DebugPassManager);
for (const auto &C : OptimizerLastEPCallbacks)
C(FPM, OptLevel);
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
#endif
MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers));
@@ -892,12 +935,17 @@ LLVMRustOptimizeWithNewPassManager(
break;
case LLVMRustOptStage::PreLinkThinLTO:
MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
#if LLVM_VERSION_GE(11, 0)
for (const auto &C : OptimizerLastEPCallbacks)
C(MPM, OptLevel);
#else
if (!OptimizerLastEPCallbacks.empty()) {
FunctionPassManager FPM(DebugPassManager);
for (const auto &C : OptimizerLastEPCallbacks)
C(FPM, OptLevel);
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
}
#endif
break;
case LLVMRustOptStage::PreLinkFatLTO:
MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
@@ -994,10 +1042,10 @@ public:
const Value *Value;
if (const CallInst *CI = dyn_cast<CallInst>(I)) {
Name = "call";
Value = CI->getCalledValue();
Value = CI->getCalledOperand();
} else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
Name = "invoke";
Value = II->getCalledValue();
Value = II->getCalledOperand();
} else {
// Could demangle more operations, e. g.
// `store %place, @function`.
@@ -1335,10 +1383,33 @@ LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) {
// `ProcessThinLTOModule` function. Here they're split up into separate steps
// so rustc can save off the intermediate bytecode between each step.
#if LLVM_VERSION_GE(11, 0)
static bool
clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) {
// When linking an ELF shared object, dso_local should be dropped. We
// conservatively do this for -fpic.
bool ClearDSOLocalOnDeclarations =
TM.getTargetTriple().isOSBinFormatELF() &&
TM.getRelocationModel() != Reloc::Static &&
Mod.getPIELevel() == PIELevel::Default;
return ClearDSOLocalOnDeclarations;
}
#endif
extern "C" bool
LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
LLVMTargetMachineRef TM) {
Module &Mod = *unwrap(M);
if (renameModuleForThinLTO(Mod, Data->Index)) {
TargetMachine &Target = *unwrap(TM);
#if LLVM_VERSION_GE(11, 0)
bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
bool error = renameModuleForThinLTO(Mod, Data->Index, ClearDSOLocal);
#else
bool error = renameModuleForThinLTO(Mod, Data->Index);
#endif
if (error) {
LLVMRustSetLastError("renameModuleForThinLTO failed");
return false;
}
@@ -1362,8 +1433,10 @@ LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef
}
extern "C" bool
LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
LLVMTargetMachineRef TM) {
Module &Mod = *unwrap(M);
TargetMachine &Target = *unwrap(TM);
const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
auto Loader = [&](StringRef Identifier) {
@@ -1399,7 +1472,12 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
return MOrErr;
};
#if LLVM_VERSION_GE(11, 0)
bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
#else
FunctionImporter Importer(Data->Index, Loader);
#endif
Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
if (!Result) {
LLVMRustSetLastError(toString(Result.takeError()).c_str());
@@ -1558,22 +1636,11 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
}
// Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
// process it recursively. Note that we specifically iterate over instructions
// to ensure we feed everything into it.
// process it recursively. Note that we used to specifically iterate over
// instructions to ensure we feed everything into it, but `processModule`
// started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
DebugInfoFinder Finder;
Finder.processModule(*M);
for (Function &F : M->functions()) {
for (auto &FI : F) {
for (Instruction &BI : FI) {
if (auto Loc = BI.getDebugLoc())
Finder.processLocation(*M, Loc);
if (auto DVI = dyn_cast<DbgValueInst>(&BI))
Finder.processValue(*M, DVI);
if (auto DDI = dyn_cast<DbgDeclareInst>(&BI))
Finder.processDeclare(*M, DDI);
}
}
}
// After we've found all our debuginfo, rewrite all subprograms to point to
// the same `DICompileUnit`.