2 * Copyright (c) 2015 Andrew Kelley
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
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.
19 #pragma GCC diagnostic push
20 #pragma GCC diagnostic ignored "-Winit-list-lifetime"
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>
68 #pragma GCC diagnostic pop
78 static const bool assertions_on
= true;
80 static const bool assertions_on
= false;
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
,
88 std::optional
<Reloc::Model
> RM
;
96 case LLVMRelocDynamicNoPic
:
97 RM
= Reloc::DynamicNoPIC
;
105 case LLVMRelocROPI_RWPI
:
106 RM
= Reloc::ROPI_RWPI
;
113 std::optional
<CodeModel::Model
> CM
= unwrap(CodeModel
, JIT
);
117 case LLVMCodeGenLevelNone
:
118 OL
= CodeGenOptLevel::None
;
120 case LLVMCodeGenLevelLess
:
121 OL
= CodeGenOptLevel::Less
;
123 case LLVMCodeGenLevelAggressive
:
124 OL
= CodeGenOptLevel::Aggressive
;
127 OL
= CodeGenOptLevel::Default
;
133 opt
.UseInitArray
= true;
134 opt
.FunctionSections
= function_sections
;
135 opt
.DataSections
= data_sections
;
137 case ZigLLVMFloatABI_Default
:
138 opt
.FloatABIType
= FloatABI::Default
;
140 case ZigLLVMFloatABI_Soft
:
141 opt
.FloatABIType
= FloatABI::Soft
;
143 case ZigLLVMFloatABI_Hard
:
144 opt
.FloatABIType
= FloatABI::Hard
;
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
,
154 return reinterpret_cast<LLVMTargetMachineRef
>(TM
);
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
{
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")),
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
);
181 if (EnableTimeTrace
) {
182 if (auto E
= llvm::timeTraceProfilerWrite(TimeTraceFile
, OutputFilename
)) {
183 handleAllErrors(std::move(E
), [&](const StringError
&SE
) {
184 errs() << SE
.getMessage() << "\n";
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
;
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
) {
227 dest_asm_ptr
= new(std::nothrow
) raw_fd_ostream(options
->asm_filename
, EC
, sys::fs::OF_None
);
229 *error_message
= strdup((const char *)StringRef(EC
.message()).bytes_begin());
233 if (options
->bin_filename
) {
235 dest_bin_ptr
= new(std::nothrow
) raw_fd_ostream(options
->bin_filename
, EC
, sys::fs::OF_None
);
237 *error_message
= strdup((const char *)StringRef(EC
.message()).bytes_begin());
241 if (options
->bitcode_filename
) {
243 dest_bitcode_ptr
= new(std::nothrow
) raw_fd_ostream(options
->bitcode_filename
, EC
, sys::fs::OF_None
);
245 *error_message
= strdup((const char *)StringRef(EC
.message()).bytes_begin());
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
;
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
) {
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) {
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
)));
325 module_pm
.addPass(ModuleThreadSanitizerPass());
326 module_pm
.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
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
;
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
);
351 module_pm
= pass_builder
.buildPerModuleDefaultPipeline(opt_level
);
354 // Unfortunately we don't have new PM for code generation
355 legacy::PassManager codegen_pm
;
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");
366 if (target_machine
.addPassesToEmitFile(codegen_pm
, *dest_asm
, nullptr, CodeGenFileType::AssemblyFile
)) {
367 *error_message
= strdup("TargetMachine can't emit an assembly file");
372 if (options
->allow_fast_isel
) {
373 target_machine
.setO0WantsFastISel(true);
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
)) {
390 if (dest_bin
&& options
->lto
) {
391 WriteBitcodeToFile(llvm_module
, *dest_bin
);
394 WriteBitcodeToFile(llvm_module
, *dest_bitcode
);
397 if (options
->time_report
) {
398 TimerGroup::printAll(errs());
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;
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
);
449 MemoryBuffer
& buf
= *bufOrErr
.get();
450 Expected
<object::COFFModuleDefinition
> def
=
451 object::parseCOFFModuleDefinition(buf
, machine
, /* MingwDef */ 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()) {
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] == '?'))
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
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;
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.
515 bool link(llvm::ArrayRef
<const char *> args
, llvm::raw_ostream
&stdoutOS
,
516 llvm::raw_ostream
&stderrOS
, bool exitEarly
, bool disableOutput
);
519 bool link(llvm::ArrayRef
<const char *> args
, llvm::raw_ostream
&stdoutOS
,
520 llvm::raw_ostream
&stderrOS
, bool exitEarly
, bool disableOutput
);
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
, "");