diff --git a/scripts/generate_llvm_version_info.cr b/scripts/generate_llvm_version_info.cr index bfe7e1f2ce96..e331f49056fa 100755 --- a/scripts/generate_llvm_version_info.cr +++ b/scripts/generate_llvm_version_info.cr @@ -5,36 +5,7 @@ # LLVM installation different from the one bundled with Crystal. require "c/libloaderapi" - -# The list of supported targets are hardcoded in: -# https://github.com/llvm/llvm-project/blob/main/llvm/CMakeLists.txt -LLVM_ALL_TARGETS = %w( - AArch64 - AMDGPU - ARM - AVR - BPF - Hexagon - Lanai - LoongArch - Mips - MSP430 - NVPTX - PowerPC - RISCV - Sparc - SPIRV - SystemZ - VE - WebAssembly - X86 - XCore - ARC - CSKY - DirectX - M68k - Xtensa -) +require "llvm/lib_llvm/config" def find_dll_in_env_path ENV["PATH"]?.try &.split(Process::PATH_DELIMITER, remove_empty: true) do |path| @@ -62,7 +33,7 @@ begin patch = uninitialized LibC::UInt llvm_get_version.call(pointerof(major), pointerof(minor), pointerof(patch)) - targets_built = LLVM_ALL_TARGETS.select do |target| + targets_built = LibLLVM::ALL_TARGETS.select do |target| LibC.GetProcAddress(dll, "LLVMInitialize#{target}Target") && LibC.GetProcAddress(dll, "LLVMInitialize#{target}TargetInfo") end diff --git a/src/llvm.cr b/src/llvm.cr index 87e8d90ba0ed..8865f6a54268 100644 --- a/src/llvm.cr +++ b/src/llvm.cr @@ -2,8 +2,6 @@ require "./llvm/**" require "c/string" module LLVM - @@initialized = false - # Returns the runtime version of LLVM. # # Starting with LLVM 16, this method returns the version as reported by @@ -20,85 +18,25 @@ module LLVM {% end %} end - def self.init_x86 : Nil - return if @@initialized_x86 - @@initialized_x86 = true - - {% if LibLLVM::BUILT_TARGETS.includes?(:x86) %} - LibLLVM.initialize_x86_target_info - LibLLVM.initialize_x86_target - LibLLVM.initialize_x86_target_mc - LibLLVM.initialize_x86_asm_printer - LibLLVM.initialize_x86_asm_parser - LibLLVM.link_in_mc_jit - {% else %} - raise "ERROR: LLVM was built without X86 target" - {% end %} - end - - def self.init_aarch64 : Nil - return if @@initialized_aarch64 - @@initialized_aarch64 = true - - {% if LibLLVM::BUILT_TARGETS.includes?(:aarch64) %} - LibLLVM.initialize_aarch64_target_info - LibLLVM.initialize_aarch64_target - LibLLVM.initialize_aarch64_target_mc - LibLLVM.initialize_aarch64_asm_printer - LibLLVM.initialize_aarch64_asm_parser - LibLLVM.link_in_mc_jit - {% else %} - raise "ERROR: LLVM was built without AArch64 target" - {% end %} - end - - def self.init_arm : Nil - return if @@initialized_arm - @@initialized_arm = true - - {% if LibLLVM::BUILT_TARGETS.includes?(:arm) %} - LibLLVM.initialize_arm_target_info - LibLLVM.initialize_arm_target - LibLLVM.initialize_arm_target_mc - LibLLVM.initialize_arm_asm_printer - LibLLVM.initialize_arm_asm_parser - LibLLVM.link_in_mc_jit - {% else %} - raise "ERROR: LLVM was built without ARM target" - {% end %} - end + {% for target in LibLLVM::ALL_TARGETS %} + {% name = target.downcase.id %} + @@initialized_{{name}} = Atomic(Bool).new(false) - def self.init_avr : Nil - return if @@initialized_avr - @@initialized_avr = true - - {% if LibLLVM::BUILT_TARGETS.includes?(:avr) %} - LibLLVM.initialize_avr_target_info - LibLLVM.initialize_avr_target - LibLLVM.initialize_avr_target_mc - LibLLVM.initialize_avr_asm_printer - LibLLVM.initialize_avr_asm_parser - LibLLVM.link_in_mc_jit - {% else %} - raise "ERROR: LLVM was built without AVR target" - {% end %} - end + def self.init_{{name}} : Nil + return if @@initialized_{{name}}.swap(true) - def self.init_webassembly : Nil - return if @@initialized_webassembly - @@initialized_webassembly = true - - {% if LibLLVM::BUILT_TARGETS.includes?(:webassembly) %} - LibLLVM.initialize_webassembly_target_info - LibLLVM.initialize_webassembly_target - LibLLVM.initialize_webassembly_target_mc - LibLLVM.initialize_webassembly_asm_printer - LibLLVM.initialize_webassembly_asm_parser - LibLLVM.link_in_mc_jit - {% else %} - raise "ERROR: LLVM was built without WebAssembly target" - {% end %} - end + \{% if LibLLVM::BUILT_TARGETS.includes?({{name.symbolize}}) %} + LibLLVM.initialize_{{name}}_target_info + LibLLVM.initialize_{{name}}_target + LibLLVM.initialize_{{name}}_target_mc + LibLLVM.initialize_{{name}}_asm_printer + LibLLVM.initialize_{{name}}_asm_parser + LibLLVM.link_in_mc_jit + \{% else %} + raise "ERROR: LLVM was built without {{target.id}} target" + \{% end %} + end + {% end %} def self.init_native_target : Nil {% if flag?(:i386) || flag?(:x86_64) %} @@ -117,10 +55,11 @@ module LLVM end def self.init_all_targets : Nil - {% for target in %i(x86 aarch64 arm avr webassembly) %} - {% if LibLLVM::BUILT_TARGETS.includes?(target) %} - init_{{ target.id }} - {% end %} + {% for target in LibLLVM::ALL_TARGETS %} + {% name = target.downcase.id %} + \{% if LibLLVM::BUILT_TARGETS.includes?({{name.symbolize}}) %} + init_{{name}} + \{% end %} {% end %} end diff --git a/src/llvm/lib_llvm.cr b/src/llvm/lib_llvm.cr index 3339942d7cea..d907be9fbeeb 100644 --- a/src/llvm/lib_llvm.cr +++ b/src/llvm/lib_llvm.cr @@ -87,4 +87,5 @@ lib LibLLVM alias SizeT = LibC::SizeT end +require "./lib_llvm/config" require "./lib_llvm/**" diff --git a/src/llvm/lib_llvm/config.cr b/src/llvm/lib_llvm/config.cr new file mode 100644 index 000000000000..c90d6d9c74d7 --- /dev/null +++ b/src/llvm/lib_llvm/config.cr @@ -0,0 +1,35 @@ +# The list of supported targets are hardcoded in: +# https://github.com/llvm/llvm-project/blob/main/llvm/CMakeLists.txt + +lib LibLLVM + ALL_TARGETS = [ + # default targets (as of LLVM 21) + "AArch64", + "AMDGPU", + "ARM", + "AVR", + "BPF", + "Hexagon", + "Lanai", + "LoongArch", + "MSP430", + "Mips", + "NVPTX", + "PowerPC", + "RISCV", + "SPIRV", + "Sparc", + "SystemZ", + "VE", + "WebAssembly", + "X86", + "XCore", + + # experimental targets (as of LLVM 21) + "ARC", + "CSKY", + "DirectX", + "M68k", + "Xtensa", + ] +end diff --git a/src/llvm/lib_llvm/target.cr b/src/llvm/lib_llvm/target.cr index 7e50e5d663fa..cd076658d574 100644 --- a/src/llvm/lib_llvm/target.cr +++ b/src/llvm/lib_llvm/target.cr @@ -3,31 +3,14 @@ require "./types" lib LibLLVM type TargetDataRef = Void* - fun initialize_aarch64_target_info = LLVMInitializeAArch64TargetInfo - fun initialize_aarch64_target = LLVMInitializeAArch64Target - fun initialize_aarch64_target_mc = LLVMInitializeAArch64TargetMC - fun initialize_aarch64_asm_printer = LLVMInitializeAArch64AsmPrinter - fun initialize_aarch64_asm_parser = LLVMInitializeAArch64AsmParser - fun initialize_arm_target_info = LLVMInitializeARMTargetInfo - fun initialize_arm_target = LLVMInitializeARMTarget - fun initialize_arm_target_mc = LLVMInitializeARMTargetMC - fun initialize_arm_asm_printer = LLVMInitializeARMAsmPrinter - fun initialize_arm_asm_parser = LLVMInitializeARMAsmParser - fun initialize_avr_target_info = LLVMInitializeAVRTargetInfo - fun initialize_avr_target = LLVMInitializeAVRTarget - fun initialize_avr_target_mc = LLVMInitializeAVRTargetMC - fun initialize_avr_asm_printer = LLVMInitializeAVRAsmPrinter - fun initialize_avr_asm_parser = LLVMInitializeAVRAsmParser - fun initialize_webassembly_target_info = LLVMInitializeWebAssemblyTargetInfo - fun initialize_webassembly_target = LLVMInitializeWebAssemblyTarget - fun initialize_webassembly_target_mc = LLVMInitializeWebAssemblyTargetMC - fun initialize_webassembly_asm_printer = LLVMInitializeWebAssemblyAsmPrinter - fun initialize_webassembly_asm_parser = LLVMInitializeWebAssemblyAsmParser - fun initialize_x86_target_info = LLVMInitializeX86TargetInfo - fun initialize_x86_target = LLVMInitializeX86Target - fun initialize_x86_target_mc = LLVMInitializeX86TargetMC - fun initialize_x86_asm_printer = LLVMInitializeX86AsmPrinter - fun initialize_x86_asm_parser = LLVMInitializeX86AsmParser + {% for target in ALL_TARGETS %} + {% name = target.downcase.id %} + fun initialize_{{name}}_target_info = LLVMInitialize{{target.id}}TargetInfo + fun initialize_{{name}}_target = LLVMInitialize{{target.id}}Target + fun initialize_{{name}}_target_mc = LLVMInitialize{{target.id}}TargetMC + fun initialize_{{name}}_asm_printer = LLVMInitialize{{target.id}}AsmPrinter + fun initialize_{{name}}_asm_parser = LLVMInitialize{{target.id}}AsmParser + {% end %} fun set_module_data_layout = LLVMSetModuleDataLayout(m : ModuleRef, dl : TargetDataRef)