class LLVM::Context def self.new(*, dispose_on_finalize : Bool = true) new(LibLLVM.create_context, dispose_on_finalize) end def initialize(@unwrap : LibLLVM::ContextRef, @dispose_on_finalize = true) @disposed = false @builders = [] of LLVM::Builder end def new_module(name : String) : Module Module.new(LibLLVM.module_create_with_name_in_context(name, self), self) end def new_builder : Builder # builder = Builder.new(LibLLVM.create_builder_in_context(self), self) builder = Builder.new(LibLLVM.create_builder_in_context(self)) @builders << builder builder end def void : Type Type.new LibLLVM.void_type_in_context(self) end def int1 : Type Type.new LibLLVM.int1_type_in_context(self) end def int8 : Type Type.new LibLLVM.int8_type_in_context(self) end def int16 : Type Type.new LibLLVM.int16_type_in_context(self) end def int32 : Type Type.new LibLLVM.int32_type_in_context(self) end def int64 : Type Type.new LibLLVM.int64_type_in_context(self) end def int128 : Type Type.new LibLLVM.int128_type_in_context(self) end def int(bits : Int) : Type Type.new LibLLVM.int_type_in_context(self, bits) end def half : Type Type.new LibLLVM.half_type_in_context(self) end def float : Type Type.new LibLLVM.float_type_in_context(self) end def double : Type Type.new LibLLVM.double_type_in_context(self) end def x86_fp80 : Type Type.new LibLLVM.x86_fp80_type_in_context(self) end def fp128 : Type Type.new LibLLVM.fp128_type_in_context(self) end def ppc_fp128 : Type Type.new LibLLVM.ppc_fp128_type_in_context(self) end def pointer(address_space = 0) : Type {% if LibLLVM::IS_LT_150 %} {% raise "Opaque pointers are only supported on LLVM 15.0 or above" %} {% else %} Type.new LibLLVM.pointer_type_in_context(self, address_space) {% end %} end def void_pointer(address_space = 0) : Type {% if LibLLVM::IS_LT_150 %} int8.pointer(address_space) {% else %} pointer(address_space) {% end %} end def struct(name : String, packed = false, &) : Type llvm_struct = LibLLVM.struct_create_named(self, name) the_struct = Type.new llvm_struct element_types = (yield the_struct).as(Array(LLVM::Type)) LibLLVM.struct_set_body(llvm_struct, (element_types.to_unsafe.as(LibLLVM::TypeRef*)), element_types.size, packed ? 1 : 0) the_struct end def struct(element_types : Array(LLVM::Type), name = nil, packed = false) : Type if name self.struct(name, packed) { element_types } else Type.new LibLLVM.struct_type_in_context(self, (element_types.to_unsafe.as(LibLLVM::TypeRef*)), element_types.size, packed ? 1 : 0) end end def const_string(string : String) : Value const_bytes(string.unsafe_byte_slice(0, string.bytesize + 1)) end def const_bytes(bytes : Bytes) : Value {% if LibLLVM::IS_LT_190 %} Value.new LibLLVM.const_string_in_context(self, bytes, bytes.size, 1) {% else %} Value.new LibLLVM.const_string_in_context2(self, bytes, bytes.size, 1) {% end %} end def const_struct(values : Array(LLVM::Value), packed = false) : Value Value.new LibLLVM.const_struct_in_context(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size, packed ? 1 : 0) end def md_string(value : String) : Value LLVM::Value.new LibLLVM.md_string_in_context2(self, value, value.bytesize) end def md_node(values : Array(Value)) : Value Value.new LibLLVM.md_node_in_context2(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size) end def parse_ir(buf : MemoryBuffer) ret = LibLLVM.parse_ir_in_context(self, buf, out mod, out msg) if ret != 0 && msg raise LLVM.string_and_dispose(msg) end Module.new(mod, self) end def ==(other : self) @unwrap == other.@unwrap end def to_unsafe @unwrap end def finalize return unless @dispose_on_finalize return if @disposed @disposed = true @builders.each &.dispose LibLLVM.dispose_context(self) end # The next lines are for ease debugging when a types/values # are incorrectly used across contexts. # @@info = {} of UInt64 => String # def self.register(context : Context, name : String) # @@info[context.@unwrap.address] = name # end # def self.lookup(context : Context) # @@info[context.@unwrap.address]? || "global" # end # def self.wrong(expected, got, msg) # raise "#{msg} (expected #{lookup(expected)}, got #{lookup(got)})" # end end