diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-04-14 14:41:57 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-04-14 14:41:57 -0700 |
| commit | 5a3ea9beced660c9cc463b921a1581cc07855dd6 (patch) | |
| tree | 7e622bd133adcdbcc0c8d854deaac97f345c4c8c /src/zig_llvm.cpp | |
| parent | 1fada3746606b3a83d4c56213de93a1017753c96 (diff) | |
| parent | cc186dac65d84ecbf29b5f8704beb2dfd00d76bb (diff) | |
| download | zig-5a3ea9beced660c9cc463b921a1581cc07855dd6.tar.gz zig-5a3ea9beced660c9cc463b921a1581cc07855dd6.zip | |
Merge remote-tracking branch 'origin/llvm12'
Happy LLVM 12 Release Day.
Please note that the llvm 12 tag does not include the latest commit in
the release/12.x branch, which is in fact a bug fix for a regression
that is causing a failure in Zig's test suite.
Zig master branch is tracking release/12.x, and will be enabling the
test that is fixed by that commit.
Diffstat (limited to 'src/zig_llvm.cpp')
| -rw-r--r-- | src/zig_llvm.cpp | 270 |
1 files changed, 165 insertions, 105 deletions
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 280920ac74..7866537c64 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -20,6 +20,7 @@ #pragma GCC diagnostic ignored "-Winit-list-lifetime" #endif +#include <llvm/Analysis/AliasAnalysis.h> #include <llvm/Analysis/TargetLibraryInfo.h> #include <llvm/Analysis/TargetTransformInfo.h> #include <llvm/Bitcode/BitcodeWriter.h> @@ -30,9 +31,12 @@ #include <llvm/IR/Instructions.h> #include <llvm/IR/LegacyPassManager.h> #include <llvm/IR/Module.h> +#include <llvm/IR/PassManager.h> #include <llvm/IR/Verifier.h> #include <llvm/InitializePasses.h> #include <llvm/MC/SubtargetFeature.h> +#include <llvm/Passes/PassBuilder.h> +#include <llvm/Passes/StandardInstrumentations.h> #include <llvm/Object/Archive.h> #include <llvm/Object/ArchiveWriter.h> #include <llvm/Object/COFF.h> @@ -54,6 +58,9 @@ #include <llvm/Transforms/Instrumentation/ThreadSanitizer.h> #include <llvm/Transforms/Scalar.h> #include <llvm/Transforms/Utils.h> +#include <llvm/Transforms/Utils/AddDiscriminators.h> +#include <llvm/Transforms/Utils/CanonicalizeAliases.h> +#include <llvm/Transforms/Utils/NameAnonGlobals.h> #include <lld/Common/Driver.h> @@ -91,14 +98,6 @@ char *ZigLLVMGetNativeFeatures(void) { return strdup((const char *)StringRef(features.getString()).bytes_begin()); } -static void addDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createAddDiscriminatorsPass()); -} - -static void addThreadSanitizerPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createThreadSanitizerLegacyPassPass()); -} - #ifndef NDEBUG static const bool assertions_on = true; #else @@ -153,6 +152,11 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri } TargetOptions opt; + + // Work around the missing initialization of this field in the default + // constructor. Use -1 so that the default value is used. + opt.StackProtectorGuardOffset = (unsigned)-1; + opt.FunctionSections = function_sections; switch (float_abi) { case ZigLLVMABITypeDefault: @@ -188,14 +192,16 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM bool is_small, bool time_report, bool tsan, bool lto, const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename) { + // TODO: Maybe we should collect time trace rather than using timer + // to get a more hierarchical timeline view TimePassesIsEnabled = time_report; - raw_fd_ostream *dest_asm = nullptr; - raw_fd_ostream *dest_bin = nullptr; + raw_fd_ostream *dest_asm_ptr = nullptr; + raw_fd_ostream *dest_bin_ptr = nullptr; if (asm_filename) { std::error_code EC; - dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None); + dest_asm_ptr = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None); if (EC) { *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); return true; @@ -203,116 +209,147 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM } if (bin_filename) { std::error_code EC; - dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None); + dest_bin_ptr = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None); if (EC) { *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); return true; } } - TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref); - target_machine->setO0WantsFastISel(true); - - Module* module = unwrap(module_ref); - - PassManagerBuilder *PMBuilder = new(std::nothrow) PassManagerBuilder(); - if (PMBuilder == nullptr) { - *error_message = strdup("memory allocation failure"); - return true; + std::unique_ptr<raw_fd_ostream> dest_asm(dest_asm_ptr), + dest_bin(dest_bin_ptr); + + TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref); + target_machine.setO0WantsFastISel(true); + + Module &module = *unwrap(module_ref); + + // Pipeline configurations + PipelineTuningOptions pipeline_opts; + pipeline_opts.LoopUnrolling = !is_debug; + pipeline_opts.SLPVectorization = !is_debug; + pipeline_opts.LoopVectorization = !is_debug; + pipeline_opts.LoopInterleaving = !is_debug; + pipeline_opts.MergeFunctions = !is_debug; + + // Instrumentations + PassInstrumentationCallbacks instr_callbacks; + StandardInstrumentations std_instrumentations(false); + std_instrumentations.registerCallbacks(instr_callbacks); + + PassBuilder pass_builder(false, &target_machine, pipeline_opts, + None, &instr_callbacks); + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + + LoopAnalysisManager loop_am; + FunctionAnalysisManager function_am; + CGSCCAnalysisManager cgscc_am; + ModuleAnalysisManager module_am; + + // Register the AA manager first so that our version is the one used + function_am.registerPass([&] { + return pass_builder.buildDefaultAAPipeline(); + }); + + Triple target_triple(module.getTargetTriple()); + auto tlii = std::make_unique<TargetLibraryInfoImpl>(target_triple); + function_am.registerPass([&] { return TargetLibraryAnalysis(*tlii); }); + + // Initialize the AnalysisManagers + pass_builder.registerModuleAnalyses(module_am); + pass_builder.registerCGSCCAnalyses(cgscc_am); + pass_builder.registerFunctionAnalyses(function_am); + pass_builder.registerLoopAnalyses(loop_am); + pass_builder.crossRegisterProxies(loop_am, function_am, + cgscc_am, module_am); + + // IR verification + if (assertions_on) { + // Verify the input + pass_builder.registerPipelineStartEPCallback( + [](ModulePassManager &module_pm, OptimizationLevel OL) { + module_pm.addPass(VerifierPass()); + }); + // Verify the output + pass_builder.registerOptimizerLastEPCallback( + [](ModulePassManager &module_pm, OptimizationLevel OL) { + module_pm.addPass(VerifierPass()); + }); } - PMBuilder->OptLevel = target_machine->getOptLevel(); - PMBuilder->SizeLevel = is_small ? 2 : 0; - - PMBuilder->DisableTailCalls = is_debug; - PMBuilder->DisableUnrollLoops = is_debug; - PMBuilder->SLPVectorize = !is_debug; - PMBuilder->LoopVectorize = !is_debug; - PMBuilder->LoopsInterleaved = !PMBuilder->DisableUnrollLoops; - PMBuilder->RerollLoops = !is_debug; - // Leaving NewGVN as default (off) because when on it caused issue #673 - //PMBuilder->NewGVN = !is_debug; - PMBuilder->DisableGVNLoadPRE = is_debug; - PMBuilder->VerifyInput = assertions_on; - PMBuilder->VerifyOutput = assertions_on; - PMBuilder->MergeFunctions = !is_debug; - PMBuilder->PrepareForLTO = lto; - PMBuilder->PrepareForThinLTO = false; - PMBuilder->PerformThinLTO = false; - - TargetLibraryInfoImpl tlii(Triple(module->getTargetTriple())); - PMBuilder->LibraryInfo = &tlii; - - if (is_debug) { - PMBuilder->Inliner = createAlwaysInlinerLegacyPass(false); - } else { - target_machine->adjustPassManager(*PMBuilder); - PMBuilder->addExtension(PassManagerBuilder::EP_EarlyAsPossible, addDiscriminatorsPass); - PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel, false); + // Passes specific for release build + if (!is_debug) { + pass_builder.registerPipelineStartEPCallback( + [](ModulePassManager &module_pm, OptimizationLevel OL) { + module_pm.addPass( + createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); + }); } + // Thread sanitizer if (tsan) { - PMBuilder->addExtension(PassManagerBuilder::EP_OptimizerLast, addThreadSanitizerPass); - PMBuilder->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, addThreadSanitizerPass); + pass_builder.registerOptimizerLastEPCallback( + [](ModulePassManager &module_pm, OptimizationLevel level) { + module_pm.addPass(ThreadSanitizerPass()); + }); } - // Set up the per-function pass manager. - legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module); - auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii); - FPM.add(tliwp); - FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); - if (assertions_on) { - FPM.add(createVerifierPass()); + ModulePassManager module_pm; + OptimizationLevel opt_level; + // Setting up the optimization level + if (is_debug) + opt_level = OptimizationLevel::O0; + else if (is_small) + opt_level = OptimizationLevel::Oz; + else + opt_level = OptimizationLevel::O3; + + // Initialize the PassManager + if (opt_level == OptimizationLevel::O0) { + module_pm = pass_builder.buildO0DefaultPipeline(opt_level, lto); + } else if (lto) { + module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level); + } else { + module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level); } - PMBuilder->populateFunctionPassManager(FPM); - - { - // Set up the per-module pass manager. - legacy::PassManager MPM; - MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); - PMBuilder->populateModulePassManager(MPM); - - // Set output passes. - if (dest_bin && !lto) { - if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, CGFT_ObjectFile)) { - *error_message = strdup("TargetMachine can't emit an object file"); - return true; - } - } - if (dest_asm) { - if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, CGFT_AssemblyFile)) { - *error_message = strdup("TargetMachine can't emit an assembly file"); - return true; - } - } - - // run per function optimization passes - FPM.doInitialization(); - for (Function &F : *module) - if (!F.isDeclaration()) - FPM.run(F); - FPM.doFinalization(); - MPM.run(*module); + // Unfortunately we don't have new PM for code generation + legacy::PassManager codegen_pm; + codegen_pm.add( + createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis())); - if (llvm_ir_filename) { - if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { - return true; - } + if (dest_bin && !lto) { + if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CGFT_ObjectFile)) { + *error_message = strdup("TargetMachine can't emit an object file"); + return true; } - if (dest_bin && lto) { - WriteBitcodeToFile(*module, *dest_bin); + } + if (dest_asm) { + if (target_machine.addPassesToEmitFile(codegen_pm, *dest_asm, nullptr, CGFT_AssemblyFile)) { + *error_message = strdup("TargetMachine can't emit an assembly file"); + return true; } + } + + // Optimization phase + module_pm.run(module, module_am); - if (time_report) { - TimerGroup::printAll(errs()); + // Code generation phase + codegen_pm.run(module); + + if (llvm_ir_filename) { + if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { + return true; } + } - // MPM goes out of scope and writes to the out streams + if (dest_bin && lto) { + WriteBitcodeToFile(module, *dest_bin); } - delete dest_asm; - delete dest_bin; + if (time_report) { + TimerGroup::printAll(errs()); + } return false; } @@ -614,8 +651,9 @@ void ZigLLVMDisposeDIBuilder(ZigLLVMDIBuilder *dbuilder) { } void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, ZigLLVMDIScope *scope) { - unwrap(builder)->SetCurrentDebugLocation(DebugLoc::get( - line, column, reinterpret_cast<DIScope*>(scope))); + DIScope* di_scope = reinterpret_cast<DIScope*>(scope); + DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, column, di_scope, nullptr, false); + unwrap(builder)->SetCurrentDebugLocation(debug_loc); } void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder) { @@ -776,7 +814,8 @@ LLVMValueRef ZigLLVMInsertDeclare(ZigLLVMDIBuilder *dibuilder, LLVMValueRef stor } ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, ZigLLVMDIScope *scope) { - DebugLoc debug_loc = DebugLoc::get(line, col, reinterpret_cast<DIScope*>(scope), nullptr); + DIScope* di_scope = reinterpret_cast<DIScope*>(scope); + DebugLoc debug_loc = DILocation::get(di_scope->getContext(), line, col, di_scope, nullptr, false); return reinterpret_cast<ZigLLVMDILocation*>(debug_loc.get()); } @@ -796,7 +835,17 @@ void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_v AttrBuilder attr_builder; Type *llvm_type = unwrap<Type>(type_val); attr_builder.addByValAttr(llvm_type); - const AttributeList new_attr_set = attr_set.addAttributes(func->getContext(), ArgNo, attr_builder); + const AttributeList new_attr_set = attr_set.addAttributes(func->getContext(), ArgNo + 1, attr_builder); + func->setAttributes(new_attr_set); +} + +void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val) { + Function *func = unwrap<Function>(fn_ref); + const AttributeList attr_set = func->getAttributes(); + AttrBuilder attr_builder; + Type *llvm_type = unwrap<Type>(type_val); + attr_builder.addStructRetAttr(llvm_type); + const AttributeList new_attr_set = attr_set.addAttributes(func->getContext(), ArgNo + 1, attr_builder); func->setAttributes(new_attr_set); } @@ -928,6 +977,15 @@ void ZigLLVMSetTailCall(LLVMValueRef Call) { unwrap<CallInst>(Call)->setTailCallKind(CallInst::TCK_MustTail); } +void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type) { + const AttributeList attr_set = unwrap<CallInst>(Call)->getAttributes(); + AttrBuilder attr_builder; + Type *llvm_type = unwrap<Type>(return_type); + attr_builder.addStructRetAttr(llvm_type); + const AttributeList new_attr_set = attr_set.addAttributes(unwrap<CallInst>(Call)->getContext(), 1, attr_builder); + unwrap<CallInst>(Call)->setAttributes(new_attr_set); +} + void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { unwrap<Function>(function)->setPrefixData(unwrap<Constant>(data)); } @@ -1194,6 +1252,7 @@ static_assert((Triple::ArchType)ZigLLVM_arc == Triple::arc, ""); static_assert((Triple::ArchType)ZigLLVM_avr == Triple::avr, ""); static_assert((Triple::ArchType)ZigLLVM_bpfel == Triple::bpfel, ""); static_assert((Triple::ArchType)ZigLLVM_bpfeb == Triple::bpfeb, ""); +static_assert((Triple::ArchType)ZigLLVM_csky == Triple::csky, ""); static_assert((Triple::ArchType)ZigLLVM_hexagon == Triple::hexagon, ""); static_assert((Triple::ArchType)ZigLLVM_mips == Triple::mips, ""); static_assert((Triple::ArchType)ZigLLVM_mipsel == Triple::mipsel, ""); @@ -1201,6 +1260,7 @@ static_assert((Triple::ArchType)ZigLLVM_mips64 == Triple::mips64, ""); static_assert((Triple::ArchType)ZigLLVM_mips64el == Triple::mips64el, ""); static_assert((Triple::ArchType)ZigLLVM_msp430 == Triple::msp430, ""); static_assert((Triple::ArchType)ZigLLVM_ppc == Triple::ppc, ""); +static_assert((Triple::ArchType)ZigLLVM_ppcle == Triple::ppcle, ""); static_assert((Triple::ArchType)ZigLLVM_ppc64 == Triple::ppc64, ""); static_assert((Triple::ArchType)ZigLLVM_ppc64le == Triple::ppc64le, ""); static_assert((Triple::ArchType)ZigLLVM_r600 == Triple::r600, ""); @@ -1242,8 +1302,6 @@ static_assert((Triple::VendorType)ZigLLVM_UnknownVendor == Triple::UnknownVendor static_assert((Triple::VendorType)ZigLLVM_Apple == Triple::Apple, ""); static_assert((Triple::VendorType)ZigLLVM_PC == Triple::PC, ""); static_assert((Triple::VendorType)ZigLLVM_SCEI == Triple::SCEI, ""); -static_assert((Triple::VendorType)ZigLLVM_BGP == Triple::BGP, ""); -static_assert((Triple::VendorType)ZigLLVM_BGQ == Triple::BGQ, ""); static_assert((Triple::VendorType)ZigLLVM_Freescale == Triple::Freescale, ""); static_assert((Triple::VendorType)ZigLLVM_IBM == Triple::IBM, ""); static_assert((Triple::VendorType)ZigLLVM_ImaginationTechnologies == Triple::ImaginationTechnologies, ""); @@ -1275,11 +1333,11 @@ static_assert((Triple::OSType)ZigLLVM_NetBSD == Triple::NetBSD, ""); static_assert((Triple::OSType)ZigLLVM_OpenBSD == Triple::OpenBSD, ""); static_assert((Triple::OSType)ZigLLVM_Solaris == Triple::Solaris, ""); static_assert((Triple::OSType)ZigLLVM_Win32 == Triple::Win32, ""); +static_assert((Triple::OSType)ZigLLVM_ZOS == Triple::ZOS, ""); static_assert((Triple::OSType)ZigLLVM_Haiku == Triple::Haiku, ""); static_assert((Triple::OSType)ZigLLVM_Minix == Triple::Minix, ""); static_assert((Triple::OSType)ZigLLVM_RTEMS == Triple::RTEMS, ""); static_assert((Triple::OSType)ZigLLVM_NaCl == Triple::NaCl, ""); -static_assert((Triple::OSType)ZigLLVM_CNK == Triple::CNK, ""); static_assert((Triple::OSType)ZigLLVM_AIX == Triple::AIX, ""); static_assert((Triple::OSType)ZigLLVM_CUDA == Triple::CUDA, ""); static_assert((Triple::OSType)ZigLLVM_NVCL == Triple::NVCL, ""); @@ -1304,6 +1362,7 @@ static_assert((Triple::EnvironmentType)ZigLLVM_GNUABI64 == Triple::GNUABI64, "") static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABI == Triple::GNUEABI, ""); static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABIHF == Triple::GNUEABIHF, ""); static_assert((Triple::EnvironmentType)ZigLLVM_GNUX32 == Triple::GNUX32, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_GNUILP32 == Triple::GNUILP32, ""); static_assert((Triple::EnvironmentType)ZigLLVM_CODE16 == Triple::CODE16, ""); static_assert((Triple::EnvironmentType)ZigLLVM_EABI == Triple::EABI, ""); static_assert((Triple::EnvironmentType)ZigLLVM_EABIHF == Triple::EABIHF, ""); @@ -1322,6 +1381,7 @@ static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::La static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, ""); static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, ""); static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, ""); +static_assert((Triple::ObjectFormatType)ZigLLVM_GOFF == Triple::GOFF, ""); static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, ""); static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, ""); static_assert((Triple::ObjectFormatType)ZigLLVM_XCOFF == Triple::XCOFF, ""); |
