Merge pull request #22808 from ziglang/fast-gpa
[zig.git] / src / zig_llvm.cpp
blob53a0faba8aa12996d52a7d5f0a0c3287fa84c4ac
1 /*
2 * Copyright (c) 2015 Andrew Kelley
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
9 /*
10 * The point of this file is to contain all the LLVM C++ API interaction so that:
11 * 1. The compile time of other files is kept under control.
12 * 2. Provide a C interface to the LLVM functions we need for self-hosting purposes.
13 * 3. Prevent C++ from infecting the rest of the project.
16 #include "zig_llvm.h"
18 #if __GNUC__ >= 9
19 #pragma GCC diagnostic push
20 #pragma GCC diagnostic ignored "-Winit-list-lifetime"
21 #endif
23 #include <llvm/Analysis/AliasAnalysis.h>
24 #include <llvm/Analysis/TargetLibraryInfo.h>
25 #include <llvm/Analysis/TargetTransformInfo.h>
26 #include <llvm/Bitcode/BitcodeWriter.h>
27 #include <llvm/IR/DiagnosticInfo.h>
28 #include <llvm/IR/InlineAsm.h>
29 #include <llvm/IR/Instructions.h>
30 #include <llvm/IR/LegacyPassManager.h>
31 #include <llvm/IR/Module.h>
32 #include <llvm/IR/OptBisect.h>
33 #include <llvm/IR/PassManager.h>
34 #include <llvm/IR/Verifier.h>
35 #include <llvm/InitializePasses.h>
36 #include <llvm/MC/TargetRegistry.h>
37 #include <llvm/Passes/OptimizationLevel.h>
38 #include <llvm/Passes/PassBuilder.h>
39 #include <llvm/Passes/StandardInstrumentations.h>
40 #include <llvm/Object/Archive.h>
41 #include <llvm/Object/ArchiveWriter.h>
42 #include <llvm/Object/COFF.h>
43 #include <llvm/Object/COFFImportFile.h>
44 #include <llvm/Object/COFFModuleDefinition.h>
45 #include <llvm/PassRegistry.h>
46 #include <llvm/Support/CommandLine.h>
47 #include <llvm/Support/FileSystem.h>
48 #include <llvm/Support/Process.h>
49 #include <llvm/Support/TimeProfiler.h>
50 #include <llvm/Support/Timer.h>
51 #include <llvm/Support/raw_ostream.h>
52 #include <llvm/Target/TargetMachine.h>
53 #include <llvm/Target/TargetOptions.h>
54 #include <llvm/Target/CodeGenCWrappers.h>
55 #include <llvm/Transforms/IPO.h>
56 #include <llvm/Transforms/IPO/AlwaysInliner.h>
57 #include <llvm/Transforms/Instrumentation/ThreadSanitizer.h>
58 #include <llvm/Transforms/Instrumentation/SanitizerCoverage.h>
59 #include <llvm/Transforms/Scalar.h>
60 #include <llvm/Transforms/Utils.h>
61 #include <llvm/Transforms/Utils/AddDiscriminators.h>
62 #include <llvm/Transforms/Utils/CanonicalizeAliases.h>
63 #include <llvm/Transforms/Utils/NameAnonGlobals.h>
65 #include <lld/Common/Driver.h>
67 #if __GNUC__ >= 9
68 #pragma GCC diagnostic pop
69 #endif
71 #include <new>
73 #include <stdlib.h>
75 using namespace llvm;
77 #ifndef NDEBUG
78 static const bool assertions_on = true;
79 #else
80 static const bool assertions_on = false;
81 #endif
83 LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
84 const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
85 LLVMCodeModel CodeModel, bool function_sections, bool data_sections, ZigLLVMFloatABI float_abi,
86 const char *abi_name)
88 std::optional<Reloc::Model> RM;
89 switch (Reloc){
90 case LLVMRelocStatic:
91 RM = Reloc::Static;
92 break;
93 case LLVMRelocPIC:
94 RM = Reloc::PIC_;
95 break;
96 case LLVMRelocDynamicNoPic:
97 RM = Reloc::DynamicNoPIC;
98 break;
99 case LLVMRelocROPI:
100 RM = Reloc::ROPI;
101 break;
102 case LLVMRelocRWPI:
103 RM = Reloc::RWPI;
104 break;
105 case LLVMRelocROPI_RWPI:
106 RM = Reloc::ROPI_RWPI;
107 break;
108 default:
109 break;
112 bool JIT;
113 std::optional<CodeModel::Model> CM = unwrap(CodeModel, JIT);
115 CodeGenOptLevel OL;
116 switch (Level) {
117 case LLVMCodeGenLevelNone:
118 OL = CodeGenOptLevel::None;
119 break;
120 case LLVMCodeGenLevelLess:
121 OL = CodeGenOptLevel::Less;
122 break;
123 case LLVMCodeGenLevelAggressive:
124 OL = CodeGenOptLevel::Aggressive;
125 break;
126 default:
127 OL = CodeGenOptLevel::Default;
128 break;
131 TargetOptions opt;
133 opt.UseInitArray = true;
134 opt.FunctionSections = function_sections;
135 opt.DataSections = data_sections;
136 switch (float_abi) {
137 case ZigLLVMFloatABI_Default:
138 opt.FloatABIType = FloatABI::Default;
139 break;
140 case ZigLLVMFloatABI_Soft:
141 opt.FloatABIType = FloatABI::Soft;
142 break;
143 case ZigLLVMFloatABI_Hard:
144 opt.FloatABIType = FloatABI::Hard;
145 break;
148 if (abi_name != nullptr) {
149 opt.MCOptions.ABIName = abi_name;
152 TargetMachine *TM = reinterpret_cast<Target*>(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM,
153 OL, JIT);
154 return reinterpret_cast<LLVMTargetMachineRef>(TM);
157 namespace {
158 // LLVM's time profiler can provide a hierarchy view of the time spent
159 // in each component. It generates JSON report in Chrome's "Trace Event"
160 // format. So the report can be easily visualized by the Chrome browser.
161 struct TimeTracerRAII {
162 // Granularity in ms
163 unsigned TimeTraceGranularity;
164 StringRef TimeTraceFile, OutputFilename;
165 bool EnableTimeTrace;
167 TimeTracerRAII(StringRef ProgramName, StringRef OF)
168 : TimeTraceGranularity(500U),
169 TimeTraceFile(std::getenv("ZIG_LLVM_TIME_TRACE_FILE")),
170 OutputFilename(OF),
171 EnableTimeTrace(!TimeTraceFile.empty()) {
172 if (EnableTimeTrace) {
173 if (const char *G = std::getenv("ZIG_LLVM_TIME_TRACE_GRANULARITY"))
174 TimeTraceGranularity = (unsigned)std::atoi(G);
176 llvm::timeTraceProfilerInitialize(TimeTraceGranularity, ProgramName);
180 ~TimeTracerRAII() {
181 if (EnableTimeTrace) {
182 if (auto E = llvm::timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) {
183 handleAllErrors(std::move(E), [&](const StringError &SE) {
184 errs() << SE.getMessage() << "\n";
186 return;
188 timeTraceProfilerCleanup();
192 } // end anonymous namespace
194 static SanitizerCoverageOptions getSanCovOptions(ZigLLVMCoverageOptions z) {
195 SanitizerCoverageOptions o;
196 o.CoverageType = (SanitizerCoverageOptions::Type)z.CoverageType;
197 o.IndirectCalls = z.IndirectCalls;
198 o.TraceBB = z.TraceBB;
199 o.TraceCmp = z.TraceCmp;
200 o.TraceDiv = z.TraceDiv;
201 o.TraceGep = z.TraceGep;
202 o.Use8bitCounters = z.Use8bitCounters;
203 o.TracePC = z.TracePC;
204 o.TracePCGuard = z.TracePCGuard;
205 o.Inline8bitCounters = z.Inline8bitCounters;
206 o.InlineBoolFlag = z.InlineBoolFlag;
207 o.PCTable = z.PCTable;
208 o.NoPrune = z.NoPrune;
209 o.StackDepth = z.StackDepth;
210 o.TraceLoads = z.TraceLoads;
211 o.TraceStores = z.TraceStores;
212 o.CollectControlFlow = z.CollectControlFlow;
213 return o;
216 ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
217 char **error_message, const ZigLLVMEmitOptions *options)
219 TimePassesIsEnabled = options->time_report;
221 raw_fd_ostream *dest_asm_ptr = nullptr;
222 raw_fd_ostream *dest_bin_ptr = nullptr;
223 raw_fd_ostream *dest_bitcode_ptr = nullptr;
225 if (options->asm_filename) {
226 std::error_code EC;
227 dest_asm_ptr = new(std::nothrow) raw_fd_ostream(options->asm_filename, EC, sys::fs::OF_None);
228 if (EC) {
229 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
230 return true;
233 if (options->bin_filename) {
234 std::error_code EC;
235 dest_bin_ptr = new(std::nothrow) raw_fd_ostream(options->bin_filename, EC, sys::fs::OF_None);
236 if (EC) {
237 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
238 return true;
241 if (options->bitcode_filename) {
242 std::error_code EC;
243 dest_bitcode_ptr = new(std::nothrow) raw_fd_ostream(options->bitcode_filename, EC, sys::fs::OF_None);
244 if (EC) {
245 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
246 return true;
250 std::unique_ptr<raw_fd_ostream> dest_asm(dest_asm_ptr),
251 dest_bin(dest_bin_ptr),
252 dest_bitcode(dest_bitcode_ptr);
255 auto PID = sys::Process::getProcessId();
256 std::string ProcName = "zig-";
257 ProcName += std::to_string(PID);
258 TimeTracerRAII TimeTracer(ProcName,
259 options->bin_filename? options->bin_filename : options->asm_filename);
261 TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref);
263 Module &llvm_module = *unwrap(module_ref);
265 // Pipeline configurations
266 PipelineTuningOptions pipeline_opts;
267 pipeline_opts.LoopUnrolling = !options->is_debug;
268 pipeline_opts.SLPVectorization = !options->is_debug;
269 pipeline_opts.LoopVectorization = !options->is_debug;
270 pipeline_opts.LoopInterleaving = !options->is_debug;
271 pipeline_opts.MergeFunctions = !options->is_debug;
273 // Instrumentations
274 PassInstrumentationCallbacks instr_callbacks;
275 StandardInstrumentations std_instrumentations(llvm_module.getContext(), false);
276 std_instrumentations.registerCallbacks(instr_callbacks);
278 std::optional<PGOOptions> opt_pgo_options = {};
279 PassBuilder pass_builder(&target_machine, pipeline_opts,
280 opt_pgo_options, &instr_callbacks);
282 LoopAnalysisManager loop_am;
283 FunctionAnalysisManager function_am;
284 CGSCCAnalysisManager cgscc_am;
285 ModuleAnalysisManager module_am;
287 // Register the AA manager first so that our version is the one used
288 function_am.registerPass([&] {
289 return pass_builder.buildDefaultAAPipeline();
292 Triple target_triple(llvm_module.getTargetTriple());
293 auto tlii = std::make_unique<TargetLibraryInfoImpl>(target_triple);
294 function_am.registerPass([&] { return TargetLibraryAnalysis(*tlii); });
296 // Initialize the AnalysisManagers
297 pass_builder.registerModuleAnalyses(module_am);
298 pass_builder.registerCGSCCAnalyses(cgscc_am);
299 pass_builder.registerFunctionAnalyses(function_am);
300 pass_builder.registerLoopAnalyses(loop_am);
301 pass_builder.crossRegisterProxies(loop_am, function_am, cgscc_am, module_am);
303 pass_builder.registerPipelineStartEPCallback([&](ModulePassManager &module_pm, OptimizationLevel OL) {
304 // Verify the input
305 if (assertions_on) {
306 module_pm.addPass(VerifierPass());
309 if (!options->is_debug) {
310 module_pm.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));
314 //pass_builder.registerOptimizerEarlyEPCallback([&](ModulePassManager &module_pm, OptimizationLevel OL) {
315 //});
317 pass_builder.registerOptimizerLastEPCallback([&](ModulePassManager &module_pm, OptimizationLevel level) {
318 // Code coverage instrumentation.
319 if (options->sancov) {
320 module_pm.addPass(SanitizerCoveragePass(getSanCovOptions(options->coverage)));
323 // Thread sanitizer
324 if (options->tsan) {
325 module_pm.addPass(ModuleThreadSanitizerPass());
326 module_pm.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
329 // Verify the output
330 if (assertions_on) {
331 module_pm.addPass(VerifierPass());
335 ModulePassManager module_pm;
336 OptimizationLevel opt_level;
337 // Setting up the optimization level
338 if (options->is_debug)
339 opt_level = OptimizationLevel::O0;
340 else if (options->is_small)
341 opt_level = OptimizationLevel::Oz;
342 else
343 opt_level = OptimizationLevel::O3;
345 // Initialize the PassManager
346 if (opt_level == OptimizationLevel::O0) {
347 module_pm = pass_builder.buildO0DefaultPipeline(opt_level, options->lto);
348 } else if (options->lto) {
349 module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level);
350 } else {
351 module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level);
354 // Unfortunately we don't have new PM for code generation
355 legacy::PassManager codegen_pm;
356 codegen_pm.add(
357 createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis()));
359 if (dest_bin && !options->lto) {
360 if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CodeGenFileType::ObjectFile)) {
361 *error_message = strdup("TargetMachine can't emit an object file");
362 return true;
365 if (dest_asm) {
366 if (target_machine.addPassesToEmitFile(codegen_pm, *dest_asm, nullptr, CodeGenFileType::AssemblyFile)) {
367 *error_message = strdup("TargetMachine can't emit an assembly file");
368 return true;
372 if (options->allow_fast_isel) {
373 target_machine.setO0WantsFastISel(true);
374 } else {
375 target_machine.setFastISel(false);
378 // Optimization phase
379 module_pm.run(llvm_module, module_am);
381 // Code generation phase
382 codegen_pm.run(llvm_module);
384 if (options->llvm_ir_filename) {
385 if (LLVMPrintModuleToFile(module_ref, options->llvm_ir_filename, error_message)) {
386 return true;
390 if (dest_bin && options->lto) {
391 WriteBitcodeToFile(llvm_module, *dest_bin);
393 if (dest_bitcode) {
394 WriteBitcodeToFile(llvm_module, *dest_bitcode);
397 if (options->time_report) {
398 TimerGroup::printAll(errs());
401 return false;
404 void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
405 static OptBisect opt_bisect;
406 opt_bisect.setLimit(limit);
407 unwrap(context_ref)->setOptPassGate(opt_bisect);
410 struct ZigDiagnosticHandler : public DiagnosticHandler {
411 bool BrokenDebugInfo;
412 ZigDiagnosticHandler() : BrokenDebugInfo(false) {}
413 bool handleDiagnostics(const DiagnosticInfo &DI) override {
414 // This dyn_cast should be casting to DiagnosticInfoIgnoringInvalidDebugMetadata
415 // but DiagnosticInfoIgnoringInvalidDebugMetadata is treated as DiagnosticInfoDebugMetadataVersion
416 // because of a bug in LLVM (see https://github.com/ziglang/zig/issues/19161).
417 // After this is fixed add an additional check for DiagnosticInfoIgnoringInvalidDebugMetadata
418 // but don't remove the current one as both indicate that debug info is broken.
419 if (auto *Remark = dyn_cast<DiagnosticInfoDebugMetadataVersion>(&DI)) {
420 BrokenDebugInfo = true;
422 return false;
426 void ZigLLVMEnableBrokenDebugInfoCheck(LLVMContextRef context_ref) {
427 unwrap(context_ref)->setDiagnosticHandler(std::make_unique<ZigDiagnosticHandler>());
430 bool ZigLLVMGetBrokenDebugInfo(LLVMContextRef context_ref) {
431 return ((const ZigDiagnosticHandler*)
432 unwrap(context_ref)->getDiagHandlerPtr())->BrokenDebugInfo;
435 void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
436 cl::ParseCommandLineOptions(argc, argv);
439 bool ZigLLVMWriteImportLibrary(const char *def_path, unsigned int coff_machine,
440 const char *output_lib_path, bool kill_at)
442 COFF::MachineTypes machine = static_cast<COFF::MachineTypes>(coff_machine);
444 auto bufOrErr = MemoryBuffer::getFile(def_path);
445 if (!bufOrErr) {
446 return false;
449 MemoryBuffer& buf = *bufOrErr.get();
450 Expected<object::COFFModuleDefinition> def =
451 object::parseCOFFModuleDefinition(buf, machine, /* MingwDef */ true);
453 if (!def) {
454 return true;
457 // The exports-juggling code below is ripped from LLVM's DlltoolDriver.cpp
459 // If ExtName is set (if the "ExtName = Name" syntax was used), overwrite
460 // Name with ExtName and clear ExtName. When only creating an import
461 // library and not linking, the internal name is irrelevant. This avoids
462 // cases where writeImportLibrary tries to transplant decoration from
463 // symbol decoration onto ExtName.
464 for (object::COFFShortExport& E : def->Exports) {
465 if (!E.ExtName.empty()) {
466 E.Name = E.ExtName;
467 E.ExtName.clear();
471 if (machine == COFF::IMAGE_FILE_MACHINE_I386 && kill_at) {
472 for (object::COFFShortExport& E : def->Exports) {
473 if (!E.ImportName.empty() || (!E.Name.empty() && E.Name[0] == '?'))
474 continue;
475 E.SymbolName = E.Name;
476 // Trim off the trailing decoration. Symbols will always have a
477 // starting prefix here (either _ for cdecl/stdcall, @ for fastcall
478 // or ? for C++ functions). Vectorcall functions won't have any
479 // fixed prefix, but the function base name will still be at least
480 // one char.
481 E.Name = E.Name.substr(0, E.Name.find('@', 1));
482 // By making sure E.SymbolName != E.Name for decorated symbols,
483 // writeImportLibrary writes these symbols with the type
484 // IMPORT_NAME_UNDECORATE.
488 return static_cast<bool>(
489 object::writeImportLibrary(def->OutputFile, output_lib_path,
490 def->Exports, machine, /* MinGW */ true));
493 bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
494 ZigLLVMArchiveKind archive_kind)
496 SmallVector<NewArchiveMember, 4> new_members;
497 for (size_t i = 0; i < file_name_count; i += 1) {
498 Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true);
499 Error err = new_member.takeError();
500 if (err) return true;
501 new_members.push_back(std::move(*new_member));
503 Error err = writeArchive(archive_name, new_members,
504 SymtabWritingMode::NormalSymtab, static_cast<object::Archive::Kind>(archive_kind), true, false, nullptr);
506 if (err) return true;
507 return false;
510 // The header file in LLD 16 exposed these functions. As of 17 they are only
511 // exposed via a macro ("LLD_HAS_DRIVER") which I have copied and pasted the
512 // body of here so that you don't have to wonder what it is doing.
513 namespace lld {
514 namespace coff {
515 bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
516 llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
518 namespace elf {
519 bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
520 llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
522 namespace wasm {
523 bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
524 llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
528 bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output) {
529 std::vector<const char *> args(argv, argv + argc);
530 return lld::coff::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
533 bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output) {
534 std::vector<const char *> args(argv, argv + argc);
535 return lld::elf::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
538 bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output) {
539 std::vector<const char *> args(argv, argv + argc);
540 return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
543 static_assert((FloatABI::ABIType)ZigLLVMFloatABI_Default == FloatABI::ABIType::Default, "");
544 static_assert((FloatABI::ABIType)ZigLLVMFloatABI_Soft == FloatABI::ABIType::Soft, "");
545 static_assert((FloatABI::ABIType)ZigLLVMFloatABI_Hard == FloatABI::ABIType::Hard, "");
547 static_assert((object::Archive::Kind)ZigLLVMArchiveKind_GNU == object::Archive::Kind::K_GNU, "");
548 static_assert((object::Archive::Kind)ZigLLVMArchiveKind_GNU64 == object::Archive::Kind::K_GNU64, "");
549 static_assert((object::Archive::Kind)ZigLLVMArchiveKind_BSD == object::Archive::Kind::K_BSD, "");
550 static_assert((object::Archive::Kind)ZigLLVMArchiveKind_DARWIN == object::Archive::Kind::K_DARWIN, "");
551 static_assert((object::Archive::Kind)ZigLLVMArchiveKind_DARWIN64 == object::Archive::Kind::K_DARWIN64, "");
552 static_assert((object::Archive::Kind)ZigLLVMArchiveKind_COFF == object::Archive::Kind::K_COFF, "");
553 static_assert((object::Archive::Kind)ZigLLVMArchiveKind_AIXBIG == object::Archive::Kind::K_AIXBIG, "");