/* * Copyright (c) 2015 Andrew Kelley * * This file is part of zig, which is MIT licensed. * See http://opensource.org/licenses/MIT */ #include "zig_llvm.hpp" /* * The point of this file is to contain all the LLVM C++ API interaction so that: * 1. The compile time of other files is kept under control. * 2. Provide a C interface to the LLVM functions we need for self-hosting purposes. * 3. Prevent C++ from infecting the rest of the project. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace llvm; void LLVMZigInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) { initializeLoopStrengthReducePass(*unwrap(R)); } void LLVMZigInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) { initializeLowerIntrinsicsPass(*unwrap(R)); } void LLVMZigInitializeUnreachableBlockElimPass(LLVMPassRegistryRef R) { initializeUnreachableBlockElimPass(*unwrap(R)); } char *LLVMZigGetHostCPUName(void) { std::string str = sys::getHostCPUName(); return strdup(str.c_str()); } char *LLVMZigGetNativeFeatures(void) { SubtargetFeatures features; StringMap host_features; if (sys::getHostCPUFeatures(host_features)) { for (auto &F : host_features) features.AddFeature(F.first(), F.second); } return strdup(features.getString().c_str()); } static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { PM.add(createAddDiscriminatorsPass()); } void LLVMZigOptimizeModule(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref) { TargetMachine* target_machine = reinterpret_cast(targ_machine_ref); Module* module = unwrap(module_ref); TargetLibraryInfoImpl tlii(Triple(module->getTargetTriple())); PassManagerBuilder *PMBuilder = new PassManagerBuilder(); PMBuilder->OptLevel = target_machine->getOptLevel(); PMBuilder->SizeLevel = 0; PMBuilder->BBVectorize = true; PMBuilder->SLPVectorize = true; PMBuilder->LoopVectorize = true; PMBuilder->DisableUnitAtATime = false; PMBuilder->DisableUnrollLoops = false; PMBuilder->MergeFunctions = true; PMBuilder->PrepareForLTO = true; PMBuilder->RerollLoops = true; PMBuilder->addExtension(PassManagerBuilder::EP_EarlyAsPossible, addAddDiscriminatorsPass); PMBuilder->LibraryInfo = &tlii; PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel); // Set up the per-function pass manager. legacy::FunctionPassManager *FPM = new legacy::FunctionPassManager(module); FPM->add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); #ifndef NDEBUG bool verify_module = true; #else bool verify_module = false; #endif if (verify_module) { FPM->add(createVerifierPass()); } PMBuilder->populateFunctionPassManager(*FPM); // Set up the per-module pass manager. legacy::PassManager *MPM = new legacy::PassManager(); MPM->add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); PMBuilder->populateModulePassManager(*MPM); // run per function optimization passes FPM->doInitialization(); for (Function &F : *module) if (!F.isDeclaration()) FPM->run(F); FPM->doFinalization(); // run per module optimization passes MPM->run(*module); } LLVMValueRef LLVMZigBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, unsigned CC, const char *Name) { CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name); call_inst->setCallingConv(CC); return wrap(unwrap(B)->Insert(call_inst)); } LLVMZigDIType *LLVMZigCreateDebugPointerType(LLVMZigDIBuilder *dibuilder, LLVMZigDIType *pointee_type, uint64_t size_in_bits, uint64_t align_in_bits, const char *name) { DIType *di_type = reinterpret_cast(dibuilder)->createPointerType( reinterpret_cast(pointee_type), size_in_bits, align_in_bits, name); return reinterpret_cast(di_type); } LLVMZigDIType *LLVMZigCreateDebugBasicType(LLVMZigDIBuilder *dibuilder, const char *name, uint64_t size_in_bits, uint64_t align_in_bits, unsigned encoding) { DIType *di_type = reinterpret_cast(dibuilder)->createBasicType( name, size_in_bits, align_in_bits, encoding); return reinterpret_cast(di_type); } unsigned LLVMZigEncoding_DW_ATE_unsigned(void) { return dwarf::DW_ATE_unsigned; } unsigned LLVMZigEncoding_DW_ATE_signed(void) { return dwarf::DW_ATE_signed; } unsigned LLVMZigLang_DW_LANG_C99(void) { return dwarf::DW_LANG_C99; } LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) { DIBuilder *di_builder = new DIBuilder(*llvm::unwrap(module), allow_unresolved); return reinterpret_cast(di_builder); } void LLVMZigSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, LLVMZigDIScope *scope) { unwrap(builder)->SetCurrentDebugLocation(llvm::DebugLoc::get( line, column, reinterpret_cast(scope))); } LLVMZigDILexicalBlock *LLVMZigCreateLexicalBlock(LLVMZigDIBuilder *dbuilder, LLVMZigDIScope *scope, LLVMZigDIFile *file, unsigned line, unsigned col) { DILexicalBlock *result = reinterpret_cast(dbuilder)->createLexicalBlock( reinterpret_cast(scope), reinterpret_cast(file), line, col); return reinterpret_cast(result); } LLVMZigDIScope *LLVMZigLexicalBlockToScope(LLVMZigDILexicalBlock *lexical_block) { DIScope *scope = reinterpret_cast(lexical_block); return reinterpret_cast(scope); } LLVMZigDIScope *LLVMZigCompileUnitToScope(LLVMZigDICompileUnit *compile_unit) { DIScope *scope = reinterpret_cast(compile_unit); return reinterpret_cast(scope); } LLVMZigDIScope *LLVMZigFileToScope(LLVMZigDIFile *difile) { DIScope *scope = reinterpret_cast(difile); return reinterpret_cast(scope); } LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram) { DIScope *scope = reinterpret_cast(subprogram); return reinterpret_cast(scope); } LLVMZigDICompileUnit *LLVMZigCreateCompileUnit(LLVMZigDIBuilder *dibuilder, unsigned lang, const char *file, const char *dir, const char *producer, bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name, uint64_t dwo_id, bool emit_debug_info) { DICompileUnit *result = reinterpret_cast(dibuilder)->createCompileUnit( lang, file, dir, producer, is_optimized, flags, runtime_version, split_name, DIBuilder::FullDebug, dwo_id, emit_debug_info); return reinterpret_cast(result); } LLVMZigDIFile *LLVMZigCreateFile(LLVMZigDIBuilder *dibuilder, const char *filename, const char *directory) { DIFile *result = reinterpret_cast(dibuilder)->createFile(filename, directory); return reinterpret_cast(result); } LLVMZigDISubprogram *LLVMZigCreateFunction(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, const char *name, const char *linkage_name, LLVMZigDIFile *file, unsigned lineno, LLVMZigDISubroutineType *ty, bool is_local_to_unit, bool is_definition, unsigned scope_line, unsigned flags, bool is_optimized, LLVMValueRef function) { llvm::Function *unwrapped_function = reinterpret_cast(unwrap(function)); DISubprogram *result = reinterpret_cast(dibuilder)->createFunction( reinterpret_cast(scope), name, linkage_name, reinterpret_cast(file), lineno, reinterpret_cast(ty), is_local_to_unit, is_definition, scope_line, flags, is_optimized, unwrapped_function); return reinterpret_cast(result); } void LLVMZigDIBuilderFinalize(LLVMZigDIBuilder *dibuilder) { reinterpret_cast(dibuilder)->finalize(); }