master
  1/*
  2 * Copyright (c) 2015 Andrew Kelley
  3 *
  4 * This file is part of zig, which is MIT licensed.
  5 * See http://opensource.org/licenses/MIT
  6 */
  7
  8
  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.
 14 */
 15
 16#include "zig_llvm.h"
 17
 18#if __GNUC__ >= 9
 19#pragma GCC diagnostic push
 20#pragma GCC diagnostic ignored "-Winit-list-lifetime"
 21#endif
 22
 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/PassRegistry.h>
 43#include <llvm/Support/CommandLine.h>
 44#include <llvm/Support/FileSystem.h>
 45#include <llvm/Support/Process.h>
 46#include <llvm/Support/TimeProfiler.h>
 47#include <llvm/Support/Timer.h>
 48#include <llvm/Support/raw_ostream.h>
 49#include <llvm/Target/TargetMachine.h>
 50#include <llvm/Target/TargetOptions.h>
 51#include <llvm/Target/CodeGenCWrappers.h>
 52#include <llvm/Transforms/IPO.h>
 53#include <llvm/Transforms/IPO/AlwaysInliner.h>
 54#include <llvm/Transforms/Instrumentation/ThreadSanitizer.h>
 55#include <llvm/Transforms/Instrumentation/SanitizerCoverage.h>
 56#include <llvm/Transforms/Scalar.h>
 57#include <llvm/Transforms/Utils.h>
 58#include <llvm/Transforms/Utils/AddDiscriminators.h>
 59#include <llvm/Transforms/Utils/CanonicalizeAliases.h>
 60#include <llvm/Transforms/Utils/NameAnonGlobals.h>
 61
 62#include <lld/Common/Driver.h>
 63
 64#if __GNUC__ >= 9
 65#pragma GCC diagnostic pop
 66#endif
 67
 68#include <new>
 69
 70#include <stdlib.h>
 71
 72using namespace llvm;
 73
 74#ifndef NDEBUG
 75static const bool assertions_on = true;
 76#else
 77static const bool assertions_on = false;
 78#endif
 79
 80LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
 81    const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
 82    LLVMCodeModel CodeModel, bool function_sections, bool data_sections, ZigLLVMFloatABI float_abi,
 83    const char *abi_name, bool emulated_tls)
 84{
 85    std::optional<Reloc::Model> RM;
 86    switch (Reloc){
 87        case LLVMRelocStatic:
 88            RM = Reloc::Static;
 89            break;
 90        case LLVMRelocPIC:
 91            RM = Reloc::PIC_;
 92            break;
 93        case LLVMRelocDynamicNoPic:
 94            RM = Reloc::DynamicNoPIC;
 95            break;
 96        case LLVMRelocROPI:
 97            RM = Reloc::ROPI;
 98            break;
 99        case LLVMRelocRWPI:
100            RM = Reloc::RWPI;
101            break;
102        case LLVMRelocROPI_RWPI:
103            RM = Reloc::ROPI_RWPI;
104            break;
105        default:
106            break;
107    }
108
109    bool JIT;
110    std::optional<CodeModel::Model> CM = unwrap(CodeModel, JIT);
111
112    CodeGenOptLevel OL;
113    switch (Level) {
114        case LLVMCodeGenLevelNone:
115            OL = CodeGenOptLevel::None;
116            break;
117        case LLVMCodeGenLevelLess:
118            OL = CodeGenOptLevel::Less;
119            break;
120        case LLVMCodeGenLevelAggressive:
121            OL = CodeGenOptLevel::Aggressive;
122            break;
123        default:
124            OL = CodeGenOptLevel::Default;
125            break;
126    }
127
128    TargetOptions opt;
129
130    opt.UseInitArray = true;
131    opt.FunctionSections = function_sections;
132    opt.DataSections = data_sections;
133    switch (float_abi) {
134        case ZigLLVMFloatABI_Default:
135            opt.FloatABIType = FloatABI::Default;
136            break;
137        case ZigLLVMFloatABI_Soft:
138            opt.FloatABIType = FloatABI::Soft;
139            break;
140        case ZigLLVMFloatABI_Hard:
141            opt.FloatABIType = FloatABI::Hard;
142            break;
143    }
144
145    if (abi_name != nullptr) {
146        opt.MCOptions.ABIName = abi_name;
147    }
148
149    if (emulated_tls) {
150        opt.EmulatedTLS = true;
151    }
152
153    TargetMachine *TM = reinterpret_cast<Target*>(T)->createTargetMachine(
154        llvm::Triple(Triple),
155        CPU,
156        Features,
157        opt,
158        RM,
159        CM,
160        OL,
161        JIT);
162
163    return reinterpret_cast<LLVMTargetMachineRef>(TM);
164}
165
166namespace {
167// LLVM's time profiler can provide a hierarchy view of the time spent
168// in each component. It generates JSON report in Chrome's "Trace Event"
169// format. So the report can be easily visualized by the Chrome browser.
170struct TimeTracerRAII {
171  // Granularity in ms
172  unsigned TimeTraceGranularity;
173  StringRef TimeTraceFile, OutputFilename;
174  bool EnableTimeTrace;
175
176  TimeTracerRAII(StringRef ProgramName, StringRef OF)
177    : TimeTraceGranularity(500U),
178      TimeTraceFile(std::getenv("ZIG_LLVM_TIME_TRACE_FILE")),
179      OutputFilename(OF),
180      EnableTimeTrace(!TimeTraceFile.empty()) {
181    if (EnableTimeTrace) {
182      if (const char *G = std::getenv("ZIG_LLVM_TIME_TRACE_GRANULARITY"))
183        TimeTraceGranularity = (unsigned)std::atoi(G);
184
185      llvm::timeTraceProfilerInitialize(TimeTraceGranularity, ProgramName);
186    }
187  }
188
189  ~TimeTracerRAII() {
190    if (EnableTimeTrace) {
191      if (auto E = llvm::timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) {
192        handleAllErrors(std::move(E), [&](const StringError &SE) {
193          errs() << SE.getMessage() << "\n";
194        });
195        return;
196      }
197      timeTraceProfilerCleanup();
198    }
199  }
200};
201} // end anonymous namespace
202
203static SanitizerCoverageOptions getSanCovOptions(ZigLLVMCoverageOptions z) {
204    SanitizerCoverageOptions o;
205    o.CoverageType = (SanitizerCoverageOptions::Type)z.CoverageType;
206    o.IndirectCalls = z.IndirectCalls;
207    o.TraceBB = z.TraceBB;
208    o.TraceCmp = z.TraceCmp;
209    o.TraceDiv = z.TraceDiv;
210    o.TraceGep = z.TraceGep;
211    o.Use8bitCounters = z.Use8bitCounters;
212    o.TracePC = z.TracePC;
213    o.TracePCGuard = z.TracePCGuard;
214    o.Inline8bitCounters = z.Inline8bitCounters;
215    o.InlineBoolFlag = z.InlineBoolFlag;
216    o.PCTable = z.PCTable;
217    o.NoPrune = z.NoPrune;
218    o.StackDepth = z.StackDepth;
219    o.TraceLoads = z.TraceLoads;
220    o.TraceStores = z.TraceStores;
221    o.CollectControlFlow = z.CollectControlFlow;
222    return o;
223}
224
225ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
226    char **error_message, const ZigLLVMEmitOptions *options)
227{
228    TimePassesIsEnabled = options->time_report_out != nullptr;
229
230    raw_fd_ostream *dest_asm_ptr = nullptr;
231    raw_fd_ostream *dest_bin_ptr = nullptr;
232    raw_fd_ostream *dest_bitcode_ptr = nullptr;
233
234    if (options->asm_filename) {
235        std::error_code EC;
236        dest_asm_ptr = new(std::nothrow) raw_fd_ostream(options->asm_filename, EC, sys::fs::OF_None);
237        if (EC) {
238            *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
239            return true;
240        }
241    }
242    if (options->bin_filename) {
243        std::error_code EC;
244        dest_bin_ptr = new(std::nothrow) raw_fd_ostream(options->bin_filename, EC, sys::fs::OF_None);
245        if (EC) {
246            *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
247            return true;
248        }
249    }
250    if (options->bitcode_filename) {
251        std::error_code EC;
252        dest_bitcode_ptr = new(std::nothrow) raw_fd_ostream(options->bitcode_filename, EC, sys::fs::OF_None);
253        if (EC) {
254            *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
255            return true;
256        }
257    }
258
259    std::unique_ptr<raw_fd_ostream> dest_asm(dest_asm_ptr),
260                                    dest_bin(dest_bin_ptr),
261                                    dest_bitcode(dest_bitcode_ptr);
262
263
264    auto PID = sys::Process::getProcessId();
265    std::string ProcName = "zig-";
266    ProcName += std::to_string(PID);
267    TimeTracerRAII TimeTracer(ProcName,
268                              options->bin_filename? options->bin_filename : options->asm_filename);
269
270    TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref);
271
272    if (options->allow_fast_isel) {
273        target_machine.setO0WantsFastISel(true);
274    } else {
275        target_machine.setFastISel(false);
276    }
277
278    if (!options->allow_machine_outliner) {
279        target_machine.setMachineOutliner(false);
280    }
281
282    Module &llvm_module = *unwrap(module_ref);
283
284    // Pipeline configurations
285    PipelineTuningOptions pipeline_opts;
286    pipeline_opts.LoopUnrolling = !options->is_debug;
287    pipeline_opts.SLPVectorization = !options->is_debug;
288    pipeline_opts.LoopVectorization = !options->is_debug;
289    pipeline_opts.LoopInterleaving = !options->is_debug;
290    pipeline_opts.MergeFunctions = !options->is_debug;
291
292    // Instrumentations
293    PassInstrumentationCallbacks instr_callbacks;
294    StandardInstrumentations std_instrumentations(llvm_module.getContext(), false);
295    std_instrumentations.registerCallbacks(instr_callbacks);
296
297    std::optional<PGOOptions> opt_pgo_options = {};
298    PassBuilder pass_builder(&target_machine, pipeline_opts,
299                             opt_pgo_options, &instr_callbacks);
300
301    LoopAnalysisManager loop_am;
302    FunctionAnalysisManager function_am;
303    CGSCCAnalysisManager cgscc_am;
304    ModuleAnalysisManager module_am;
305
306    // Register the AA manager first so that our version is the one used
307    function_am.registerPass([&] {
308      return pass_builder.buildDefaultAAPipeline();
309    });
310
311    Triple target_triple(llvm_module.getTargetTriple());
312    auto tlii = std::make_unique<TargetLibraryInfoImpl>(target_triple);
313    function_am.registerPass([&] { return TargetLibraryAnalysis(*tlii); });
314
315    // Initialize the AnalysisManagers
316    pass_builder.registerModuleAnalyses(module_am);
317    pass_builder.registerCGSCCAnalyses(cgscc_am);
318    pass_builder.registerFunctionAnalyses(function_am);
319    pass_builder.registerLoopAnalyses(loop_am);
320    pass_builder.crossRegisterProxies(loop_am, function_am, cgscc_am, module_am);
321
322    pass_builder.registerPipelineStartEPCallback([&](ModulePassManager &module_pm, OptimizationLevel level) {
323        // Verify the input
324        if (assertions_on) {
325            module_pm.addPass(VerifierPass());
326        }
327
328        if (!options->is_debug) {
329            module_pm.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));
330        }
331    });
332
333    const bool early_san = options->is_debug;
334
335    pass_builder.registerOptimizerEarlyEPCallback([&](ModulePassManager &module_pm, OptimizationLevel level, ThinOrFullLTOPhase lto_phase) {
336        if (early_san) {
337            // Code coverage instrumentation.
338            if (options->sancov) {
339                module_pm.addPass(SanitizerCoveragePass(getSanCovOptions(options->coverage)));
340            }
341
342            // Thread sanitizer
343            if (options->tsan) {
344                module_pm.addPass(ModuleThreadSanitizerPass());
345                module_pm.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
346            }
347        }
348    });
349
350    pass_builder.registerOptimizerLastEPCallback([&](ModulePassManager &module_pm, OptimizationLevel level, ThinOrFullLTOPhase lto_phase) {
351        if (!early_san) {
352            // Code coverage instrumentation.
353            if (options->sancov) {
354                module_pm.addPass(SanitizerCoveragePass(getSanCovOptions(options->coverage)));
355            }
356
357            // Thread sanitizer
358            if (options->tsan) {
359                module_pm.addPass(ModuleThreadSanitizerPass());
360                module_pm.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
361            }
362        }
363
364        // Verify the output
365        if (assertions_on) {
366            module_pm.addPass(VerifierPass());
367        }
368    });
369
370    ModulePassManager module_pm;
371    OptimizationLevel opt_level;
372    // Setting up the optimization level
373    if (options->is_debug)
374      opt_level = OptimizationLevel::O0;
375    else if (options->is_small)
376      opt_level = OptimizationLevel::Oz;
377    else
378      opt_level = OptimizationLevel::O3;
379
380    // Initialize the PassManager
381    if (opt_level == OptimizationLevel::O0) {
382      module_pm = pass_builder.buildO0DefaultPipeline(opt_level, static_cast<ThinOrFullLTOPhase>(options->lto));
383    } else if (options->lto) {
384      module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level);
385    } else {
386      module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level);
387    }
388
389    // Unfortunately we don't have new PM for code generation
390    legacy::PassManager codegen_pm;
391    codegen_pm.add(
392      createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis()));
393
394    if (dest_bin && !options->lto) {
395        if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CodeGenFileType::ObjectFile)) {
396            *error_message = strdup("TargetMachine can't emit an object file");
397            return true;
398        }
399    }
400    if (dest_asm) {
401        if (target_machine.addPassesToEmitFile(codegen_pm, *dest_asm, nullptr, CodeGenFileType::AssemblyFile)) {
402            *error_message = strdup("TargetMachine can't emit an assembly file");
403            return true;
404        }
405    }
406
407    // Optimization phase
408    module_pm.run(llvm_module, module_am);
409
410    // Code generation phase
411    codegen_pm.run(llvm_module);
412
413    if (options->llvm_ir_filename) {
414        if (LLVMPrintModuleToFile(module_ref, options->llvm_ir_filename, error_message)) {
415            return true;
416        }
417    }
418
419    if (dest_bin && options->lto) {
420        WriteBitcodeToFile(llvm_module, *dest_bin);
421    }
422    if (dest_bitcode) {
423        WriteBitcodeToFile(llvm_module, *dest_bitcode);
424    }
425
426    // This must only happen once we know we've succeeded and will be returning `false`, because
427    // this code `malloc`s memory which will become owned by the caller (in Zig code).
428    if (options->time_report_out != nullptr) {
429        std::string out_str;
430        auto os = raw_string_ostream(out_str);
431        TimerGroup::printAll(os);
432        TimerGroup::clearAll();
433        auto c_str = (char *)malloc(out_str.length() + 1);
434        strcpy(c_str, out_str.c_str());
435        *options->time_report_out = c_str;
436    }
437    return false;
438}
439
440void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) {
441    static OptBisect opt_bisect;
442    opt_bisect.setLimit(limit);
443    unwrap(context_ref)->setOptPassGate(opt_bisect);
444}
445
446struct ZigDiagnosticHandler : public DiagnosticHandler {
447    bool BrokenDebugInfo;
448    ZigDiagnosticHandler() : BrokenDebugInfo(false) {}
449    bool handleDiagnostics(const DiagnosticInfo &DI) override {
450        // This dyn_cast should be casting to DiagnosticInfoIgnoringInvalidDebugMetadata
451        // but DiagnosticInfoIgnoringInvalidDebugMetadata is treated as DiagnosticInfoDebugMetadataVersion
452        // because of a bug in LLVM (see https://github.com/ziglang/zig/issues/19161).
453        // After this is fixed add an additional check for DiagnosticInfoIgnoringInvalidDebugMetadata
454        // but don't remove the current one as both indicate that debug info is broken.
455        if (auto *Remark = dyn_cast<DiagnosticInfoDebugMetadataVersion>(&DI)) {
456            BrokenDebugInfo = true;
457        }
458        return false;
459    }
460};
461
462void ZigLLVMEnableBrokenDebugInfoCheck(LLVMContextRef context_ref) {
463    unwrap(context_ref)->setDiagnosticHandler(std::make_unique<ZigDiagnosticHandler>());
464}
465
466bool ZigLLVMGetBrokenDebugInfo(LLVMContextRef context_ref) {
467    return ((const ZigDiagnosticHandler*)
468        unwrap(context_ref)->getDiagHandlerPtr())->BrokenDebugInfo;
469}
470
471void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
472    cl::ParseCommandLineOptions(argc, argv);
473}
474
475bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
476    ZigLLVMArchiveKind archive_kind)
477{
478    SmallVector<NewArchiveMember, 4> new_members;
479    for (size_t i = 0; i < file_name_count; i += 1) {
480        Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true);
481        Error err = new_member.takeError();
482        if (err) return true;
483        new_members.push_back(std::move(*new_member));
484    }
485    Error err = writeArchive(archive_name, new_members,
486        SymtabWritingMode::NormalSymtab, static_cast<object::Archive::Kind>(archive_kind), true, false, nullptr);
487
488    if (err) return true;
489    return false;
490}
491
492// The header file in LLD 16 exposed these functions. As of 17 they are only
493// exposed via a macro ("LLD_HAS_DRIVER") which I have copied and pasted the
494// body of here so that you don't have to wonder what it is doing.
495namespace lld {
496    namespace coff {
497        bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
498                llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
499    }
500    namespace elf {
501        bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
502                llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
503    }
504    namespace wasm {
505        bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
506                llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
507    }
508}
509
510bool ZigLLDLinkCOFF(int argc, const char **argv, bool can_exit_early, bool disable_output) {
511    std::vector<const char *> args(argv, argv + argc);
512    return lld::coff::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
513}
514
515bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output) {
516    std::vector<const char *> args(argv, argv + argc);
517    return lld::elf::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
518}
519
520bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output) {
521    std::vector<const char *> args(argv, argv + argc);
522    return lld::wasm::link(args, llvm::outs(), llvm::errs(), can_exit_early, disable_output);
523}
524
525static_assert((FloatABI::ABIType)ZigLLVMFloatABI_Default == FloatABI::ABIType::Default, "");
526static_assert((FloatABI::ABIType)ZigLLVMFloatABI_Soft == FloatABI::ABIType::Soft, "");
527static_assert((FloatABI::ABIType)ZigLLVMFloatABI_Hard == FloatABI::ABIType::Hard, "");
528
529static_assert((object::Archive::Kind)ZigLLVMArchiveKind_GNU == object::Archive::Kind::K_GNU, "");
530static_assert((object::Archive::Kind)ZigLLVMArchiveKind_GNU64 == object::Archive::Kind::K_GNU64, "");
531static_assert((object::Archive::Kind)ZigLLVMArchiveKind_BSD == object::Archive::Kind::K_BSD, "");
532static_assert((object::Archive::Kind)ZigLLVMArchiveKind_DARWIN == object::Archive::Kind::K_DARWIN, "");
533static_assert((object::Archive::Kind)ZigLLVMArchiveKind_DARWIN64 == object::Archive::Kind::K_DARWIN64, "");
534static_assert((object::Archive::Kind)ZigLLVMArchiveKind_COFF == object::Archive::Kind::K_COFF, "");
535static_assert((object::Archive::Kind)ZigLLVMArchiveKind_AIXBIG == object::Archive::Kind::K_AIXBIG, "");