IR builders
IRBuilder
is the workhorse of LLVM Intermediate representation (IR) generation.
It allows you to fill the basic blocks of
your functions with LLVM instructions.
An IRBuilder
internally maintains a current basic block
and a pointer inside the block’s list of instructions. When a
new instruction is added, it is inserted at that point, and then
the pointer is advanced after the new instruction.
A IRBuilder
also maintains a reference to metadata
describing the current source location, which is attached to all
inserted instructions.
Instantiation
Attributes
IRBuilder
has the following attributes:
- IRBuilder.block
The basic block that the builder is operating on.
- IRBuilder.function
The function that the builder is operating on.
- IRBuilder.module
The module that the builder’s function is defined in.
- IRBuilder.debug_metadata
If not
None
, the metadata that is attached to any inserted instructions as!dbg
, unless the instruction already has!dbg
set.
Utilities
Positioning
The following IRBuilder
methods help you move the
current instruction pointer:
- IRBuilder.position_before(instruction)
Position immediately before the given instruction. The current block is also changed to the instruction’s basic block.
- IRBuilder.position_after(instruction)
Position immediately after the given instruction. The current block is also changed to the instruction’s basic block.
- IRBuilder.position_at_start(block)
Position at the start of the basic block.
- IRBuilder.position_at_end(block)
Position at the end of the basic block.
The following context managers allow you to temporarily switch to another basic block and then go back to where you were.
- IRBuilder.goto_block(block)
Position the builder either at the end of the basic block, if it is not terminated, or just before the block’s terminator:
new_block = builder.append_basic_block('foo') with builder.goto_block(new_block): # Now the builder is at the end of *new_block* # ... add instructions # Now the builder has returned to its previous position
- IRBuilder.goto_entry_block()
The same as
goto_block()
, but with the current function’s entry block.
Flow control helpers
The following context managers make it easier to create conditional code.
- IRBuilder.if_then(pred, likely=None)
Create a basic block whose execution is conditioned on predicate pred, a value of type
IntType(1)
. Another basic block is created for instructions after the conditional block. The current basic block is terminated with a conditional branch based on pred.When the context manager is entered, the builder positions at the end of the conditional block. When the context manager is exited, the builder positions at the start of the continuation block.
If likely is not
None
, it indicates whether pred is likely to beTrue
, and metadata is emitted to specify branch weights accordingly.
- IRBuilder.if_else(pred, likely=None)
Set up 2 basic blocks whose execution is conditioned on predicate pred, a value of type
IntType(1)
. likely has the same meaning as inif_then()
.A pair of context managers is yielded. Each of them acts as an
if_then()
context manager—the first for the block to be executed if pred isTrue
and the second for the block to be executed if pred isFalse
.When the context manager is exited, the builder is positioned on a new continuation block that both conditional blocks jump into.
Typical use:
with builder.if_else(pred) as (then, otherwise): with then: # emit instructions for when the predicate is true with otherwise: # emit instructions for when the predicate is false # emit instructions following the if-else block
Instruction building
The following methods insert a new instruction—an
Instruction
instance—at the current index in the
current block. The new instruction is returned.
An instruction’s operands are almost always values.
Many of these methods also take an optional name argument, specifying the local name of the result value. If not given, a unique name is automatically generated.
Arithmetic
In the methods below, the flags argument is an optional sequence of strings that modify the instruction’s semantics. Examples include the fast-math flags for floating-point operations, and whether wraparound on overflow can be ignored on integer operations.
Integer
- IRBuilder.shl(lhs, rhs, name='', flags=())
Left-shift lhs by rhs bits.
- IRBuilder.lshr(lhs, rhs, name='', flags=())
Logical right-shift lhs by rhs bits.
- IRBuilder.ashr(lhs, rhs, name='', flags=())
Arithmetic, signed, right-shift lhs by rhs bits.
- IRBuilder.cttz(value, flag)
Counts trailing zero bits in value. Boolean flag indicates whether the result is defined for
0
.
- IRBuilder.ctlz(value, flag)
Counts leading zero bits in value. Boolean flag indicates whether the result is defined for
0
.
- IRBuilder.add(lhs, rhs, name='', flags=())
Integer add lhs and rhs.
- IRBuilder.sadd_with_overflow(lhs, rhs, name='', flags=())
Integer add lhs and rhs. A
{ result, overflow bit }
structure is returned.
- IRBuilder.sub(lhs, rhs, name='', flags=())
Integer subtract rhs from lhs.
- IRBuilder.ssub_with_overflow(lhs, rhs, name='', flags=())
Integer subtract rhs from lhs. A
{ result, overflow bit }
structure is returned.
- IRBuilder.mul(lhs, rhs, name='', flags=())
Integer multiply lhs with rhs.
- IRBuilder.smul_with_overflow(lhs, rhs, name='', flags=())
Integer multiply lhs with rhs. A
{ result, overflow bit }
structure is returned.
- IRBuilder.sdiv(lhs, rhs, name='', flags=())
Signed integer divide lhs by rhs.
- IRBuilder.udiv(lhs, rhs, name='', flags=())
Unsigned integer divide lhs by rhs.
- IRBuilder.srem(lhs, rhs, name='', flags=())
Signed integer remainder of lhs divided by rhs.
- IRBuilder.urem(lhs, rhs, name='', flags=())
Unsigned integer remainder of lhs divided by rhs.
- IRBuilder.and_(lhs, rhs, name='', flags=())
Bitwise AND lhs with rhs.
- IRBuilder.or_(lhs, rhs, name='', flags=())
Bitwise OR lhs with rhs.
- IRBuilder.xor(lhs, rhs, name='', flags=())
Bitwise XOR lhs with rhs.
- IRBuilder.not_(value, name='')
Bitwise complement value.
- IRBuilder.neg(value, name='')
Negate value.
Floating-point
- IRBuilder.fadd(lhs, rhs, name='', flags=())
Floating-point add lhs and rhs.
- IRBuilder.fsub(lhs, rhs, name='', flags=())
Floating-point subtract rhs from lhs.
- IRBuilder.fmul(lhs, rhs, name='', flags=())
Floating-point multiply lhs by rhs.
- IRBuilder.fdiv(lhs, rhs, name='', flags=())
Floating-point divide lhs by rhs.
- IRBuilder.frem(lhs, rhs, name='', flags=())
Floating-point remainder of lhs divided by rhs.
- IRBuilder.fneg(arg, name='', flags=())
Floating-point negation of arg.
Conversions
- IRBuilder.trunc(value, typ, name='')
Truncate integer value to integer type typ.
- IRBuilder.zext(value, typ, name='')
Zero-extend integer value to integer type typ.
- IRBuilder.sext(value, typ, name='')
Sign-extend integer value to integer type typ.
- IRBuilder.fptrunc(value, typ, name='')
Truncate—approximate—floating-point value to floating-point type typ.
- IRBuilder.fpext(value, typ, name='')
Extend floating-point value to floating-point type typ.
- IRBuilder.fptosi(value, typ, name='')
Convert floating-point value to signed integer type typ.
- IRBuilder.fptoui(value, typ, name='')
Convert floating-point value to unsigned integer type typ.
- IRBuilder.sitofp(value, typ, name='')
Convert signed integer value to floating-point type typ.
- IRBuilder.uitofp(value, typ, name='')
Convert unsigned integer value to floating-point type typ.
- IRBuilder.ptrtoint(value, typ, name='')
Convert pointer value to integer type typ.
- IRBuilder.inttoptr(value, typ, name='')
Convert integer value to pointer type typ.
- IRBuilder.bitcast(value, typ, name='')
Convert pointer value to pointer type typ.
- IRBuilder.addrspacecast(value, typ, name='')
Convert pointer value to pointer type typ of different address space.
Comparisons
- IRBuilder.icmp_signed(cmpop, lhs, rhs, name='')
Signed integer compare lhs with rhs. The string cmpop can be one of
<
,<=
,==
,!=
,>=
or>
.
- IRBuilder.icmp_unsigned(cmpop, lhs, rhs, name='')
Unsigned integer compare lhs with rhs. The string cmpop can be one of
<
,<=
,==
,!=
,>=
or>
.
- IRBuilder.fcmp_ordered(cmpop, lhs, rhs, name='', flags=[])
Floating-point ordered compare lhs with rhs.
The string cmpop can be one of
<
,<=
,==
,!=
,>=
,>
,ord
oruno
.The flags list can include any of
nnan
,ninf
,nsz
,arcp
andfast
, which implies all previous flags.
- IRBuilder.fcmp_unordered(cmpop, lhs, rhs, name='', flags=[])
Floating-point unordered compare lhs with rhs.
The string cmpop, can be one of
<
,<=
,==
,!=
,>=
,>
,ord
oruno
.The flags list can include any of
nnan
,ninf
,nsz
,arcp
andfast
, which implies all previous flags.
Conditional move
- IRBuilder.select(cond, lhs, rhs, name='')
A 2-way select—lhs if cond, else rhs.
Phi
- IRBuilder.phi(typ, name='')
Create a phi node. To add incoming edges and their values, use the
add_incoming()
method on the return value.
Aggregate operations
- IRBuilder.extract_value(agg, index, name='')
Extract the element at index of the aggregate value agg.
index may be an integer or a sequence of integers.
Indices must be constant.
- IRBuilder.insert_value(agg, value, index, name='')
Build a copy of aggregate value agg by setting the new value at index. The value for index can be of the same types as in
extract_value()
.
Vector operations
- IRBuilder.extract_element(vector, idx, name='')
Returns the value at position idx.
- IRBuilder.insert_element(vector, value, idx, name='')
Returns vector with
vector[idx]
replaced byvalue
. The result is undefined if the idx is larger or equal the vector length.
- IRBuilder.shuffle_vector(vector1, vector2, mask, name='')
Constructs a permutation of elements from vector1 and vector2. Returns a new vector in the same length of mask.
vector1 and vector2 must have the same element type.
mask must be a constant vector of integer types.
Memory
- IRBuilder.alloca(typ, size=None, name='')
Statically allocate a stack slot for size values of type typ. If size is not given, a stack slot for 1 value is allocated.
- IRBuilder.load(ptr, name='', align=None)
Load value from pointer ptr. If align is passed, it should be a Python integer specifying the guaranteed pointer alignment.
- IRBuilder.store(value, ptr, align=None)
Store value to pointer ptr. If align is passed, it should be a Python integer specifying the guaranteed pointer alignment.
- IRBuilder.load_atomic(ptr, ordering, align, name='')
Load value from pointer ptr as an atomic operation with the given ordering. align must be a Python integer specifying the guaranteed pointer alignment.
- IRBuilder.store_atomic(value, ptr, ordering, align)
Store value to pointer ptr as an atomic operation with the given ordering. align must be a Python integer specifying the guaranteed pointer alignment.
- IRBuilder.gep(ptr, indices, inbounds=False, name='')
The getelementptr instruction. Given a pointer ptr to an aggregate value, compute the address of the inner element given by the sequence of indices.
- llvmlite.ir.cmpxchg(ptr, cmp, val, ordering, failordering=None, name='')
Atomic compare-and-swap at address ptr.
cmp is the value to compare the contents with.
val is the new value to be swapped into.
Optional ordering and failordering specify the memory model for this instruction.
- llvmlite.ir.atomic_rmw(op, ptr, val, ordering, name='')
Atomic in-memory operation op at address ptr, with operand val.
The string op specifies the operation—for example,
add
orsub
.The optional ordering specifies the memory model for this instruction.
Function call
- IRBuilder.call(fn, args, name='', cconv=None, tail=None, fastmath=(), attrs=(), arg_attrs=None)
Call function fn with arguments args, a sequence of values.
cconv is the optional calling convention.
tail controls tail-call optimization behavior. It may be one of:
None
(the default): indicates no specific tail-call optimization behavior."tail"
: a hint that indicates that the call should be tail-call optimized, but may be ignored."musttail"
: indicates that the call must be tail-call optimized for program correctness."notail"
: indicates that the call should never be tail-call optimized.
For backwards compatibility with previous versions, the following values are also accepted:
False
is equivalent toNone
, indicating no specific behavior.True
is equivalent to"tail"
, suggesting tail-call optimization.
fastmath is a string or a sequence of strings of names for fast-math flags.
attrs is a string or sequence of strings of function attributes to attach to the call site.
arg_attrs is a dictionary matching argument indices (as regular integers, starting at zero) to strings or sequences of strings giving the attributes to attach to the respective argument at this call site. If an index is not present in the dictionary, or arg_attrs is missing entirely, no attributes are emitted for the given argument.
If some attributes, such as
sret
, are specified at the function declaration, they must also be specified at each call site for correctness. (As of LLVM 11, this does not seem to be explicitly specified in the LLVM language reference.)
Branches
The following methods are all terminators:
- IRBuilder.cbranch(cond, truebr, falsebr)
Conditional jump to either truebr or falsebr—both
Block
instances—depending on cond, a value of typeIntType(1)
. This instruction is aPredictableInstr
.
- IRBuilder.ret(value)
Return the value from the current function.
- IRBuilder.ret_void()
Return from the current function without a value.
- IRBuilder.switch(value, default)
Switch to different blocks based on the value. default is the block to switch to if no other block is matched.
To add non-default targets, use the
add_case()
method on the return value.
- IRBuilder.branch_indirect(address)
Jump to the basic block with the address address, a value of type IntType(8).as_pointer().
To obtain a block address, use the
BlockAddress
constant.To add all possible jump destinations, use the
add_destination()
method on the return value.
Exception handling
- IRBuilder.invoke(fn, args, normal_to, unwind_to, name='', cconv=None, fastmath=(), attrs=(), arg_attrs=None)
Call function fn with arguments args, a sequence of values.
If the function fn returns normally, control is transferred to normal_to. Otherwise, it is transferred to unwind_to, whose first non-phi instruction must be
LandingPad
.The remaining arguments give additional attributes to specify at the call site; see
call()
for a description.
- IRBuilder.landingpad(typ, personality, name='', cleanup=False)
Describe which exceptions this basic block can handle.
typ specifies the return type of the landing pad. It is a structure with 2 pointer-sized fields.
personality specifies an exception personality function.
cleanup specifies whether control should always be transferred to this landing pad, even when no matching exception is caught.
To add landing pad clauses, use the
add_clause()
method on the return value.There are 2 kinds of landing pad clauses:
A
CatchClause
, which specifies a typeinfo for a single exception to be caught. The typeinfo is a value of type IntType(8).as_pointer().as_pointer();A
FilterClause
, which specifies an array of typeinfos.
Every landing pad must either contain at least 1 clause or be marked for cleanup.
The semantics of a landing pad are entirely determined by the personality function. For details on the way LLVM handles landing pads in the optimizer, see Exception handling in LLVM. For details on the implementation of personality functions, see Itanium exception handling ABI.
- IRBuilder.resume(landingpad)
Resume an exception caught by landingpad. Used to indicate that the landing pad did not catch the exception after all, perhaps because it only performed cleanup.
Inline assembler
- IRBuilder.asm(ftype, asm, constraint, args, side_effect, name='')
Add an inline assembler call instruction. For example, this is used in
load_reg()
andstore_reg()
.Arguments:
ftype is a function type specifying the inputs and output of the inline assembler call.
asm is the inline assembler snippet—for example,
"mov $2, $0\nadd $1, $0"
. x86 inline ASM uses the AT&T syntax.constraint defines the input/output constraints—for example
=r,r,r
.args is the list of inputs, as IR values.
side_effect is a boolean that specifies whether or not this instruction has side effects not visible in the constraint list.
name is the optional name of the returned LLVM value.
For more information about these parameters, see the official LLVM documentation.
EXAMPLE: Adding 2 64-bit values on x86:
fty = FunctionType(IntType(64), [IntType(64),IntType(64)]) add = builder.asm(fty, "mov $2, $0\nadd $1, $0", "=r,r,r", (arg_0, arg_1), True, name="asm_add")
- IRBuilder.load_reg(reg_type, reg_name, name='')
Load a register value into an LLVM value.
EXAMPLE: Obtaining the value of the
rax
register:builder.load_reg(IntType(64), "rax")
- IRBuilder.store_reg(value, reg_type, reg_name, name='')
Store an LLVM value inside a register.
EXAMPLE: Storing
0xAAAAAAAAAAAAAAAA
into therax
register:builder.store_reg(Constant(IntType(64), 0xAAAAAAAAAAAAAAAA), IntType(64), "rax")
Miscellaneous
- IRBuilder.assume(cond)
Let the LLVM optimizer assume that cond—a value of type
IntType(1)
—isTrue
.
- IRBuilder.unreachable()
Mark an unreachable point in the code.
- IRBuilder.comment(text)
Puts a single-line comment into the generated IR. This will be ignored by LLVM, but can be useful for debugging the output of a compiler.
Arguments:
text is a string that does not contain new line characters.