Types
LLVM has a rich type-system that is used to describe the types of values in a program. LLVM.jl attempts to reconstruct as much of this type-system as possible in Julia, beyond the abstractions that the C API provides (where types are opaque objects).
Each type object, represented by a subtype of LLVMType, supports a few property functions:
issized: whether the type has a fixed size (e.g.Int32).context: the context in which the type was created.eltype: the element type of the type (if applicable, e.g., for arrays and vectors).
The types describing LLVM types are not exported by default, so always need to be prefixed by the LLVM module name.
Integer types
Integer types are subtypes of the LLVM.IntegerType abstract type. They can be created using explicit constructors that encode the bit-width, or using constructors that take a width argument:
julia> LLVM.Int1Type()
i1
julia> LLVM.IntType(32)
i32It is possible to query the bit-width of an integer type using the width property:
julia> LLVM.Int32Type().width
32Floating-point types
Floating-point types are subtypes of the LLVM.FloatingPointType abstract type. They can only be constructed using explicitly named constructors:
julia> LLVM.HalfType()
half
julia> LLVM.BFloatType()
bfloatFunction types
Function types are used to create functions, and encode both the return type and the argument types, which can be queried using respectively the return_type and parameters properties. Types cannot be changed, so the parameters are a read-only view.
julia> LLVM.FunctionType(LLVM.Int1Type())
i1 ()
julia> ft = LLVM.FunctionType(LLVM.Int1Type(), [LLVM.FloatType()])
i1 (float)
julia> ft.return_type
i1
julia> collect(ft.parameters)
1-element Vector{LLVMType}:
floatTo create vararg functions, the vararg keyword argument to the FunctionType constructor can be used. This property can be queried using the isvararg function.
Pointer types
Pointer types are represented by the LLVM.PointerType type. Since LLVM 17, all pointers are opaque, i.e., they don't have an element type. Older versions of LLVM also support typed pointers, whose element type is available as the element_type property:
julia> supports_typed_pointers()
true
julia> ty = LLVM.PointerType(LLVM.Int1Type())
i1*
julia> ty.element_type
i1When constructing a pointer type, you can also set the address space, and query it back using the addrspace property:
julia> ty = LLVM.PointerType(LLVM.Int1Type(), 1)
ptr addrspace(1)
julia> ty.addrspace
1Array types
LLVM arrays represent a fixed-size, homoeneous collection of elements. They can be created using the LLVM.ArrayType constructor:
julia> ty = LLVM.ArrayType(LLVM.Int1Type(), 8)
[8 x i1]
julia> ty.length
8
julia> ty.element_type
i1Vector types
LLVM vectors are similar, but mostly used for SIMD operations:
julia> ty = LLVM.VectorType(LLVM.Int1Type(), 8)
<8 x i1>
julia> ty.length
8
julia> ty.element_type
i1Structure types
Structure types are used to represent a collection of elements of different types. They can be created using the LLVM.StructType constructor:
julia> ty = LLVM.StructType([LLVM.Int32Type(), LLVM.FloatType()])
{ i32, float }It is also possible to start with an empty type and add elements to it:
julia> ty = LLVM.StructType("MyStruct")
%MyStruct = type opaque
julia> elements!(ty, [LLVM.Int32Type(), LLVM.FloatType()])
julia> ty
%MyStruct = type { i32, float }Structure types support a number of queries:
ty.name: the name of the structure type.ty.elements: the element types of the structure type, as a read-only view (useelements!to set the body of an opaque structure type).ispacked: whether the structure is packed.isopaque: whether the structure is opaque.isempty: whether the structure is empty.
Other types
There are a few other types that do not fit in a specific category:
LLVM.VoidType: thevoidtype.LLVM.LabelType: thelabeltype.LLVM.MetadataType: themetadatatype.LLVM.TokenType: thetokentype.
Named types
Although uncommon, it is possible to look up the named types that are registered in a context using its types property. LLVM does not support iterating these types, but the property can be used to check whether a type is registered in a context:
julia> ctx = context();
julia> haskey(ctx.types, "Foo")
false
julia> ty = LLVM.StructType("Foo")
%Foo = type opaque
julia> haskey(ctx.types, "Foo")
true
julia> ctx.types["Foo"]
%Foo = type opaque