diff --git a/src/emitter.cpp b/src/emitter.cpp index be4fb2f..4de037a 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -7594,6 +7594,48 @@ fn void emit_debug_argument(Module* module, Argument* argument, LLVMBasicBlockRe LLVMDIBuilderInsertDeclareRecordAtEnd(module->llvm.di_builder, argument->variable.storage->llvm, parameter_variable, LLVMDIBuilderCreateExpression(module->llvm.di_builder, 0, 0), debug_location, basic_block); } +struct ObjectGenerate +{ + String path; + BBLLVMOptimizationLevel optimization_level; + bool run_optimization_passes; + bool has_debug_info; +}; + +fn BBLLVMCodeGenerationPipelineResult generate_object(LLVMModuleRef module, LLVMTargetMachineRef target_machine, ObjectGenerate options) +{ + llvm_module_set_target(module, target_machine); + + if (options.run_optimization_passes) + { + // BBLLVM + bool prefer_speed = options.optimization_level == BBLLVMOptimizationLevel::O2 || options.optimization_level == BBLLVMOptimizationLevel::O3; + BBLLVMOptimizationPipelineOptions optimization_options = { + .optimization_level = (u64)options.optimization_level, + .debug_info = options.has_debug_info, + .loop_unrolling = prefer_speed, + .loop_interleaving = prefer_speed, + .loop_vectorization = prefer_speed, + .slp_vectorization = prefer_speed, + .merge_functions = prefer_speed, + .call_graph_profile = false, + .unified_lto = false, + .assignment_tracking = options.has_debug_info, + .verify_module = true, + }; + llvm_module_run_optimization_pipeline(module, target_machine, optimization_options); + } + + BBLLVMCodeGenerationPipelineOptions code_generation_options = { + .output_file_path = options.path, + .code_generation_file_type = 0, + .optimize_when_possible = options.optimization_level > BBLLVMOptimizationLevel::O0, + .verify_module = true, + }; + auto result = llvm_module_run_code_generation_pipeline(module, target_machine, &code_generation_options); + return result; +} + void emit(Module* module) { assert(!module->current_function); @@ -8234,4 +8276,72 @@ void emit(Module* module) { dump_module(module); } + + BBLLVMCodeGenerationOptimizationLevel code_generation_optimization_level; + switch (module->build_mode) + { + case BuildMode::debug_none: + case BuildMode::debug: + code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::none; + break; + case BuildMode::soft_optimize: + code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::less; + break; + case BuildMode::optimize_for_speed: + case BuildMode::optimize_for_size: + code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::normal; + break; + case BuildMode::aggressively_optimize_for_speed: + case BuildMode::aggressively_optimize_for_size: + code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::aggressive; + break; + case BuildMode::count: + unreachable(); + } + BBLLVMTargetMachineCreate target_machine_options = { + .target_triple = llvm_default_target_triple(), + .cpu_model = llvm_host_cpu_name(), + .cpu_features = llvm_host_cpu_features(), + .relocation_model = BBLLVMRelocationModel::default_relocation, + .code_model = BBLLVMCodeModel::none, + .optimization_level = code_generation_optimization_level, + }; + String error_message = {}; + auto target_machine = llvm_create_target_machine(&target_machine_options, &error_message); + assert(target_machine); + BBLLVMOptimizationLevel optimization_level; + switch (module->build_mode) + { + case BuildMode::debug_none: + case BuildMode::debug: + optimization_level = BBLLVMOptimizationLevel::O0; + break; + case BuildMode::soft_optimize: + optimization_level = BBLLVMOptimizationLevel::O1; + break; + case BuildMode::optimize_for_speed: + optimization_level = BBLLVMOptimizationLevel::O2; + break; + case BuildMode::optimize_for_size: + optimization_level = BBLLVMOptimizationLevel::Os; + break; + case BuildMode::aggressively_optimize_for_speed: + optimization_level = BBLLVMOptimizationLevel::O3; + break; + case BuildMode::aggressively_optimize_for_size: + optimization_level = BBLLVMOptimizationLevel::Oz; + break; + case BuildMode::count: + unreachable(); + } + auto object_generation_result = generate_object(module->llvm.module, target_machine, { + .path = module->executable, + .optimization_level = optimization_level, + .run_optimization_passes = module->build_mode != BuildMode::debug_none, + .has_debug_info = module->has_debug_info, + }); + if (object_generation_result != BBLLVMCodeGenerationPipelineResult::success) + { + report_error(); + } } diff --git a/src/llvm.cpp b/src/llvm.cpp index 57ba474..b3ee123 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -922,268 +922,15 @@ EXPORT String llvm_host_cpu_features() return { result, length }; } -enum class BBLLVMEmitDwarfUnwindType : u8 -{ - always = 0, - no_compact_unwind = 1, - normal = 2, -}; - -enum class BBLLVMDwarfDirectory : u8 -{ - disable = 0, - enable = 1, - normal = 2, -}; - -enum class BBLLVMDebugCompressionType : u8 -{ - none = 0, - zlib = 1, - zstd = 2, -}; - -#define BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT (7) - -struct BBLLVMMCTargetOptions -{ - String abi_name; - String assembly_language; - String split_dwarf_file; - String as_secure_log_file; - const char* argv0; - String* argv_pointer; - u64 argv_count; - String* integrated_assembler_search_path_pointer; - u64 integrated_assembler_search_path_count; - u32 relax_all:1; - u32 no_exec_stack:1; - u32 fatal_warnings:1; - u32 no_warn:1; - u32 no_deprecated_warn:1; - u32 no_type_check:1; - u32 save_temp_labels:1; - u32 incremental_linker_compatible:1; - u32 fdpic:1; - u32 show_mc_encoding:1; - u32 show_mc_inst:1; - u32 asm_verbose:1; - u32 preserve_asm_comments:1; - u32 dwarf64:1; - u32 crel:1; - u32 x86_relax_relocations:1; - u32 x86_sse2_avx:1; - u32 emit_dwarf_unwind:2; - u32 use_dwarf_directory:2; - u32 debug_compression_type:2; - u32 emit_compact_unwind_non_canonical:1; - u32 ppc_use_full_register_names:1; - u32 reserved:BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT; -}; - -static_assert(sizeof(BBLLVMMCTargetOptions) == 112); -static_assert(BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT == 7); - -enum class BBLLVMCodeModel : u8 -{ - none = 0, - tiny = 1, - small = 2, - kernel = 3, - medium = 4, - large = 5, -}; - -enum class BBLLVMRelocationModel : u8 -{ - default_relocation = 0, - static_relocation = 1, - pic = 2, - dynamic_no_pic = 3, - ropi = 4, - rwpi = 5, - ropi_rwpi = 6, -}; - -enum class BBLLVMCodeGenerationOptimizationLevel : u8 -{ - none = 0, // -O0 - less = 1, // -O1 - normal = 2, // -O2, -Os - aggressive = 3 // -O3 -}; - -enum class BBLLVMGlobalISelAbortMode : u8 -{ - disable = 0, - enable = 1, - disable_with_diag = 2, -}; - -enum class BBLLVMSwiftAsyncFramePointerMode : u8 -{ - deployment_based = 0, - always = 1, - never = 2, -}; - -enum class BBLLVMBasicBlockSection : u8 -{ - all = 0, - list = 1, - preset = 2, - none = 3, -}; - -enum class BBLLVMFloatAbi : u8 -{ - normal = 0, - soft = 1, - hard = 2, -}; - -enum class BBLLVMFPOpFusion : u8 -{ - fast = 0, - standard = 1, - strict = 2, -}; - -enum class BBLLVMThreadModel : u8 -{ - posix = 0, - single = 1, -}; - -enum class BBLLVMEAbi : u8 -{ - unknown = 0, - normal = 1, - eabi4 = 2, - eabi5 = 3, - gnu = 4, -}; - -enum class BBLLVMDebuggerKind : u8 -{ - normal = 0, - gdb = 1, - lldb = 2, - sce = 3, - dbx = 4, -}; - -enum class BBLLVMExceptionHandling : u8 -{ - none = 0, - dwarf_cfi = 1, - setjmp_longjmp = 2, - arm = 3, - win_eh = 4, - wasm = 5, - aix = 6, - zos = 7, -}; - -#define BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT (21) - -struct BBLLVMTargetOptions -{ - u64 unsafe_fp_math:1; - u64 no_infs_fp_math:1; - u64 no_nans_fp_math:1; - u64 no_trapping_fp_math:1; - u64 no_signed_zeroes_fp_math:1; - u64 approx_func_fp_math:1; - u64 enable_aix_extended_altivec_abi:1; - u64 honor_sign_dependent_rounding_fp_math:1; - u64 no_zeroes_in_bss:1; - u64 guaranteed_tail_call_optimization:1; - u64 stack_symbol_ordering:1; - u64 enable_fast_isel:1; - u64 enable_global_isel:1; - u64 global_isel_abort_mode:2; - u64 swift_async_frame_pointer:2; - u64 use_init_array:1; - u64 disable_integrated_assembler:1; - u64 function_sections:1; - u64 data_sections:1; - u64 ignore_xcoff_visibility:1; - u64 xcoff_traceback_table:1; - u64 unique_section_names:1; - u64 unique_basic_block_section_names:1; - u64 separate_named_sections:1; - u64 trap_unreachable:1; - u64 no_trap_after_noreturn:1; - u64 tls_size:8; - u64 emulated_tls:1; - u64 enable_tls_descriptors:1; - u64 enable_ipra:1; - u64 emit_stack_size_section:1; - u64 enable_machine_outliner:1; - u64 enable_machine_function_splitter:1; - u64 supports_default_outlining:1; - u64 emit_address_significance_table:1; - u64 bb_address_map:1; - u64 bb_sections:3; - u64 emit_call_site_information:1; - u64 supports_debug_entry_values:1; - u64 enable_debug_entry_values:1; - u64 value_tracking_variable_locations:1; - u64 force_dwarf_frame_section:1; - u64 xray_function_index:1; - u64 debug_strict_dwarf:1; - u64 hotpatch:1; - u64 ppc_gen_scalar_mass_entries:1; - u64 jmc_instrument:1; - u64 enable_cfi_fixup:1; - u64 mis_expect:1; - u64 xcoff_read_only_pointers:1; - u64 float_abi:2; - u64 thread_model:1; - u32 fp_op_fusion_mode:2; - u32 eabi_version:3; - u32 debugger_kind:3; - u32 exception_handling:3; - u32 reserved:BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT; - unsigned loop_alignment; - int binutils_version[2]; - - BBLLVMMCTargetOptions mc; -}; - -static_assert(sizeof(BBLLVMTargetOptions) == 136); -static_assert(BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT == 21); - -#define BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT (4) - -struct BBLLVMTargetMachineCreate -{ - BBLLVMTargetOptions target_options; - String target_triple; - String cpu_model; - String cpu_features; - BBLLVMRelocationModel relocation_model; - BBLLVMCodeModel code_model; - BBLLVMCodeGenerationOptimizationLevel optimization_level; - bool jit; - u8 reserved[BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT]; -}; - -static_assert(sizeof(BBLLVMTargetMachineCreate) == 192); -static_assert(BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT == 4); - -EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate& create, String* error_message) +EXPORT LLVMTargetMachineRef llvm_create_target_machine(const BBLLVMTargetMachineCreate* create, String* error_message) { std::string error_message_string; - const llvm::Target* target = llvm::TargetRegistry::lookupTarget(string_ref(create.target_triple), error_message_string); - - llvm::TargetMachine* target_machine; + const llvm::Target* target = llvm::TargetRegistry::lookupTarget(string_ref(create->target_triple), error_message_string); if (target) { std::optional code_model; - switch (create.code_model) + switch (create->code_model) { case BBLLVMCodeModel::none: code_model = std::nullopt; break; case BBLLVMCodeModel::tiny: code_model = llvm::CodeModel::Tiny; break; @@ -1195,7 +942,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine std::optional relocation_model; - switch (create.relocation_model) + switch (create->relocation_model) { case BBLLVMRelocationModel::default_relocation: relocation_model = std::nullopt; break; case BBLLVMRelocationModel::static_relocation: relocation_model = llvm::Reloc::Static; break; @@ -1207,7 +954,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine } llvm::CodeGenOptLevel optimization_level; - switch (create.optimization_level) + switch (create->optimization_level) { case BBLLVMCodeGenerationOptimizationLevel::none: optimization_level = llvm::CodeGenOptLevel::None; break; case BBLLVMCodeGenerationOptimizationLevel::less: optimization_level = llvm::CodeGenOptLevel::Less; break; @@ -1218,28 +965,28 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine // INFO: This calls the default constructor, so all LLVM defaults are set and we only override what we control llvm::TargetOptions target_options; - target_options.UnsafeFPMath = create.target_options.unsafe_fp_math; - target_options.NoInfsFPMath = create.target_options.no_infs_fp_math; - target_options.NoNaNsFPMath = create.target_options.no_nans_fp_math; - target_options.NoTrappingFPMath = create.target_options.no_trapping_fp_math; - target_options.NoSignedZerosFPMath = create.target_options.no_signed_zeroes_fp_math; - target_options.ApproxFuncFPMath = create.target_options.approx_func_fp_math; - target_options.EnableAIXExtendedAltivecABI = create.target_options.enable_aix_extended_altivec_abi; - target_options.HonorSignDependentRoundingFPMathOption = create.target_options.honor_sign_dependent_rounding_fp_math; - target_options.NoZerosInBSS = create.target_options.no_zeroes_in_bss; - target_options.GuaranteedTailCallOpt = create.target_options.guaranteed_tail_call_optimization; - target_options.StackSymbolOrdering = create.target_options.stack_symbol_ordering; - target_options.EnableFastISel = create.target_options.enable_fast_isel; - target_options.EnableGlobalISel = create.target_options.enable_global_isel; + target_options.UnsafeFPMath = create->target_options.unsafe_fp_math; + target_options.NoInfsFPMath = create->target_options.no_infs_fp_math; + target_options.NoNaNsFPMath = create->target_options.no_nans_fp_math; + target_options.NoTrappingFPMath = create->target_options.no_trapping_fp_math; + target_options.NoSignedZerosFPMath = create->target_options.no_signed_zeroes_fp_math; + target_options.ApproxFuncFPMath = create->target_options.approx_func_fp_math; + target_options.EnableAIXExtendedAltivecABI = create->target_options.enable_aix_extended_altivec_abi; + target_options.HonorSignDependentRoundingFPMathOption = create->target_options.honor_sign_dependent_rounding_fp_math; + target_options.NoZerosInBSS = create->target_options.no_zeroes_in_bss; + target_options.GuaranteedTailCallOpt = create->target_options.guaranteed_tail_call_optimization; + target_options.StackSymbolOrdering = create->target_options.stack_symbol_ordering; + target_options.EnableFastISel = create->target_options.enable_fast_isel; + target_options.EnableGlobalISel = create->target_options.enable_global_isel; - auto global_isel_abort_mode = (BBLLVMGlobalISelAbortMode)create.target_options.global_isel_abort_mode; + auto global_isel_abort_mode = (BBLLVMGlobalISelAbortMode)create->target_options.global_isel_abort_mode; switch (global_isel_abort_mode) { case BBLLVMGlobalISelAbortMode::disable: target_options.GlobalISelAbort = llvm::GlobalISelAbortMode::Disable; break; case BBLLVMGlobalISelAbortMode::enable: target_options.GlobalISelAbort = llvm::GlobalISelAbortMode::Enable; break; case BBLLVMGlobalISelAbortMode::disable_with_diag: target_options.GlobalISelAbort = llvm::GlobalISelAbortMode::DisableWithDiag; break; } - auto swift_async_frame_pointer = (BBLLVMSwiftAsyncFramePointerMode)create.target_options.swift_async_frame_pointer; + auto swift_async_frame_pointer = (BBLLVMSwiftAsyncFramePointerMode)create->target_options.swift_async_frame_pointer; switch (swift_async_frame_pointer) { case BBLLVMSwiftAsyncFramePointerMode::deployment_based: target_options.SwiftAsyncFramePointer = llvm::SwiftAsyncFramePointerMode::DeploymentBased; break; @@ -1247,33 +994,33 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMSwiftAsyncFramePointerMode::never: target_options.SwiftAsyncFramePointer = llvm::SwiftAsyncFramePointerMode::Never; break; } - target_options.UseInitArray = create.target_options.use_init_array; - target_options.DisableIntegratedAS = create.target_options.disable_integrated_assembler; - target_options.FunctionSections = create.target_options.function_sections; - target_options.DataSections = create.target_options.data_sections; - target_options.IgnoreXCOFFVisibility = create.target_options.ignore_xcoff_visibility; - target_options.XCOFFTracebackTable = create.target_options.xcoff_traceback_table; - target_options.UniqueSectionNames = create.target_options.unique_section_names; - target_options.UniqueBasicBlockSectionNames = create.target_options.unique_basic_block_section_names; + target_options.UseInitArray = create->target_options.use_init_array; + target_options.DisableIntegratedAS = create->target_options.disable_integrated_assembler; + target_options.FunctionSections = create->target_options.function_sections; + target_options.DataSections = create->target_options.data_sections; + target_options.IgnoreXCOFFVisibility = create->target_options.ignore_xcoff_visibility; + target_options.XCOFFTracebackTable = create->target_options.xcoff_traceback_table; + target_options.UniqueSectionNames = create->target_options.unique_section_names; + target_options.UniqueBasicBlockSectionNames = create->target_options.unique_basic_block_section_names; #if LLVM_VERSION_MAJOR >= 19 - target_options.SeparateNamedSections = create.target_options.separate_named_sections; + target_options.SeparateNamedSections = create->target_options.separate_named_sections; #endif - target_options.TrapUnreachable = create.target_options.trap_unreachable; - target_options.NoTrapAfterNoreturn = create.target_options.no_trap_after_noreturn; - target_options.TLSSize = create.target_options.tls_size; - target_options.EmulatedTLS = create.target_options.emulated_tls; - target_options.EnableTLSDESC = create.target_options.enable_tls_descriptors; - target_options.EnableIPRA = create.target_options.enable_ipra; - target_options.EmitStackSizeSection = create.target_options.emit_stack_size_section; - target_options.EnableMachineOutliner = create.target_options.enable_machine_outliner; - target_options.EnableMachineFunctionSplitter = create.target_options.enable_machine_function_splitter; - target_options.SupportsDefaultOutlining = create.target_options.supports_default_outlining; - target_options.EmitAddrsig = create.target_options.emit_address_significance_table; + target_options.TrapUnreachable = create->target_options.trap_unreachable; + target_options.NoTrapAfterNoreturn = create->target_options.no_trap_after_noreturn; + target_options.TLSSize = create->target_options.tls_size; + target_options.EmulatedTLS = create->target_options.emulated_tls; + target_options.EnableTLSDESC = create->target_options.enable_tls_descriptors; + target_options.EnableIPRA = create->target_options.enable_ipra; + target_options.EmitStackSizeSection = create->target_options.emit_stack_size_section; + target_options.EnableMachineOutliner = create->target_options.enable_machine_outliner; + target_options.EnableMachineFunctionSplitter = create->target_options.enable_machine_function_splitter; + target_options.SupportsDefaultOutlining = create->target_options.supports_default_outlining; + target_options.EmitAddrsig = create->target_options.emit_address_significance_table; #if LLVM_VERSION_MAJOR >= 19 - target_options.BBAddrMap = create.target_options.bb_address_map; + target_options.BBAddrMap = create->target_options.bb_address_map; #endif - auto bb_sections = (BBLLVMBasicBlockSection) create.target_options.bb_sections; + auto bb_sections = (BBLLVMBasicBlockSection) create->target_options.bb_sections; switch (bb_sections) { case BBLLVMBasicBlockSection::all: target_options.BBSections = llvm::BasicBlockSection::All; break; @@ -1282,21 +1029,21 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMBasicBlockSection::none: target_options.BBSections = llvm::BasicBlockSection::None; break; } - target_options.EmitCallSiteInfo = create.target_options.emit_call_site_information; - target_options.SupportsDebugEntryValues = create.target_options.supports_debug_entry_values; - target_options.EnableDebugEntryValues = create.target_options.enable_debug_entry_values; - target_options.ValueTrackingVariableLocations = create.target_options.value_tracking_variable_locations; - target_options.ForceDwarfFrameSection = create.target_options.force_dwarf_frame_section; - target_options.XRayFunctionIndex = create.target_options.xray_function_index; - target_options.DebugStrictDwarf = create.target_options.debug_strict_dwarf; - target_options.Hotpatch = create.target_options.hotpatch; - target_options.PPCGenScalarMASSEntries = create.target_options.ppc_gen_scalar_mass_entries; - target_options.JMCInstrument = create.target_options.jmc_instrument; - target_options.EnableCFIFixup = create.target_options.enable_cfi_fixup; - target_options.MisExpect = create.target_options.mis_expect; - target_options.XCOFFReadOnlyPointers = create.target_options.xcoff_read_only_pointers; + target_options.EmitCallSiteInfo = create->target_options.emit_call_site_information; + target_options.SupportsDebugEntryValues = create->target_options.supports_debug_entry_values; + target_options.EnableDebugEntryValues = create->target_options.enable_debug_entry_values; + target_options.ValueTrackingVariableLocations = create->target_options.value_tracking_variable_locations; + target_options.ForceDwarfFrameSection = create->target_options.force_dwarf_frame_section; + target_options.XRayFunctionIndex = create->target_options.xray_function_index; + target_options.DebugStrictDwarf = create->target_options.debug_strict_dwarf; + target_options.Hotpatch = create->target_options.hotpatch; + target_options.PPCGenScalarMASSEntries = create->target_options.ppc_gen_scalar_mass_entries; + target_options.JMCInstrument = create->target_options.jmc_instrument; + target_options.EnableCFIFixup = create->target_options.enable_cfi_fixup; + target_options.MisExpect = create->target_options.mis_expect; + target_options.XCOFFReadOnlyPointers = create->target_options.xcoff_read_only_pointers; - auto float_abi = (BBLLVMFloatAbi) create.target_options.float_abi; + auto float_abi = (BBLLVMFloatAbi) create->target_options.float_abi; switch (float_abi) { case BBLLVMFloatAbi::normal: target_options.FloatABIType = llvm::FloatABI::Default; break; @@ -1304,14 +1051,14 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMFloatAbi::hard: target_options.FloatABIType = llvm::FloatABI::Hard; break; } - auto thread_model = (BBLLVMThreadModel) create.target_options.thread_model; + auto thread_model = (BBLLVMThreadModel) create->target_options.thread_model; switch (thread_model) { case BBLLVMThreadModel::posix: target_options.ThreadModel = llvm::ThreadModel::POSIX; break; case BBLLVMThreadModel::single: target_options.ThreadModel = llvm::ThreadModel::Single; break; } - auto fp_op_fusion_mode = (BBLLVMFPOpFusion) create.target_options.fp_op_fusion_mode; + auto fp_op_fusion_mode = (BBLLVMFPOpFusion) create->target_options.fp_op_fusion_mode; switch (fp_op_fusion_mode) { case BBLLVMFPOpFusion::fast: target_options.AllowFPOpFusion = llvm::FPOpFusion::Fast; break; @@ -1319,7 +1066,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMFPOpFusion::strict: target_options.AllowFPOpFusion = llvm::FPOpFusion::Strict; break; } - auto eabi_version = (BBLLVMEAbi) create.target_options.eabi_version; + auto eabi_version = (BBLLVMEAbi) create->target_options.eabi_version; switch (eabi_version) { case BBLLVMEAbi::unknown: target_options.EABIVersion = llvm::EABI::Unknown; break; @@ -1329,7 +1076,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMEAbi::gnu: target_options.EABIVersion = llvm::EABI::GNU; break; } - auto debugger_kind = (BBLLVMDebuggerKind) create.target_options.debugger_kind; + auto debugger_kind = (BBLLVMDebuggerKind) create->target_options.debugger_kind; switch (debugger_kind) { case BBLLVMDebuggerKind::normal: target_options.DebuggerTuning = llvm::DebuggerKind::Default; break; @@ -1339,7 +1086,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMDebuggerKind::dbx: target_options.DebuggerTuning = llvm::DebuggerKind::DBX; break; } - auto exception_handling = (BBLLVMExceptionHandling) create.target_options.exception_handling; + auto exception_handling = (BBLLVMExceptionHandling) create->target_options.exception_handling; switch (exception_handling) { case BBLLVMExceptionHandling::none: target_options.ExceptionModel = llvm::ExceptionHandling::None; break; @@ -1352,66 +1099,66 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMExceptionHandling::zos: target_options.ExceptionModel = llvm::ExceptionHandling::ZOS; break; } - target_options.LoopAlignment = create.target_options.loop_alignment; - target_options.BinutilsVersion = { create.target_options.binutils_version[0], create.target_options.binutils_version[1] }; + target_options.LoopAlignment = create->target_options.loop_alignment; + target_options.BinutilsVersion = { create->target_options.binutils_version[0], create->target_options.binutils_version[1] }; - if (create.target_options.mc.abi_name.length) + if (create->target_options.mc.abi_name.length) { - target_options.MCOptions.ABIName = { (char*)create.target_options.mc.abi_name.pointer, create.target_options.mc.abi_name.length }; + target_options.MCOptions.ABIName = { (char*)create->target_options.mc.abi_name.pointer, create->target_options.mc.abi_name.length }; } - if (create.target_options.mc.assembly_language.length) + if (create->target_options.mc.assembly_language.length) { - target_options.MCOptions.AssemblyLanguage = { (char*)create.target_options.mc.assembly_language.pointer, create.target_options.mc.assembly_language.length }; + target_options.MCOptions.AssemblyLanguage = { (char*)create->target_options.mc.assembly_language.pointer, create->target_options.mc.assembly_language.length }; } - if (create.target_options.mc.split_dwarf_file.length) + if (create->target_options.mc.split_dwarf_file.length) { - target_options.MCOptions.SplitDwarfFile = { (char*)create.target_options.mc.split_dwarf_file.pointer, create.target_options.mc.split_dwarf_file.length }; + target_options.MCOptions.SplitDwarfFile = { (char*)create->target_options.mc.split_dwarf_file.pointer, create->target_options.mc.split_dwarf_file.length }; } - if (create.target_options.mc.as_secure_log_file.length) + if (create->target_options.mc.as_secure_log_file.length) { - target_options.MCOptions.AsSecureLogFile = { (char*)create.target_options.mc.as_secure_log_file.pointer, create.target_options.mc.as_secure_log_file.length }; + target_options.MCOptions.AsSecureLogFile = { (char*)create->target_options.mc.as_secure_log_file.pointer, create->target_options.mc.as_secure_log_file.length }; } - if (create.target_options.mc.argv_count) + if (create->target_options.mc.argv_count) { - target_options.MCOptions.Argv0 = create.target_options.mc.argv0; + target_options.MCOptions.Argv0 = create->target_options.mc.argv0; // TODO: __builtin_trap(); } - if (create.target_options.mc.integrated_assembler_search_path_count) + if (create->target_options.mc.integrated_assembler_search_path_count) { // TODO: __builtin_trap(); } - target_options.MCOptions.MCRelaxAll = create.target_options.mc.relax_all; - target_options.MCOptions.MCNoExecStack = create.target_options.mc.no_exec_stack; - target_options.MCOptions.MCFatalWarnings = create.target_options.mc.fatal_warnings; - target_options.MCOptions.MCNoWarn = create.target_options.mc.no_warn; - target_options.MCOptions.MCNoDeprecatedWarn = create.target_options.mc.no_deprecated_warn; - target_options.MCOptions.MCNoTypeCheck = create.target_options.mc.no_type_check; - target_options.MCOptions.MCSaveTempLabels = create.target_options.mc.save_temp_labels; - target_options.MCOptions.MCIncrementalLinkerCompatible = create.target_options.mc.incremental_linker_compatible; + target_options.MCOptions.MCRelaxAll = create->target_options.mc.relax_all; + target_options.MCOptions.MCNoExecStack = create->target_options.mc.no_exec_stack; + target_options.MCOptions.MCFatalWarnings = create->target_options.mc.fatal_warnings; + target_options.MCOptions.MCNoWarn = create->target_options.mc.no_warn; + target_options.MCOptions.MCNoDeprecatedWarn = create->target_options.mc.no_deprecated_warn; + target_options.MCOptions.MCNoTypeCheck = create->target_options.mc.no_type_check; + target_options.MCOptions.MCSaveTempLabels = create->target_options.mc.save_temp_labels; + target_options.MCOptions.MCIncrementalLinkerCompatible = create->target_options.mc.incremental_linker_compatible; #if LLVM_VERSION_MAJOR >= 19 - target_options.MCOptions.FDPIC = create.target_options.mc.fdpic; + target_options.MCOptions.FDPIC = create->target_options.mc.fdpic; #endif - target_options.MCOptions.ShowMCEncoding = create.target_options.mc.show_mc_encoding; - target_options.MCOptions.ShowMCInst = create.target_options.mc.show_mc_inst; - target_options.MCOptions.AsmVerbose = create.target_options.mc.asm_verbose; - target_options.MCOptions.PreserveAsmComments = create.target_options.mc.preserve_asm_comments; - target_options.MCOptions.Dwarf64 = create.target_options.mc.dwarf64; + target_options.MCOptions.ShowMCEncoding = create->target_options.mc.show_mc_encoding; + target_options.MCOptions.ShowMCInst = create->target_options.mc.show_mc_inst; + target_options.MCOptions.AsmVerbose = create->target_options.mc.asm_verbose; + target_options.MCOptions.PreserveAsmComments = create->target_options.mc.preserve_asm_comments; + target_options.MCOptions.Dwarf64 = create->target_options.mc.dwarf64; #if LLVM_VERSION_MAJOR >= 19 - target_options.MCOptions.Crel = create.target_options.mc.crel; - target_options.MCOptions.X86RelaxRelocations = create.target_options.mc.x86_relax_relocations; - target_options.MCOptions.X86Sse2Avx = create.target_options.mc.x86_sse2_avx; + target_options.MCOptions.Crel = create->target_options.mc.crel; + target_options.MCOptions.X86RelaxRelocations = create->target_options.mc.x86_relax_relocations; + target_options.MCOptions.X86Sse2Avx = create->target_options.mc.x86_sse2_avx; #endif - auto emit_dwarf_unwind = (BBLLVMEmitDwarfUnwindType) create.target_options.mc.emit_dwarf_unwind; + auto emit_dwarf_unwind = (BBLLVMEmitDwarfUnwindType) create->target_options.mc.emit_dwarf_unwind; switch (emit_dwarf_unwind) { case BBLLVMEmitDwarfUnwindType::always: target_options.MCOptions.EmitDwarfUnwind = llvm::EmitDwarfUnwindType::Always; break; @@ -1419,7 +1166,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine case BBLLVMEmitDwarfUnwindType::normal: target_options.MCOptions.EmitDwarfUnwind = llvm::EmitDwarfUnwindType::Default; break; } - auto use_dwarf_directory = (BBLLVMDwarfDirectory) create.target_options.mc.use_dwarf_directory; + auto use_dwarf_directory = (BBLLVMDwarfDirectory) create->target_options.mc.use_dwarf_directory; switch (use_dwarf_directory) { case BBLLVMDwarfDirectory::disable: target_options.MCOptions.MCUseDwarfDirectory = llvm::MCTargetOptions::DwarfDirectory::DisableDwarfDirectory; break; @@ -1428,7 +1175,7 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine } #if LLVM_VERSION_MAJOR >= 19 - auto debug_compression_type = (BBLLVMDebugCompressionType) create.target_options.mc.debug_compression_type; + auto debug_compression_type = (BBLLVMDebugCompressionType) create->target_options.mc.debug_compression_type; switch (debug_compression_type) { case BBLLVMDebugCompressionType::none: target_options.MCOptions.CompressDebugSections = llvm::DebugCompressionType::None; break; @@ -1437,10 +1184,10 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine } #endif - target_options.MCOptions.EmitCompactUnwindNonCanonical = create.target_options.mc.emit_compact_unwind_non_canonical; - target_options.MCOptions.PPCUseFullRegisterNames = create.target_options.mc.ppc_use_full_register_names; + target_options.MCOptions.EmitCompactUnwindNonCanonical = create->target_options.mc.emit_compact_unwind_non_canonical; + target_options.MCOptions.PPCUseFullRegisterNames = create->target_options.mc.ppc_use_full_register_names; - target_machine = target->createTargetMachine(string_ref(create.target_triple), string_ref(create.cpu_model), string_ref(create.cpu_features), target_options, relocation_model, code_model, optimization_level, create.jit); + return reinterpret_cast(const_cast(target->createTargetMachine(string_ref(create->target_triple), string_ref(create->cpu_model), string_ref(create->cpu_features), target_options, relocation_model, code_model, optimization_level, create->jit))); } else { @@ -1449,52 +1196,23 @@ EXPORT llvm::TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachine memcpy(result, error_message_string.c_str(), length); *error_message = { result, length }; - - target_machine = 0; + return 0; } - - return target_machine; } -EXPORT void llvm_module_set_target(llvm::Module& module, llvm::TargetMachine& target_machine) +EXPORT void llvm_module_set_target(LLVMModuleRef m, LLVMTargetMachineRef tm) { - module.setDataLayout(target_machine.createDataLayout()); - auto& triple_string = target_machine.getTargetTriple().getTriple(); - module.setTargetTriple(llvm::StringRef(triple_string)); + auto module = llvm::unwrap(m); + auto target_machine = (llvm::TargetMachine*)tm; + module->setDataLayout(target_machine->createDataLayout()); + auto& triple_string = target_machine->getTargetTriple().getTriple(); + module->setTargetTriple(llvm::StringRef(triple_string)); } -enum class BBLLVMOptimizationLevel : u8 -{ - O0 = 0, - O1 = 1, - O2 = 2, - O3 = 3, - Os = 4, - Oz = 5, -}; - -#define BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (51) -struct BBLLVMOptimizationPipelineOptions -{ - u64 optimization_level:3; - u64 debug_info:1; - u64 loop_unrolling:1; - u64 loop_interleaving:1; - u64 loop_vectorization:1; - u64 slp_vectorization:1; - u64 merge_functions:1; - u64 call_graph_profile:1; - u64 unified_lto:1; - u64 assignment_tracking:1; - u64 verify_module:1; - u64 reserved:BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT; -}; - -static_assert(sizeof(BBLLVMOptimizationPipelineOptions) == sizeof(u64)); -static_assert(BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 51); - -EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::TargetMachine& target_machine, BBLLVMOptimizationPipelineOptions options) +EXPORT void llvm_module_run_optimization_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, BBLLVMOptimizationPipelineOptions options) { + auto module = llvm::unwrap(m); + auto target_machine = (llvm::TargetMachine*)tm; // TODO: PGO // TODO: CS profile @@ -1514,7 +1232,7 @@ EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::Ta llvm::CGSCCAnalysisManager cgscc_analysis_manager; llvm::ModuleAnalysisManager module_analysis_manager; - llvm::PassBuilder pass_builder(&target_machine, pipeline_tuning_options); + llvm::PassBuilder pass_builder(target_machine, pipeline_tuning_options); if (options.assignment_tracking && options.debug_info != 0) { @@ -1524,7 +1242,7 @@ EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::Ta }); } - llvm::Triple target_triple = target_machine.getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718 + llvm::Triple target_triple = target_machine->getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718 // TODO: add library (?) std::unique_ptr TLII(llvm::driver::createTLII(target_triple, llvm::driver::VectorLibrary::NoLibrary)); function_analysis_manager.registerPass([&] { return llvm::TargetLibraryAnalysis(*TLII); }); @@ -1570,60 +1288,34 @@ EXPORT void llvm_module_run_optimization_pipeline(llvm::Module& module, llvm::Ta // TODO: if emit bitcode/IR - module_pass_manager.run(module, module_analysis_manager); + module_pass_manager.run(*module, module_analysis_manager); } -enum class BBLLVMCodeGenerationFileType : u8 +EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, const BBLLVMCodeGenerationPipelineOptions* options) { - assembly_file = 0, - object_file = 1, - null = 2, -}; + auto module = llvm::unwrap(m); + auto target_machine = (llvm::TargetMachine*)tm; -#define BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (60) - -struct BBLLVMCodeGenerationPipelineOptions -{ - String output_dwarf_file_path; - String output_file_path; - u64 code_generation_file_type:2; - u64 optimize_when_possible:1; - u64 verify_module:1; - u64 reserved: BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT; -}; - -static_assert(sizeof(BBLLVMCodeGenerationPipelineOptions) == 5 * sizeof(u64)); -static_assert(BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 60); - -enum class BBLLVMCodeGenerationPipelineResult : u8 -{ - success = 0, - failed_to_create_file = 1, - failed_to_add_emit_passes = 2, -}; - -EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeline(llvm::Module& module, llvm::TargetMachine& target_machine, BBLLVMCodeGenerationPipelineOptions options) -{ // We still use the legacy PM to run the codegen pipeline since the new PM // does not work with the codegen pipeline. // FIXME: make the new PM work with the codegen pipeline. llvm::legacy::PassManager CodeGenPasses; #if LLVM_VERSION_MAJOR >= 19 - if (options.optimize_when_possible) + if (options->optimize_when_possible) { - CodeGenPasses.add(createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis())); + CodeGenPasses.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); } #endif llvm::raw_pwrite_stream* dwarf_object_file = 0; - if (options.output_dwarf_file_path.length) + if (options->output_dwarf_file_path.length) { __builtin_trap(); } - if (options.optimize_when_possible) + if (options->optimize_when_possible) { - llvm::Triple target_triple = target_machine.getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718 + llvm::Triple target_triple = target_machine->getTargetTriple(); // Need to make a copy, incoming bugfix: https://github.com/llvm/llvm-project/pull/127718 // TODO: add library (?) std::unique_ptr TLII(llvm::driver::createTLII(target_triple, llvm::driver::VectorLibrary::NoLibrary)); CodeGenPasses.add(new llvm::TargetLibraryInfoWrapperPass(*TLII)); @@ -1631,11 +1323,11 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli std::unique_ptr stream; - if (options.output_file_path.length) + if (options->output_file_path.length) { std::error_code error_code; - stream = std::make_unique(string_ref(options.output_file_path), error_code, llvm::sys::fs::OF_None); + stream = std::make_unique(string_ref(options->output_file_path), error_code, llvm::sys::fs::OF_None); if (error_code) { @@ -1648,20 +1340,20 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli } llvm::CodeGenFileType file_type; - switch ((BBLLVMCodeGenerationFileType)options.code_generation_file_type) + switch ((BBLLVMCodeGenerationFileType)options->code_generation_file_type) { case BBLLVMCodeGenerationFileType::assembly_file: file_type = llvm::CodeGenFileType::AssemblyFile; break; case BBLLVMCodeGenerationFileType::object_file: file_type = llvm::CodeGenFileType::ObjectFile; break; case BBLLVMCodeGenerationFileType::null: file_type = llvm::CodeGenFileType::Null; break; } - auto disable_verify = !options.verify_module; - if (target_machine.addPassesToEmitFile(CodeGenPasses, *stream, dwarf_object_file, file_type, disable_verify)) + auto disable_verify = !options->verify_module; + if (target_machine->addPassesToEmitFile(CodeGenPasses, *stream, dwarf_object_file, file_type, disable_verify)) { return BBLLVMCodeGenerationPipelineResult::failed_to_add_emit_passes; } - CodeGenPasses.run(module); + CodeGenPasses.run(*module); return BBLLVMCodeGenerationPipelineResult::success; } diff --git a/src/llvm.h b/src/llvm.h index 94a3d99..5999c6e 100644 --- a/src/llvm.h +++ b/src/llvm.h @@ -2,10 +2,70 @@ #include #include +#include #include #include #include -#include +#include + +enum class BBLLVMCodeGenerationPipelineResult : u8 +{ + success = 0, + failed_to_create_file = 1, + failed_to_add_emit_passes = 2, +}; + +enum class BBLLVMCodeGenerationFileType : u8 +{ + assembly_file = 0, + object_file = 1, + null = 2, +}; + +#define BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (60) + +struct BBLLVMCodeGenerationPipelineOptions +{ + String output_dwarf_file_path; + String output_file_path; + u64 code_generation_file_type:2; + u64 optimize_when_possible:1; + u64 verify_module:1; + u64 reserved: BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT; +}; + +static_assert(sizeof(BBLLVMCodeGenerationPipelineOptions) == 5 * sizeof(u64)); +static_assert(BB_LLVM_CODE_GENERATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 60); + +enum class BBLLVMOptimizationLevel : u8 +{ + O0 = 0, + O1 = 1, + O2 = 2, + O3 = 3, + Os = 4, + Oz = 5, +}; + +#define BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT (51) +struct BBLLVMOptimizationPipelineOptions +{ + u64 optimization_level:3; + u64 debug_info:1; + u64 loop_unrolling:1; + u64 loop_interleaving:1; + u64 loop_vectorization:1; + u64 slp_vectorization:1; + u64 merge_functions:1; + u64 call_graph_profile:1; + u64 unified_lto:1; + u64 assignment_tracking:1; + u64 verify_module:1; + u64 reserved:BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT; +}; + +static_assert(sizeof(BBLLVMOptimizationPipelineOptions) == sizeof(u64)); +static_assert(BB_LLVM_OPTIMIZATION_PIPELINE_OPTIONS_PADDING_BIT_COUNT == 51); enum class BBLLVMUWTableKind : u64 { @@ -284,6 +344,256 @@ struct DIFlags static_assert(sizeof(DIFlags) == sizeof(u32)); +enum class BBLLVMEmitDwarfUnwindType : u8 +{ + always = 0, + no_compact_unwind = 1, + normal = 2, +}; + +enum class BBLLVMDwarfDirectory : u8 +{ + disable = 0, + enable = 1, + normal = 2, +}; + +enum class BBLLVMDebugCompressionType : u8 +{ + none = 0, + zlib = 1, + zstd = 2, +}; + +#define BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT (7) + +struct BBLLVMMCTargetOptions +{ + String abi_name; + String assembly_language; + String split_dwarf_file; + String as_secure_log_file; + const char* argv0; + String* argv_pointer; + u64 argv_count; + String* integrated_assembler_search_path_pointer; + u64 integrated_assembler_search_path_count; + u32 relax_all:1; + u32 no_exec_stack:1; + u32 fatal_warnings:1; + u32 no_warn:1; + u32 no_deprecated_warn:1; + u32 no_type_check:1; + u32 save_temp_labels:1; + u32 incremental_linker_compatible:1; + u32 fdpic:1; + u32 show_mc_encoding:1; + u32 show_mc_inst:1; + u32 asm_verbose:1; + u32 preserve_asm_comments:1 = true; + u32 dwarf64:1; + u32 crel:1; + u32 x86_relax_relocations:1; + u32 x86_sse2_avx:1; + u32 emit_dwarf_unwind:2 = 2; + u32 use_dwarf_directory:2 = 2; + u32 debug_compression_type:2 = 0; + u32 emit_compact_unwind_non_canonical:1; + u32 ppc_use_full_register_names:1; + u32 reserved:BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT; +}; + +static_assert(sizeof(BBLLVMMCTargetOptions) == 112); +static_assert(BB_LLVM_MC_TARGET_OPTIONS_PADDING_BIT_COUNT == 7); + +enum class BBLLVMCodeModel : u8 +{ + none = 0, + tiny = 1, + small = 2, + kernel = 3, + medium = 4, + large = 5, +}; + +enum class BBLLVMRelocationModel : u8 +{ + default_relocation = 0, + static_relocation = 1, + pic = 2, + dynamic_no_pic = 3, + ropi = 4, + rwpi = 5, + ropi_rwpi = 6, +}; + +enum class BBLLVMCodeGenerationOptimizationLevel : u8 +{ + none = 0, // -O0 + less = 1, // -O1 + normal = 2, // -O2, -Os + aggressive = 3 // -O3 +}; + +enum class BBLLVMGlobalISelAbortMode : u8 +{ + disable = 0, + enable = 1, + disable_with_diag = 2, +}; + +enum class BBLLVMSwiftAsyncFramePointerMode : u8 +{ + deployment_based = 0, + always = 1, + never = 2, +}; + +enum class BBLLVMBasicBlockSection : u8 +{ + all = 0, + list = 1, + preset = 2, + none = 3, +}; + +enum class BBLLVMFloatAbi : u8 +{ + normal = 0, + soft = 1, + hard = 2, +}; + +enum class BBLLVMFPOpFusion : u8 +{ + fast = 0, + standard = 1, + strict = 2, +}; + +enum class BBLLVMThreadModel : u8 +{ + posix = 0, + single = 1, +}; + +enum class BBLLVMEAbi : u8 +{ + unknown = 0, + normal = 1, + eabi4 = 2, + eabi5 = 3, + gnu = 4, +}; + +enum class BBLLVMDebuggerKind : u8 +{ + normal = 0, + gdb = 1, + lldb = 2, + sce = 3, + dbx = 4, +}; + +enum class BBLLVMExceptionHandling : u8 +{ + none = 0, + dwarf_cfi = 1, + setjmp_longjmp = 2, + arm = 3, + win_eh = 4, + wasm = 5, + aix = 6, + zos = 7, +}; + +#define BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT (21) + +struct BBLLVMTargetOptions +{ + u64 unsafe_fp_math:1; + u64 no_infs_fp_math:1; + u64 no_nans_fp_math:1; + u64 no_trapping_fp_math:1 = true; + u64 no_signed_zeroes_fp_math:1; + u64 approx_func_fp_math:1; + u64 enable_aix_extended_altivec_abi:1; + u64 honor_sign_dependent_rounding_fp_math:1; + u64 no_zeroes_in_bss:1; + u64 guaranteed_tail_call_optimization:1; + u64 stack_symbol_ordering:1 = true; + u64 enable_fast_isel:1; + u64 enable_global_isel:1 = 1; + u64 global_isel_abort_mode:2; + u64 swift_async_frame_pointer:2 = 1; + u64 use_init_array:1; + u64 disable_integrated_assembler:1; + u64 function_sections:1; + u64 data_sections:1; + u64 ignore_xcoff_visibility:1; + u64 xcoff_traceback_table:1 = true; + u64 unique_section_names:1 = true; + u64 unique_basic_block_section_names:1; + u64 separate_named_sections:1; + u64 trap_unreachable:1; + u64 no_trap_after_noreturn:1; + u64 tls_size:8; + u64 emulated_tls:1; + u64 enable_tls_descriptors:1; + u64 enable_ipra:1; + u64 emit_stack_size_section:1; + u64 enable_machine_outliner:1; + u64 enable_machine_function_splitter:1; + u64 supports_default_outlining:1; + u64 emit_address_significance_table:1; + u64 bb_address_map:1; + u64 bb_sections:3 = 3; + u64 emit_call_site_information:1; + u64 supports_debug_entry_values:1; + u64 enable_debug_entry_values:1; + u64 value_tracking_variable_locations:1; + u64 force_dwarf_frame_section:1; + u64 xray_function_index:1 = true; + u64 debug_strict_dwarf:1; + u64 hotpatch:1; + u64 ppc_gen_scalar_mass_entries:1; + u64 jmc_instrument:1; + u64 enable_cfi_fixup:1; + u64 mis_expect:1; + u64 xcoff_read_only_pointers:1; + u64 float_abi:2 = 0; + u64 thread_model:1 = 0; + u32 fp_op_fusion_mode:2 = 1; + u32 eabi_version:3 = 1; + u32 debugger_kind:3 = 0; + u32 exception_handling:3 = 0; + u32 reserved:BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT; + unsigned loop_alignment = 0; + int binutils_version[2]; + + BBLLVMMCTargetOptions mc; +}; + +static_assert(sizeof(BBLLVMTargetOptions) == 136); +static_assert(BB_LLVM_TARGET_OPTIONS_PADDING_BIT_COUNT == 21); + +#define BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT (4) + +struct BBLLVMTargetMachineCreate +{ + BBLLVMTargetOptions target_options; + String target_triple; + String cpu_model; + String cpu_features; + BBLLVMRelocationModel relocation_model; + BBLLVMCodeModel code_model; + BBLLVMCodeGenerationOptimizationLevel optimization_level; + bool jit; + u8 reserved[BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT]; +}; + +static_assert(sizeof(BBLLVMTargetMachineCreate) == 192); +static_assert(BB_LLVM_TARGET_MACHINE_CREATE_PADDING_BYTE_COUNT == 4); fn bool llvm_initialized = false; @@ -318,3 +628,7 @@ extern "C" void llvm_subprogram_replace_type(LLVMMetadataRef subprogram, LLVMMet extern "C" String llvm_module_to_string(LLVMModuleRef module); +extern "C" LLVMTargetMachineRef llvm_create_target_machine(const BBLLVMTargetMachineCreate* create, String* error_message); +extern "C" void llvm_module_set_target(LLVMModuleRef m, LLVMTargetMachineRef tm); +extern "C" void llvm_module_run_optimization_pipeline(LLVMModuleRef module, LLVMTargetMachineRef target_machine, BBLLVMOptimizationPipelineOptions options); +extern "C" BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeline(LLVMModuleRef m, LLVMTargetMachineRef tm, const BBLLVMCodeGenerationPipelineOptions* options);