/* * Copyright (c) 2015 Andrew Kelley * * This file is part of zig, which is MIT licensed. * See http://opensource.org/licenses/MIT */ // This must go before all includes. #include "config.h" #if defined(ZIG_LLVM_OLD_CXX_ABI) #define _GLIBCXX_USE_CXX11_ABI 0 #endif #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 #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)); } void LLVMZigAddNonNullAttr(LLVMValueRef fn, unsigned i) { assert( isa(unwrap(fn)) ); Function *unwrapped_function = reinterpret_cast(unwrap(fn)); unwrapped_function->addAttribute(i, Attribute::NonNull); } void ZigLLVMFnSetSubprogram(LLVMValueRef fn, LLVMZigDISubprogram *subprogram) { assert( isa(unwrap(fn)) ); Function *unwrapped_function = reinterpret_cast(unwrap(fn)); unwrapped_function->setSubprogram(reinterpret_cast(subprogram)); } 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); } LLVMZigDIType *LLVMZigCreateDebugArrayType(LLVMZigDIBuilder *dibuilder, uint64_t size_in_bits, uint64_t align_in_bits, LLVMZigDIType *elem_type, int elem_count) { SmallVector subrange; subrange.push_back(reinterpret_cast(dibuilder)->getOrCreateSubrange(0, elem_count)); DIType *di_type = reinterpret_cast(dibuilder)->createArrayType( size_in_bits, align_in_bits, reinterpret_cast(elem_type), reinterpret_cast(dibuilder)->getOrCreateArray(subrange)); return reinterpret_cast(di_type); } LLVMZigDIEnumerator *LLVMZigCreateDebugEnumerator(LLVMZigDIBuilder *dibuilder, const char *name, int64_t val) { DIEnumerator *di_enumerator = reinterpret_cast(dibuilder)->createEnumerator(name, val); return reinterpret_cast(di_enumerator); } LLVMZigDIType *LLVMZigCreateDebugEnumerationType(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_number, uint64_t size_in_bits, uint64_t align_in_bits, LLVMZigDIEnumerator **enumerator_array, int enumerator_array_len, LLVMZigDIType *underlying_type, const char *unique_id) { SmallVector fields; for (int i = 0; i < enumerator_array_len; i += 1) { DIEnumerator *dienumerator = reinterpret_cast(enumerator_array[i]); fields.push_back(dienumerator); } DIType *di_type = reinterpret_cast(dibuilder)->createEnumerationType( reinterpret_cast(scope), name, reinterpret_cast(file), line_number, size_in_bits, align_in_bits, reinterpret_cast(dibuilder)->getOrCreateArray(fields), reinterpret_cast(underlying_type), unique_id); return reinterpret_cast(di_type); } LLVMZigDIType *LLVMZigCreateDebugMemberType(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line, uint64_t size_in_bits, uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, LLVMZigDIType *type) { DIType *di_type = reinterpret_cast(dibuilder)->createMemberType( reinterpret_cast(scope), name, reinterpret_cast(file), line, size_in_bits, align_in_bits, offset_in_bits, flags, reinterpret_cast(type)); return reinterpret_cast(di_type); } LLVMZigDIType *LLVMZigCreateDebugUnionType(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_number, uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, LLVMZigDIType **types_array, int types_array_len, unsigned run_time_lang, const char *unique_id) { SmallVector fields; for (int i = 0; i < types_array_len; i += 1) { DIType *ditype = reinterpret_cast(types_array[i]); fields.push_back(ditype); } DIType *di_type = reinterpret_cast(dibuilder)->createUnionType( reinterpret_cast(scope), name, reinterpret_cast(file), line_number, size_in_bits, align_in_bits, flags, reinterpret_cast(dibuilder)->getOrCreateArray(fields), run_time_lang, unique_id); return reinterpret_cast(di_type); } LLVMZigDIType *LLVMZigCreateDebugStructType(LLVMZigDIBuilder *dibuilder, LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_number, uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, LLVMZigDIType *derived_from, LLVMZigDIType **types_array, int types_array_len, unsigned run_time_lang, LLVMZigDIType *vtable_holder, const char *unique_id) { SmallVector fields; for (int i = 0; i < types_array_len; i += 1) { DIType *ditype = reinterpret_cast(types_array[i]); fields.push_back(ditype); } DIType *di_type = reinterpret_cast(dibuilder)->createStructType( reinterpret_cast(scope), name, reinterpret_cast(file), line_number, size_in_bits, align_in_bits, flags, reinterpret_cast(derived_from), reinterpret_cast(dibuilder)->getOrCreateArray(fields), run_time_lang, reinterpret_cast(vtable_holder), unique_id); return reinterpret_cast(di_type); } LLVMZigDIType *LLVMZigCreateReplaceableCompositeType(LLVMZigDIBuilder *dibuilder, unsigned tag, const char *name, LLVMZigDIScope *scope, LLVMZigDIFile *file, unsigned line) { DIType *di_type = reinterpret_cast(dibuilder)->createReplaceableCompositeType( tag, name, reinterpret_cast(scope), reinterpret_cast(file), line); return reinterpret_cast(di_type); } LLVMZigDIType *LLVMZigCreateDebugForwardDeclType(LLVMZigDIBuilder *dibuilder, unsigned tag, const char *name, LLVMZigDIScope *scope, LLVMZigDIFile *file, unsigned line) { DIType *di_type = reinterpret_cast(dibuilder)->createForwardDecl( tag, name, reinterpret_cast(scope), reinterpret_cast(file), line); return reinterpret_cast(di_type); } void LLVMZigReplaceTemporary(LLVMZigDIBuilder *dibuilder, LLVMZigDIType *type, LLVMZigDIType *replacement) { reinterpret_cast(dibuilder)->replaceTemporary( TempDIType(reinterpret_cast(type)), reinterpret_cast(replacement)); } void LLVMZigReplaceDebugArrays(LLVMZigDIBuilder *dibuilder, LLVMZigDIType *type, LLVMZigDIType **types_array, int types_array_len) { SmallVector fields; for (int i = 0; i < types_array_len; i += 1) { DIType *ditype = reinterpret_cast(types_array[i]); fields.push_back(ditype); } DICompositeType *composite_type = (DICompositeType*)reinterpret_cast(type); reinterpret_cast(dibuilder)->replaceArrays( composite_type, reinterpret_cast(dibuilder)->getOrCreateArray(fields)); } LLVMZigDIType *LLVMZigCreateSubroutineType(LLVMZigDIBuilder *dibuilder_wrapped, LLVMZigDIType **types_array, int types_array_len, unsigned flags) { SmallVector types; for (int i = 0; i < types_array_len; i += 1) { DIType *ditype = reinterpret_cast(types_array[i]); types.push_back(ditype); } DIBuilder *dibuilder = reinterpret_cast(dibuilder_wrapped); DISubroutineType *subroutine_type = dibuilder->createSubroutineType( dibuilder->getOrCreateTypeArray(types), flags); DIType *ditype = subroutine_type; return reinterpret_cast(ditype); } unsigned LLVMZigEncoding_DW_ATE_unsigned(void) { return dwarf::DW_ATE_unsigned; } unsigned LLVMZigEncoding_DW_ATE_signed(void) { return dwarf::DW_ATE_signed; } unsigned LLVMZigEncoding_DW_ATE_float(void) { return dwarf::DW_ATE_float; } unsigned LLVMZigEncoding_DW_ATE_boolean(void) { return dwarf::DW_ATE_boolean; } unsigned LLVMZigEncoding_DW_ATE_unsigned_char(void) { return dwarf::DW_ATE_unsigned_char; } unsigned LLVMZigEncoding_DW_ATE_signed_char(void) { return dwarf::DW_ATE_signed_char; } unsigned LLVMZigLang_DW_LANG_C99(void) { return dwarf::DW_LANG_C99; } unsigned LLVMZigTag_DW_variable(void) { return dwarf::DW_TAG_variable; } unsigned LLVMZigTag_DW_structure_type(void) { return dwarf::DW_TAG_structure_type; } LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) { DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved); return reinterpret_cast(di_builder); } void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, LLVMZigDIScope *scope) { unwrap(builder)->SetCurrentDebugLocation(DebugLoc::get( line, column, reinterpret_cast(scope))); } void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder) { unwrap(builder)->SetCurrentDebugLocation(DebugLoc()); } 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); } LLVMZigDILocalVariable *LLVMZigCreateAutoVariable(LLVMZigDIBuilder *dbuilder, LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no, LLVMZigDIType *type, bool always_preserve, unsigned flags) { DILocalVariable *result = reinterpret_cast(dbuilder)->createAutoVariable( reinterpret_cast(scope), name, reinterpret_cast(file), line_no, reinterpret_cast(type), always_preserve, flags); return reinterpret_cast(result); } LLVMZigDILocalVariable *LLVMZigCreateParameterVariable(LLVMZigDIBuilder *dbuilder, LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no, LLVMZigDIType *type, bool always_preserve, unsigned flags, unsigned arg_no) { DILocalVariable *result = reinterpret_cast(dbuilder)->createParameterVariable( reinterpret_cast(scope), name, arg_no, reinterpret_cast(file), line_no, reinterpret_cast(type), always_preserve, flags); 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); } LLVMZigDIScope *LLVMZigTypeToScope(LLVMZigDIType *type) { DIScope *scope = reinterpret_cast(type); 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, LLVMZigDIType *fn_di_type, bool is_local_to_unit, bool is_definition, unsigned scope_line, unsigned flags, bool is_optimized, LLVMZigDISubprogram *decl_subprogram) { DISubroutineType *di_sub_type = static_cast(reinterpret_cast(fn_di_type)); DISubprogram *result = reinterpret_cast(dibuilder)->createFunction( reinterpret_cast(scope), name, linkage_name, reinterpret_cast(file), lineno, di_sub_type, is_local_to_unit, is_definition, scope_line, flags, is_optimized, nullptr, reinterpret_cast(decl_subprogram)); return reinterpret_cast(result); } void LLVMZigDIBuilderFinalize(LLVMZigDIBuilder *dibuilder) { reinterpret_cast(dibuilder)->finalize(); } LLVMZigInsertionPoint *LLVMZigSaveInsertPoint(LLVMBuilderRef builder_wrapped) { IRBuilderBase::InsertPoint *ip = new IRBuilderBase::InsertPoint(); *ip = unwrap(builder_wrapped)->saveIP(); return reinterpret_cast(ip); } void LLVMZigRestoreInsertPoint(LLVMBuilderRef builder, LLVMZigInsertionPoint *ip_wrapped) { IRBuilderBase::InsertPoint *ip = reinterpret_cast(ip_wrapped); unwrap(builder)->restoreIP(*ip); } LLVMValueRef LLVMZigInsertDeclareAtEnd(LLVMZigDIBuilder *dibuilder, LLVMValueRef storage, LLVMZigDILocalVariable *var_info, LLVMZigDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref) { Instruction *result = reinterpret_cast(dibuilder)->insertDeclare( unwrap(storage), reinterpret_cast(var_info), reinterpret_cast(dibuilder)->createExpression(), reinterpret_cast(debug_loc), static_cast(unwrap(basic_block_ref))); return wrap(result); } LLVMValueRef LLVMZigInsertDeclare(LLVMZigDIBuilder *dibuilder, LLVMValueRef storage, LLVMZigDILocalVariable *var_info, LLVMZigDILocation *debug_loc, LLVMValueRef insert_before_instr) { Instruction *result = reinterpret_cast(dibuilder)->insertDeclare( unwrap(storage), reinterpret_cast(var_info), reinterpret_cast(dibuilder)->createExpression(), reinterpret_cast(debug_loc), static_cast(unwrap(insert_before_instr))); return wrap(result); } LLVMZigDILocation *LLVMZigGetDebugLoc(unsigned line, unsigned col, LLVMZigDIScope *scope) { DebugLoc debug_loc = DebugLoc::get(line, col, reinterpret_cast(scope), nullptr); return reinterpret_cast(debug_loc.get()); } void LLVMZigSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) { if (on_state) { FastMathFlags fmf; fmf.setUnsafeAlgebra(); unwrap(builder_wrapped)->setFastMathFlags(fmf); } else { unwrap(builder_wrapped)->clearFastMathFlags(); } } void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) { Function *func = unwrap(fn_ref); const AttributeSet attr_set = func->getAttributes(); AttrBuilder attr_builder; if (attr_value) { attr_builder.addAttribute(attr_name, attr_value); } else { attr_builder.addAttribute(attr_name); } const AttributeSet new_attr_set = attr_set.addAttributes(func->getContext(), AttributeSet::FunctionIndex, AttributeSet::get(func->getContext(), AttributeSet::FunctionIndex, attr_builder)); func->setAttributes(new_attr_set); } static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, ""); static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, ""); static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, ""); static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, ""); 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_MachO == Triple::MachO, ""); const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { return Triple::getArchTypeName((Triple::ArchType)arch); } const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor) { return Triple::getVendorTypeName((Triple::VendorType)vendor); } const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os) { return Triple::getOSTypeName((Triple::OSType)os); } const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) { return Triple::getEnvironmentTypeName((Triple::EnvironmentType)env_type); } void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type, ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type, ZigLLVM_ObjectFormatType *oformat) { char *native_triple = LLVMGetDefaultTargetTriple(); Triple triple(native_triple); *arch_type = (ZigLLVM_ArchType)triple.getArch(); *sub_arch_type = (ZigLLVM_SubArchType)triple.getSubArch(); *vendor_type = (ZigLLVM_VendorType)triple.getVendor(); *os_type = (ZigLLVM_OSType)triple.getOS(); *environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment(); *oformat = (ZigLLVM_ObjectFormatType)triple.getObjectFormat(); free(native_triple); } const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { switch (sub_arch) { case ZigLLVM_NoSubArch: return "(none)"; case ZigLLVM_ARMSubArch_v8_2a: return "v8_2a"; case ZigLLVM_ARMSubArch_v8_1a: return "v8_1a"; case ZigLLVM_ARMSubArch_v8: return "v8"; case ZigLLVM_ARMSubArch_v7: return "v7"; case ZigLLVM_ARMSubArch_v7em: return "v7em"; case ZigLLVM_ARMSubArch_v7m: return "v7m"; case ZigLLVM_ARMSubArch_v7s: return "v7s"; case ZigLLVM_ARMSubArch_v7k: return "v7k"; case ZigLLVM_ARMSubArch_v6: return "v6"; case ZigLLVM_ARMSubArch_v6m: return "v6m"; case ZigLLVM_ARMSubArch_v6k: return "v6k"; case ZigLLVM_ARMSubArch_v6t2: return "v6t2"; case ZigLLVM_ARMSubArch_v5: return "v5"; case ZigLLVM_ARMSubArch_v5te: return "v5te"; case ZigLLVM_ARMSubArch_v4t: return "v4t"; case ZigLLVM_KalimbaSubArch_v3: return "v3"; case ZigLLVM_KalimbaSubArch_v4: return "v4"; case ZigLLVM_KalimbaSubArch_v5: return "v5"; } abort(); } void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); } unsigned ZigLLVMGetPrefTypeAlignment(LLVMTargetDataRef TD, LLVMTypeRef Ty) { return unwrap(TD)->getPrefTypeAlignment(unwrap(Ty)); } static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { switch (Ordering) { case LLVMAtomicOrderingNotAtomic: return NotAtomic; case LLVMAtomicOrderingUnordered: return Unordered; case LLVMAtomicOrderingMonotonic: return Monotonic; case LLVMAtomicOrderingAcquire: return Acquire; case LLVMAtomicOrderingRelease: return Release; case LLVMAtomicOrderingAcquireRelease: return AcquireRelease; case LLVMAtomicOrderingSequentiallyConsistent: return SequentiallyConsistent; } abort(); } LLVMValueRef ZigLLVMBuildCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef new_val, LLVMAtomicOrdering success_ordering, LLVMAtomicOrdering failure_ordering) { return wrap(unwrap(builder)->CreateAtomicCmpXchg(unwrap(ptr), unwrap(cmp), unwrap(new_val), mapFromLLVMOrdering(success_ordering), mapFromLLVMOrdering(failure_ordering), CrossThread)); } LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { return wrap(unwrap(builder)->CreateShl(unwrap(LHS), unwrap(RHS), name, false, true)); } LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS, const char *name) { return wrap(unwrap(builder)->CreateShl(unwrap(LHS), unwrap(RHS), name, false, true)); } LLVMValueRef ZigLLVMBuildExactUDiv(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name) { return wrap(unwrap(B)->CreateExactUDiv(unwrap(LHS), unwrap(RHS), Name)); } //------------------------------------ #include "buffer.hpp" void ZigLLVMGetTargetTriple(Buf *out_buf, ZigLLVM_ArchType arch_type, ZigLLVM_SubArchType sub_arch_type, ZigLLVM_VendorType vendor_type, ZigLLVM_OSType os_type, ZigLLVM_EnvironmentType environ_type, ZigLLVM_ObjectFormatType oformat) { Triple triple; triple.setArch((Triple::ArchType)arch_type); // TODO how to set the sub arch? triple.setVendor((Triple::VendorType)vendor_type); triple.setOS((Triple::OSType)os_type); triple.setEnvironment((Triple::EnvironmentType)environ_type); // I guess it's a "triple" because we don't set the object format? //triple.setObjectFormat((Triple::ObjectFormatType)oformat); const std::string &str = triple.str(); buf_init_from_mem(out_buf, str.c_str(), str.size()); } enum FloatAbi { FloatAbiHard, FloatAbiSoft, FloatAbiSoftFp, }; static FloatAbi get_float_abi(const Triple &triple) { zig_panic("TODO implement get_float_abi for ARM"); } Buf *get_dynamic_linker(LLVMTargetMachineRef target_machine_ref) { TargetMachine *target_machine = reinterpret_cast(target_machine_ref); const Triple &triple = target_machine->getTargetTriple(); const Triple::ArchType arch = triple.getArch(); if (triple.getEnvironment() == Triple::Android) { if (triple.isArch64Bit()) { return buf_create_from_str("/system/bin/linker64"); } else { return buf_create_from_str("/system/bin/linker"); } } else if (arch == Triple::x86 || arch == Triple::sparc || arch == Triple::sparcel) { return buf_create_from_str("/lib/ld-linux.so.2"); } else if (arch == Triple::aarch64) { return buf_create_from_str("/lib/ld-linux-aarch64.so.1"); } else if (arch == Triple::aarch64_be) { return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1"); } else if (arch == Triple::arm || arch == Triple::thumb) { if (triple.getEnvironment() == Triple::GNUEABIHF || get_float_abi(triple) == FloatAbiHard) { return buf_create_from_str("/lib/ld-linux-armhf.so.3"); } else { return buf_create_from_str("/lib/ld-linux.so.3"); } } else if (arch == Triple::armeb || arch == Triple::thumbeb) { if (triple.getEnvironment() == Triple::GNUEABIHF || get_float_abi(triple) == FloatAbiHard) { return buf_create_from_str("/lib/ld-linux-armhf.so.3"); } else { return buf_create_from_str("/lib/ld-linux.so.3"); } } else if (arch == Triple::mips || arch == Triple::mipsel || arch == Triple::mips64 || arch == Triple::mips64el) { // when you want to solve this TODO, grep clang codebase for // getLinuxDynamicLinker zig_panic("TODO figure out MIPS dynamic linker name"); } else if (arch == Triple::ppc) { return buf_create_from_str("/lib/ld.so.1"); } else if (arch == Triple::ppc64) { return buf_create_from_str("/lib64/ld64.so.2"); } else if (arch == Triple::ppc64le) { return buf_create_from_str("/lib64/ld64.so.2"); } else if (arch == Triple::systemz) { return buf_create_from_str("/lib64/ld64.so.1"); } else if (arch == Triple::sparcv9) { return buf_create_from_str("/lib64/ld-linux.so.2"); } else if (arch == Triple::x86_64 && triple.getEnvironment() == Triple::GNUX32) { return buf_create_from_str("/libx32/ld-linux-x32.so.2"); } else { return buf_create_from_str("/lib64/ld-linux-x86-64.so.2"); } }