Struct inkwell::builder::Builder

source ·
pub struct Builder<'ctx> { /* private fields */ }
Expand description

All build_* methods return a Result<_, BuilderError> type containing either the returned value or some error. Those methods all may return BuilderError::UnsetPosition if a position_* method has not yet been called, in addition to any other possibility.

Implementations§

source§

impl<'ctx> Builder<'ctx>

source

pub unsafe fn new(builder: LLVMBuilderRef) -> Self

source

pub fn as_mut_ptr(&self) -> LLVMBuilderRef

Acquires the underlying raw pointer belonging to this Builder type.

source

pub fn build_return( &self, value: Option<&dyn BasicValue<'ctx>> ) -> Result<InstructionValue<'ctx>, BuilderError>

Builds a function return instruction. It should be provided with None if the return type is void otherwise Some(&value) should be provided.

§Example
use inkwell::context::Context;

// A simple function which returns its argument:
let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();
let i32_type = context.i32_type();
let arg_types = [i32_type.into()];
let fn_type = i32_type.fn_type(&arg_types, false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
let i32_arg = fn_value.get_first_param().unwrap();

builder.position_at_end(entry);
builder.build_return(Some(&i32_arg)).unwrap();
source

pub fn build_aggregate_return( &self, values: &[BasicValueEnum<'ctx>] ) -> Result<InstructionValue<'ctx>, BuilderError>

Builds a function return instruction for a return type which is an aggregate type (ie structs and arrays). It is not necessary to use this over build_return but may be more convenient to use.

§Example
use inkwell::context::Context;

// This builds a simple function which returns a struct (tuple) of two ints.
let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();
let i32_type = context.i32_type();
let i32_three = i32_type.const_int(3, false);
let i32_seven = i32_type.const_int(7, false);
let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false);
let fn_type = struct_type.fn_type(&[], false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");

builder.position_at_end(entry);
builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]).unwrap();
source

pub fn build_call( &self, function: FunctionValue<'ctx>, args: &[BasicMetadataValueEnum<'ctx>], name: &str ) -> Result<CallSiteValue<'ctx>, BuilderError>

Builds a function call instruction. Alias for Builder::build_direct_call.

source

pub fn build_direct_call( &self, function: FunctionValue<'ctx>, args: &[BasicMetadataValueEnum<'ctx>], name: &str ) -> Result<CallSiteValue<'ctx>, BuilderError>

Builds a function call instruction. The function being called is known at compile time. If you want to call a function pointer, see Builder::build_indirect_call.

§Example
use inkwell::context::Context;

// A simple function which calls itself:
let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();
let i32_type = context.i32_type();
let fn_type = i32_type.fn_type(&[i32_type.into()], false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
let i32_arg = fn_value.get_first_param().unwrap();
let md_string = context.metadata_string("a metadata");

builder.position_at_end(entry);

let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call").unwrap()
    .try_as_basic_value()
    .left()
    .unwrap();

builder.build_return(Some(&ret_val)).unwrap();
source

pub fn build_indirect_call( &self, function_type: FunctionType<'ctx>, function_pointer: PointerValue<'ctx>, args: &[BasicMetadataValueEnum<'ctx>], name: &str ) -> Result<CallSiteValue<'ctx>, BuilderError>

Call a function pointer. Because a pointer does not carry a type, the type of the function must be specified explicitly.

See Context::create_inline_asm for a practical example. Basic usage looks like this:

use inkwell::context::Context;

// A simple function which calls itself:
let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();
let i32_type = context.i32_type();
let fn_type = i32_type.fn_type(&[i32_type.into()], false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
let i32_arg = fn_value.get_first_param().unwrap();
let md_string = context.metadata_string("a metadata");

builder.position_at_end(entry);

let function_pointer = fn_value.as_global_value().as_pointer_value();
let ret_val = builder.build_indirect_call(fn_value.get_type(), function_pointer, &[i32_arg.into(), md_string.into()], "call").unwrap()
    .try_as_basic_value()
    .left()
    .unwrap();

builder.build_return(Some(&ret_val)).unwrap();
source

pub fn build_invoke( &self, function: FunctionValue<'ctx>, args: &[BasicValueEnum<'ctx>], then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str ) -> Result<CallSiteValue<'ctx>, BuilderError>

An invoke is similar to a normal function call, but used to call functions that may throw an exception, and then respond to the exception.

When the called function returns normally, the then block is evaluated next. If instead the function threw an exception, the catch block is entered. The first non-phi instruction of the catch block must be a landingpad instruction. See also Builder::build_landing_pad.

The add_prune_eh_pass turns an invoke into a call when the called function is guaranteed to never throw an exception.

This example catches C++ exceptions of type int, and returns 0 if an exceptions is thrown. For usage of a cleanup landing pad and the resume instruction, see Builder::build_resume

use inkwell::context::Context;
use inkwell::AddressSpace;
use inkwell::module::Linkage;

let context = Context::create();
let module = context.create_module("sum");
let builder = context.create_builder();

let f32_type = context.f32_type();
let fn_type = f32_type.fn_type(&[], false);

// we will pretend this function can throw an exception
let function = module.add_function("bomb", fn_type, None);
let basic_block = context.append_basic_block(function, "entry");

builder.position_at_end(basic_block);

let pi = f32_type.const_float(::std::f64::consts::PI);

builder.build_return(Some(&pi)).unwrap();

let function2 = module.add_function("wrapper", fn_type, None);
let basic_block2 = context.append_basic_block(function2, "entry");

builder.position_at_end(basic_block2);

let then_block = context.append_basic_block(function2, "then_block");
let catch_block = context.append_basic_block(function2, "catch_block");

let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();

{
    builder.position_at_end(then_block);

    // in the then_block, the `call_site` value is defined and can be used
    let result = call_site.try_as_basic_value().left().unwrap();

    builder.build_return(Some(&result)).unwrap();
}

{
    builder.position_at_end(catch_block);

    // the personality function used by C++
    let personality_function = {
        let name = "__gxx_personality_v0";
        let linkage = Some(Linkage::External);

        module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
    };

    // type of an exception in C++
    let ptr_type = context.ptr_type(AddressSpace::default());
    let i32_type = context.i32_type();
    let exception_type = context.struct_type(&[ptr_type.into(), i32_type.into()], false);

    let null = ptr_type.const_zero();
    let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();

    // we handle the exception by returning a default value
    builder.build_return(Some(&f32_type.const_zero())).unwrap();
}
source

pub fn build_direct_invoke( &self, function: FunctionValue<'ctx>, args: &[BasicValueEnum<'ctx>], then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str ) -> Result<CallSiteValue<'ctx>, BuilderError>

source

pub fn build_indirect_invoke( &self, function_type: FunctionType<'ctx>, function_pointer: PointerValue<'ctx>, args: &[BasicValueEnum<'ctx>], then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str ) -> Result<CallSiteValue<'ctx>, BuilderError>

source

pub fn build_landing_pad<T>( &self, exception_type: T, personality_function: FunctionValue<'ctx>, clauses: &[BasicValueEnum<'ctx>], is_cleanup: bool, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>
where T: BasicType<'ctx>,

Landing pads are places where control flow jumps to if a Builder::build_invoke triggered an exception. The landing pad will match the exception against its clauses. Depending on the clause that is matched, the exception can then be handled, or resumed after some optional cleanup, causing the exception to bubble up.

Exceptions in LLVM are designed based on the needs of a C++ compiler, but can be used more generally. Here are some specific examples of landing pads. For a full example of handling an exception, see Builder::build_invoke.

  • cleanup: a cleanup landing pad is always visited when unwinding the stack. A cleanup is extra code that needs to be run when unwinding a scope. C++ destructors are a typical example. In a language with reference counting, the cleanup block can decrement the refcount of values in scope. The Builder::build_resume function has a full example using a cleanup lading pad.
use inkwell::context::Context;
use inkwell::AddressSpace;
use inkwell::module::Linkage;

let context = Context::create();
let module = context.create_module("sum");
let builder = context.create_builder();

// type of an exception in C++
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i8_ptr_type = context.ptr_type(AddressSpace::default());
let i32_type = context.i32_type();
let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);

// the personality function used by C++
let personality_function = {
    let name = "__gxx_personality_v0";
    let linkage = Some(Linkage::External);

    module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
};

// make the cleanup landing pad
let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res").unwrap();
  • catch all: An implementation of the C++ catch(...), which catches all exceptions. A catch clause with a NULL pointer value will match anything.
use inkwell::context::Context;
use inkwell::AddressSpace;
use inkwell::module::Linkage;

let context = Context::create();
let module = context.create_module("sum");
let builder = context.create_builder();

// type of an exception in C++
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i8_ptr_type = context.ptr_type(AddressSpace::default());
let i32_type = context.i32_type();
let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);

// the personality function used by C++
let personality_function = {
    let name = "__gxx_personality_v0";
    let linkage = Some(Linkage::External);

    module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
};

// make a null pointer of type i8
let null = i8_ptr_type.const_zero();

// make the catch all landing pad
let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
  • catch a type of exception: Catch a specific type of exception. The example uses C++’s type info.
use inkwell::context::Context;
use inkwell::module::Linkage;
use inkwell::AddressSpace;
use inkwell::values::BasicValue;

let context = Context::create();
let module = context.create_module("sum");
let builder = context.create_builder();

// type of an exception in C++
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i8_ptr_type = context.ptr_type(AddressSpace::default());
let i32_type = context.i32_type();
let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);

// the personality function used by C++
let personality_function = {
    let name = "__gxx_personality_v0";
    let linkage = Some(Linkage::External);

    module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
};

// link in the C++ type info for the `int` type
let type_info_int = module.add_global(i8_ptr_type, Some(AddressSpace::default()), "_ZTIi");
type_info_int.set_linkage(Linkage::External);

// make the catch landing pad
let clause = type_info_int.as_basic_value_enum();
let res = builder.build_landing_pad(exception_type, personality_function, &[clause], false, "res").unwrap();
  • filter: A filter clause encodes that only some types of exceptions are valid at this point. A filter clause is made by constructing a clause from a constant array.
use inkwell::context::Context;
use inkwell::module::Linkage;
use inkwell::values::AnyValue;
use inkwell::AddressSpace;

let context = Context::create();
let module = context.create_module("sum");
let builder = context.create_builder();

// type of an exception in C++
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i8_ptr_type = context.ptr_type(AddressSpace::default());
let i32_type = context.i32_type();
let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);

// the personality function used by C++
let personality_function = {
    let name = "__gxx_personality_v0";
    let linkage = Some(Linkage::External);

    module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
};

// link in the C++ type info for the `int` type
let type_info_int = module.add_global(i8_ptr_type, Some(AddressSpace::default()), "_ZTIi");
type_info_int.set_linkage(Linkage::External);

// make the filter landing pad
let filter_pattern = i8_ptr_type.const_array(&[type_info_int.as_any_value_enum().into_pointer_value()]);
let res = builder.build_landing_pad(exception_type, personality_function, &[filter_pattern.into()], false, "res").unwrap();
source

pub fn build_resume<V: BasicValue<'ctx>>( &self, value: V ) -> Result<InstructionValue<'ctx>, BuilderError>

Resume propagation of an existing (in-flight) exception whose unwinding was interrupted with a landingpad instruction.

This example uses a cleanup landing pad. A cleanup is extra code that needs to be run when unwinding a scope. C++ destructors are a typical example. In a language with reference counting, the cleanup block can decrement the refcount of values in scope.

use inkwell::context::Context;
use inkwell::AddressSpace;
use inkwell::module::Linkage;

let context = Context::create();
let module = context.create_module("sum");
let builder = context.create_builder();

let f32_type = context.f32_type();
let fn_type = f32_type.fn_type(&[], false);

// we will pretend this function can throw an exception
let function = module.add_function("bomb", fn_type, None);
let basic_block = context.append_basic_block(function, "entry");

builder.position_at_end(basic_block);

let pi = f32_type.const_float(::std::f64::consts::PI);

builder.build_return(Some(&pi)).unwrap();

let function2 = module.add_function("wrapper", fn_type, None);
let basic_block2 = context.append_basic_block(function2, "entry");

builder.position_at_end(basic_block2);

let then_block = context.append_basic_block(function2, "then_block");
let catch_block = context.append_basic_block(function2, "catch_block");

let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();

{
    builder.position_at_end(then_block);

    // in the then_block, the `call_site` value is defined and can be used
    let result = call_site.try_as_basic_value().left().unwrap();

    builder.build_return(Some(&result)).unwrap();
}

{
    builder.position_at_end(catch_block);

    // the personality function used by C++
    let personality_function = {
        let name = "__gxx_personality_v0";
        let linkage = Some(Linkage::External);

        module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
    };

    // type of an exception in C++
    #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
    let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
    #[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
    let i8_ptr_type = context.ptr_type(AddressSpace::default());
    let i32_type = context.i32_type();
    let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);

    // make the landing pad; must give a concrete type to the slice
    let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res").unwrap();

    // do cleanup ...

    builder.build_resume(res).unwrap();
}
source

pub unsafe fn build_gep<T: BasicType<'ctx>>( &self, pointee_ty: T, ptr: PointerValue<'ctx>, ordered_indexes: &[IntValue<'ctx>], name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.

source

pub unsafe fn build_in_bounds_gep<T: BasicType<'ctx>>( &self, pointee_ty: T, ptr: PointerValue<'ctx>, ordered_indexes: &[IntValue<'ctx>], name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.

source

pub fn build_struct_gep<T: BasicType<'ctx>>( &self, pointee_ty: T, ptr: PointerValue<'ctx>, index: u32, name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

Builds a GEP instruction on a struct pointer. Returns Err BuilderError::GEPPointee or BuilderError::GEPIndex if input PointerValue doesn’t point to a struct or if index is out of bounds.

§Example
use inkwell::AddressSpace;
use inkwell::context::Context;

let context = Context::create();
let builder = context.create_builder();
let module = context.create_module("struct_gep");
let void_type = context.void_type();
let i32_ty = context.i32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i32_ptr_ty = context.ptr_type(AddressSpace::default());
let field_types = &[i32_ty.into(), i32_ty.into()];
let struct_ty = context.struct_type(field_types, false);
let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default());
let fn_type = void_type.fn_type(&[i32_ptr_ty.into(), struct_ptr_ty.into()], false);
let fn_value = module.add_function("", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");

builder.position_at_end(entry);

let i32_ptr = fn_value.get_first_param().unwrap().into_pointer_value();
let struct_ptr = fn_value.get_last_param().unwrap().into_pointer_value();

assert!(builder.build_struct_gep(i32_ty, i32_ptr, 0, "struct_gep").is_err());
assert!(builder.build_struct_gep(i32_ty, i32_ptr, 10, "struct_gep").is_err());
assert!(builder.build_struct_gep(struct_ty, struct_ptr, 0, "struct_gep").is_ok());
assert!(builder.build_struct_gep(struct_ty, struct_ptr, 1, "struct_gep").is_ok());
assert!(builder.build_struct_gep(struct_ty, struct_ptr, 2, "struct_gep").is_err());
source

pub fn build_ptr_diff<T: BasicType<'ctx>>( &self, pointee_ty: T, lhs_ptr: PointerValue<'ctx>, rhs_ptr: PointerValue<'ctx>, name: &str ) -> Result<IntValue<'ctx>, BuilderError>

Builds an instruction which calculates the difference of two pointers.

§Example
use inkwell::context::Context;
use inkwell::AddressSpace;

// Builds a function which diffs two pointers
let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();
let void_type = context.void_type();
let i32_type = context.i32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i32_ptr_type = context.ptr_type(AddressSpace::default());
let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_ptr_type.into()], false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
let i32_ptr_param1 = fn_value.get_first_param().unwrap().into_pointer_value();
let i32_ptr_param2 = fn_value.get_nth_param(1).unwrap().into_pointer_value();

builder.position_at_end(entry);
builder.build_ptr_diff(i32_ptr_type, i32_ptr_param1, i32_ptr_param2, "diff").unwrap();
builder.build_return(None).unwrap();
source

pub fn build_phi<T: BasicType<'ctx>>( &self, type_: T, name: &str ) -> Result<PhiValue<'ctx>, BuilderError>

source

pub fn build_store<V: BasicValue<'ctx>>( &self, ptr: PointerValue<'ctx>, value: V ) -> Result<InstructionValue<'ctx>, BuilderError>

Builds a store instruction. It allows you to store a value of type T in a pointer to a type T.

§Example
use inkwell::context::Context;
use inkwell::AddressSpace;

// Builds a function which takes an i32 pointer and stores a 7 in it.
let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();
let void_type = context.void_type();
let i32_type = context.i32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i32_ptr_type = context.ptr_type(AddressSpace::default());
let i32_seven = i32_type.const_int(7, false);
let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();

builder.position_at_end(entry);
builder.build_store(i32_ptr_param, i32_seven).unwrap();
builder.build_return(None).unwrap();
source

pub fn build_load<T: BasicType<'ctx>>( &self, pointee_ty: T, ptr: PointerValue<'ctx>, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>

Builds a load2 instruction. It allows you to retrieve a value of type T from a pointer to a type T.

§Example
use inkwell::context::Context;
use inkwell::AddressSpace;

// Builds a function which takes an i32 pointer and returns the pointed at i32.
let context = Context::create();
let module = context.create_module("ret");
let builder = context.create_builder();
let i32_type = context.i32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i32_ptr_type = context.ptr_type(AddressSpace::default());
let fn_type = i32_type.fn_type(&[i32_ptr_type.into()], false);
let fn_value = module.add_function("ret", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();

builder.position_at_end(entry);

let pointee = builder.build_load(i32_type, i32_ptr_param, "load2").unwrap();

builder.build_return(Some(&pointee)).unwrap();
source

pub fn build_alloca<T: BasicType<'ctx>>( &self, ty: T, name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

source

pub fn build_array_alloca<T: BasicType<'ctx>>( &self, ty: T, size: IntValue<'ctx>, name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

source

pub fn build_memcpy( &self, dest: PointerValue<'ctx>, dest_align_bytes: u32, src: PointerValue<'ctx>, src_align_bytes: u32, size: IntValue<'ctx> ) -> Result<PointerValue<'ctx>, BuilderError>

Build a memcpy instruction.

Alignment arguments are specified in bytes, and should always be both a power of 2 and under 2^64.

The final argument should be a pointer-sized integer.

Returns an Err(BuilderError::AlignmentError) if the source or destination alignments are not a power of 2.

TargetData::ptr_sized_int_type_in_context will get you one of those.

source

pub fn build_memmove( &self, dest: PointerValue<'ctx>, dest_align_bytes: u32, src: PointerValue<'ctx>, src_align_bytes: u32, size: IntValue<'ctx> ) -> Result<PointerValue<'ctx>, BuilderError>

Build a memmove instruction.

Alignment arguments are specified in bytes, and should always be both a power of 2 and under 2^64.

The final argument should be a pointer-sized integer.

Returns an Err(BuilderError::AlignmentError) if the source or destination alignments are not a power of 2 under 2^64.

TargetData::ptr_sized_int_type_in_context will get you one of those.

source

pub fn build_memset( &self, dest: PointerValue<'ctx>, dest_align_bytes: u32, val: IntValue<'ctx>, size: IntValue<'ctx> ) -> Result<PointerValue<'ctx>, BuilderError>

Build a memset instruction.

Alignment arguments are specified in bytes, and should always be both a power of 2 and under 2^64.

The final argument should be a pointer-sized integer.

Returns an Err(BuilderError::AlignmentError) if the source alignment is not a power of 2 under 2^64.

TargetData::ptr_sized_int_type_in_context will get you one of those.

source

pub fn build_malloc<T: BasicType<'ctx>>( &self, ty: T, name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

Returns Err(BuilderError::AlignmentError) if the type is unsized.

source

pub fn build_array_malloc<T: BasicType<'ctx>>( &self, ty: T, size: IntValue<'ctx>, name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

Returns Err(BuilderError::AlignmentError) if the type is unsized.

source

pub fn build_free( &self, ptr: PointerValue<'ctx> ) -> Result<InstructionValue<'ctx>, BuilderError>

source

pub fn insert_instruction( &self, instruction: &InstructionValue<'ctx>, name: Option<&str> )

source

pub fn get_insert_block(&self) -> Option<BasicBlock<'ctx>>

source

pub fn build_int_unsigned_div<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_signed_div<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_exact_signed_div<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_unsigned_rem<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_signed_rem<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_s_extend<T: IntMathValue<'ctx>>( &self, int_value: T, int_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_address_space_cast( &self, ptr_val: PointerValue<'ctx>, ptr_type: PointerType<'ctx>, name: &str ) -> Result<PointerValue<'ctx>, BuilderError>

source

pub fn build_bit_cast<T, V>( &self, val: V, ty: T, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>
where T: BasicType<'ctx>, V: BasicValue<'ctx>,

Builds a bitcast instruction. A bitcast reinterprets the bits of one value into a value of another type which has the same bit width.

§Example
use inkwell::AddressSpace;
use inkwell::context::Context;

let context = Context::create();
let module = context.create_module("bc");
let void_type = context.void_type();
let f32_type = context.f32_type();
let i32_type = context.i32_type();
let arg_types = [i32_type.into()];
let fn_type = void_type.fn_type(&arg_types, false);
let fn_value = module.add_function("bc", fn_type, None);
let builder = context.create_builder();
let entry = context.append_basic_block(fn_value, "entry");
let i32_arg = fn_value.get_first_param().unwrap();

builder.position_at_end(entry);

builder.build_bit_cast(i32_arg, f32_type, "i32tof32").unwrap();
builder.build_return(None).unwrap();

assert!(module.verify().is_ok());
source

pub fn build_int_s_extend_or_bit_cast<T: IntMathValue<'ctx>>( &self, int_value: T, int_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_z_extend<T: IntMathValue<'ctx>>( &self, int_value: T, int_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_z_extend_or_bit_cast<T: IntMathValue<'ctx>>( &self, int_value: T, int_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_truncate<T: IntMathValue<'ctx>>( &self, int_value: T, int_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_truncate_or_bit_cast<T: IntMathValue<'ctx>>( &self, int_value: T, int_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_rem<T: FloatMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_to_unsigned_int<T: FloatMathValue<'ctx>>( &self, float: T, int_type: <T::BaseType as FloatMathType<'ctx>>::MathConvType, name: &str ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_float_to_signed_int<T: FloatMathValue<'ctx>>( &self, float: T, int_type: <T::BaseType as FloatMathType<'ctx>>::MathConvType, name: &str ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_unsigned_int_to_float<T: IntMathValue<'ctx>>( &self, int: T, float_type: <T::BaseType as IntMathType<'ctx>>::MathConvType, name: &str ) -> Result<<<T::BaseType as IntMathType<'ctx>>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_signed_int_to_float<T: IntMathValue<'ctx>>( &self, int: T, float_type: <T::BaseType as IntMathType<'ctx>>::MathConvType, name: &str ) -> Result<<<T::BaseType as IntMathType<'ctx>>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_float_trunc<T: FloatMathValue<'ctx>>( &self, float: T, float_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_ext<T: FloatMathValue<'ctx>>( &self, float: T, float_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_cast<T: FloatMathValue<'ctx>>( &self, float: T, float_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_cast<T: IntMathValue<'ctx>>( &self, int: T, int_type: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_cast_sign_flag<T: IntMathValue<'ctx>>( &self, int: T, int_type: T::BaseType, is_signed: bool, name: &str ) -> Result<T, BuilderError>

Like build_int_cast, but respects the signedness of the type being cast to.

source

pub fn build_float_div<T: FloatMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_add<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nsw_add<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nuw_add<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_add<T: FloatMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_xor<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_and<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_or<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_left_shift<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

Builds an IntValue containing the result of a logical left shift instruction.

§Example

A logical left shift is an operation in which an integer value’s bits are shifted left by N number of positions.

assert_eq!(0b0000_0001 << 0, 0b0000_0001);
assert_eq!(0b0000_0001 << 1, 0b0000_0010);
assert_eq!(0b0000_0011 << 2, 0b0000_1100);

In Rust, a function that could do this for 8bit values looks like:

fn left_shift(value: u8, n: u8) -> u8 {
    value << n
}

And in Inkwell, the corresponding function would look roughly like:

use inkwell::context::Context;

// Setup
let context = Context::create();
let module = context.create_module("my_module");
let builder = context.create_builder();
let i8_type = context.i8_type();
let fn_type = i8_type.fn_type(&[i8_type.into(), i8_type.into()], false);

// Function Definition
let function = module.add_function("left_shift", fn_type, None);
let value = function.get_first_param().unwrap().into_int_value();
let n = function.get_nth_param(1).unwrap().into_int_value();
let entry_block = context.append_basic_block(function, "entry");

builder.position_at_end(entry_block);

let shift = builder.build_left_shift(value, n, "left_shift").unwrap(); // value << n

builder.build_return(Some(&shift)).unwrap();
source

pub fn build_right_shift<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, sign_extend: bool, name: &str ) -> Result<T, BuilderError>

Builds an IntValue containing the result of a right shift instruction.

§Example

A right shift is an operation in which an integer value’s bits are shifted right by N number of positions. It may either be logical and have its leftmost N bit(s) filled with zeros or sign extended and filled with ones if the leftmost bit was one.

//fix doc error about overflowing_literals
//rendered rfc: https://github.com/rust-lang/rfcs/blob/master/text/2438-deny-integer-literal-overflow-lint.md
//tracking issue: https://github.com/rust-lang/rust/issues/54502
#![allow(overflowing_literals)]

// Logical Right Shift
assert_eq!(0b1100_0000u8 >> 2, 0b0011_0000);
assert_eq!(0b0000_0010u8 >> 1, 0b0000_0001);
assert_eq!(0b0000_1100u8 >> 2, 0b0000_0011);

// Sign Extended Right Shift
assert_eq!(0b0100_0000i8 >> 2, 0b0001_0000);
assert_eq!(0b1110_0000u8 as i8 >> 1, 0b1111_0000u8 as i8);
assert_eq!(0b1100_0000u8 as i8 >> 2, 0b1111_0000u8 as i8);

In Rust, functions that could do this for 8bit values look like:

fn logical_right_shift(value: u8, n: u8) -> u8 {
    value >> n
}

fn sign_extended_right_shift(value: i8, n: u8) -> i8 {
    value >> n
}

Notice that, in Rust (and most other languages), whether or not a value is sign extended depends wholly on whether or not the type is signed (ie an i8 is a signed 8 bit value). LLVM does not make this distinction for you.

In Inkwell, the corresponding functions would look roughly like:

use inkwell::context::Context;

// Setup
let context = Context::create();
let module = context.create_module("my_module");
let builder = context.create_builder();
let i8_type = context.i8_type();
let fn_type = i8_type.fn_type(&[i8_type.into(), i8_type.into()], false);

// Function Definition
let function = module.add_function("right_shift", fn_type, None);
let value = function.get_first_param().unwrap().into_int_value();
let n = function.get_nth_param(1).unwrap().into_int_value();
let entry_block = context.append_basic_block(function, "entry");

builder.position_at_end(entry_block);

// Whether or not your right shift is sign extended (true) or logical (false) depends
// on the boolean input parameter:
let shift = builder.build_right_shift(value, n, false, "right_shift").unwrap(); // value >> n

builder.build_return(Some(&shift)).unwrap();
source

pub fn build_int_sub<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nsw_sub<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nuw_sub<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_sub<T: FloatMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_mul<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nsw_mul<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nuw_mul<T: IntMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_mul<T: FloatMathValue<'ctx>>( &self, lhs: T, rhs: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_cast<T: BasicType<'ctx>, V: BasicValue<'ctx>>( &self, op: InstructionOpcode, from_value: V, to_type: T, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>

source

pub fn build_pointer_cast<T: PointerMathValue<'ctx>>( &self, from: T, to: T::BaseType, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_compare<T: IntMathValue<'ctx>>( &self, op: IntPredicate, lhs: T, rhs: T, name: &str ) -> Result<<T::BaseType as IntMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_float_compare<T: FloatMathValue<'ctx>>( &self, op: FloatPredicate, lhs: T, rhs: T, name: &str ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_unconditional_branch( &self, destination_block: BasicBlock<'ctx> ) -> Result<InstructionValue<'ctx>, BuilderError>

source

pub fn build_conditional_branch( &self, comparison: IntValue<'ctx>, then_block: BasicBlock<'ctx>, else_block: BasicBlock<'ctx> ) -> Result<InstructionValue<'ctx>, BuilderError>

source

pub fn build_indirect_branch<BV: BasicValue<'ctx>>( &self, address: BV, destinations: &[BasicBlock<'ctx>] ) -> Result<InstructionValue<'ctx>, BuilderError>

source

pub fn build_int_neg<T: IntMathValue<'ctx>>( &self, value: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nsw_neg<T: IntMathValue<'ctx>>( &self, value: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_int_nuw_neg<T: IntMathValue<'ctx>>( &self, value: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_float_neg<T: FloatMathValue<'ctx>>( &self, value: T, name: &str ) -> Result<T, BuilderError>

source

pub fn build_not<T: IntMathValue<'ctx>>( &self, value: T, name: &str ) -> Result<T, BuilderError>

source

pub fn position_at( &self, basic_block: BasicBlock<'ctx>, instruction: &InstructionValue<'ctx> )

Set the position of the builder to after an instruction.

Be sure to call one of the position_* methods or all build_* methods will return Err(BuilderError::UnsetPosition).

source

pub fn position_before(&self, instruction: &InstructionValue<'ctx>)

Set the position of the builder to before an instruction.

Be sure to call one of the position_* methods or all build_* methods will return Err(BuilderError::UnsetPosition).

source

pub fn position_at_end(&self, basic_block: BasicBlock<'ctx>)

Set the position of the builder to the end of a basic block.

Be sure to call one of the position_* methods or all build_* methods will return Err(BuilderError::UnsetPosition).

source

pub fn build_extract_value<AV: AggregateValue<'ctx>>( &self, agg: AV, index: u32, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>

Builds an extract value instruction which extracts a BasicValueEnum from a struct or array.

Returns Err(BuilderError::ExtractOutOfRange) if the provided index is out of bounds of the aggregate value length.

§Example
use inkwell::context::Context;
use inkwell::builder::BuilderError;

let context = Context::create();
let module = context.create_module("av");
let void_type = context.void_type();
let f32_type = context.f32_type();
let i32_type = context.i32_type();
let struct_type = context.struct_type(&[i32_type.into(), f32_type.into()], false);
let array_type = i32_type.array_type(3);
let fn_type = void_type.fn_type(&[], false);
let fn_value = module.add_function("av_fn", fn_type, None);
let builder = context.create_builder();
let entry = context.append_basic_block(fn_value, "entry");

builder.position_at_end(entry);

let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap();

#[cfg(any(
    feature = "llvm4-0",
    feature = "llvm5-0",
    feature = "llvm6-0",
    feature = "llvm7-0",
    feature = "llvm8-0",
    feature = "llvm9-0",
    feature = "llvm10-0",
    feature = "llvm11-0",
    feature = "llvm12-0",
    feature = "llvm13-0",
    feature = "llvm14-0"
))]
let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value();
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value();

let const_int1 = i32_type.const_int(2, false);
let const_int2 = i32_type.const_int(5, false);
let const_int3 = i32_type.const_int(6, false);

assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_ok());
assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_ok());
assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_ok());
assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_err_and(|e| e == BuilderError::ExtractOutOfRange));

assert!(builder.build_extract_value(array, 0, "extract").unwrap().is_int_value());
assert!(builder.build_extract_value(array, 1, "extract").unwrap().is_int_value());
assert!(builder.build_extract_value(array, 2, "extract").unwrap().is_int_value());
assert!(builder.build_extract_value(array, 3, "extract").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
source

pub fn build_insert_value<AV, BV>( &self, agg: AV, value: BV, index: u32, name: &str ) -> Result<AggregateValueEnum<'ctx>, BuilderError>
where AV: AggregateValue<'ctx>, BV: BasicValue<'ctx>,

Builds an insert value instruction which inserts a BasicValue into a struct or array and returns the resulting aggregate value.

Returns Err(BuilderError::ExtractOutOfRange) if the provided index is out of bounds of the aggregate value length.

§Example
use inkwell::context::Context;
use inkwell::builder::BuilderError;

let context = Context::create();
let module = context.create_module("av");
let void_type = context.void_type();
let f32_type = context.f32_type();
let i32_type = context.i32_type();
let struct_type = context.struct_type(&[i32_type.into(), f32_type.into()], false);
let array_type = i32_type.array_type(3);
let fn_type = void_type.fn_type(&[], false);
let fn_value = module.add_function("av_fn", fn_type, None);
let builder = context.create_builder();
let entry = context.append_basic_block(fn_value, "entry");

builder.position_at_end(entry);

let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap();

#[cfg(any(
    feature = "llvm4-0",
    feature = "llvm5-0",
    feature = "llvm6-0",
    feature = "llvm7-0",
    feature = "llvm8-0",
    feature = "llvm9-0",
    feature = "llvm10-0",
    feature = "llvm11-0",
    feature = "llvm12-0",
    feature = "llvm13-0",
    feature = "llvm14-0"
))]
let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value();
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value();

let const_int1 = i32_type.const_int(2, false);
let const_int2 = i32_type.const_int(5, false);
let const_int3 = i32_type.const_int(6, false);

assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_ok());
assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_ok());
assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_ok());
assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
source

pub fn build_extract_element( &self, vector: VectorValue<'ctx>, index: IntValue<'ctx>, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>

Builds an extract element instruction which extracts a BasicValueEnum from a vector.

§Example
use inkwell::context::Context;

let context = Context::create();
let module = context.create_module("av");
let i32_type = context.i32_type();
let i32_zero = i32_type.const_int(0, false);
let vec_type = i32_type.vec_type(2);
let fn_type = i32_type.fn_type(&[vec_type.into()], false);
let fn_value = module.add_function("vec_fn", fn_type, None);
let builder = context.create_builder();
let entry = context.append_basic_block(fn_value, "entry");
let vector_param = fn_value.get_first_param().unwrap().into_vector_value();

builder.position_at_end(entry);

let extracted = builder.build_extract_element(vector_param, i32_zero, "insert").unwrap();

builder.build_return(Some(&extracted)).unwrap();
source

pub fn build_insert_element<V: BasicValue<'ctx>>( &self, vector: VectorValue<'ctx>, element: V, index: IntValue<'ctx>, name: &str ) -> Result<VectorValue<'ctx>, BuilderError>

Builds an insert element instruction which inserts a BasicValue into a vector and returns the resulting vector.

§Example
use inkwell::context::Context;

let context = Context::create();
let module = context.create_module("av");
let void_type = context.void_type();
let i32_type = context.i32_type();
let i32_zero = i32_type.const_int(0, false);
let i32_seven = i32_type.const_int(7, false);
let vec_type = i32_type.vec_type(2);
let fn_type = void_type.fn_type(&[vec_type.into()], false);
let fn_value = module.add_function("vec_fn", fn_type, None);
let builder = context.create_builder();
let entry = context.append_basic_block(fn_value, "entry");
let vector_param = fn_value.get_first_param().unwrap().into_vector_value();

builder.position_at_end(entry);
builder.build_insert_element(vector_param, i32_seven, i32_zero, "insert").unwrap();
builder.build_return(None).unwrap();
source

pub fn build_unreachable(&self) -> Result<InstructionValue<'ctx>, BuilderError>

source

pub fn build_fence( &self, atomic_ordering: AtomicOrdering, num: i32, name: &str ) -> Result<InstructionValue<'ctx>, BuilderError>

source

pub fn build_is_null<T: PointerMathValue<'ctx>>( &self, ptr: T, name: &str ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_is_not_null<T: PointerMathValue<'ctx>>( &self, ptr: T, name: &str ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_int_to_ptr<T: IntMathValue<'ctx>>( &self, int: T, ptr_type: <T::BaseType as IntMathType<'ctx>>::PtrConvType, name: &str ) -> Result<<<T::BaseType as IntMathType<'ctx>>::PtrConvType as PointerMathType<'ctx>>::ValueType, BuilderError>

source

pub fn build_ptr_to_int<T: PointerMathValue<'ctx>>( &self, ptr: T, int_type: <T::BaseType as PointerMathType<'ctx>>::PtrConvType, name: &str ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>

source

pub fn clear_insertion_position(&self)

source

pub fn build_switch( &self, value: IntValue<'ctx>, else_block: BasicBlock<'ctx>, cases: &[(IntValue<'ctx>, BasicBlock<'ctx>)] ) -> Result<InstructionValue<'ctx>, BuilderError>

source

pub fn build_select<BV: BasicValue<'ctx>, IMV: IntMathValue<'ctx>>( &self, condition: IMV, then: BV, else_: BV, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>

source

pub unsafe fn build_global_string( &self, value: &str, name: &str ) -> Result<GlobalValue<'ctx>, BuilderError>

source

pub fn build_global_string_ptr( &self, value: &str, name: &str ) -> Result<GlobalValue<'ctx>, BuilderError>

source

pub fn build_shuffle_vector( &self, left: VectorValue<'ctx>, right: VectorValue<'ctx>, mask: VectorValue<'ctx>, name: &str ) -> Result<VectorValue<'ctx>, BuilderError>

source

pub fn build_va_arg<BT: BasicType<'ctx>>( &self, list: PointerValue<'ctx>, type_: BT, name: &str ) -> Result<BasicValueEnum<'ctx>, BuilderError>

source

pub fn build_atomicrmw( &self, op: AtomicRMWBinOp, ptr: PointerValue<'ctx>, value: IntValue<'ctx>, ordering: AtomicOrdering ) -> Result<IntValue<'ctx>, BuilderError>

Builds an atomicrmw instruction. It allows you to atomically modify memory.

May return of the following errors:

  • Err(BuilderError::BitwidthError) if the bitwidth of the value is not a power of 2 and less than 8
  • Err(BuilderError:PointeeTypeMismatch) if the pointee type does not match the value’s type
§Example
use inkwell::context::Context;
use inkwell::{AddressSpace, AtomicOrdering, AtomicRMWBinOp};
let context = Context::create();
let module = context.create_module("rmw");
let void_type = context.void_type();
let i32_type = context.i32_type();
let i32_seven = i32_type.const_int(7, false);
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i32_ptr_type = context.ptr_type(AddressSpace::default());
let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
let fn_value = module.add_function("rmw", fn_type, None);
let entry = context.append_basic_block(fn_value, "entry");
let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
let builder = context.create_builder();
builder.position_at_end(entry);
builder.build_atomicrmw(AtomicRMWBinOp::Add, i32_ptr_param, i32_seven, AtomicOrdering::Unordered).unwrap();
builder.build_return(None).unwrap();
source

pub fn build_cmpxchg<V: BasicValue<'ctx>>( &self, ptr: PointerValue<'ctx>, cmp: V, new: V, success: AtomicOrdering, failure: AtomicOrdering ) -> Result<StructValue<'ctx>, BuilderError>

Builds a cmpxchg instruction. It allows you to atomically compare and replace memory.

May return one of the following errors:

  • Err(BuilderError::PointeeTypeMismatch) if the pointer does not point to an element of the value type
  • Err(BuilderError::ValueTypeMismatch) if the value to compare and the new values are not of the same type, or if the value does not have a pointer or integer type
  • Err(BuilderError::OrderingError) if the following conditions are not satisfied:
    • Both success and failure orderings are not Monotonic or stronger
    • The failure ordering is stronger than the success ordering
    • The failure ordering is release or acquire release
§Example
use inkwell::context::Context;
use inkwell::{AddressSpace, AtomicOrdering};
let context = Context::create();
let module = context.create_module("cmpxchg");
let void_type = context.void_type();
let i32_type = context.i32_type();
#[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0")))]
let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
#[cfg(any(feature = "llvm15-0", feature = "llvm16-0", feature = "llvm17-0", feature = "llvm18-0"))]
let i32_ptr_type = context.ptr_type(AddressSpace::default());
let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
let fn_value = module.add_function("", fn_type, None);
let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
let i32_seven = i32_type.const_int(7, false);
let i32_eight = i32_type.const_int(8, false);
let entry = context.append_basic_block(fn_value, "entry");
let builder = context.create_builder();
builder.position_at_end(entry);
builder.build_cmpxchg(i32_ptr_param, i32_seven, i32_eight, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic).unwrap();
builder.build_return(None).unwrap();
source

pub fn set_current_debug_location(&self, location: DILocation<'ctx>)

Set the debug info source location of the instruction currently pointed at by the builder

source

pub fn get_current_debug_location(&self) -> Option<DILocation<'ctx>>

Get the debug info source location of the instruction currently pointed at by the builder, if available.

source

pub fn unset_current_debug_location(&self)

Unset the debug info source location of the instruction currently pointed at by the builder. If there isn’t any debug info, this is a no-op.

Trait Implementations§

source§

impl<'ctx> Debug for Builder<'ctx>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Drop for Builder<'_>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'ctx> !Freeze for Builder<'ctx>

§

impl<'ctx> !RefUnwindSafe for Builder<'ctx>

§

impl<'ctx> !Send for Builder<'ctx>

§

impl<'ctx> !Sync for Builder<'ctx>

§

impl<'ctx> Unpin for Builder<'ctx>

§

impl<'ctx> UnwindSafe for Builder<'ctx>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.