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)
i32
It is possible to query the bit-width of an integer type using the width
function:
julia> width(LLVM.Int32Type())
32
Floating-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()
bfloat
Function 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
functions.
julia> LLVM.FunctionType(LLVM.Int1Type())
i1 ()
julia> ft = LLVM.FunctionType(LLVM.Int1Type(), [LLVM.FloatType()])
i1 (float)
julia> return_type(ft)
i1
julia> parameters(ft)
1-element Vector{LLVMType}:
float
To 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. Depending on the LLVM version, they can be opaque or have an element type that can be queried using the eltype
function:
julia> supports_typed_pointers()
true
julia> ty = LLVM.PointerType(LLVM.Int1Type())
i1*
julia> eltype(ty)
i1
julia> supports_typed_pointers()
false
julia> ty = LLVM.PointerType()
ptr
julia> eltype(ty)
ERROR: Taking the type of an opaque pointer is illegal
When constructing a pointer type, you can also set the address space, and query it back using the addrspace
function:
julia> ty = LLVM.PointerType(LLVM.Int1Type(), 1)
i1 addrspace(1)*
julia> addrspace(ty)
1
Array 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> length(ty)
8
julia> eltype(ty)
i1
Vector types
LLVM vectors are similar, but mostly used for SIMD operations:
julia> ty = LLVM.VectorType(LLVM.Int1Type(), 8)
<8 x i1>
julia> length(ty)
8
julia> eltype(ty)
i1
Structure 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:
name
: the name of the structure type.elements
: the element types of the 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
: thevoid
type.LLVM.LabelType
: thelabel
type.LLVM.MetadataType
: themetadata
type.LLVM.TokenType
: thetoken
type.
Type iteration
Although uncommon, it is possible to iterate the types that are registered in a context using the iterator returned by the types
function. This iterator is not actually iterable, but it can be used to check whether a type is registered in a context:
julia> ctx = context();
julia> haskey(types(ctx), "Foo")
false
julia> ty = LLVM.StructType("Foo")
%Foo = type opaque
julia> haskey(types(ctx), "Foo")
true
julia> types(ctx)["Foo"]
%Foo = type opaque