diff --git a/Cargo.toml b/Cargo.toml index 089320ab43d..86bb616e461 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ llvm13-0 = ["llvm-sys-130"] llvm14-0 = ["llvm-sys-140"] llvm15-0 = ["llvm-sys-150"] llvm16-0 = ["llvm-sys-160"] -# Don't link aganist LLVM libraries. This is useful if another dependency is +# Don't link against LLVM libraries. This is useful if another dependency is # installing LLVM. See llvm-sys for more details. We can't enable a single # `no-llvm-linking` feature across the board of llvm versions, as it'll cause # cargo to try and download and compile them all. See @@ -140,6 +140,7 @@ llvm-sys-160 = { package = "llvm-sys", version = "160.1.0", optional = true } once_cell = "1.16" parking_lot = "0.12" static-alloc = { version = "0.2", optional = true } +thiserror = "1.0.48" [dev-dependencies] regex = "1" diff --git a/README.md b/README.md index c6899f0dc84..2158ba70142 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,12 @@ Documentation is automatically [deployed here](https://thedan64.github.io/inkwel ### Tari's [llvm-sys example](https://gitlab.com/taricorp/llvm-sys.rs/blob/6411edb2fed1a805b7ec5029afc9c3ae1cf6c842/examples/jit-function.rs) written in safe code1 with Inkwell: ```rust -use inkwell::OptimizationLevel; use inkwell::builder::Builder; use inkwell::context::Context; use inkwell::execution_engine::{ExecutionEngine, JitFunction}; use inkwell::module::Module; +use inkwell::OptimizationLevel; + use std::error::Error; /// Convenience type alias for the `sum` function. @@ -89,16 +90,15 @@ impl<'ctx> CodeGen<'ctx> { let y = function.get_nth_param(1)?.into_int_value(); let z = function.get_nth_param(2)?.into_int_value(); - let sum = self.builder.build_int_add(x, y, "sum"); - let sum = self.builder.build_int_add(sum, z, "sum"); + let sum = self.builder.build_int_add(x, y, "sum").unwrap(); + let sum = self.builder.build_int_add(sum, z, "sum").unwrap(); - self.builder.build_return(Some(&sum)); + self.builder.build_return(Some(&sum)).unwrap(); unsafe { self.execution_engine.get_function("sum").ok() } } } - fn main() -> Result<(), Box> { let context = Context::create(); let module = context.create_module("sum"); diff --git a/examples/jit.rs b/examples/jit.rs index dfdef206ea9..eb220a688e5 100644 --- a/examples/jit.rs +++ b/examples/jit.rs @@ -32,10 +32,10 @@ impl<'ctx> CodeGen<'ctx> { let y = function.get_nth_param(1)?.into_int_value(); let z = function.get_nth_param(2)?.into_int_value(); - let sum = self.builder.build_int_add(x, y, "sum"); - let sum = self.builder.build_int_add(sum, z, "sum"); + let sum = self.builder.build_int_add(x, y, "sum").unwrap(); + let sum = self.builder.build_int_add(sum, z, "sum").unwrap(); - self.builder.build_return(Some(&sum)); + self.builder.build_return(Some(&sum)).unwrap(); unsafe { self.execution_engine.get_function("sum").ok() } } diff --git a/examples/kaleidoscope/implementation_typed_pointers.rs b/examples/kaleidoscope/implementation_typed_pointers.rs index 3713f57def6..60c6b0b5046 100644 --- a/examples/kaleidoscope/implementation_typed_pointers.rs +++ b/examples/kaleidoscope/implementation_typed_pointers.rs @@ -855,7 +855,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { None => builder.position_at_end(entry), } - builder.build_alloca(self.context.f64_type(), name) + builder.build_alloca(self.context.f64_type(), name).unwrap() } /// Compiles the specified `Expr` into an LLVM `FloatValue`. @@ -864,7 +864,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { Expr::Number(nb) => Ok(self.context.f64_type().const_float(nb)), Expr::Variable(ref name) => match self.variables.get(name.as_str()) { - Some(var) => Ok(self.builder.build_load(*var, name.as_str()).into_float_value()), + Some(var) => Ok(self.builder.build_load(*var, name.as_str()).unwrap().into_float_value()), None => Err("Could not find a matching variable."), }, @@ -884,7 +884,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { let alloca = self.create_entry_block_alloca(var_name); - self.builder.build_store(alloca, initial_val); + self.builder.build_store(alloca, initial_val).unwrap(); if let Some(old_binding) = self.variables.remove(var_name) { old_bindings.push(old_binding); @@ -909,18 +909,18 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { ref right, } => { if op == '=' { - // handle assignement + // handle assignment let var_name = match *left.borrow() { Expr::Variable(ref var_name) => var_name, _ => { - return Err("Expected variable as left-hand operator of assignement."); + return Err("Expected variable as left-hand operator of assignment."); }, }; let var_val = self.compile_expr(right)?; let var = self.variables.get(var_name.as_str()).ok_or("Undefined variable.")?; - self.builder.build_store(*var, var_val); + self.builder.build_store(*var, var_val).unwrap(); Ok(var_val) } else { @@ -928,25 +928,29 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { let rhs = self.compile_expr(right)?; match op { - '+' => Ok(self.builder.build_float_add(lhs, rhs, "tmpadd")), - '-' => Ok(self.builder.build_float_sub(lhs, rhs, "tmpsub")), - '*' => Ok(self.builder.build_float_mul(lhs, rhs, "tmpmul")), - '/' => Ok(self.builder.build_float_div(lhs, rhs, "tmpdiv")), + '+' => Ok(self.builder.build_float_add(lhs, rhs, "tmpadd").unwrap()), + '-' => Ok(self.builder.build_float_sub(lhs, rhs, "tmpsub").unwrap()), + '*' => Ok(self.builder.build_float_mul(lhs, rhs, "tmpmul").unwrap()), + '/' => Ok(self.builder.build_float_div(lhs, rhs, "tmpdiv").unwrap()), '<' => Ok({ let cmp = self .builder - .build_float_compare(FloatPredicate::ULT, lhs, rhs, "tmpcmp"); + .build_float_compare(FloatPredicate::ULT, lhs, rhs, "tmpcmp") + .unwrap(); self.builder .build_unsigned_int_to_float(cmp, self.context.f64_type(), "tmpbool") + .unwrap() }), '>' => Ok({ let cmp = self .builder - .build_float_compare(FloatPredicate::ULT, rhs, lhs, "tmpcmp"); + .build_float_compare(FloatPredicate::ULT, rhs, lhs, "tmpcmp") + .unwrap(); self.builder .build_unsigned_int_to_float(cmp, self.context.f64_type(), "tmpbool") + .unwrap() }), custom => { @@ -959,6 +963,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { match self .builder .build_call(fun, &[lhs.into(), rhs.into()], "tmpbin") + .unwrap() .try_as_basic_value() .left() { @@ -988,6 +993,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { match self .builder .build_call(fun, argsv.as_slice(), "tmp") + .unwrap() .try_as_basic_value() .left() { @@ -1010,33 +1016,34 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { let cond = self.compile_expr(cond)?; let cond = self .builder - .build_float_compare(FloatPredicate::ONE, cond, zero_const, "ifcond"); + .build_float_compare(FloatPredicate::ONE, cond, zero_const, "ifcond") + .unwrap(); // build branch let then_bb = self.context.append_basic_block(parent, "then"); let else_bb = self.context.append_basic_block(parent, "else"); let cont_bb = self.context.append_basic_block(parent, "ifcont"); - self.builder.build_conditional_branch(cond, then_bb, else_bb); + self.builder.build_conditional_branch(cond, then_bb, else_bb).unwrap(); // build then block self.builder.position_at_end(then_bb); let then_val = self.compile_expr(consequence)?; - self.builder.build_unconditional_branch(cont_bb); + self.builder.build_unconditional_branch(cont_bb).unwrap(); let then_bb = self.builder.get_insert_block().unwrap(); // build else block self.builder.position_at_end(else_bb); let else_val = self.compile_expr(alternative)?; - self.builder.build_unconditional_branch(cont_bb); + self.builder.build_unconditional_branch(cont_bb).unwrap(); let else_bb = self.builder.get_insert_block().unwrap(); // emit merge block self.builder.position_at_end(cont_bb); - let phi = self.builder.build_phi(self.context.f64_type(), "iftmp"); + let phi = self.builder.build_phi(self.context.f64_type(), "iftmp").unwrap(); phi.add_incoming(&[(&then_val, then_bb), (&else_val, else_bb)]); @@ -1055,12 +1062,12 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { let start_alloca = self.create_entry_block_alloca(var_name); let start = self.compile_expr(start)?; - self.builder.build_store(start_alloca, start); + self.builder.build_store(start_alloca, start).unwrap(); // go from current block to loop block let loop_bb = self.context.append_basic_block(parent, "loop"); - self.builder.build_unconditional_branch(loop_bb); + self.builder.build_unconditional_branch(loop_bb).unwrap(); self.builder.position_at_end(loop_bb); let old_val = self.variables.remove(var_name.as_str()); @@ -1079,22 +1086,28 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { // compile end condition let end_cond = self.compile_expr(end)?; - let curr_var = self.builder.build_load(start_alloca, var_name); + let curr_var = self.builder.build_load(start_alloca, var_name).unwrap(); let next_var = self .builder - .build_float_add(curr_var.into_float_value(), step, "nextvar"); + .build_float_add(curr_var.into_float_value(), step, "nextvar") + .unwrap(); - self.builder.build_store(start_alloca, next_var); + self.builder.build_store(start_alloca, next_var).unwrap(); - let end_cond = self.builder.build_float_compare( - FloatPredicate::ONE, - end_cond, - self.context.f64_type().const_float(0.0), - "loopcond", - ); + let end_cond = self + .builder + .build_float_compare( + FloatPredicate::ONE, + end_cond, + self.context.f64_type().const_float(0.0), + "loopcond", + ) + .unwrap(); let after_bb = self.context.append_basic_block(parent, "afterloop"); - self.builder.build_conditional_branch(end_cond, loop_bb, after_bb); + self.builder + .build_conditional_branch(end_cond, loop_bb, after_bb) + .unwrap(); self.builder.position_at_end(after_bb); self.variables.remove(var_name); @@ -1153,7 +1166,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { let arg_name = proto.args[i].as_str(); let alloca = self.create_entry_block_alloca(arg_name); - self.builder.build_store(alloca, arg); + self.builder.build_store(alloca, arg).unwrap(); self.variables.insert(proto.args[i].clone(), alloca); } @@ -1161,7 +1174,7 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { // compile body let body = self.compile_expr(self.function.body.as_ref().unwrap())?; - self.builder.build_return(Some(&body)); + self.builder.build_return(Some(&body)).unwrap(); // return the whole thing after verification and optimization if function.verify(true) { diff --git a/src/basic_block.rs b/src/basic_block.rs index 83ca8b6eb9f..231169a8dbb 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -76,7 +76,7 @@ impl<'ctx> BasicBlock<'ctx> { unsafe { FunctionValue::new(LLVMGetBasicBlockParent(self.basic_block)) } } - /// Gets the `BasicBlock` preceeding the current one, in its own scope, if any. + /// Gets the `BasicBlock` preceding the current one, in its own scope, if any. /// /// # Example /// ```no_run @@ -295,9 +295,9 @@ impl<'ctx> BasicBlock<'ctx> { /// let entry = context.append_basic_block(fn_value, "entry"); /// builder.position_at_end(entry); /// - /// let var = builder.build_alloca(i32_type, "some_number"); - /// builder.build_store(var, i32_type.const_int(1 as u64, false)); - /// builder.build_return(None); + /// let var = builder.build_alloca(i32_type, "some_number").unwrap(); + /// builder.build_store(var, i32_type.const_int(1 as u64, false)).unwrap(); + /// builder.build_return(None).unwrap(); /// /// let block = fn_value.get_first_basic_block().unwrap(); /// let some_number = block.get_instruction_with_name("some_number"); @@ -494,7 +494,7 @@ impl<'ctx> BasicBlock<'ctx> { /// let bb1 = context.append_basic_block(fn_val, "bb1"); /// let bb2 = context.append_basic_block(fn_val, "bb2"); /// builder.position_at_end(entry); - /// let branch_inst = builder.build_unconditional_branch(bb1); + /// let branch_inst = builder.build_unconditional_branch(bb1).unwrap(); /// /// bb1.replace_all_uses_with(&bb2); /// diff --git a/src/builder.rs b/src/builder.rs index a34028a7487..da47b4afcd1 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -33,6 +33,7 @@ use llvm_sys::core::{ use llvm_sys::core::{LLVMBuildIntCast2, LLVMBuildMemCpy, LLVMBuildMemMove, LLVMBuildMemSet}; use llvm_sys::prelude::{LLVMBuilderRef, LLVMValueRef}; +use thiserror::Error; use crate::basic_block::BasicBlock; #[llvm_versions(7.0..=8.0)] @@ -51,11 +52,47 @@ use crate::values::{ use crate::{AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate}; +use std::cell::Cell; use std::marker::PhantomData; +#[derive(Debug, PartialEq, Clone, Copy)] +enum PositionState { + NotSet, + Set, +} + +/// Errors that can be generated by the Builder. All `build_*` methods return a `Result<_, BuilderError>`, which must be handled. +#[derive(Error, Debug, PartialEq, Eq)] +pub enum BuilderError { + #[error("Builder position is not set")] + UnsetPosition, + #[error("GEP error: does not point to a struct or index is out of bounds")] + GEPError, + #[error("Alignment error")] + AlignmentError(&'static str), + #[error("Aggregate extract index out of range")] + ExtractOutOfRange, + #[error("Bitwidth of a value is incorrect")] + BitwidthError(&'static str), + #[error("Pointee type does not match the value's type")] + PointeeTypeMismatch(&'static str), + #[error("Values do not have the same type")] + ValueTypeMismatch(&'static str), + #[error("Ordering error or mismatch")] + OrderingError(&'static str), + #[error("GEP pointee is not a struct")] + GEPPointee, + #[error("GEP index out of range")] + GEPIndex, +} + #[derive(Debug)] +/// 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. pub struct Builder<'ctx> { builder: LLVMBuilderRef, + positioned: Cell, _marker: PhantomData<&'ctx ()>, } @@ -67,6 +104,7 @@ impl<'ctx> Builder<'ctx> { debug_assert!(!builder.is_null()); Builder { + positioned: Cell::from(PositionState::NotSet), builder, _marker: PhantomData, } @@ -99,9 +137,12 @@ impl<'ctx> Builder<'ctx> { /// let i32_arg = fn_value.get_first_param().unwrap(); /// /// builder.position_at_end(entry); - /// builder.build_return(Some(&i32_arg)); + /// builder.build_return(Some(&i32_arg)).unwrap(); /// ``` - pub fn build_return(&self, value: Option<&dyn BasicValue<'ctx>>) -> InstructionValue<'ctx> { + pub fn build_return(&self, value: Option<&dyn BasicValue<'ctx>>) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let value = unsafe { value.map_or_else( || LLVMBuildRetVoid(self.builder), @@ -109,7 +150,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { InstructionValue::new(value) } + unsafe { Ok(InstructionValue::new(value)) } } /// Builds a function return instruction for a return type which is an aggregate type (ie structs and arrays). @@ -133,13 +174,19 @@ impl<'ctx> Builder<'ctx> { /// let entry = context.append_basic_block(fn_value, "entry"); /// /// builder.position_at_end(entry); - /// builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]); + /// builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]).unwrap(); /// ``` - pub fn build_aggregate_return(&self, values: &[BasicValueEnum<'ctx>]) -> InstructionValue<'ctx> { + pub fn build_aggregate_return( + &self, + values: &[BasicValueEnum<'ctx>], + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let mut args: Vec = values.iter().map(|val| val.as_value_ref()).collect(); let value = unsafe { LLVMBuildAggregateRet(self.builder, args.as_mut_ptr(), args.len() as u32) }; - unsafe { InstructionValue::new(value) } + unsafe { Ok(InstructionValue::new(value)) } } /// Builds a function call instruction. @@ -166,18 +213,26 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call") + /// 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)); + /// builder.build_return(Some(&ret_val)).unwrap(); /// ``` #[llvm_versions(4.0..=14.0)] - pub fn build_call(&self, function: F, args: &[BasicMetadataValueEnum<'ctx>], name: &str) -> CallSiteValue<'ctx> + pub fn build_call( + &self, + function: F, + args: &[BasicMetadataValueEnum<'ctx>], + name: &str, + ) -> Result, BuilderError> where F: Into>, { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let callable_value = function.into(); let fn_val_ref = callable_value.as_value_ref(); @@ -197,7 +252,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { CallSiteValue::new(value) } + unsafe { Ok(CallSiteValue::new(value)) } } /// Builds a function call instruction. Alias for [Builder::build_direct_call]. @@ -207,7 +262,10 @@ impl<'ctx> Builder<'ctx> { function: FunctionValue<'ctx>, args: &[BasicMetadataValueEnum<'ctx>], name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } self.build_direct_call(function, args, name) } @@ -232,12 +290,12 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call") + /// 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)); + /// builder.build_return(Some(&ret_val)).unwrap(); /// ``` #[llvm_versions(15.0..=latest)] pub fn build_direct_call( @@ -245,7 +303,10 @@ impl<'ctx> Builder<'ctx> { function: FunctionValue<'ctx>, args: &[BasicMetadataValueEnum<'ctx>], name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } self.build_call_help(function.get_type(), function.as_value_ref(), args, name) } @@ -271,12 +332,12 @@ impl<'ctx> Builder<'ctx> { /// 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") + /// 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)); + /// builder.build_return(Some(&ret_val)).unwrap(); /// ``` /// #[llvm_versions(15.0..=latest)] @@ -286,7 +347,10 @@ impl<'ctx> Builder<'ctx> { function_pointer: PointerValue<'ctx>, args: &[BasicMetadataValueEnum<'ctx>], name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } self.build_call_help(function_type, function_pointer.as_value_ref(), args, name) } @@ -297,7 +361,10 @@ impl<'ctx> Builder<'ctx> { fn_val_ref: LLVMValueRef, args: &[BasicMetadataValueEnum<'ctx>], name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } // LLVM gets upset when void return calls are named because they don't return anything let name = match function_type.get_return_type() { None => "", @@ -320,7 +387,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { CallSiteValue::new(value) } + unsafe { Ok(CallSiteValue::new(value)) } } /// An invoke is similar to a normal function call, but used to @@ -358,7 +425,7 @@ impl<'ctx> Builder<'ctx> { /// /// let pi = f32_type.const_float(::std::f64::consts::PI); /// - /// builder.build_return(Some(&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"); @@ -368,7 +435,7 @@ impl<'ctx> Builder<'ctx> { /// 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"); + /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap(); /// /// { /// builder.position_at_end(then_block); @@ -376,7 +443,7 @@ impl<'ctx> Builder<'ctx> { /// // 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)); + /// builder.build_return(Some(&result)).unwrap(); /// } /// /// { @@ -396,10 +463,10 @@ impl<'ctx> Builder<'ctx> { /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); /// /// let null = i8_ptr_type.const_zero(); - /// let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res"); + /// 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())); + /// builder.build_return(Some(&f32_type.const_zero())).unwrap(); /// } /// ``` #[llvm_versions(4.0..=14.0)] @@ -410,10 +477,13 @@ impl<'ctx> Builder<'ctx> { then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str, - ) -> CallSiteValue<'ctx> + ) -> Result, BuilderError> where F: Into>, { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let callable_value: CallableValue<'ctx> = function.into(); let fn_val_ref = callable_value.as_value_ref(); @@ -435,7 +505,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { CallSiteValue::new(value) } + Ok(unsafe { CallSiteValue::new(value) }) } /// An invoke is similar to a normal function call, but used to @@ -473,7 +543,7 @@ impl<'ctx> Builder<'ctx> { /// /// let pi = f32_type.const_float(::std::f64::consts::PI); /// - /// builder.build_return(Some(&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"); @@ -483,7 +553,7 @@ impl<'ctx> Builder<'ctx> { /// 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"); + /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap(); /// /// { /// builder.position_at_end(then_block); @@ -491,7 +561,7 @@ impl<'ctx> Builder<'ctx> { /// // 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)); + /// builder.build_return(Some(&result)).unwrap(); /// } /// /// { @@ -511,10 +581,10 @@ impl<'ctx> Builder<'ctx> { /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); /// /// let null = i8_ptr_type.const_zero(); - /// let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res"); + /// 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())); + /// builder.build_return(Some(&f32_type.const_zero())).unwrap(); /// } /// ``` #[llvm_versions(15.0..=latest)] @@ -525,7 +595,10 @@ impl<'ctx> Builder<'ctx> { then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } self.build_direct_invoke(function, args, then_block, catch_block, name) } @@ -537,7 +610,10 @@ impl<'ctx> Builder<'ctx> { then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } self.build_invoke_help( function.get_type(), function.as_value_ref(), @@ -557,7 +633,10 @@ impl<'ctx> Builder<'ctx> { then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } self.build_invoke_help( function_type, function_pointer.as_value_ref(), @@ -577,7 +656,10 @@ impl<'ctx> Builder<'ctx> { then_block: BasicBlock<'ctx>, catch_block: BasicBlock<'ctx>, name: &str, - ) -> CallSiteValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let fn_ty_ref = fn_ty.as_type_ref(); // LLVM gets upset when void return calls are named because they don't return anything @@ -599,7 +681,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { CallSiteValue::new(value) } + unsafe { Ok(CallSiteValue::new(value)) } } /// Landing pads are places where control flow jumps to if a [`Builder::build_invoke`] triggered an exception. @@ -638,7 +720,7 @@ impl<'ctx> Builder<'ctx> { /// }; /// /// // make the cleanup landing pad - /// let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res"); + /// 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. @@ -670,7 +752,7 @@ impl<'ctx> Builder<'ctx> { /// 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"); + /// 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. @@ -704,7 +786,7 @@ impl<'ctx> Builder<'ctx> { /// /// // 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"); + /// 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 @@ -739,7 +821,7 @@ impl<'ctx> Builder<'ctx> { /// /// // 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"); + /// let res = builder.build_landing_pad(exception_type, personality_function, &[filter_pattern.into()], false, "res").unwrap(); /// ``` pub fn build_landing_pad( &self, @@ -748,10 +830,13 @@ impl<'ctx> Builder<'ctx> { clauses: &[BasicValueEnum<'ctx>], is_cleanup: bool, name: &str, - ) -> BasicValueEnum<'ctx> + ) -> Result, BuilderError> where T: BasicType<'ctx>, { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let num_clauses = clauses.len() as u32; @@ -775,7 +860,7 @@ impl<'ctx> Builder<'ctx> { LLVMSetCleanup(value, is_cleanup as _); }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } /// Resume propagation of an existing (in-flight) exception whose unwinding was interrupted with a landingpad instruction. @@ -804,7 +889,7 @@ impl<'ctx> Builder<'ctx> { /// /// let pi = f32_type.const_float(::std::f64::consts::PI); /// - /// builder.build_return(Some(&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"); @@ -814,7 +899,7 @@ impl<'ctx> Builder<'ctx> { /// 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"); + /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap(); /// /// { /// builder.position_at_end(then_block); @@ -822,7 +907,7 @@ impl<'ctx> Builder<'ctx> { /// // 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)); + /// builder.build_return(Some(&result)).unwrap(); /// } /// /// { @@ -842,17 +927,20 @@ impl<'ctx> Builder<'ctx> { /// 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"); + /// let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res").unwrap(); /// /// // do cleanup ... /// - /// builder.build_resume(res); + /// builder.build_resume(res).unwrap(); /// } /// ``` - pub fn build_resume>(&self, value: V) -> InstructionValue<'ctx> { + pub fn build_resume>(&self, value: V) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let val = unsafe { LLVMBuildResume(self.builder, value.as_value_ref()) }; - unsafe { InstructionValue::new(val) } + unsafe { Ok(InstructionValue::new(val)) } } // REVIEW: Doesn't GEP work on array too? @@ -863,7 +951,10 @@ impl<'ctx> Builder<'ctx> { ptr: PointerValue<'ctx>, ordered_indexes: &[IntValue<'ctx>], name: &str, - ) -> PointerValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); @@ -876,7 +967,7 @@ impl<'ctx> Builder<'ctx> { c_string.as_ptr(), ); - PointerValue::new(value) + Ok(PointerValue::new(value)) } // REVIEW: Doesn't GEP work on array too? @@ -888,7 +979,10 @@ impl<'ctx> Builder<'ctx> { ptr: PointerValue<'ctx>, ordered_indexes: &[IntValue<'ctx>], name: &str, - ) -> PointerValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); @@ -902,7 +996,7 @@ impl<'ctx> Builder<'ctx> { c_string.as_ptr(), ); - PointerValue::new(value) + Ok(PointerValue::new(value)) } // REVIEW: Doesn't GEP work on array too? @@ -914,7 +1008,10 @@ impl<'ctx> Builder<'ctx> { ptr: PointerValue<'ctx>, ordered_indexes: &[IntValue<'ctx>], name: &str, - ) -> PointerValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); @@ -927,7 +1024,7 @@ impl<'ctx> Builder<'ctx> { c_string.as_ptr(), ); - PointerValue::new(value) + Ok(PointerValue::new(value)) } // REVIEW: Doesn't GEP work on array too? @@ -940,7 +1037,10 @@ impl<'ctx> Builder<'ctx> { ptr: PointerValue<'ctx>, ordered_indexes: &[IntValue<'ctx>], name: &str, - ) -> PointerValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); @@ -954,10 +1054,10 @@ impl<'ctx> Builder<'ctx> { c_string.as_ptr(), ); - PointerValue::new(value) + Ok(PointerValue::new(value)) } - /// Builds a GEP instruction on a struct pointer. Returns `Err(())` if input `PointerValue` doesn't + /// Builds a GEP instruction on a struct pointer. Returns `Err(BuilderError::GEPError)` if input `PointerValue` doesn't /// point to a struct or if index is out of bounds. /// /// # Example @@ -991,18 +1091,26 @@ impl<'ctx> Builder<'ctx> { /// assert!(builder.build_struct_gep(struct_ptr, 2, "struct_gep").is_err()); /// ``` #[llvm_versions(4.0..=14.0)] - pub fn build_struct_gep(&self, ptr: PointerValue<'ctx>, index: u32, name: &str) -> Result, ()> { + pub fn build_struct_gep( + &self, + ptr: PointerValue<'ctx>, + index: u32, + name: &str, + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let ptr_ty = ptr.get_type(); let pointee_ty = ptr_ty.get_element_type(); if !pointee_ty.is_struct_type() { - return Err(()); + return Err(BuilderError::GEPError); } let struct_ty = pointee_ty.into_struct_type(); if index >= struct_ty.count_fields() { - return Err(()); + return Err(BuilderError::GEPError); } let c_string = to_c_str(name); @@ -1012,7 +1120,7 @@ impl<'ctx> Builder<'ctx> { unsafe { Ok(PointerValue::new(value)) } } - /// Builds a GEP instruction on a struct pointer. Returns `Err(())` if input `PointerValue` doesn't + /// 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 @@ -1052,17 +1160,20 @@ impl<'ctx> Builder<'ctx> { ptr: PointerValue<'ctx>, index: u32, name: &str, - ) -> Result, ()> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let pointee_ty = pointee_ty.as_any_type_enum(); if !pointee_ty.is_struct_type() { - return Err(()); + return Err(BuilderError::GEPPointee); } let struct_ty = pointee_ty.into_struct_type(); if index >= struct_ty.count_fields() { - return Err(()); + return Err(BuilderError::GEPIndex); } let c_string = to_c_str(name); @@ -1102,8 +1213,8 @@ impl<'ctx> Builder<'ctx> { /// 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_param1, i32_ptr_param2, "diff"); - /// builder.build_return(None); + /// builder.build_ptr_diff(i32_ptr_param1, i32_ptr_param2, "diff").unwrap(); + /// builder.build_return(None).unwrap(); /// ``` #[llvm_versions(4.0..=14.0)] pub fn build_ptr_diff( @@ -1111,7 +1222,10 @@ impl<'ctx> Builder<'ctx> { lhs_ptr: PointerValue<'ctx>, rhs_ptr: PointerValue<'ctx>, name: &str, - ) -> IntValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildPtrDiff( @@ -1122,7 +1236,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { IntValue::new(value) } + unsafe { Ok(IntValue::new(value)) } } /// Builds an instruction which calculates the difference of two pointers. @@ -1147,8 +1261,8 @@ impl<'ctx> Builder<'ctx> { /// 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"); - /// builder.build_return(None); + /// builder.build_ptr_diff(i32_ptr_type, i32_ptr_param1, i32_ptr_param2, "diff").unwrap(); + /// builder.build_return(None).unwrap(); /// ``` #[llvm_versions(15.0..=latest)] pub fn build_ptr_diff>( @@ -1157,7 +1271,10 @@ impl<'ctx> Builder<'ctx> { lhs_ptr: PointerValue<'ctx>, rhs_ptr: PointerValue<'ctx>, name: &str, - ) -> IntValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -1170,7 +1287,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { IntValue::new(value) } + unsafe { Ok(IntValue::new(value)) } } // SubTypes: Maybe this should return PhiValue? That way we could force incoming values to be of T::Value? @@ -1178,11 +1295,14 @@ impl<'ctx> Builder<'ctx> { // tricky with VoidType since it has no instance value? // TODOC: Phi Instruction(s) must be first instruction(s) in a BasicBlock. // REVIEW: Not sure if we can enforce the above somehow via types. - pub fn build_phi>(&self, type_: T, name: &str) -> PhiValue<'ctx> { + pub fn build_phi>(&self, type_: T, name: &str) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildPhi(self.builder, type_.as_type_ref(), c_string.as_ptr()) }; - unsafe { PhiValue::new(value) } + unsafe { Ok(PhiValue::new(value)) } } /// Builds a store instruction. It allows you to store a value of type `T` in a pointer to a type `T`. @@ -1207,13 +1327,20 @@ impl<'ctx> Builder<'ctx> { /// 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); - /// builder.build_return(None); + /// builder.build_store(i32_ptr_param, i32_seven).unwrap(); + /// builder.build_return(None).unwrap(); /// ``` - pub fn build_store>(&self, ptr: PointerValue<'ctx>, value: V) -> InstructionValue<'ctx> { + pub fn build_store>( + &self, + ptr: PointerValue<'ctx>, + value: V, + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let value = unsafe { LLVMBuildStore(self.builder, value.as_value_ref(), ptr.as_value_ref()) }; - unsafe { InstructionValue::new(value) } + unsafe { Ok(InstructionValue::new(value)) } } /// Builds a load instruction. It allows you to retrieve a value of type `T` from a pointer to a type `T`. @@ -1237,17 +1364,20 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// let pointee = builder.build_load(i32_ptr_param, "load"); + /// let pointee = builder.build_load(i32_ptr_param, "load").unwrap(); /// - /// builder.build_return(Some(&pointee)); + /// builder.build_return(Some(&pointee)).unwrap(); /// ``` #[llvm_versions(4.0..=14.0)] - pub fn build_load(&self, ptr: PointerValue<'ctx>, name: &str) -> BasicValueEnum<'ctx> { + pub fn build_load(&self, ptr: PointerValue<'ctx>, name: &str) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildLoad(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } /// Builds a load2 instruction. It allows you to retrieve a value of type `T` from a pointer to a type `T`. @@ -1271,9 +1401,9 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// let pointee = builder.build_load(i32_type, i32_ptr_param, "load2"); + /// let pointee = builder.build_load(i32_type, i32_ptr_param, "load2").unwrap(); /// - /// builder.build_return(Some(&pointee)); + /// builder.build_return(Some(&pointee)).unwrap(); /// ``` #[llvm_versions(15.0..=latest)] pub fn build_load>( @@ -1281,7 +1411,10 @@ impl<'ctx> Builder<'ctx> { pointee_ty: T, ptr: PointerValue<'ctx>, name: &str, - ) -> BasicValueEnum<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -1293,15 +1426,18 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } // TODOC: Stack allocation - pub fn build_alloca>(&self, ty: T, name: &str) -> PointerValue<'ctx> { + pub fn build_alloca>(&self, ty: T, name: &str) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildAlloca(self.builder, ty.as_type_ref(), c_string.as_ptr()) }; - unsafe { PointerValue::new(value) } + unsafe { Ok(PointerValue::new(value)) } } // TODOC: Stack allocation @@ -1310,12 +1446,15 @@ impl<'ctx> Builder<'ctx> { ty: T, size: IntValue<'ctx>, name: &str, - ) -> PointerValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildArrayAlloca(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr()) }; - unsafe { PointerValue::new(value) } + unsafe { Ok(PointerValue::new(value)) } } /// Build a [memcpy](https://llvm.org/docs/LangRef.html#llvm-memcpy-intrinsic) instruction. @@ -1324,6 +1463,8 @@ impl<'ctx> Builder<'ctx> { /// 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`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those. #[llvm_versions(8.0..=latest)] @@ -1334,13 +1475,20 @@ impl<'ctx> Builder<'ctx> { src: PointerValue<'ctx>, src_align_bytes: u32, size: IntValue<'ctx>, - ) -> Result, &'static str> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } if !is_alignment_ok(src_align_bytes) { - return Err("The src_align_bytes argument to build_memcpy was not a power of 2."); + return Err(BuilderError::AlignmentError( + "The src_align_bytes argument to build_memcpy was not a power of 2.", + )); } if !is_alignment_ok(dest_align_bytes) { - return Err("The dest_align_bytes argument to build_memcpy was not a power of 2."); + return Err(BuilderError::AlignmentError( + "The dest_align_bytes argument to build_memcpy was not a power of 2.", + )); } let value = unsafe { @@ -1363,6 +1511,8 @@ impl<'ctx> Builder<'ctx> { /// 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`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those. #[llvm_versions(8.0..=latest)] @@ -1373,13 +1523,20 @@ impl<'ctx> Builder<'ctx> { src: PointerValue<'ctx>, src_align_bytes: u32, size: IntValue<'ctx>, - ) -> Result, &'static str> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } if !is_alignment_ok(src_align_bytes) { - return Err("The src_align_bytes argument to build_memmove was not a power of 2 under 2^64."); + return Err(BuilderError::AlignmentError( + "The src_align_bytes argument to build_memmove was not a power of 2 under 2^64.", + )); } if !is_alignment_ok(dest_align_bytes) { - return Err("The dest_align_bytes argument to build_memmove was not a power of 2 under 2^64."); + return Err(BuilderError::AlignmentError( + "The dest_align_bytes argument to build_memmove was not a power of 2 under 2^64.", + )); } let value = unsafe { @@ -1402,6 +1559,8 @@ impl<'ctx> Builder<'ctx> { /// 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`](https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetData.html#method.ptr_sized_int_type_in_context) will get you one of those. #[llvm_versions(8.0..=latest)] @@ -1411,9 +1570,14 @@ impl<'ctx> Builder<'ctx> { dest_align_bytes: u32, val: IntValue<'ctx>, size: IntValue<'ctx>, - ) -> Result, &'static str> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } if !is_alignment_ok(dest_align_bytes) { - return Err("The src_align_bytes argument to build_memmove was not a power of 2 under 2^64."); + return Err(BuilderError::AlignmentError( + "The src_align_bytes argument to build_memmove was not a power of 2 under 2^64.", + )); } let value = unsafe { @@ -1430,10 +1594,16 @@ impl<'ctx> Builder<'ctx> { } // TODOC: Heap allocation - pub fn build_malloc>(&self, ty: T, name: &str) -> Result, &'static str> { - // LLVMBulidMalloc segfaults if ty is unsized + /// Returns `Err(BuilderError::AlignmentError)` if the type is unsized. + pub fn build_malloc>(&self, ty: T, name: &str) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } + // LLVMBuildMalloc segfaults if ty is unsized if !ty.is_sized() { - return Err("Cannot build malloc call for an unsized type"); + return Err(BuilderError::AlignmentError( + "Cannot build malloc call for an unsized type", + )); } let c_string = to_c_str(name); @@ -1444,15 +1614,21 @@ impl<'ctx> Builder<'ctx> { } // TODOC: Heap allocation + /// Returns `Err(BuilderError::AlignmentError)` if the type is unsized. pub fn build_array_malloc>( &self, ty: T, size: IntValue<'ctx>, name: &str, - ) -> Result, &'static str> { - // LLVMBulidArrayMalloc segfaults if ty is unsized + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } + // LLVMBuildArrayMalloc segfaults if ty is unsized if !ty.is_sized() { - return Err("Cannot build array malloc call for an unsized type"); + return Err(BuilderError::AlignmentError( + "Cannot build array malloc call for an unsized type", + )); } let c_string = to_c_str(name); @@ -1464,8 +1640,11 @@ impl<'ctx> Builder<'ctx> { } // SubType:

(&self, ptr: PointerValue

) -> InstructionValue { - pub fn build_free(&self, ptr: PointerValue<'ctx>) -> InstructionValue<'ctx> { - unsafe { InstructionValue::new(LLVMBuildFree(self.builder, ptr.as_value_ref())) } + pub fn build_free(&self, ptr: PointerValue<'ctx>) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } + unsafe { Ok(InstructionValue::new(LLVMBuildFree(self.builder, ptr.as_value_ref()))) } } pub fn insert_instruction(&self, instruction: &InstructionValue<'ctx>, name: Option<&str>) { @@ -1488,51 +1667,79 @@ impl<'ctx> Builder<'ctx> { // TODO: Possibly make this generic over sign via struct metadata or subtypes // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { // if I::sign() == Unsigned { LLVMBuildUDiv() } else { LLVMBuildSDiv() } - pub fn build_int_unsigned_div>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_unsigned_div>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildUDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // TODO: Possibly make this generic over sign via struct metadata or subtypes // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_signed_div>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_signed_div>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // TODO: Possibly make this generic over sign via struct metadata or subtypes // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_exact_signed_div>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_exact_signed_div>( + &self, + lhs: T, + rhs: T, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildExactSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // TODO: Possibly make this generic over sign via struct metadata or subtypes // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_unsigned_rem>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_unsigned_rem>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildURem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // TODO: Possibly make this generic over sign via struct metadata or subtypes // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_signed_rem>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_signed_rem>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildSRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - pub fn build_int_s_extend>(&self, int_value: T, int_type: T::BaseType, name: &str) -> T { + pub fn build_int_s_extend>( + &self, + int_value: T, + int_type: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildSExt( @@ -1543,7 +1750,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // REVIEW: Does this need vector support? @@ -1552,7 +1759,10 @@ impl<'ctx> Builder<'ctx> { ptr_val: PointerValue<'ctx>, ptr_type: PointerType<'ctx>, name: &str, - ) -> PointerValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildAddrSpaceCast( @@ -1563,7 +1773,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { PointerValue::new(value) } + unsafe { Ok(PointerValue::new(value)) } } /// Builds a bitcast instruction. A bitcast reinterprets the bits of one value @@ -1589,20 +1799,23 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// builder.build_bitcast(i32_arg, f32_type, "i32tof32"); - /// builder.build_return(None); + /// builder.build_bitcast(i32_arg, f32_type, "i32tof32").unwrap(); + /// builder.build_return(None).unwrap(); /// /// assert!(module.verify().is_ok()); /// ``` - pub fn build_bitcast(&self, val: V, ty: T, name: &str) -> BasicValueEnum<'ctx> + pub fn build_bitcast(&self, val: V, ty: T, name: &str) -> Result, BuilderError> where T: BasicType<'ctx>, V: BasicValue<'ctx>, { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildBitCast(self.builder, val.as_value_ref(), ty.as_type_ref(), c_string.as_ptr()) }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } pub fn build_int_s_extend_or_bit_cast>( @@ -1610,7 +1823,10 @@ impl<'ctx> Builder<'ctx> { int_value: T, int_type: T::BaseType, name: &str, - ) -> T { + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildSExtOrBitCast( @@ -1621,10 +1837,18 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - pub fn build_int_z_extend>(&self, int_value: T, int_type: T::BaseType, name: &str) -> T { + pub fn build_int_z_extend>( + &self, + int_value: T, + int_type: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildZExt( @@ -1635,7 +1859,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } pub fn build_int_z_extend_or_bit_cast>( @@ -1643,7 +1867,10 @@ impl<'ctx> Builder<'ctx> { int_value: T, int_type: T::BaseType, name: &str, - ) -> T { + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildZExtOrBitCast( @@ -1654,10 +1881,18 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - pub fn build_int_truncate>(&self, int_value: T, int_type: T::BaseType, name: &str) -> T { + pub fn build_int_truncate>( + &self, + int_value: T, + int_type: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -1669,7 +1904,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } pub fn build_int_truncate_or_bit_cast>( @@ -1677,7 +1912,10 @@ impl<'ctx> Builder<'ctx> { int_value: T, int_type: T::BaseType, name: &str, - ) -> T { + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -1689,14 +1927,17 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - pub fn build_float_rem>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_float_rem>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // REVIEW: Consolidate these two casts into one via subtypes @@ -1705,7 +1946,11 @@ impl<'ctx> Builder<'ctx> { float: T, int_type: >::MathConvType, name: &str, - ) -> <>::MathConvType as IntMathType<'ctx>>::ValueType { + ) -> Result<<>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPToUI( @@ -1716,7 +1961,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { <::MathConvType as IntMathType>::ValueType::new(value) } + unsafe { Ok(<::MathConvType as IntMathType>::ValueType::new(value)) } } pub fn build_float_to_signed_int>( @@ -1724,7 +1969,11 @@ impl<'ctx> Builder<'ctx> { float: T, int_type: >::MathConvType, name: &str, - ) -> <>::MathConvType as IntMathType<'ctx>>::ValueType { + ) -> Result<<>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPToSI( @@ -1735,7 +1984,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { <::MathConvType as IntMathType>::ValueType::new(value) } + unsafe { Ok(<::MathConvType as IntMathType>::ValueType::new(value)) } } // REVIEW: Consolidate these two casts into one via subtypes @@ -1744,7 +1993,11 @@ impl<'ctx> Builder<'ctx> { int: T, float_type: >::MathConvType, name: &str, - ) -> <>::MathConvType as FloatMathType<'ctx>>::ValueType { + ) -> Result<<>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildUIToFP( @@ -1755,7 +2008,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { <::MathConvType as FloatMathType>::ValueType::new(value) } + unsafe { Ok(<::MathConvType as FloatMathType>::ValueType::new(value)) } } pub fn build_signed_int_to_float>( @@ -1763,7 +2016,11 @@ impl<'ctx> Builder<'ctx> { int: T, float_type: >::MathConvType, name: &str, - ) -> <>::MathConvType as FloatMathType<'ctx>>::ValueType { + ) -> Result<<>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildSIToFP( @@ -1774,10 +2031,18 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { <::MathConvType as FloatMathType>::ValueType::new(value) } + unsafe { Ok(<::MathConvType as FloatMathType>::ValueType::new(value)) } } - pub fn build_float_trunc>(&self, float: T, float_type: T::BaseType, name: &str) -> T { + pub fn build_float_trunc>( + &self, + float: T, + float_type: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPTrunc( @@ -1788,10 +2053,18 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - pub fn build_float_ext>(&self, float: T, float_type: T::BaseType, name: &str) -> T { + pub fn build_float_ext>( + &self, + float: T, + float_type: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPExt( @@ -1802,10 +2075,18 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - pub fn build_float_cast>(&self, float: T, float_type: T::BaseType, name: &str) -> T { + pub fn build_float_cast>( + &self, + float: T, + float_type: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPCast( @@ -1816,11 +2097,19 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &IntValue, rhs: &IntType, name: &str) -> IntValue { - pub fn build_int_cast>(&self, int: T, int_type: T::BaseType, name: &str) -> T { + pub fn build_int_cast>( + &self, + int: T, + int_type: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildIntCast( @@ -1831,7 +2120,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } /// Like `build_int_cast`, but respects the signedness of the type being cast to. @@ -1842,7 +2131,10 @@ impl<'ctx> Builder<'ctx> { int_type: T::BaseType, is_signed: bool, name: &str, - ) -> T { + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildIntCast2( @@ -1854,72 +2146,93 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - pub fn build_float_div>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_float_div>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_add>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_add>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - // REVIEW: Possibly incorperate into build_int_add via flag param + // REVIEW: Possibly incorporate into build_int_add via flag param // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_nsw_add>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_nsw_add>(&self, lhs: T, rhs: T, name: &str) -> Result { let c_string = to_c_str(name); let value = unsafe { LLVMBuildNSWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - // REVIEW: Possibly incorperate into build_int_add via flag param + // REVIEW: Possibly incorporate into build_int_add via flag param // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_nuw_add>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_nuw_add>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNUWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &FloatValue, rhs: &FloatValue, name: &str) -> FloatValue { - pub fn build_float_add>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_float_add>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_xor>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_xor>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildXor(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_and>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_and>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildAnd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_or>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_or>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildOr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } /// Builds an `IntValue` containing the result of a logical left shift instruction. @@ -1961,15 +2274,18 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry_block); /// - /// let shift = builder.build_left_shift(value, n, "left_shift"); // value << n + /// let shift = builder.build_left_shift(value, n, "left_shift").unwrap(); // value << n /// - /// builder.build_return(Some(&shift)); + /// builder.build_return(Some(&shift)).unwrap(); /// ``` - pub fn build_left_shift>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_left_shift>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildShl(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } /// Builds an `IntValue` containing the result of a right shift instruction. @@ -2032,11 +2348,20 @@ impl<'ctx> Builder<'ctx> { /// /// // 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"); // value >> n + /// let shift = builder.build_right_shift(value, n, false, "right_shift").unwrap(); // value >> n /// - /// builder.build_return(Some(&shift)); + /// builder.build_return(Some(&shift)).unwrap(); /// ``` - pub fn build_right_shift>(&self, lhs: T, rhs: T, sign_extend: bool, name: &str) -> T { + pub fn build_right_shift>( + &self, + lhs: T, + rhs: T, + sign_extend: bool, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { if sign_extend { @@ -2046,74 +2371,98 @@ impl<'ctx> Builder<'ctx> { } }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_sub>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_sub>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - // REVIEW: Possibly incorperate into build_int_sub via flag param - pub fn build_int_nsw_sub>(&self, lhs: T, rhs: T, name: &str) -> T { + // REVIEW: Possibly incorporate into build_int_sub via flag param + pub fn build_int_nsw_sub>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNSWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - // REVIEW: Possibly incorperate into build_int_sub via flag param + // REVIEW: Possibly incorporate into build_int_sub via flag param // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_nuw_sub>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_nuw_sub>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNUWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &FloatValue, rhs: &FloatValue, name: &str) -> FloatValue { - pub fn build_float_sub>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_float_sub>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_mul>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_mul>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - // REVIEW: Possibly incorperate into build_int_mul via flag param + // REVIEW: Possibly incorporate into build_int_mul via flag param // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_nsw_mul>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_nsw_mul>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNSWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - // REVIEW: Possibly incorperate into build_int_mul via flag param + // REVIEW: Possibly incorporate into build_int_mul via flag param // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { - pub fn build_int_nuw_mul>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_int_nuw_mul>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNUWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, lhs: &FloatValue, rhs: &FloatValue, name: &str) -> FloatValue { - pub fn build_float_mul>(&self, lhs: T, rhs: T, name: &str) -> T { + pub fn build_float_mul>(&self, lhs: T, rhs: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } pub fn build_cast, V: BasicValue<'ctx>>( @@ -2122,7 +2471,10 @@ impl<'ctx> Builder<'ctx> { from_value: V, to_type: T, name: &str, - ) -> BasicValueEnum<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildCast( @@ -2134,16 +2486,24 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } // SubType: (&self, from: &PointerValue, to: &PointerType, name: &str) -> PointerValue { - pub fn build_pointer_cast>(&self, from: T, to: T::BaseType, name: &str) -> T { + pub fn build_pointer_cast>( + &self, + from: T, + to: T::BaseType, + name: &str, + ) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildPointerCast(self.builder, from.as_value_ref(), to.as_type_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, op, lhs: &IntValue, rhs: &IntValue, name) -> IntValue { ? @@ -2156,7 +2516,10 @@ impl<'ctx> Builder<'ctx> { lhs: T, rhs: T, name: &str, - ) -> >::ValueType { + ) -> Result<>::ValueType, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildICmp( @@ -2168,7 +2531,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { >::ValueType::new(value) } + unsafe { Ok(>::ValueType::new(value)) } } // SubType: (&self, op, lhs: &FloatValue, rhs: &FloatValue, name) -> IntValue { ? @@ -2179,7 +2542,11 @@ impl<'ctx> Builder<'ctx> { lhs: T, rhs: T, name: &str, - ) -> <>::MathConvType as IntMathType<'ctx>>::ValueType { + ) -> Result<<>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -2192,13 +2559,19 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { <::MathConvType as IntMathType>::ValueType::new(value) } + unsafe { Ok(<::MathConvType as IntMathType>::ValueType::new(value)) } } - pub fn build_unconditional_branch(&self, destination_block: BasicBlock<'ctx>) -> InstructionValue<'ctx> { + pub fn build_unconditional_branch( + &self, + destination_block: BasicBlock<'ctx>, + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let value = unsafe { LLVMBuildBr(self.builder, destination_block.basic_block) }; - unsafe { InstructionValue::new(value) } + unsafe { Ok(InstructionValue::new(value)) } } pub fn build_conditional_branch( @@ -2206,7 +2579,10 @@ impl<'ctx> Builder<'ctx> { comparison: IntValue<'ctx>, then_block: BasicBlock<'ctx>, else_block: BasicBlock<'ctx>, - ) -> InstructionValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let value = unsafe { LLVMBuildCondBr( self.builder, @@ -2216,75 +2592,108 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { InstructionValue::new(value) } + unsafe { Ok(InstructionValue::new(value)) } } pub fn build_indirect_branch>( &self, address: BV, destinations: &[BasicBlock<'ctx>], - ) -> InstructionValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let value = unsafe { LLVMBuildIndirectBr(self.builder, address.as_value_ref(), destinations.len() as u32) }; for destination in destinations { unsafe { LLVMAddDestination(value, destination.basic_block) } } - unsafe { InstructionValue::new(value) } + unsafe { Ok(InstructionValue::new(value)) } } // SubType: (&self, value: &IntValue, name) -> IntValue { - pub fn build_int_neg>(&self, value: T, name: &str) -> T { + pub fn build_int_neg>(&self, value: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } - // REVIEW: Possibly incorperate into build_int_neg via flag and subtypes + // REVIEW: Possibly incorporate into build_int_neg via flag and subtypes // SubType: (&self, value: &IntValue, name) -> IntValue { - pub fn build_int_nsw_neg>(&self, value: T, name: &str) -> T { + pub fn build_int_nsw_neg>(&self, value: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNSWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, value: &IntValue, name) -> IntValue { - pub fn build_int_nuw_neg>(&self, value: T, name: &str) -> T { + pub fn build_int_nuw_neg>(&self, value: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNUWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, value: &FloatValue, name) -> FloatValue { - pub fn build_float_neg>(&self, value: T, name: &str) -> T { + pub fn build_float_neg>(&self, value: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildFNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // SubType: (&self, value: &IntValue, name) -> IntValue { ? - pub fn build_not>(&self, value: T, name: &str) -> T { + pub fn build_not>(&self, value: T, name: &str) -> Result { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildNot(self.builder, value.as_value_ref(), c_string.as_ptr()) }; - unsafe { T::new(value) } + unsafe { Ok(T::new(value)) } } // REVIEW: What if instruction and basic_block are completely unrelated? // It'd be great if we could get the BB from the instruction behind the scenes + /// 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)`. pub fn position_at(&self, basic_block: BasicBlock<'ctx>, instruction: &InstructionValue<'ctx>) { + self.positioned.set(PositionState::Set); + unsafe { LLVMPositionBuilder(self.builder, basic_block.basic_block, instruction.as_value_ref()) } } + /// 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)`. pub fn position_before(&self, instruction: &InstructionValue<'ctx>) { + self.positioned.set(PositionState::Set); + unsafe { LLVMPositionBuilderBefore(self.builder, instruction.as_value_ref()) } } + /// 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)`. pub fn position_at_end(&self, basic_block: BasicBlock<'ctx>) { + self.positioned.set(PositionState::Set); + unsafe { LLVMPositionBuilderAtEnd(self.builder, basic_block.basic_block); } @@ -2292,11 +2701,14 @@ impl<'ctx> Builder<'ctx> { /// 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 /// /// ```no_run /// use inkwell::context::Context; + /// use inkwell::builder::BuilderError; /// /// let context = Context::create(); /// let module = context.create_module("av"); @@ -2312,7 +2724,7 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// let array_alloca = builder.build_alloca(array_type, "array_alloca"); + /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap(); /// /// #[cfg(any( /// feature = "llvm4-0", @@ -2327,53 +2739,59 @@ impl<'ctx> Builder<'ctx> { /// feature = "llvm13-0", /// feature = "llvm14-0" /// ))] - /// let array = builder.build_load(array_alloca, "array_load").into_array_value(); + /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value(); /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - /// let array = builder.build_load(i32_type, array_alloca, "array_load").into_array_value(); + /// 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_some()); - /// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_some()); - /// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_some()); - /// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_none()); + /// 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_none()); + /// assert!(builder.build_extract_value(array, 3, "extract").is_err_and(|e| e == BuilderError::ExtractOutOfRange)); /// ``` pub fn build_extract_value>( &self, agg: AV, index: u32, name: &str, - ) -> Option> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let size = match agg.as_aggregate_value_enum() { AggregateValueEnum::ArrayValue(av) => av.get_type().len(), AggregateValueEnum::StructValue(sv) => sv.get_type().count_fields(), }; if index >= size { - return None; + return Err(BuilderError::ExtractOutOfRange); } let c_string = to_c_str(name); let value = unsafe { LLVMBuildExtractValue(self.builder, agg.as_value_ref(), index, c_string.as_ptr()) }; - unsafe { Some(BasicValueEnum::new(value)) } + unsafe { Ok(BasicValueEnum::new(value)) } } /// 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 /// /// ```no_run /// use inkwell::context::Context; + /// use inkwell::builder::BuilderError; /// /// let context = Context::create(); /// let module = context.create_module("av"); @@ -2389,7 +2807,7 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// let array_alloca = builder.build_alloca(array_type, "array_alloca"); + /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap(); /// /// #[cfg(any( /// feature = "llvm4-0", @@ -2404,18 +2822,18 @@ impl<'ctx> Builder<'ctx> { /// feature = "llvm13-0", /// feature = "llvm14-0" /// ))] - /// let array = builder.build_load(array_alloca, "array_load").into_array_value(); + /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value(); /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - /// let array = builder.build_load(i32_type, array_alloca, "array_load").into_array_value(); + /// 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_some()); - /// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_some()); - /// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_some()); - /// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_none()); + /// 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)); /// ``` pub fn build_insert_value( &self, @@ -2423,18 +2841,21 @@ impl<'ctx> Builder<'ctx> { value: BV, index: u32, name: &str, - ) -> Option> + ) -> Result, BuilderError> where AV: AggregateValue<'ctx>, BV: BasicValue<'ctx>, { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let size = match agg.as_aggregate_value_enum() { AggregateValueEnum::ArrayValue(av) => av.get_type().len(), AggregateValueEnum::StructValue(sv) => sv.get_type().count_fields(), }; if index >= size { - return None; + return Err(BuilderError::ExtractOutOfRange); } let c_string = to_c_str(name); @@ -2449,7 +2870,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { Some(AggregateValueEnum::new(value)) } + unsafe { Ok(AggregateValueEnum::new(value)) } } /// Builds an extract element instruction which extracts a `BasicValueEnum` @@ -2472,16 +2893,19 @@ impl<'ctx> Builder<'ctx> { /// /// builder.position_at_end(entry); /// - /// let extracted = builder.build_extract_element(vector_param, i32_zero, "insert"); + /// let extracted = builder.build_extract_element(vector_param, i32_zero, "insert").unwrap(); /// - /// builder.build_return(Some(&extracted)); + /// builder.build_return(Some(&extracted)).unwrap(); /// ``` pub fn build_extract_element( &self, vector: VectorValue<'ctx>, index: IntValue<'ctx>, name: &str, - ) -> BasicValueEnum<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -2493,7 +2917,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } /// Builds an insert element instruction which inserts a `BasicValue` into a vector @@ -2518,8 +2942,8 @@ impl<'ctx> Builder<'ctx> { /// 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"); - /// builder.build_return(None); + /// builder.build_insert_element(vector_param, i32_seven, i32_zero, "insert").unwrap(); + /// builder.build_return(None).unwrap(); /// ``` pub fn build_insert_element>( &self, @@ -2527,7 +2951,10 @@ impl<'ctx> Builder<'ctx> { element: V, index: IntValue<'ctx>, name: &str, - ) -> VectorValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -2540,23 +2967,34 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { VectorValue::new(value) } + unsafe { Ok(VectorValue::new(value)) } } - pub fn build_unreachable(&self) -> InstructionValue<'ctx> { + pub fn build_unreachable(&self) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let val = unsafe { LLVMBuildUnreachable(self.builder) }; - unsafe { InstructionValue::new(val) } + unsafe { Ok(InstructionValue::new(val)) } } // REVIEW: Not sure if this should return InstructionValue or an actual value // TODO: Better name for num? - pub fn build_fence(&self, atomic_ordering: AtomicOrdering, num: i32, name: &str) -> InstructionValue<'ctx> { + pub fn build_fence( + &self, + atomic_ordering: AtomicOrdering, + num: i32, + name: &str, + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let val = unsafe { LLVMBuildFence(self.builder, atomic_ordering.into(), num, c_string.as_ptr()) }; - unsafe { InstructionValue::new(val) } + unsafe { Ok(InstructionValue::new(val)) } } // SubType:

(&self, ptr: &PointerValue

, name) -> IntValue { @@ -2564,11 +3002,15 @@ impl<'ctx> Builder<'ctx> { &self, ptr: T, name: &str, - ) -> <>::PtrConvType as IntMathType<'ctx>>::ValueType { + ) -> Result<<>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let val = unsafe { LLVMBuildIsNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; - unsafe { <::PtrConvType as IntMathType>::ValueType::new(val) } + unsafe { Ok(<::PtrConvType as IntMathType>::ValueType::new(val)) } } // SubType:

(&self, ptr: &PointerValue

, name) -> IntValue { @@ -2576,11 +3018,15 @@ impl<'ctx> Builder<'ctx> { &self, ptr: T, name: &str, - ) -> <>::PtrConvType as IntMathType<'ctx>>::ValueType { + ) -> Result<<>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let val = unsafe { LLVMBuildIsNotNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; - unsafe { <::PtrConvType as IntMathType>::ValueType::new(val) } + unsafe { Ok(<::PtrConvType as IntMathType>::ValueType::new(val)) } } // SubType: (&self, int: &IntValue, ptr_type: &PointerType

, name) -> PointerValue

{ @@ -2589,7 +3035,11 @@ impl<'ctx> Builder<'ctx> { int: T, ptr_type: >::PtrConvType, name: &str, - ) -> <>::PtrConvType as PointerMathType<'ctx>>::ValueType { + ) -> Result<<>::PtrConvType as PointerMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -2601,7 +3051,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { <::PtrConvType as PointerMathType>::ValueType::new(value) } + unsafe { Ok(<::PtrConvType as PointerMathType>::ValueType::new(value)) } } // SubType: (&self, ptr: &PointerValue

, int_type: &IntType, name) -> IntValue { @@ -2610,7 +3060,11 @@ impl<'ctx> Builder<'ctx> { ptr: T, int_type: >::PtrConvType, name: &str, - ) -> <>::PtrConvType as IntMathType<'ctx>>::ValueType { + ) -> Result<<>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError> + { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -2622,7 +3076,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { <::PtrConvType as IntMathType>::ValueType::new(value) } + unsafe { Ok(<::PtrConvType as IntMathType>::ValueType::new(value)) } } pub fn clear_insertion_position(&self) { @@ -2637,7 +3091,10 @@ impl<'ctx> Builder<'ctx> { value: IntValue<'ctx>, else_block: BasicBlock<'ctx>, cases: &[(IntValue<'ctx>, BasicBlock<'ctx>)], - ) -> InstructionValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let switch_value = unsafe { LLVMBuildSwitch( self.builder, @@ -2651,7 +3108,7 @@ impl<'ctx> Builder<'ctx> { unsafe { LLVMAddCase(switch_value, value.as_value_ref(), basic_block.basic_block) } } - unsafe { InstructionValue::new(switch_value) } + unsafe { Ok(InstructionValue::new(switch_value)) } } // SubTypes: condition can only be IntValue or VectorValue> @@ -2661,7 +3118,10 @@ impl<'ctx> Builder<'ctx> { then: BV, else_: BV, name: &str, - ) -> BasicValueEnum<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildSelect( @@ -2673,26 +3133,32 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } // The unsafety of this function should be fixable with subtypes. See GH #32 - pub unsafe fn build_global_string(&self, value: &str, name: &str) -> GlobalValue<'ctx> { + pub unsafe fn build_global_string(&self, value: &str, name: &str) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string_value = to_c_str(value); let c_string_name = to_c_str(name); let value = LLVMBuildGlobalString(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr()); - GlobalValue::new(value) + Ok(GlobalValue::new(value)) } // REVIEW: Does this similar fn have the same issue build_global_string does? If so, mark as unsafe // and fix with subtypes. - pub fn build_global_string_ptr(&self, value: &str, name: &str) -> GlobalValue<'ctx> { + pub fn build_global_string_ptr(&self, value: &str, name: &str) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string_value = to_c_str(value); let c_string_name = to_c_str(name); let value = unsafe { LLVMBuildGlobalStringPtr(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr()) }; - unsafe { GlobalValue::new(value) } + unsafe { Ok(GlobalValue::new(value)) } } // REVIEW: Do we need to constrain types here? subtypes? @@ -2702,7 +3168,10 @@ impl<'ctx> Builder<'ctx> { right: VectorValue<'ctx>, mask: VectorValue<'ctx>, name: &str, - ) -> VectorValue<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { LLVMBuildShuffleVector( @@ -2714,7 +3183,7 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { VectorValue::new(value) } + unsafe { Ok(VectorValue::new(value)) } } // REVIEW: Is return type correct? @@ -2725,7 +3194,10 @@ impl<'ctx> Builder<'ctx> { list: PointerValue<'ctx>, type_: BT, name: &str, - ) -> BasicValueEnum<'ctx> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let c_string = to_c_str(name); let value = unsafe { @@ -2737,11 +3209,15 @@ impl<'ctx> Builder<'ctx> { ) }; - unsafe { BasicValueEnum::new(value) } + unsafe { Ok(BasicValueEnum::new(value)) } } /// 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 /// /// ``` @@ -2759,8 +3235,8 @@ impl<'ctx> Builder<'ctx> { /// 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); - /// builder.build_return(None); + /// builder.build_atomicrmw(AtomicRMWBinOp::Add, i32_ptr_param, i32_seven, AtomicOrdering::Unordered).unwrap(); + /// builder.build_return(None).unwrap(); /// ``` // https://llvm.org/docs/LangRef.html#atomicrmw-instruction pub fn build_atomicrmw( @@ -2769,17 +3245,24 @@ impl<'ctx> Builder<'ctx> { ptr: PointerValue<'ctx>, value: IntValue<'ctx>, ordering: AtomicOrdering, - ) -> Result, &'static str> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } // TODO: add support for fadd, fsub and xchg on floating point types in LLVM 9+. // "The type of ‘’ must be an integer type whose bit width is a power of two greater than or equal to eight and less than or equal to a target-specific size limit. The type of the ‘’ operand must be a pointer to that type." -- https://releases.llvm.org/3.6.2/docs/LangRef.html#atomicrmw-instruction if value.get_type().get_bit_width() < 8 || !value.get_type().get_bit_width().is_power_of_two() { - return Err("The bitwidth of value must be a power of 2 and greater than 8."); + return Err(BuilderError::BitwidthError( + "The bitwidth of value must be a power of 2 and greater than 8.", + )); } #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0")))] if ptr.get_type().get_element_type() != value.get_type().into() { - return Err("Pointer's pointee type must match the value's type."); + return Err(BuilderError::PointeeTypeMismatch( + "Pointer's pointee type must match the value's type.", + )); } let val = unsafe { @@ -2797,6 +3280,15 @@ impl<'ctx> Builder<'ctx> { } /// 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 /// @@ -2816,8 +3308,8 @@ impl<'ctx> Builder<'ctx> { /// 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); - /// builder.build_return(None); + /// builder.build_cmpxchg(i32_ptr_param, i32_seven, i32_eight, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic).unwrap(); + /// builder.build_return(None).unwrap(); /// ``` // https://llvm.org/docs/LangRef.html#cmpxchg-instruction pub fn build_cmpxchg>( @@ -2827,30 +3319,45 @@ impl<'ctx> Builder<'ctx> { new: V, success: AtomicOrdering, failure: AtomicOrdering, - ) -> Result, &'static str> { + ) -> Result, BuilderError> { + if self.positioned.get() != PositionState::Set { + return Err(BuilderError::UnsetPosition); + } let cmp = cmp.as_basic_value_enum(); let new = new.as_basic_value_enum(); if cmp.get_type() != new.get_type() { - return Err("The value to compare against and the value to replace with must have the same type."); + return Err(BuilderError::ValueTypeMismatch( + "The value to compare against and the value to replace with must have the same type.", + )); } if !cmp.is_int_value() && !cmp.is_pointer_value() { - return Err("The values must have pointer or integer type."); + return Err(BuilderError::ValueTypeMismatch( + "The values must have pointer or integer type.", + )); } #[cfg(not(any(feature = "llvm15-0", feature = "llvm16-0")))] if ptr.get_type().get_element_type().to_basic_type_enum() != cmp.get_type() { - return Err("The pointer does not point to an element of the value type."); + return Err(BuilderError::PointeeTypeMismatch( + "The pointer does not point to an element of the value type.", + )); } // "Both ordering parameters must be at least monotonic, the ordering constraint on failure must be no stronger than that on success, and the failure ordering cannot be either release or acq_rel." -- https://llvm.org/docs/LangRef.html#cmpxchg-instruction if success < AtomicOrdering::Monotonic || failure < AtomicOrdering::Monotonic { - return Err("Both success and failure orderings must be Monotonic or stronger."); + return Err(BuilderError::OrderingError( + "Both success and failure orderings must be Monotonic or stronger.", + )); } if failure > success { - return Err("The failure ordering may not be stronger than the success ordering."); + return Err(BuilderError::OrderingError( + "The failure ordering may not be stronger than the success ordering.", + )); } if failure == AtomicOrdering::Release || failure == AtomicOrdering::AcquireRelease { - return Err("The failure ordering may not be release or acquire release."); + return Err(BuilderError::OrderingError( + "The failure ordering may not be release or acquire release.", + )); } let val = unsafe { diff --git a/src/context.rs b/src/context.rs index 4581cde9336..71b7b667d97 100644 --- a/src/context.rs +++ b/src/context.rs @@ -496,7 +496,7 @@ impl Context { /// let basic_block = context.append_basic_block(fn_val, "entry"); /// /// builder.position_at_end(basic_block); - /// builder.build_return(None); + /// builder.build_return(None).unwrap(); /// /// let memory_buffer = module.write_bitcode_to_memory(); /// @@ -566,13 +566,13 @@ impl Context { /// { /// use inkwell::values::CallableValue; /// let callable_value = CallableValue::try_from(asm).unwrap(); - /// builder.build_call(callable_value, params, "exit"); + /// builder.build_call(callable_value, params, "exit").unwrap(); /// } /// /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - /// builder.build_indirect_call(asm_fn, asm, params, "exit"); + /// builder.build_indirect_call(asm_fn, asm, params, "exit").unwrap(); /// - /// builder.build_return(None); + /// builder.build_return(None).unwrap(); /// ``` #[inline] pub fn create_inline_asm<'ctx>( @@ -917,7 +917,7 @@ impl Context { self.context.ppc_f128_type() } - /// Creates a `StructType` definiton from heterogeneous types in the current `Context`. + /// Creates a `StructType` definition from heterogeneous types in the current `Context`. /// /// # Example /// @@ -1106,7 +1106,7 @@ impl Context { /// /// builder.position_at_end(entry_block); /// - /// let ret_instr = builder.build_return(None); + /// let ret_instr = builder.build_return(None).unwrap(); /// /// assert!(md_node.is_node()); /// @@ -1140,7 +1140,7 @@ impl Context { /// /// builder.position_at_end(entry_block); /// - /// let ret_instr = builder.build_return(None); + /// let ret_instr = builder.build_return(None).unwrap(); /// /// assert!(md_string.is_string()); /// @@ -1344,7 +1344,7 @@ impl<'ctx> ContextRef<'ctx> { /// let basic_block = context.append_basic_block(fn_val, "entry"); /// /// builder.position_at_end(basic_block); - /// builder.build_return(None); + /// builder.build_return(None).unwrap(); /// /// let memory_buffer = module.write_bitcode_to_memory(); /// @@ -1414,13 +1414,13 @@ impl<'ctx> ContextRef<'ctx> { /// { /// use inkwell::values::CallableValue; /// let callable_value = CallableValue::try_from(asm).unwrap(); - /// builder.build_call(callable_value, params, "exit"); + /// builder.build_call(callable_value, params, "exit").unwrap(); /// } /// /// #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - /// builder.build_indirect_call(asm_fn, asm, params, "exit"); + /// builder.build_indirect_call(asm_fn, asm, params, "exit").unwrap(); /// - /// builder.build_return(None); + /// builder.build_return(None).unwrap(); /// ``` #[inline] pub fn create_inline_asm( @@ -1765,7 +1765,7 @@ impl<'ctx> ContextRef<'ctx> { self.context.ppc_f128_type() } - /// Creates a `StructType` definiton from heterogeneous types in the current `Context`. + /// Creates a `StructType` definition from heterogeneous types in the current `Context`. /// /// # Example /// @@ -1954,7 +1954,7 @@ impl<'ctx> ContextRef<'ctx> { /// /// builder.position_at_end(entry_block); /// - /// let ret_instr = builder.build_return(None); + /// let ret_instr = builder.build_return(None).unwrap(); /// /// assert!(md_node.is_node()); /// @@ -1988,7 +1988,7 @@ impl<'ctx> ContextRef<'ctx> { /// /// builder.position_at_end(entry_block); /// - /// let ret_instr = builder.build_return(None); + /// let ret_instr = builder.build_return(None).unwrap(); /// /// assert!(md_string.is_string()); /// diff --git a/src/debug_info.rs b/src/debug_info.rs index 05dedd2c3a8..d2612bce452 100644 --- a/src/debug_info.rs +++ b/src/debug_info.rs @@ -1236,7 +1236,7 @@ impl<'ctx> DICompositeType<'ctx> { } } - /// Acquires the underlying raw pointer belonging to this `DICompositType` type. + /// Acquires the underlying raw pointer belonging to this `DICompositeType` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { self.metadata_ref } diff --git a/src/execution_engine.rs b/src/execution_engine.rs index 2a07954dac2..f0cb1a5a8ec 100644 --- a/src/execution_engine.rs +++ b/src/execution_engine.rs @@ -165,10 +165,10 @@ impl<'ctx> ExecutionEngine<'ctx> { /// let extf = module.add_function("sumf", ft.fn_type(&[ft.into(), ft.into()], false), None); /// /// let argf = ft.const_float(64.); - /// let call_site_value = builder.build_call(extf, &[argf.into(), argf.into()], "retv"); + /// let call_site_value = builder.build_call(extf, &[argf.into(), argf.into()], "retv").unwrap(); /// let retv = call_site_value.try_as_basic_value().left().unwrap().into_float_value(); /// - /// builder.build_return(Some(&retv)); + /// builder.build_return(Some(&retv)).unwrap(); /// /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap(); /// ee.add_global_mapping(&extf, sumf as usize); @@ -279,7 +279,7 @@ impl<'ctx> ExecutionEngine<'ctx> { /// /// // Insert a return statement /// let ret = double.const_float(64.0); - /// builder.build_return(Some(&ret)); + /// builder.build_return(Some(&ret)).unwrap(); /// /// // create the JIT engine /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap(); diff --git a/src/module.rs b/src/module.rs index 73321da6afd..6bf8d5680b1 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,4 +1,4 @@ -//! A `Module` represets a single code compilation unit. +//! A `Module` represents a single code compilation unit. use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyModule}; #[allow(deprecated)] @@ -59,7 +59,7 @@ use crate::{AddressSpace, OptimizationLevel}; #[llvm_enum(LLVMLinkage)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -/// This enum defines how to link a global variable or function in a module. The variant documenation is +/// This enum defines how to link a global variable or function in a module. The variant documentation is /// mostly taken straight from LLVM's own documentation except for some minor clarification. /// /// It is illegal for a function declaration to have any linkage type other than external or extern_weak. @@ -1536,7 +1536,7 @@ impl Drop for Module<'_> { #[llvm_versions(7.0..=latest)] #[llvm_enum(LLVMModuleFlagBehavior)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -/// Defines the operational behavior for a module wide flag. This documenation comes directly +/// Defines the operational behavior for a module wide flag. This documentation comes directly /// from the LLVM docs pub enum FlagBehavior { /// Emits an error if two values disagree, otherwise the resulting value is that of the operands. diff --git a/src/passes.rs b/src/passes.rs index 7dcd7f5e539..e2f9526cbcd 100644 --- a/src/passes.rs +++ b/src/passes.rs @@ -248,7 +248,7 @@ impl<'ctx> PassManagerSubType for FunctionValue<'ctx> { // SubTypes: PassManager, PassManager /// A manager for running optimization and simplification passes. Much of the -/// documenation for specific passes is directly from the [LLVM +/// documentation for specific passes is directly from the [LLVM /// documentation](https://llvm.org/docs/Passes.html). #[derive(Debug)] pub struct PassManager { @@ -527,7 +527,7 @@ impl PassManager { /// This pass performs global value numbering to eliminate /// fully and partially redundant instructions. It also /// performs redundant load elimination. - // REVIEW: Is `LLVMAddGVNPass` deprecated? Should we just seemlessly replace + // REVIEW: Is `LLVMAddGVNPass` deprecated? Should we just seamlessly replace // the old one with this one in 4.0+? #[llvm_versions(4.0..=latest)] pub fn add_new_gvn_pass(&self) { @@ -595,7 +595,7 @@ impl PassManager { /// /// This is a simple worklist driven algorithm. /// - /// This pass guarantees that the following canonicalizations are performed + /// This pass guarantees that the following canonicalization are performed /// on the program: /// /// 1. If a binary operator has a constant operand, it is moved to the diff --git a/src/support/mod.rs b/src/support/mod.rs index 9cf042bfe4b..5b8ab3316e8 100644 --- a/src/support/mod.rs +++ b/src/support/mod.rs @@ -117,7 +117,7 @@ impl PartialEq for LLVMStringOrRaw { } } -/// This function is very unsafe. Any reference to LLVM data after this function is called will likey segfault. +/// This function is very unsafe. Any reference to LLVM data after this function is called will likely segfault. /// Probably only ever useful to call before your program ends. Might not even be absolutely necessary. pub unsafe fn shutdown_llvm() { use llvm_sys::core::LLVMShutdown; diff --git a/src/types/float_type.rs b/src/types/float_type.rs index ed1aa663552..cd254cdf50e 100644 --- a/src/types/float_type.rs +++ b/src/types/float_type.rs @@ -82,7 +82,7 @@ impl<'ctx> FloatType<'ctx> { self.float_type.vec_type(size) } - /// Creates a `FloatValue` repesenting a constant value of this `FloatType`. + /// Creates a `FloatValue` representing a constant value of this `FloatType`. /// It will be automatically assigned this `FloatType`'s `Context`. /// /// # Example diff --git a/src/types/int_type.rs b/src/types/int_type.rs index 485c2659871..1053f3762b5 100644 --- a/src/types/int_type.rs +++ b/src/types/int_type.rs @@ -88,7 +88,7 @@ impl<'ctx> IntType<'ctx> { } } - /// Creates an `IntValue` repesenting a constant value of this `IntType`. It will be automatically assigned this `IntType`'s `Context`. + /// Creates an `IntValue` representing a constant value of this `IntType`. It will be automatically assigned this `IntType`'s `Context`. /// /// # Example /// ```no_run diff --git a/src/types/mod.rs b/src/types/mod.rs index 3fd966e1cea..1ed6ab5072d 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -39,8 +39,8 @@ use llvm_sys::core::LLVMGetPoison; use llvm_sys::core::{ LLVMAlignOf, LLVMArrayType, LLVMConstNull, LLVMConstPointerNull, LLVMFunctionType, LLVMGetElementType, - LLVMGetTypeContext, LLVMGetTypeKind, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, - LLVMSizeOf, LLVMTypeIsSized, LLVMVectorType, + LLVMGetTypeContext, LLVMGetTypeKind, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMSizeOf, + LLVMTypeIsSized, LLVMVectorType, }; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; use llvm_sys::LLVMTypeKind; diff --git a/src/types/struct_type.rs b/src/types/struct_type.rs index 19cb4c680c9..11d6ddd60e9 100644 --- a/src/types/struct_type.rs +++ b/src/types/struct_type.rs @@ -376,7 +376,7 @@ impl<'ctx> StructType<'ctx> { /// Defines the body of a `StructType`. /// /// If the struct is an opaque type, it will no longer be after this call. - /// + /// /// Resetting the `packed` state of a non-opaque struct type may not work. /// /// # Example diff --git a/src/values/array_value.rs b/src/values/array_value.rs index 9bdef56bed0..8416051ffac 100644 --- a/src/values/array_value.rs +++ b/src/values/array_value.rs @@ -1,4 +1,4 @@ -use llvm_sys::core::{LLVMIsAConstantArray, LLVMIsAConstantDataArray, LLVMIsConstantString, LLVMGetAsString}; +use llvm_sys::core::{LLVMGetAsString, LLVMIsAConstantArray, LLVMIsAConstantDataArray, LLVMIsConstantString}; use llvm_sys::prelude::LLVMValueRef; use std::ffi::CStr; @@ -102,16 +102,16 @@ impl<'ctx> ArrayValue<'ctx> { /// Obtain the string from the ArrayValue /// if the value points to a constant string. - /// + /// /// # Example - /// + /// /// ```no_run /// use inkwell::context::Context; /// use std::ffi::CStr; - /// + /// /// let context = Context::create(); /// let string = context.const_string(b"hello!", true); - /// + /// /// let result = CStr::from_bytes_with_nul(b"hello!\0").unwrap(); /// assert_eq!(string.get_string_constant(), Some(result)); /// ``` diff --git a/src/values/basic_value_use.rs b/src/values/basic_value_use.rs index 0bd6e51e62b..afbbfcbe74f 100644 --- a/src/values/basic_value_use.rs +++ b/src/values/basic_value_use.rs @@ -45,9 +45,9 @@ impl<'ctx> BasicValueUse<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// let arg1_first_use = arg1.get_first_use().unwrap(); /// @@ -106,9 +106,9 @@ impl<'ctx> BasicValueUse<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// let store_operand_use0 = store_instruction.get_operand_use(0).unwrap(); /// let store_operand_use1 = store_instruction.get_operand_use(1).unwrap(); @@ -142,9 +142,9 @@ impl<'ctx> BasicValueUse<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// let free_operand0 = free_instruction.get_operand(0).unwrap().left().unwrap(); /// let free_operand0_instruction = free_operand0.as_instruction_value().unwrap(); diff --git a/src/values/call_site_value.rs b/src/values/call_site_value.rs index 3c0b2481d4f..3d2d8c2b2c6 100644 --- a/src/values/call_site_value.rs +++ b/src/values/call_site_value.rs @@ -41,7 +41,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.set_tail_call(true); /// ``` @@ -66,7 +66,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.set_tail_call(true); /// @@ -93,7 +93,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// assert!(call_site_value.try_as_basic_value().is_right()); /// ``` @@ -126,7 +126,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute); /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute); @@ -156,7 +156,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// assert_eq!(call_site_value.get_called_fn_value(), fn_value); /// ``` @@ -186,7 +186,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute); /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute); @@ -219,7 +219,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute); /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute); @@ -277,7 +277,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute); /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute); @@ -317,7 +317,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute); /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute); @@ -364,7 +364,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute); /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute); @@ -398,7 +398,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.add_attribute(AttributeLoc::Return, string_attribute); /// call_site_value.add_attribute(AttributeLoc::Return, enum_attribute); @@ -439,7 +439,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// assert_eq!(call_site_value.count_arguments(), 0); /// ``` @@ -466,7 +466,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// assert_eq!(call_site_value.get_call_convention(), 0); /// ``` @@ -491,7 +491,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.set_call_convention(2); /// @@ -523,7 +523,7 @@ impl<'ctx> CallSiteValue<'ctx> { /// /// builder.position_at_end(entry_bb); /// - /// let call_site_value = builder.build_call(fn_value, &[], "my_fn"); + /// let call_site_value = builder.build_call(fn_value, &[], "my_fn").unwrap(); /// /// call_site_value.set_alignment_attribute(AttributeLoc::Param(0), 2); /// ``` diff --git a/src/values/callable_value.rs b/src/values/callable_value.rs index 31074931edd..a30c34d2545 100644 --- a/src/values/callable_value.rs +++ b/src/values/callable_value.rs @@ -34,12 +34,12 @@ use llvm_sys::LLVMTypeKind; /// /// builder.position_at_end(entry); /// -/// let ret_val = builder.build_call(fn_value, &[i32_arg.into()], "call") +/// let ret_val = builder.build_call(fn_value, &[i32_arg.into()], "call").unwrap() /// .try_as_basic_value() /// .left() /// .unwrap(); /// -/// builder.build_return(Some(&ret_val)); +/// builder.build_return(Some(&ret_val)).unwrap(); /// ``` /// /// A [`PointerValue`] cannot be implicitly converted to a `CallableValue` because the pointer may @@ -69,12 +69,12 @@ use llvm_sys::LLVMTypeKind; /// // explicitly handling the failure case (here with `unwrap`) /// let callable_value = CallableValue::try_from(fn_pointer_value).unwrap(); /// -/// let ret_val = builder.build_call(callable_value, &[i32_arg.into()], "call") +/// let ret_val = builder.build_call(callable_value, &[i32_arg.into()], "call").unwrap() /// .try_as_basic_value() /// .left() /// .unwrap(); /// -/// builder.build_return(Some(&ret_val)); +/// builder.build_return(Some(&ret_val)).unwrap(); /// ``` #[derive(Debug)] pub struct CallableValue<'ctx>(Either, PointerValue<'ctx>>); diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index f1951e12faf..bfc5dccef0e 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -369,9 +369,9 @@ impl<'ctx> InstructionValue<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// assert_eq!(store_instruction.get_num_operands(), 2); /// assert_eq!(free_instruction.get_num_operands(), 2); @@ -429,9 +429,9 @@ impl<'ctx> InstructionValue<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// assert!(store_instruction.get_operand(0).is_some()); /// assert!(store_instruction.get_operand(1).is_some()); @@ -512,9 +512,9 @@ impl<'ctx> InstructionValue<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// // This will produce invalid IR: /// free_instruction.set_operand(0, f32_val); @@ -555,9 +555,9 @@ impl<'ctx> InstructionValue<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// assert_eq!(store_instruction.get_operand_use(1), arg1.get_first_use()); /// ``` @@ -601,9 +601,9 @@ impl<'ctx> InstructionValue<'ctx> { /// /// let arg1 = function.get_first_param().unwrap().into_pointer_value(); /// let f32_val = f32_type.const_float(::std::f64::consts::PI); - /// let store_instruction = builder.build_store(arg1, f32_val); - /// let free_instruction = builder.build_free(arg1); - /// let return_instruction = builder.build_return(None); + /// let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + /// let free_instruction = builder.build_free(arg1).unwrap(); + /// let return_instruction = builder.build_return(None).unwrap(); /// /// assert!(arg1.get_first_use().is_some()); /// ``` diff --git a/src/values/mod.rs b/src/values/mod.rs index 6e2a5588aa5..d133d31325d 100644 --- a/src/values/mod.rs +++ b/src/values/mod.rs @@ -51,8 +51,8 @@ pub use crate::values::vec_value::VectorValue; use llvm_sys::core::LLVMIsPoison; use llvm_sys::core::{ - LLVMDumpValue, LLVMGetFirstUse, LLVMGetSection, LLVMIsAInstruction, LLVMIsConstant, LLVMIsNull, - LLVMIsUndef, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMReplaceAllUsesWith, LLVMSetSection, LLVMTypeOf, + LLVMDumpValue, LLVMGetFirstUse, LLVMGetSection, LLVMIsAInstruction, LLVMIsConstant, LLVMIsNull, LLVMIsUndef, + LLVMPrintTypeToString, LLVMPrintValueToString, LLVMReplaceAllUsesWith, LLVMSetSection, LLVMTypeOf, }; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; @@ -205,7 +205,13 @@ impl<'ctx> Value<'ctx> { /// Sets the section of the global value fn set_section(self, section: Option<&str>) { #[cfg(target_os = "macos")] - let section = section.map(|s| if s.contains(",") { format!("{}", s) } else { format!(",{}", s) }); + let section = section.map(|s| { + if s.contains(",") { + format!("{}", s) + } else { + format!(",{}", s) + } + }); let c_string = section.as_deref().map(to_c_str); diff --git a/src/values/traits.rs b/src/values/traits.rs index ccaf7d6eade..47084670538 100644 --- a/src/values/traits.rs +++ b/src/values/traits.rs @@ -94,7 +94,7 @@ pub unsafe trait BasicValue<'ctx>: AnyValue<'ctx> { } /// Most `BasicValue`s are the byproduct of an instruction - /// and so are convertable into an `InstructionValue` + /// and so are convertible into an `InstructionValue` fn as_instruction_value(&self) -> Option> { let value = unsafe { Value::new(self.as_value_ref()) }; diff --git a/src/values/vec_value.rs b/src/values/vec_value.rs index 8051817407d..79667e00f25 100644 --- a/src/values/vec_value.rs +++ b/src/values/vec_value.rs @@ -1,6 +1,6 @@ use llvm_sys::core::{ - LLVMConstExtractElement, LLVMConstInsertElement, LLVMConstSelect, LLVMConstShuffleVector, - LLVMGetElementAsConstant, LLVMIsAConstantDataVector, LLVMIsAConstantVector, + LLVMConstExtractElement, LLVMConstInsertElement, LLVMConstSelect, LLVMConstShuffleVector, LLVMGetElementAsConstant, + LLVMIsAConstantDataVector, LLVMIsAConstantVector, }; use llvm_sys::prelude::LLVMValueRef; diff --git a/tests/all/test_attributes.rs b/tests/all/test_attributes.rs index b0f19e20976..17e8942bc26 100644 --- a/tests/all/test_attributes.rs +++ b/tests/all/test_attributes.rs @@ -94,7 +94,7 @@ fn test_attributes_on_function_values() { builder.position_at_end(entry_bb); let null: BasicValueEnum = i32_ptr_type.const_null().into(); - builder.build_return(Some(&null)); + builder.build_return(Some(&null)).unwrap(); assert_eq!(fn_value.count_attributes(AttributeLoc::Return), 0); assert_eq!(fn_value.count_attributes(AttributeLoc::Param(0)), 0); @@ -175,9 +175,11 @@ fn test_attributes_on_call_site_values() { builder.position_at_end(entry_bb); - let call_site_value = builder.build_call(fn_value, &[i32_type.const_int(1, false).into()], "my_fn"); + let call_site_value = builder + .build_call(fn_value, &[i32_type.const_int(1, false).into()], "my_fn") + .unwrap(); - builder.build_return(None); + builder.build_return(None).unwrap(); assert_eq!(call_site_value.count_arguments(), 1); assert_eq!(call_site_value.count_attributes(AttributeLoc::Return), 0); diff --git a/tests/all/test_basic_block.rs b/tests/all/test_basic_block.rs index 9d906be9c96..f4c52da0727 100644 --- a/tests/all/test_basic_block.rs +++ b/tests/all/test_basic_block.rs @@ -123,7 +123,7 @@ fn test_get_terminator() { assert!(basic_block.get_first_instruction().is_none()); assert!(basic_block.get_last_instruction().is_none()); - builder.build_return(None); + builder.build_return(None).unwrap(); assert_eq!( basic_block.get_terminator().unwrap().get_opcode(), @@ -178,7 +178,7 @@ fn test_rauw() { let bb1 = context.append_basic_block(fn_val, "bb1"); let bb2 = context.append_basic_block(fn_val, "bb2"); builder.position_at_end(entry); - let branch_inst = builder.build_unconditional_branch(bb1); + let branch_inst = builder.build_unconditional_branch(bb1).unwrap(); bb1.replace_all_uses_with(&bb1); // no-op bb1.replace_all_uses_with(&bb2); @@ -198,7 +198,7 @@ fn test_get_first_use() { let bb1 = context.append_basic_block(fn_val, "bb1"); let bb2 = context.append_basic_block(fn_val, "bb2"); builder.position_at_end(entry); - let branch_inst = builder.build_unconditional_branch(bb1); + let branch_inst = builder.build_unconditional_branch(bb1).unwrap(); assert!(bb2.get_first_use().is_none()); assert!(bb1.get_first_use().is_some()); diff --git a/tests/all/test_builder.rs b/tests/all/test_builder.rs index dd3deffb798..ac11f2bafbe 100644 --- a/tests/all/test_builder.rs +++ b/tests/all/test_builder.rs @@ -1,3 +1,4 @@ +use inkwell::builder::BuilderError; use inkwell::context::Context; use inkwell::{AddressSpace, AtomicOrdering, AtomicRMWBinOp, OptimizationLevel}; @@ -20,14 +21,14 @@ fn test_build_call() { let pi = f32_type.const_float(::std::f64::consts::PI); - builder.build_return(Some(&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 pi2_call_site = builder.build_call(function, &[], "get_pi"); + let pi2_call_site = builder.build_call(function, &[], "get_pi").unwrap(); assert!(!pi2_call_site.is_tail_call()); @@ -37,7 +38,7 @@ fn test_build_call() { let pi2 = pi2_call_site.try_as_basic_value().left().unwrap(); - builder.build_return(Some(&pi2)); + builder.build_return(Some(&pi2)).unwrap(); assert!(module.verify().is_ok()); @@ -51,9 +52,9 @@ fn test_build_call() { builder.position_at_end(basic_block3); - let alloca = builder.build_alloca(fn_ptr_type, "alloca"); + let alloca = builder.build_alloca(fn_ptr_type, "alloca").unwrap(); - builder.build_store(alloca, fn_ptr); + builder.build_store(alloca, fn_ptr).unwrap(); #[cfg(any( feature = "llvm4-0", @@ -68,9 +69,12 @@ fn test_build_call() { feature = "llvm13-0", feature = "llvm14-0" ))] - let load = builder.build_load(alloca, "load").into_pointer_value(); + let load = builder.build_load(alloca, "load").unwrap().into_pointer_value(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let load = builder.build_load(fn_ptr_type, alloca, "load").into_pointer_value(); + let load = builder + .build_load(fn_ptr_type, alloca, "load") + .unwrap() + .into_pointer_value(); #[cfg(any( feature = "llvm4-0", @@ -88,11 +92,11 @@ fn test_build_call() { { use inkwell::values::CallableValue; let callable_value = CallableValue::try_from(load).unwrap(); - builder.build_call(callable_value, &[], "call"); + builder.build_call(callable_value, &[], "call").unwrap(); } #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] builder.build_indirect_call(fn_type2, load, &[], "call"); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(module.verify().is_ok()); } @@ -114,7 +118,7 @@ fn test_build_invoke_cleanup_resume() { let pi = f32_type.const_float(::std::f64::consts::PI); - builder.build_return(Some(&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"); @@ -124,7 +128,9 @@ fn test_build_invoke_cleanup_resume() { 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"); + let call_site = builder + .build_invoke(function, &[], then_block, catch_block, "get_pi") + .unwrap(); assert!(!call_site.is_tail_call()); @@ -137,7 +143,7 @@ fn test_build_invoke_cleanup_resume() { let result = call_site.try_as_basic_value().left().unwrap(); - builder.build_return(Some(&result)); + builder.build_return(Some(&result)).unwrap(); } { @@ -155,11 +161,13 @@ fn test_build_invoke_cleanup_resume() { let i32_type = context.i32_type(); let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); - let res = builder.build_landing_pad(exception_type, personality_function, &[], true, "res"); + let res = builder + .build_landing_pad(exception_type, personality_function, &[], true, "res") + .unwrap(); // do cleanup ... - builder.build_resume(res); + builder.build_resume(res).unwrap(); } assert!(module.verify().is_ok()); @@ -181,7 +189,7 @@ fn test_build_invoke_catch_all() { let pi = f32_type.const_float(::std::f64::consts::PI); - builder.build_return(Some(&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"); @@ -191,7 +199,9 @@ fn test_build_invoke_catch_all() { let then_block = context.append_basic_block(function2, "then_block"); let catch_block = context.append_basic_block(function2, "catch_block"); - let pi2_call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi"); + let pi2_call_site = builder + .build_invoke(function, &[], then_block, catch_block, "get_pi") + .unwrap(); assert!(!pi2_call_site.is_tail_call()); @@ -204,7 +214,7 @@ fn test_build_invoke_catch_all() { let pi2 = pi2_call_site.try_as_basic_value().left().unwrap(); - builder.build_return(Some(&pi2)); + builder.build_return(Some(&pi2)).unwrap(); } { @@ -223,11 +233,13 @@ fn test_build_invoke_catch_all() { let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false); let null = i8_ptr_type.const_zero(); - builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res"); + builder + .build_landing_pad(exception_type, personality_function, &[null.into()], false, "res") + .unwrap(); let fakepi = f32_type.const_zero(); - builder.build_return(Some(&fakepi)); + builder.build_return(Some(&fakepi)).unwrap(); } assert!(module.verify().is_ok()); @@ -252,7 +264,7 @@ fn landing_pad_filter() { let pi = f32_type.const_float(::std::f64::consts::PI); - builder.build_return(Some(&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"); @@ -262,7 +274,9 @@ fn landing_pad_filter() { let then_block = context.append_basic_block(function2, "then_block"); let catch_block = context.append_basic_block(function2, "catch_block"); - let pi2_call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi"); + let pi2_call_site = builder + .build_invoke(function, &[], then_block, catch_block, "get_pi") + .unwrap(); assert!(!pi2_call_site.is_tail_call()); @@ -275,7 +289,7 @@ fn landing_pad_filter() { let pi2 = pi2_call_site.try_as_basic_value().left().unwrap(); - builder.build_return(Some(&pi2)); + builder.build_return(Some(&pi2)).unwrap(); } { @@ -299,17 +313,19 @@ fn landing_pad_filter() { // make the filter landing pad let filter_pattern = i8_ptr_type.const_array(&[type_info_int.as_any_value_enum().into_pointer_value()]); - builder.build_landing_pad( - exception_type, - personality_function, - &[filter_pattern.into()], - false, - "res", - ); + builder + .build_landing_pad( + exception_type, + personality_function, + &[filter_pattern.into()], + false, + "res", + ) + .unwrap(); let fakepi = f32_type.const_zero(); - builder.build_return(Some(&fakepi)); + builder.build_return(Some(&fakepi)).unwrap(); } module.print_to_stderr(); @@ -345,23 +361,25 @@ fn test_null_checked_ptr_ops() { let ptr = function.get_first_param().unwrap().into_pointer_value(); - let is_null = builder.build_is_null(ptr, "is_null"); + let is_null = builder.build_is_null(ptr, "is_null").unwrap(); let ret_0 = context.append_basic_block(function, "ret_0"); let ret_idx = context.append_basic_block(function, "ret_idx"); - builder.build_conditional_branch(is_null, ret_0, ret_idx); + builder.build_conditional_branch(is_null, ret_0, ret_idx).unwrap(); builder.position_at_end(ret_0); - builder.build_return(Some(&neg_one)); + builder.build_return(Some(&neg_one)).unwrap(); builder.position_at_end(ret_idx); // FIXME: This might not work if compiled on non 64bit devices. Ideally we'd // be able to create pointer sized ints easily - let ptr_as_int = builder.build_ptr_to_int(ptr, i64_type, "ptr_as_int"); - let new_ptr_as_int = builder.build_int_add(ptr_as_int, one, "add"); - let new_ptr = builder.build_int_to_ptr(new_ptr_as_int, i8_ptr_type, "int_as_ptr"); + let ptr_as_int = builder.build_ptr_to_int(ptr, i64_type, "ptr_as_int").unwrap(); + let new_ptr_as_int = builder.build_int_add(ptr_as_int, one, "add").unwrap(); + let new_ptr = builder + .build_int_to_ptr(new_ptr_as_int, i8_ptr_type, "int_as_ptr") + .unwrap(); #[cfg(any( feature = "llvm4-0", feature = "llvm5-0", @@ -375,11 +393,11 @@ fn test_null_checked_ptr_ops() { feature = "llvm13-0", feature = "llvm14-0" ))] - let index1 = builder.build_load(new_ptr, "deref"); + let index1 = builder.build_load(new_ptr, "deref").unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let index1 = builder.build_load(i8_ptr_type, new_ptr, "deref"); + let index1 = builder.build_load(i8_ptr_type, new_ptr, "deref").unwrap(); - builder.build_return(Some(&index1)); + builder.build_return(Some(&index1)).unwrap(); // Here we're going to create a function that looks roughly like: // fn check_null_index2(ptr: *const i8) -> i8 { @@ -397,23 +415,25 @@ fn test_null_checked_ptr_ops() { let ptr = function.get_first_param().unwrap().into_pointer_value(); - let is_not_null = builder.build_is_not_null(ptr, "is_not_null"); + let is_not_null = builder.build_is_not_null(ptr, "is_not_null").unwrap(); let ret_idx = context.append_basic_block(function, "ret_idx"); let ret_0 = context.append_basic_block(function, "ret_0"); - builder.build_conditional_branch(is_not_null, ret_idx, ret_0); + builder.build_conditional_branch(is_not_null, ret_idx, ret_0).unwrap(); builder.position_at_end(ret_0); - builder.build_return(Some(&neg_one)); + builder.build_return(Some(&neg_one)).unwrap(); builder.position_at_end(ret_idx); // FIXME: This might not work if compiled on non 64bit devices. Ideally we'd // be able to create pointer sized ints easily - let ptr_as_int = builder.build_ptr_to_int(ptr, i64_type, "ptr_as_int"); - let new_ptr_as_int = builder.build_int_add(ptr_as_int, one, "add"); - let new_ptr = builder.build_int_to_ptr(new_ptr_as_int, i8_ptr_type, "int_as_ptr"); + let ptr_as_int = builder.build_ptr_to_int(ptr, i64_type, "ptr_as_int").unwrap(); + let new_ptr_as_int = builder.build_int_add(ptr_as_int, one, "add").unwrap(); + let new_ptr = builder + .build_int_to_ptr(new_ptr_as_int, i8_ptr_type, "int_as_ptr") + .unwrap(); #[cfg(any( feature = "llvm4-0", feature = "llvm5-0", @@ -427,11 +447,11 @@ fn test_null_checked_ptr_ops() { feature = "llvm13-0", feature = "llvm14-0" ))] - let index1 = builder.build_load(new_ptr, "deref"); + let index1 = builder.build_load(new_ptr, "deref").unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let index1 = builder.build_load(i8_ptr_type, new_ptr, "deref"); + let index1 = builder.build_load(i8_ptr_type, new_ptr, "deref").unwrap(); - builder.build_return(Some(&index1)); + builder.build_return(Some(&index1)).unwrap(); let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap(); @@ -476,9 +496,9 @@ fn test_binary_ops() { let left = fn_value.get_first_param().unwrap().into_int_value(); let right = fn_value.get_last_param().unwrap().into_int_value(); - let and = builder.build_and(left, right, "and_op"); + let and = builder.build_and(left, right, "and_op").unwrap(); - builder.build_return(Some(&and)); + builder.build_return(Some(&and)).unwrap(); // Here we're going to create an or function which looks roughly like: // fn or(left: bool, right: bool) -> bool { @@ -493,9 +513,9 @@ fn test_binary_ops() { let left = fn_value.get_first_param().unwrap().into_int_value(); let right = fn_value.get_last_param().unwrap().into_int_value(); - let or = builder.build_or(left, right, "or_op"); + let or = builder.build_or(left, right, "or_op").unwrap(); - builder.build_return(Some(&or)); + builder.build_return(Some(&or)).unwrap(); // Here we're going to create a xor function which looks roughly like: // fn xor(left: bool, right: bool) -> bool { @@ -510,9 +530,9 @@ fn test_binary_ops() { let left = fn_value.get_first_param().unwrap().into_int_value(); let right = fn_value.get_last_param().unwrap().into_int_value(); - let xor = builder.build_xor(left, right, "xor_op"); + let xor = builder.build_xor(left, right, "xor_op").unwrap(); - builder.build_return(Some(&xor)); + builder.build_return(Some(&xor)).unwrap(); unsafe { type BoolFunc = unsafe extern "C" fn(bool, bool) -> bool; @@ -571,19 +591,21 @@ fn test_switch() { let value = fn_value.get_first_param().unwrap().into_int_value(); builder.position_at_end(entry); - builder.build_switch(value, else_, &[(i8_zero, check), (i8_42, elif)]); + builder + .build_switch(value, else_, &[(i8_zero, check), (i8_42, elif)]) + .unwrap(); builder.position_at_end(check); - builder.build_return(Some(&i8_one)); + builder.build_return(Some(&i8_one)).unwrap(); builder.position_at_end(elif); - builder.build_return(Some(&i8_255)); + builder.build_return(Some(&i8_255)).unwrap(); builder.position_at_end(else_); - let double = builder.build_int_mul(value, i8_two, "double"); + let double = builder.build_int_mul(value, i8_two, "double").unwrap(); - builder.build_return(Some(&double)); + builder.build_return(Some(&double)).unwrap(); unsafe { let switch = execution_engine @@ -619,9 +641,9 @@ fn test_bit_shifts() { builder.position_at_end(entry); - let shift = builder.build_left_shift(value, bits, "shl"); + let shift = builder.build_left_shift(value, bits, "shl").unwrap(); - builder.build_return(Some(&shift)); + builder.build_return(Some(&shift)).unwrap(); // Here we're going to create a function which looks roughly like: // fn right_shift(value: u8, bits: u8) -> u8 { @@ -635,9 +657,9 @@ fn test_bit_shifts() { builder.position_at_end(entry); - let shift = builder.build_right_shift(value, bits, false, "shr"); + let shift = builder.build_right_shift(value, bits, false, "shr").unwrap(); - builder.build_return(Some(&shift)); + builder.build_return(Some(&shift)).unwrap(); // Here we're going to create a function which looks roughly like: // fn right_shift(value: u8, bits: u8) -> u8 { @@ -651,9 +673,9 @@ fn test_bit_shifts() { builder.position_at_end(entry); - let shift = builder.build_right_shift(value, bits, true, "shr"); + let shift = builder.build_right_shift(value, bits, true, "shr").unwrap(); - builder.build_return(Some(&shift)); + builder.build_return(Some(&shift)).unwrap(); unsafe { let left_shift = execution_engine @@ -709,10 +731,10 @@ fn test_unconditional_branch() { let end_bb = context.append_basic_block(fn_value, "end"); builder.position_at_end(entry_bb); - builder.build_unconditional_branch(end_bb); + builder.build_unconditional_branch(end_bb).unwrap(); builder.position_at_end(skipped_bb); - builder.build_unreachable(); + builder.build_unreachable().unwrap(); } #[test] @@ -774,9 +796,9 @@ fn test_vector_convert_ops() { builder.position_at_end(entry); let in_vec = fn_value.get_first_param().unwrap().into_vector_value(); - let casted_vec = builder.build_int_cast(in_vec, int32_vec_type, "casted_vec"); + let casted_vec = builder.build_int_cast(in_vec, int32_vec_type, "casted_vec").unwrap(); let _uncasted_vec = builder.build_int_cast(casted_vec, int8_vec_type, "uncasted_vec"); - builder.build_return(Some(&casted_vec)); + builder.build_return(Some(&casted_vec)).unwrap(); assert!(fn_value.verify(true)); // Here we're building a function that takes in a <3 x f32> and returns it casted to and from a <3 x f16> @@ -787,9 +809,11 @@ fn test_vector_convert_ops() { builder.position_at_end(entry); let in_vec = fn_value.get_first_param().unwrap().into_vector_value(); - let casted_vec = builder.build_float_cast(in_vec, float16_vec_type, "casted_vec"); + let casted_vec = builder + .build_float_cast(in_vec, float16_vec_type, "casted_vec") + .unwrap(); let _uncasted_vec = builder.build_float_cast(casted_vec, float32_vec_type, "uncasted_vec"); - builder.build_return(Some(&casted_vec)); + builder.build_return(Some(&casted_vec)).unwrap(); assert!(fn_value.verify(true)); // Here we're building a function that takes in a <3 x f32> and returns it casted to and from a <3 x i32> @@ -800,9 +824,11 @@ fn test_vector_convert_ops() { builder.position_at_end(entry); let in_vec = fn_value.get_first_param().unwrap().into_vector_value(); - let casted_vec = builder.build_float_to_signed_int(in_vec, int32_vec_type, "casted_vec"); + let casted_vec = builder + .build_float_to_signed_int(in_vec, int32_vec_type, "casted_vec") + .unwrap(); let _uncasted_vec = builder.build_signed_int_to_float(casted_vec, float32_vec_type, "uncasted_vec"); - builder.build_return(Some(&casted_vec)); + builder.build_return(Some(&casted_vec)).unwrap(); assert!(fn_value.verify(true)); } @@ -821,9 +847,11 @@ fn test_vector_convert_ops_respect_target_signedness() { builder.position_at_end(entry); let in_vec = fn_value.get_first_param().unwrap().into_vector_value(); - let casted_vec = builder.build_int_cast_sign_flag(in_vec, int8_vec_type, true, "casted_vec"); + let casted_vec = builder + .build_int_cast_sign_flag(in_vec, int8_vec_type, true, "casted_vec") + .unwrap(); let _uncasted_vec = builder.build_int_cast_sign_flag(casted_vec, int8_vec_type, true, "uncasted_vec"); - builder.build_return(Some(&casted_vec)); + builder.build_return(Some(&casted_vec)).unwrap(); assert!(fn_value.verify(true)); } @@ -849,9 +877,9 @@ fn test_vector_binary_ops() { let p1_vec = fn_value.get_first_param().unwrap().into_vector_value(); let p2_vec = fn_value.get_nth_param(1).unwrap().into_vector_value(); let p3_vec = fn_value.get_nth_param(2).unwrap().into_vector_value(); - let added_vec = builder.build_int_add(p1_vec, p2_vec, "added_vec"); - let added_vec = builder.build_int_add(added_vec, p3_vec, "added_vec"); - builder.build_return(Some(&added_vec)); + let added_vec = builder.build_int_add(p1_vec, p2_vec, "added_vec").unwrap(); + let added_vec = builder.build_int_add(added_vec, p3_vec, "added_vec").unwrap(); + builder.build_return(Some(&added_vec)).unwrap(); assert!(fn_value.verify(true)); // Here we're building a function that takes in three <2 x f32>s and returns x * y / z as an @@ -872,9 +900,9 @@ fn test_vector_binary_ops() { let p1_vec = fn_value.get_first_param().unwrap().into_vector_value(); let p2_vec = fn_value.get_nth_param(1).unwrap().into_vector_value(); let p3_vec = fn_value.get_nth_param(2).unwrap().into_vector_value(); - let multiplied_vec = builder.build_float_mul(p1_vec, p2_vec, "multipled_vec"); - let divided_vec = builder.build_float_div(multiplied_vec, p3_vec, "divided_vec"); - builder.build_return(Some(÷d_vec)); + let multiplied_vec = builder.build_float_mul(p1_vec, p2_vec, "multiplied_vec").unwrap(); + let divided_vec = builder.build_float_div(multiplied_vec, p3_vec, "divided_vec").unwrap(); + builder.build_return(Some(÷d_vec)).unwrap(); assert!(fn_value.verify(true)); // Here we're building a function that takes two <2 x f32>s and a <2 x bool> and returns (x < y) * z @@ -891,9 +919,11 @@ fn test_vector_binary_ops() { let p1_vec = fn_value.get_first_param().unwrap().into_vector_value(); let p2_vec = fn_value.get_nth_param(1).unwrap().into_vector_value(); let p3_vec = fn_value.get_nth_param(2).unwrap().into_vector_value(); - let compared_vec = builder.build_float_compare(inkwell::FloatPredicate::OLT, p1_vec, p2_vec, "compared_vec"); - let multiplied_vec = builder.build_int_mul(compared_vec, p3_vec, "multiplied_vec"); - builder.build_return(Some(&multiplied_vec)); + let compared_vec = builder + .build_float_compare(inkwell::FloatPredicate::OLT, p1_vec, p2_vec, "compared_vec") + .unwrap(); + let multiplied_vec = builder.build_int_mul(compared_vec, p3_vec, "multiplied_vec").unwrap(); + builder.build_return(Some(&multiplied_vec)).unwrap(); assert!(fn_value.verify(true)); } @@ -914,9 +944,9 @@ fn test_vector_pointer_ops() { builder.position_at_end(entry); let in_vec = fn_value.get_first_param().unwrap().into_vector_value(); - let ptr_vec = builder.build_int_to_ptr(in_vec, i8_ptr_vec_type, "ptr_vec"); - let is_null_vec = builder.build_is_null(ptr_vec, "is_null_vec"); - builder.build_return(Some(&is_null_vec)); + let ptr_vec = builder.build_int_to_ptr(in_vec, i8_ptr_vec_type, "ptr_vec").unwrap(); + let is_null_vec = builder.build_is_null(ptr_vec, "is_null_vec").unwrap(); + builder.build_return(Some(&is_null_vec)).unwrap(); assert!(fn_value.verify(true)); } @@ -936,7 +966,7 @@ fn test_insert_value() { builder.position_at_end(entry); - let array_alloca = builder.build_alloca(array_type, "array_alloca"); + let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap(); #[cfg(any( feature = "llvm4-0", feature = "llvm5-0", @@ -950,10 +980,14 @@ fn test_insert_value() { feature = "llvm13-0", feature = "llvm14-0" ))] - let array = builder.build_load(array_alloca, "array_load").into_array_value(); + let array = builder + .build_load(array_alloca, "array_load") + .unwrap() + .into_array_value(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] let array = builder .build_load(array_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); @@ -972,15 +1006,21 @@ fn test_insert_value() { .build_insert_value(array, const_int3, 2, "insert") .unwrap() .is_array_value()); - assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_none()); - assert!(builder.build_insert_value(array, const_int3, 4, "insert").is_none()); + assert!(builder + .build_insert_value(array, const_int3, 3, "insert") + .is_err_and(|e| e == BuilderError::ExtractOutOfRange)); + assert!(builder + .build_insert_value(array, const_int3, 4, "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_none()); + assert!(builder + .build_extract_value(array, 3, "extract") + .is_err_and(|e| e == BuilderError::ExtractOutOfRange)); - let struct_alloca = builder.build_alloca(struct_type, "struct_alloca"); + let struct_alloca = builder.build_alloca(struct_type, "struct_alloca").unwrap(); #[cfg(any( feature = "llvm4-0", feature = "llvm5-0", @@ -994,10 +1034,14 @@ fn test_insert_value() { feature = "llvm13-0", feature = "llvm14-0" ))] - let struct_value = builder.build_load(struct_alloca, "struct_load").into_struct_value(); + let struct_value = builder + .build_load(struct_alloca, "struct_load") + .unwrap() + .into_struct_value(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] let struct_value = builder .build_load(struct_type, struct_alloca, "struct_load") + .unwrap() .into_struct_value(); assert!(builder @@ -1010,10 +1054,10 @@ fn test_insert_value() { .is_struct_value()); assert!(builder .build_insert_value(struct_value, const_float, 2, "insert") - .is_none()); + .is_err_and(|e| e == BuilderError::ExtractOutOfRange)); assert!(builder .build_insert_value(struct_value, const_float, 3, "insert") - .is_none()); + .is_err_and(|e| e == BuilderError::ExtractOutOfRange)); assert!(builder .build_extract_value(struct_value, 0, "extract") @@ -1023,10 +1067,14 @@ fn test_insert_value() { .build_extract_value(struct_value, 1, "extract") .unwrap() .is_float_value()); - assert!(builder.build_extract_value(struct_value, 2, "extract").is_none()); - assert!(builder.build_extract_value(struct_value, 3, "extract").is_none()); + assert!(builder + .build_extract_value(struct_value, 2, "extract") + .is_err_and(|e| e == BuilderError::ExtractOutOfRange)); + assert!(builder + .build_extract_value(struct_value, 3, "extract") + .is_err_and(|e| e == BuilderError::ExtractOutOfRange)); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(module.verify().is_ok()); } @@ -1058,12 +1106,20 @@ fn test_insert_element() { let i8_ty = context.i8_type(); let i32_ty = context.i32_type(); let mut v = get_empty_vector_of(i8_ty); - v = builder.build_insert_element(v, i8_ty.const_int(0, false), i32_ty.const_int(0, false), "v0"); - v = builder.build_insert_element(v, i8_ty.const_int(1, false), i32_ty.const_int(1, false), "v1"); - v = builder.build_insert_element(v, i8_ty.const_int(2, false), i32_ty.const_int(2, false), "v2"); - v = builder.build_insert_element(v, i8_ty.const_int(3, false), i32_ty.const_int(3, false), "v3"); - - builder.build_return(None); + v = builder + .build_insert_element(v, i8_ty.const_int(0, false), i32_ty.const_int(0, false), "v0") + .unwrap(); + v = builder + .build_insert_element(v, i8_ty.const_int(1, false), i32_ty.const_int(1, false), "v1") + .unwrap(); + v = builder + .build_insert_element(v, i8_ty.const_int(2, false), i32_ty.const_int(2, false), "v2") + .unwrap(); + v = builder + .build_insert_element(v, i8_ty.const_int(3, false), i32_ty.const_int(3, false), "v3") + .unwrap(); + + builder.build_return(None).unwrap(); assert!(module.verify().is_ok()); } @@ -1118,7 +1174,7 @@ fn run_memcpy_on<'ctx>( context: &'ctx Context, module: &inkwell::module::Module<'ctx>, alignment: u32, -) -> Result<(), &'static str> { +) -> Result<(), BuilderError> { let i32_type = context.i32_type(); let i64_type = context.i64_type(); let array_len = 4; @@ -1150,12 +1206,16 @@ fn run_memcpy_on<'ctx>( feature = "llvm13-0", feature = "llvm14-0" ))] - let elem_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }; + let elem_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let elem_ptr = unsafe { builder.build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") }; + let elem_ptr = unsafe { + builder + .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") + .unwrap() + }; let int_val = i32_type.const_int(index + 1, false); - builder.build_store(elem_ptr, int_val); + builder.build_store(elem_ptr, int_val).unwrap(); } // Memcpy the first half of the array over the second half of the array. @@ -1176,13 +1236,17 @@ fn run_memcpy_on<'ctx>( feature = "llvm13-0", feature = "llvm14-0" ))] - let dest_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }; + let dest_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let dest_ptr = unsafe { builder.build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") }; + let dest_ptr = unsafe { + builder + .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") + .unwrap() + }; builder.build_memcpy(dest_ptr, alignment, array_ptr, alignment, size_val)?; - builder.build_return(Some(&array_ptr)); + builder.build_return(Some(&array_ptr)).unwrap(); Ok(()) } @@ -1220,7 +1284,7 @@ fn run_memmove_on<'ctx>( context: &'ctx Context, module: &inkwell::module::Module<'ctx>, alignment: u32, -) -> Result<(), &'static str> { +) -> Result<(), BuilderError> { let i32_type = context.i32_type(); let i64_type = context.i64_type(); let array_len = 4; @@ -1252,12 +1316,16 @@ fn run_memmove_on<'ctx>( feature = "llvm13-0", feature = "llvm14-0" ))] - let elem_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }; + let elem_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let elem_ptr = unsafe { builder.build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") }; + let elem_ptr = unsafe { + builder + .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") + .unwrap() + }; let int_val = i32_type.const_int(index + 1, false); - builder.build_store(elem_ptr, int_val); + builder.build_store(elem_ptr, int_val).unwrap(); } // Memcpy the first half of the array over the second half of the array. @@ -1278,13 +1346,17 @@ fn run_memmove_on<'ctx>( feature = "llvm13-0", feature = "llvm14-0" ))] - let dest_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }; + let dest_ptr = unsafe { builder.build_in_bounds_gep(array_ptr, &[index_val], "index") }.unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let dest_ptr = unsafe { builder.build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") }; + let dest_ptr = unsafe { + builder + .build_in_bounds_gep(element_type, array_ptr, &[index_val], "index") + .unwrap() + }; builder.build_memmove(dest_ptr, alignment, array_ptr, alignment, size_val)?; - builder.build_return(Some(&array_ptr)); + builder.build_return(Some(&array_ptr)).unwrap(); Ok(()) } @@ -1322,7 +1394,7 @@ fn run_memset_on<'ctx>( context: &'ctx Context, module: &inkwell::module::Module<'ctx>, alignment: u32, -) -> Result<(), &'static str> { +) -> Result<(), BuilderError> { let i8_type = context.i8_type(); let i32_type = context.i32_type(); let i64_type = context.i64_type(); @@ -1361,11 +1433,15 @@ fn run_memset_on<'ctx>( feature = "llvm13-0", feature = "llvm14-0" ))] - let part_2 = unsafe { builder.build_in_bounds_gep(array_ptr, &[index], "index") }; + let part_2 = unsafe { builder.build_in_bounds_gep(array_ptr, &[index], "index") }.unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let part_2 = unsafe { builder.build_in_bounds_gep(element_type, array_ptr, &[index], "index") }; + let part_2 = unsafe { + builder + .build_in_bounds_gep(element_type, array_ptr, &[index], "index") + .unwrap() + }; builder.build_memset(part_2, alignment, val, size_val)?; - builder.build_return(Some(&array_ptr)); + builder.build_return(Some(&array_ptr)).unwrap(); Ok(()) } @@ -1431,20 +1507,20 @@ fn test_bitcast() { builder.position_at_end(entry); - let cast = builder.build_bitcast(i32_arg, f32_type, "i32tof32"); + let cast = builder.build_bitcast(i32_arg, f32_type, "i32tof32").unwrap(); - builder.build_bitcast(f32_arg, f32_type, "f32tof32"); - builder.build_bitcast(i32_vec_arg, i64_type, "2xi32toi64"); - builder.build_bitcast(i32_ptr_arg, i64_ptr_type, "i32*toi64*"); + builder.build_bitcast(f32_arg, f32_type, "f32tof32").unwrap(); + builder.build_bitcast(i32_vec_arg, i64_type, "2xi32toi64").unwrap(); + builder.build_bitcast(i32_ptr_arg, i64_ptr_type, "i32*toi64*").unwrap(); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(module.verify().is_ok(), "{}", module.print_to_string().to_string()); let first_iv = cast.as_instruction_value().unwrap(); builder.position_before(&first_iv); - builder.build_bitcast(f64_arg, i64_type, "f64toi64"); + builder.build_bitcast(f64_arg, i64_type, "f64toi64").unwrap(); assert!(module.verify().is_ok()); } diff --git a/tests/all/test_debug_info.rs b/tests/all/test_debug_info.rs index c94d0a0d35c..cf7575ffb52 100644 --- a/tests/all/test_debug_info.rs +++ b/tests/all/test_debug_info.rs @@ -76,7 +76,7 @@ fn test_smoke() { let basic_block = context.append_basic_block(fn_val, "entry"); builder.position_at_end(basic_block); - builder.build_return(Some(&context.i64_type().const_zero())); + builder.build_return(Some(&context.i64_type().const_zero())).unwrap(); let lexical_block = dibuilder.create_lexical_block(func_scope.as_debug_info_scope(), compile_unit.get_file(), 0, 0); diff --git a/tests/all/test_execution_engine.rs b/tests/all/test_execution_engine.rs index 71b083f4af1..8b15c20f4de 100644 --- a/tests/all/test_execution_engine.rs +++ b/tests/all/test_execution_engine.rs @@ -34,7 +34,7 @@ fn test_get_function_address() { let basic_block = context.append_basic_block(fn_value, "entry"); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap(); @@ -73,22 +73,24 @@ fn test_jit_execution_engine() { // If anything goes wrong, jump to returning 1 builder.position_at_end(error1); - builder.build_return(Some(&one_i32)); + builder.build_return(Some(&one_i32)).unwrap(); // If successful, jump to returning 42 builder.position_at_end(success); - builder.build_return(Some(&fourtytwo_i32)); + builder.build_return(Some(&fourtytwo_i32)).unwrap(); // See if argc == 3 builder.position_at_end(check_argc); let eq = IntPredicate::EQ; - let argc_check = builder.build_int_compare(eq, main_argc, three_i32, "argc_cmp"); + let argc_check = builder.build_int_compare(eq, main_argc, three_i32, "argc_cmp").unwrap(); - builder.build_conditional_branch(argc_check, check_arg3, error1); + builder + .build_conditional_branch(argc_check, check_arg3, error1) + .unwrap(); builder.position_at_end(check_arg3); - builder.build_unconditional_branch(success); + builder.build_unconditional_branch(success).unwrap(); Target::initialize_native(&InitializationConfig::default()).expect("Failed to initialize native target"); diff --git a/tests/all/test_instruction_conversion.rs b/tests/all/test_instruction_conversion.rs index f4d71474178..76bd421cae0 100644 --- a/tests/all/test_instruction_conversion.rs +++ b/tests/all/test_instruction_conversion.rs @@ -18,7 +18,7 @@ fn test_phi_conversion() { // test that conversion succeeds let bool_type = context.bool_type(); let expect_phi_name = "phi_node"; - let phi = builder.build_phi(bool_type, expect_phi_name); + let phi = builder.build_phi(bool_type, expect_phi_name).unwrap(); let instruction = phi.as_instruction(); let phi_from_instruction: PhiValue = instruction.try_into().unwrap(); @@ -26,7 +26,7 @@ fn test_phi_conversion() { assert_eq!(name, expect_phi_name); // test that conversion fails - let ret_instruction = builder.build_return(None); + let ret_instruction = builder.build_return(None).unwrap(); let phi_from_instruction: Result = ret_instruction.try_into(); assert!(phi_from_instruction.is_err()); } @@ -49,6 +49,7 @@ fn test_conversion_to_int_value() { let int_const = i64_type.const_int(1, false); let int_instr = builder .build_int_add(int_arg, int_const, "add") + .unwrap() .as_instruction() .unwrap(); @@ -81,6 +82,7 @@ fn test_conversion_to_float_value() { let float_const = f16_type.const_float(1.2); let float_instr = builder .build_float_add(float_arg, float_const, "add") + .unwrap() .as_instruction() .unwrap(); @@ -110,7 +112,11 @@ fn test_conversion_to_pointer_value() { // Create a PointerType instruction let i64_type = context.i64_type(); let i64_ptr_type = i64_type.ptr_type(AddressSpace::default()); - let alloca_instr = builder.build_alloca(i64_ptr_type, "alloca").as_instruction().unwrap(); + let alloca_instr = builder + .build_alloca(i64_ptr_type, "alloca") + .unwrap() + .as_instruction() + .unwrap(); // Test the instruction conversion to a FloatValue let ptr_conversion: Result = alloca_instr.try_into(); diff --git a/tests/all/test_instruction_values.rs b/tests/all/test_instruction_values.rs index 03c0e29f730..c9ed8231df6 100644 --- a/tests/all/test_instruction_values.rs +++ b/tests/all/test_instruction_values.rs @@ -21,9 +21,9 @@ fn test_operands() { let arg1 = function.get_first_param().unwrap().into_pointer_value(); let f32_val = f32_type.const_float(::std::f64::consts::PI); - let store_instruction = builder.build_store(arg1, f32_val); - let free_instruction = builder.build_free(arg1); - let return_instruction = builder.build_return(None); + let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + let free_instruction = builder.build_free(arg1).unwrap(); + let return_instruction = builder.build_return(None).unwrap(); assert_eq!(store_instruction.get_opcode(), Store); assert_eq!(free_instruction.get_opcode(), Call); @@ -47,7 +47,7 @@ fn test_operands() { let free_operand0 = free_instruction.get_operand(0).unwrap().left().unwrap(); let free_operand1 = free_instruction.get_operand(1).unwrap().left().unwrap(); - assert!(free_operand0.is_pointer_value()); // (implictly casted) i8* arg1 + assert!(free_operand0.is_pointer_value()); // (implicitly casted) i8* arg1 assert!(free_operand1.is_pointer_value()); // Free function ptr assert!(free_instruction.get_operand(2).is_none()); assert!(free_instruction.get_operand(3).is_none()); @@ -167,7 +167,7 @@ fn test_basic_block_operand() { builder.position_at_end(basic_block); - let branch_instruction = builder.build_unconditional_branch(basic_block2); + let branch_instruction = builder.build_unconditional_branch(basic_block2).unwrap(); let bb_operand = branch_instruction.get_operand(0).unwrap().right().unwrap(); assert_eq!(bb_operand, basic_block2); @@ -177,7 +177,7 @@ fn test_basic_block_operand() { assert_eq!(bb_operand_use.get_used_value().right().unwrap(), basic_block2); builder.position_at_end(basic_block2); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(module.verify().is_ok()); } @@ -196,10 +196,10 @@ fn test_get_next_use() { let arg1 = function.get_first_param().unwrap().into_float_value(); let f32_val = f32_type.const_float(::std::f64::consts::PI); - let add_pi0 = builder.build_float_add(arg1, f32_val, "add_pi"); - let add_pi1 = builder.build_float_add(add_pi0, f32_val, "add_pi"); + let add_pi0 = builder.build_float_add(arg1, f32_val, "add_pi").unwrap(); + let add_pi1 = builder.build_float_add(add_pi0, f32_val, "add_pi").unwrap(); - builder.build_return(Some(&add_pi1)); + builder.build_return(Some(&add_pi1)).unwrap(); // f32_val constant appears twice, so there are two uses (first, next) let first_use = f32_val.get_first_use().unwrap(); @@ -238,14 +238,16 @@ fn test_instructions() { let f32_val = f32_type.const_float(::std::f64::consts::PI); - let store_instruction = builder.build_store(arg1, f32_val); - let ptr_val = builder.build_ptr_to_int(arg1, i64_type, "ptr_val"); - let ptr = builder.build_int_to_ptr(ptr_val, f32_ptr_type, "ptr"); - let icmp = builder.build_int_compare(IntPredicate::EQ, arg1, arg1, "icmp"); - let f32_sum = builder.build_float_add(arg2, f32_val, "f32_sum"); - let fcmp = builder.build_float_compare(FloatPredicate::OEQ, f32_sum, arg2, "fcmp"); - let free_instruction = builder.build_free(arg1); - let return_instruction = builder.build_return(None); + let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + let ptr_val = builder.build_ptr_to_int(arg1, i64_type, "ptr_val").unwrap(); + let ptr = builder.build_int_to_ptr(ptr_val, f32_ptr_type, "ptr").unwrap(); + let icmp = builder.build_int_compare(IntPredicate::EQ, arg1, arg1, "icmp").unwrap(); + let f32_sum = builder.build_float_add(arg2, f32_val, "f32_sum").unwrap(); + let fcmp = builder + .build_float_compare(FloatPredicate::OEQ, f32_sum, arg2, "fcmp") + .unwrap(); + let free_instruction = builder.build_free(arg1).unwrap(); + let return_instruction = builder.build_return(None).unwrap(); assert_eq!(store_instruction.get_opcode(), Store); assert_eq!(ptr_val.as_instruction().unwrap().get_opcode(), PtrToInt); @@ -367,8 +369,8 @@ fn test_mem_instructions() { let f32_val = f32_type.const_float(::std::f64::consts::PI); - let store_instruction = builder.build_store(arg1, f32_val); - let load = builder.build_load(arg1, ""); + let store_instruction = builder.build_store(arg1, f32_val).unwrap(); + let load = builder.build_load(arg1, "").unwrap(); let load_instruction = load.as_instruction_value().unwrap(); assert_eq!(store_instruction.get_volatile().unwrap(), false); @@ -398,6 +400,7 @@ fn test_mem_instructions() { let fadd_instruction = builder .build_float_add(load.into_float_value(), f32_val, "") + .unwrap() .as_instruction_value() .unwrap(); assert!(fadd_instruction.get_volatile().is_err()); @@ -431,7 +434,7 @@ fn test_mem_instructions() { let f32_val = f32_type.const_float(::std::f64::consts::PI); - let store_instruction = builder.build_store(arg1, f32_val); + let store_instruction = builder.build_store(arg1, f32_val).unwrap(); #[cfg(any( feature = "llvm4-0", feature = "llvm5-0", @@ -445,9 +448,9 @@ fn test_mem_instructions() { feature = "llvm13-0", feature = "llvm14-0" ))] - let load = builder.build_load(arg1, ""); + let load = builder.build_load(arg1, "").unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let load = builder.build_load(f32_type, arg1, ""); + let load = builder.build_load(f32_type, arg1, "").unwrap(); let load_instruction = load.as_instruction_value().unwrap(); assert_eq!(store_instruction.get_volatile().unwrap(), false); @@ -477,6 +480,7 @@ fn test_mem_instructions() { let fadd_instruction = builder .build_float_add(load.into_float_value(), f32_val, "") + .unwrap() .as_instruction_value() .unwrap(); assert!(fadd_instruction.get_volatile().is_err()); @@ -509,7 +513,7 @@ fn test_atomic_ordering_mem_instructions() { let f32_val = f32_type.const_float(::std::f64::consts::PI); - let store_instruction = builder.build_store(arg1, f32_val); + let store_instruction = builder.build_store(arg1, f32_val).unwrap(); #[cfg(any( feature = "llvm4-0", feature = "llvm5-0", @@ -523,9 +527,9 @@ fn test_atomic_ordering_mem_instructions() { feature = "llvm13-0", feature = "llvm14-0" ))] - let load = builder.build_load(arg1, ""); + let load = builder.build_load(arg1, "").unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] - let load = builder.build_load(f32_type, arg1, ""); + let load = builder.build_load(f32_type, arg1, "").unwrap(); let load_instruction = load.as_instruction_value().unwrap(); assert_eq!( @@ -555,6 +559,7 @@ fn test_atomic_ordering_mem_instructions() { let fadd_instruction = builder .build_float_add(load.into_float_value(), f32_val, "") + .unwrap() .as_instruction_value() .unwrap(); assert!(fadd_instruction.get_atomic_ordering().is_err()); @@ -608,9 +613,9 @@ fn test_find_instruction_with_name() { let entry = context.append_basic_block(fn_value, "entry"); builder.position_at_end(entry); - let var = builder.build_alloca(i32_type, "some_number"); - builder.build_store(var, i32_type.const_int(1 as u64, false)); - builder.build_return(None); + let var = builder.build_alloca(i32_type, "some_number").unwrap(); + builder.build_store(var, i32_type.const_int(1 as u64, false)).unwrap(); + builder.build_return(None).unwrap(); let block = fn_value.get_first_basic_block().unwrap(); let some_number = block.get_instruction_with_name("some_number"); diff --git a/tests/all/test_module.rs b/tests/all/test_module.rs index af09073c368..f6e946c97bb 100644 --- a/tests/all/test_module.rs +++ b/tests/all/test_module.rs @@ -127,7 +127,7 @@ fn test_write_and_load_memory_buffer() { let basic_block = context.append_basic_block(function, "entry"); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); let memory_buffer = module.write_bitcode_to_memory(); @@ -234,7 +234,7 @@ fn test_parse_from_buffer() { let builder = context.create_builder(); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(module.verify().is_ok()); @@ -275,7 +275,7 @@ fn test_parse_from_path() { let builder = context.create_builder(); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(module.verify().is_ok(), "3"); @@ -303,7 +303,7 @@ fn test_clone() { let builder = context.create_builder(); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); let module2 = module.clone(); @@ -322,7 +322,7 @@ fn test_print_to_file() { let builder = context.create_builder(); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); let bad_path = Path::new("/tmp/some/silly/path/that/sure/doesn't/exist"); @@ -377,7 +377,7 @@ fn test_linking_modules() { let basic_block = context.append_basic_block(fn_val, "entry"); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); let module2 = context.create_module("mod2"); @@ -391,7 +391,7 @@ fn test_linking_modules() { let basic_block2 = context.append_basic_block(fn_val2, "entry"); builder.position_at_end(basic_block2); - builder.build_return(None); + builder.build_return(None).unwrap(); // Unowned module links in unowned module assert!(module.link_in_module(module3).is_ok()); @@ -413,10 +413,10 @@ fn test_linking_modules() { let basic_block3 = context.append_basic_block(fn_val3, "entry"); builder.position_at_end(basic_block3); - builder.build_return(None); + builder.build_return(None).unwrap(); // EE owned module links in unowned module which has - // another definition for the same funciton name, "f2" + // another definition for the same function name, "f2" assert_eq!( module.link_in_module(module5).unwrap_err().to_str(), Ok("Linking globals named \'f2\': symbol multiply defined!") @@ -427,7 +427,7 @@ fn test_linking_modules() { let basic_block4 = context.append_basic_block(fn_val4, "entry"); builder.position_at_end(basic_block4); - builder.build_return(None); + builder.build_return(None).unwrap(); let execution_engine2 = module6 .create_jit_execution_engine(OptimizationLevel::None) @@ -487,7 +487,7 @@ fn test_double_ee_from_same_module() { let basic_block = context.append_basic_block(fn_val, "entry"); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); module .create_execution_engine() diff --git a/tests/all/test_object_file.rs b/tests/all/test_object_file.rs index a1cf9703727..f6de74c6be6 100644 --- a/tests/all/test_object_file.rs +++ b/tests/all/test_object_file.rs @@ -86,7 +86,7 @@ fn test_section_iterator() { let basic_block = context.append_basic_block(func, "entry"); let builder = context.create_builder(); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); apply_target_to_module(&target_machine, &module); diff --git a/tests/all/test_passes.rs b/tests/all/test_passes.rs index e41fa5d62eb..2212cd3d09f 100644 --- a/tests/all/test_passes.rs +++ b/tests/all/test_passes.rs @@ -178,7 +178,7 @@ fn test_pass_manager_builder() { let entry = context.append_basic_block(fn_value, "entry"); builder.position_at_end(entry); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(!fn_pass_manager.initialize()); diff --git a/tests/all/test_targets.rs b/tests/all/test_targets.rs index 089211a29bf..9a374471735 100644 --- a/tests/all/test_targets.rs +++ b/tests/all/test_targets.rs @@ -14,7 +14,7 @@ use std::str::from_utf8; // REVIEW: Inconsistently failing on different tries :( // #[test] // fn test_target() { -// // REVIEW: Some of the machine specific stuff may vary. Should allow multiple possibilites +// // REVIEW: Some of the machine specific stuff may vary. Should allow multiple possibilities // assert!(Target::get_first().is_none()); // let mut config = InitializationConfig { diff --git a/tests/all/test_tari_example.rs b/tests/all/test_tari_example.rs index 940aa27ad1e..b306640069f 100644 --- a/tests/all/test_tari_example.rs +++ b/tests/all/test_tari_example.rs @@ -24,10 +24,10 @@ fn test_tari_example() { let y = function.get_nth_param(1).unwrap().into_int_value(); let z = function.get_nth_param(2).unwrap().into_int_value(); - let sum = builder.build_int_add(x, y, "sum"); - let sum = builder.build_int_add(sum, z, "sum"); + let sum = builder.build_int_add(x, y, "sum").unwrap(); + let sum = builder.build_int_add(sum, z, "sum").unwrap(); - builder.build_return(Some(&sum)); + builder.build_return(Some(&sum)).unwrap(); unsafe { type Sum = unsafe extern "C" fn(u64, u64, u64) -> u64; diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index 0491451f9ae..b8baeaaf25c 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -38,7 +38,11 @@ fn test_call_site() { let fn_type = void_type.fn_type(&[], false); let function = module.add_function("do_nothing", fn_type, None); - let call_site = builder.build_call(function, &[], "to_infinity_and_beyond"); + + let block = context.append_basic_block(function, "entry"); + builder.position_at_end(block); + + let call_site = builder.build_call(function, &[], "to_infinity_and_beyond").unwrap(); assert_eq!(call_site.count_arguments(), 0); assert!(!call_site.is_tail_call()); @@ -171,7 +175,7 @@ fn test_set_get_name() { let array_param = function.get_nth_param(3).unwrap().into_array_value(); let ptr_param = function.get_nth_param(4).unwrap().into_pointer_value(); let vec_param = function.get_nth_param(5).unwrap().into_vector_value(); - let phi_val = builder.build_phi(bool_type, "phi_node"); + let phi_val = builder.build_phi(bool_type, "phi_node").unwrap(); assert_eq!(int_param.get_name().to_str(), Ok("")); assert_eq!(float_param.get_name().to_str(), Ok("")); @@ -407,7 +411,7 @@ fn test_verify_fn() { let basic_block = context.append_basic_block(function, "entry"); builder.position_at_end(basic_block); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(function.verify(false)); @@ -579,7 +583,7 @@ fn test_metadata() { builder.position_at_end(entry_block); - let ret_instr = builder.build_return(None); + let ret_instr = builder.build_return(None).unwrap(); let ret_instr_md = context.metadata_node(&[md_string.into()]); assert!(ret_instr.set_metadata(ret_instr_md, 2).is_ok()); @@ -966,7 +970,7 @@ fn test_phi_values() { let false_val = bool_type.const_int(0, false); let true_val = bool_type.const_int(1, false); - let phi = builder.build_phi(bool_type, "if"); + let phi = builder.build_phi(bool_type, "if").unwrap(); assert!(!phi.is_null()); assert!(!phi.is_undef()); @@ -1022,11 +1026,11 @@ fn test_allocations() { // methods on positioned variant if so. But leave positioning methods // on both? - let stack_ptr = builder.build_alloca(i32_type, "stack_ptr"); + let stack_ptr = builder.build_alloca(i32_type, "stack_ptr").unwrap(); assert_eq!(stack_ptr.get_type().print_to_string().to_str(), Ok(ptr_type)); - let stack_array = builder.build_array_alloca(i32_type, i32_three, "stack_array"); + let stack_array = builder.build_array_alloca(i32_type, i32_three, "stack_array").unwrap(); assert_eq!(stack_array.get_type().print_to_string().to_str(), Ok(ptr_type)); @@ -1213,7 +1217,7 @@ fn test_function_value_to_global_to_pointer() { let bb = context.append_basic_block(fn_value, "entry"); builder.position_at_end(bb); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(!fn_global_value.is_declaration()); assert_eq!(fn_global_value.get_dll_storage_class(), DLLStorageClass::Default); @@ -1262,11 +1266,11 @@ fn test_non_fn_ptr_called() { { use inkwell::values::CallableValue; let callable_value = CallableValue::try_from(i8_ptr_param).unwrap(); - builder.build_call(callable_value, &[], "call"); + builder.build_call(callable_value, &[], "call").unwrap(); } #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] builder.build_indirect_call(i8_ptr_type.fn_type(&[], false), i8_ptr_param, &[], "call"); - builder.build_return(None); + builder.build_return(None).unwrap(); assert!(module.verify().is_ok()); } @@ -1286,11 +1290,15 @@ fn test_vectors() { let vector_param = fn_value.get_first_param().unwrap().into_vector_value(); builder.position_at_end(bb); - builder.build_insert_element(vector_param, i32_seven, i32_zero, "insert"); + builder + .build_insert_element(vector_param, i32_seven, i32_zero, "insert") + .unwrap(); - let extracted = builder.build_extract_element(vector_param, i32_zero, "extract"); + let extracted = builder + .build_extract_element(vector_param, i32_zero, "extract") + .unwrap(); - builder.build_return(Some(&extracted)); + builder.build_return(Some(&extracted)).unwrap(); assert!(module.verify().is_ok()); } @@ -1325,10 +1333,12 @@ fn test_aggregate_returns() { feature = "llvm13-0", feature = "llvm14-0" ))] - builder.build_ptr_diff(ptr_param1, ptr_param2, "diff"); + builder.build_ptr_diff(ptr_param1, ptr_param2, "diff").unwrap(); #[cfg(any(feature = "llvm15-0", feature = "llvm16-0"))] builder.build_ptr_diff(i32_ptr_type, ptr_param1, ptr_param2, "diff"); - builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]); + builder + .build_aggregate_return(&[i32_three.into(), i32_seven.into()]) + .unwrap(); assert!(module.verify().is_ok()); } @@ -1344,7 +1354,13 @@ fn test_constant_expression() { let fn_type = void_type.fn_type(&[], false); let function = module.add_function("", fn_type, None); - let expr = builder.build_ptr_to_int(function.as_global_value().as_pointer_value(), i32_type, ""); + + let block = context.append_basic_block(function, "entry"); + builder.position_at_end(block); + + let expr = builder + .build_ptr_to_int(function.as_global_value().as_pointer_value(), i32_type, "") + .unwrap(); assert!(expr.is_const()); assert!(!expr.is_constant_int());