inkwell/builder.rs
1//! A `Builder` enables you to build instructions.
2
3#[llvm_versions(18..)]
4use llvm_sys::core::LLVMBuildCallWithOperandBundles;
5use llvm_sys::core::{
6 LLVMAddCase, LLVMAddClause, LLVMAddDestination, LLVMBuildAShr, LLVMBuildAdd, LLVMBuildAddrSpaceCast,
7 LLVMBuildAggregateRet, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildArrayMalloc,
8 LLVMBuildAtomicCmpXchg, LLVMBuildAtomicRMW, LLVMBuildBinOp, LLVMBuildBitCast, LLVMBuildBr, LLVMBuildCast,
9 LLVMBuildCondBr, LLVMBuildExactSDiv, LLVMBuildExtractElement, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFCmp,
10 LLVMBuildFDiv, LLVMBuildFMul, LLVMBuildFNeg, LLVMBuildFPCast, LLVMBuildFPExt, LLVMBuildFPToSI, LLVMBuildFPToUI,
11 LLVMBuildFPTrunc, LLVMBuildFRem, LLVMBuildFSub, LLVMBuildFence, LLVMBuildFree, LLVMBuildGlobalString,
12 LLVMBuildGlobalStringPtr, LLVMBuildICmp, LLVMBuildIndirectBr, LLVMBuildInsertElement, LLVMBuildInsertValue,
13 LLVMBuildIntCast, LLVMBuildIntToPtr, LLVMBuildIsNotNull, LLVMBuildIsNull, LLVMBuildLShr, LLVMBuildLandingPad,
14 LLVMBuildMalloc, LLVMBuildMul, LLVMBuildNSWAdd, LLVMBuildNSWMul, LLVMBuildNSWNeg, LLVMBuildNSWSub, LLVMBuildNUWAdd,
15 LLVMBuildNUWMul, LLVMBuildNUWNeg, LLVMBuildNUWSub, LLVMBuildNeg, LLVMBuildNot, LLVMBuildOr, LLVMBuildPhi,
16 LLVMBuildPointerCast, LLVMBuildPtrToInt, LLVMBuildResume, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildSDiv,
17 LLVMBuildSExt, LLVMBuildSExtOrBitCast, LLVMBuildSIToFP, LLVMBuildSRem, LLVMBuildSelect, LLVMBuildShl,
18 LLVMBuildShuffleVector, LLVMBuildStore, LLVMBuildSub, LLVMBuildSwitch, LLVMBuildTrunc, LLVMBuildTruncOrBitCast,
19 LLVMBuildUDiv, LLVMBuildUIToFP, LLVMBuildURem, LLVMBuildUnreachable, LLVMBuildVAArg, LLVMBuildXor, LLVMBuildZExt,
20 LLVMBuildZExtOrBitCast, LLVMClearInsertionPosition, LLVMDisposeBuilder, LLVMGetInsertBlock, LLVMInsertIntoBuilder,
21 LLVMInsertIntoBuilderWithName, LLVMPositionBuilder, LLVMPositionBuilderAtEnd, LLVMPositionBuilderBefore,
22 LLVMSetCleanup,
23};
24#[llvm_versions(..=14)]
25use llvm_sys::core::{LLVMBuildCall, LLVMBuildInvoke};
26#[llvm_versions(15..)]
27use llvm_sys::core::{LLVMBuildCall2, LLVMBuildInvoke2};
28#[cfg(all(feature = "typed-pointers", not(feature = "llvm16-0")))]
29#[cfg_attr(feature = "llvm15-0", allow(deprecated))]
30use llvm_sys::core::{LLVMBuildGEP, LLVMBuildInBoundsGEP, LLVMBuildLoad, LLVMBuildPtrDiff, LLVMBuildStructGEP};
31#[cfg(any(not(feature = "typed-pointers"), feature = "llvm16-0"))]
32use llvm_sys::core::{LLVMBuildGEP2, LLVMBuildInBoundsGEP2, LLVMBuildLoad2, LLVMBuildPtrDiff2, LLVMBuildStructGEP2};
33#[llvm_versions(8..)]
34use llvm_sys::core::{LLVMBuildIntCast2, LLVMBuildMemCpy, LLVMBuildMemMove, LLVMBuildMemSet};
35
36use llvm_sys::prelude::{LLVMBuilderRef, LLVMValueRef};
37use thiserror::Error;
38
39use crate::basic_block::BasicBlock;
40#[llvm_versions(7..=8)]
41use crate::context::AsContextRef;
42#[llvm_versions(7..)]
43use crate::debug_info::DILocation;
44use crate::support::to_c_str;
45use crate::types::{AsTypeRef, BasicType, FloatMathType, FunctionType, IntMathType, PointerMathType, PointerType};
46#[llvm_versions(18..)]
47use crate::values::operand_bundle::OperandBundle;
48#[llvm_versions(..=14)]
49use crate::values::CallableValue;
50use crate::values::{
51 AggregateValue, AggregateValueEnum, AsValueRef, BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue,
52 FloatMathValue, FunctionValue, GlobalValue, InstructionOpcode, InstructionValue, IntMathValue, IntValue, PhiValue,
53 PointerMathValue, PointerValue, StructValue, VectorBaseValue,
54};
55
56use crate::{AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate};
57
58use std::cell::Cell;
59use std::marker::PhantomData;
60
61#[derive(Debug, PartialEq, Clone, Copy)]
62enum PositionState {
63 NotSet,
64 Set,
65}
66
67/// Errors that can be generated by the Builder. All `build_*` methods return a `Result<_, BuilderError>`, which must be handled.
68#[derive(Error, Debug, PartialEq, Eq)]
69pub enum BuilderError {
70 #[error("Builder position is not set")]
71 UnsetPosition,
72 #[error("Alignment error")]
73 AlignmentError(&'static str),
74 #[error("Aggregate extract index out of range")]
75 ExtractOutOfRange,
76 #[error("Bitwidth of a value is incorrect")]
77 BitwidthError(&'static str),
78 #[error("Pointee type does not match the value's type")]
79 PointeeTypeMismatch(&'static str),
80 #[error("Values do not have the same type")]
81 ValueTypeMismatch(&'static str),
82 #[error("Ordering error or mismatch")]
83 OrderingError(&'static str),
84 #[error("GEP pointee is not a struct")]
85 GEPPointee,
86 #[error("GEP index out of range")]
87 GEPIndex,
88}
89
90#[derive(Debug)]
91/// All `build_*` methods return a `Result<_, BuilderError>` type containing either the returned value or some error.
92/// Those methods all may return `BuilderError::UnsetPosition` if a `position_*` method has not yet been called, in addition
93/// to any other possibility.
94pub struct Builder<'ctx> {
95 builder: LLVMBuilderRef,
96 positioned: Cell<PositionState>,
97 _marker: PhantomData<&'ctx ()>,
98}
99
100#[allow(unused)] // only used in documentation
101use crate::context::Context;
102
103impl<'ctx> Builder<'ctx> {
104 pub unsafe fn new(builder: LLVMBuilderRef) -> Self {
105 debug_assert!(!builder.is_null());
106
107 Builder {
108 positioned: Cell::from(PositionState::NotSet),
109 builder,
110 _marker: PhantomData,
111 }
112 }
113
114 /// Acquires the underlying raw pointer belonging to this `Builder` type.
115 pub fn as_mut_ptr(&self) -> LLVMBuilderRef {
116 self.builder
117 }
118
119 // REVIEW: Would probably make this API a bit simpler by taking Into<Option<&BasicValue>>
120 // So that you could just do build_return(&value) or build_return(None). Is that frowned upon?
121 /// Builds a function return instruction. It should be provided with `None` if the return type
122 /// is void otherwise `Some(&value)` should be provided.
123 ///
124 /// # Example
125 ///
126 /// ```no_run
127 /// use inkwell::context::Context;
128 ///
129 /// // A simple function which returns its argument:
130 /// let context = Context::create();
131 /// let module = context.create_module("ret");
132 /// let builder = context.create_builder();
133 /// let i32_type = context.i32_type();
134 /// let arg_types = [i32_type.into()];
135 /// let fn_type = i32_type.fn_type(&arg_types, false);
136 /// let fn_value = module.add_function("ret", fn_type, None);
137 /// let entry = context.append_basic_block(fn_value, "entry");
138 /// let i32_arg = fn_value.get_first_param().unwrap();
139 ///
140 /// builder.position_at_end(entry);
141 /// builder.build_return(Some(&i32_arg)).unwrap();
142 /// ```
143 pub fn build_return(&self, value: Option<&dyn BasicValue<'ctx>>) -> Result<InstructionValue<'ctx>, BuilderError> {
144 if self.positioned.get() != PositionState::Set {
145 return Err(BuilderError::UnsetPosition);
146 }
147 let value = unsafe {
148 value.map_or_else(
149 || LLVMBuildRetVoid(self.builder),
150 |value| LLVMBuildRet(self.builder, value.as_value_ref()),
151 )
152 };
153
154 unsafe { Ok(InstructionValue::new(value)) }
155 }
156
157 /// Builds a function return instruction for a return type which is an aggregate type (ie structs and arrays).
158 /// It is not necessary to use this over `build_return` but may be more convenient to use.
159 ///
160 /// # Example
161 ///
162 /// ```no_run
163 /// use inkwell::context::Context;
164 ///
165 /// // This builds a simple function which returns a struct (tuple) of two ints.
166 /// let context = Context::create();
167 /// let module = context.create_module("ret");
168 /// let builder = context.create_builder();
169 /// let i32_type = context.i32_type();
170 /// let i32_three = i32_type.const_int(3, false);
171 /// let i32_seven = i32_type.const_int(7, false);
172 /// let struct_type = context.struct_type(&[i32_type.into(), i32_type.into()], false);
173 /// let fn_type = struct_type.fn_type(&[], false);
174 /// let fn_value = module.add_function("ret", fn_type, None);
175 /// let entry = context.append_basic_block(fn_value, "entry");
176 ///
177 /// builder.position_at_end(entry);
178 /// builder.build_aggregate_return(&[i32_three.into(), i32_seven.into()]).unwrap();
179 /// ```
180 pub fn build_aggregate_return(
181 &self,
182 values: &[BasicValueEnum<'ctx>],
183 ) -> Result<InstructionValue<'ctx>, BuilderError> {
184 if self.positioned.get() != PositionState::Set {
185 return Err(BuilderError::UnsetPosition);
186 }
187 let mut args: Vec<LLVMValueRef> = values.iter().map(|val| val.as_value_ref()).collect();
188 let value = unsafe { LLVMBuildAggregateRet(self.builder, args.as_mut_ptr(), args.len() as u32) };
189
190 unsafe { Ok(InstructionValue::new(value)) }
191 }
192
193 /// Builds a function call instruction.
194 /// [`FunctionValue`]s can be implicitly converted into a [`CallableValue`].
195 /// See [`CallableValue`] for details on calling a [`PointerValue`] that points to a function.
196 ///
197 /// [`FunctionValue`]: crate::values::FunctionValue
198 ///
199 /// # Example
200 ///
201 /// ```no_run
202 /// use inkwell::context::Context;
203 ///
204 /// // A simple function which calls itself:
205 /// let context = Context::create();
206 /// let module = context.create_module("ret");
207 /// let builder = context.create_builder();
208 /// let i32_type = context.i32_type();
209 /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
210 /// let fn_value = module.add_function("ret", fn_type, None);
211 /// let entry = context.append_basic_block(fn_value, "entry");
212 /// let i32_arg = fn_value.get_first_param().unwrap();
213 /// let md_string = context.metadata_string("a metadata");
214 ///
215 /// builder.position_at_end(entry);
216 ///
217 /// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call").unwrap()
218 /// .try_as_basic_value()
219 /// .left()
220 /// .unwrap();
221 ///
222 /// builder.build_return(Some(&ret_val)).unwrap();
223 /// ```
224 #[llvm_versions(..=14)]
225 pub fn build_call<F>(
226 &self,
227 function: F,
228 args: &[BasicMetadataValueEnum<'ctx>],
229 name: &str,
230 ) -> Result<CallSiteValue<'ctx>, BuilderError>
231 where
232 F: Into<CallableValue<'ctx>>,
233 {
234 if self.positioned.get() != PositionState::Set {
235 return Err(BuilderError::UnsetPosition);
236 }
237 let callable_value = function.into();
238 let fn_val_ref = callable_value.as_value_ref();
239
240 // LLVM gets upset when void return calls are named because they don't return anything
241 let name = if callable_value.returns_void() { "" } else { name };
242
243 let c_string = to_c_str(name);
244 let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
245
246 let value = unsafe {
247 LLVMBuildCall(
248 self.builder,
249 fn_val_ref,
250 args.as_mut_ptr(),
251 args.len() as u32,
252 c_string.as_ptr(),
253 )
254 };
255
256 unsafe { Ok(CallSiteValue::new(value)) }
257 }
258
259 /// Builds a function call instruction. Alias for [Builder::build_direct_call].
260 #[llvm_versions(15..)]
261 pub fn build_call(
262 &self,
263 function: FunctionValue<'ctx>,
264 args: &[BasicMetadataValueEnum<'ctx>],
265 name: &str,
266 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
267 if self.positioned.get() != PositionState::Set {
268 return Err(BuilderError::UnsetPosition);
269 }
270 self.build_direct_call(function, args, name)
271 }
272
273 /// Builds a function call instruction. The function being called is known at compile time. If
274 /// you want to call a function pointer, see [Builder::build_indirect_call].
275 ///
276 /// # Example
277 ///
278 /// ```no_run
279 /// use inkwell::context::Context;
280 ///
281 /// // A simple function which calls itself:
282 /// let context = Context::create();
283 /// let module = context.create_module("ret");
284 /// let builder = context.create_builder();
285 /// let i32_type = context.i32_type();
286 /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
287 /// let fn_value = module.add_function("ret", fn_type, None);
288 /// let entry = context.append_basic_block(fn_value, "entry");
289 /// let i32_arg = fn_value.get_first_param().unwrap();
290 /// let md_string = context.metadata_string("a metadata");
291 ///
292 /// builder.position_at_end(entry);
293 ///
294 /// let ret_val = builder.build_call(fn_value, &[i32_arg.into(), md_string.into()], "call").unwrap()
295 /// .try_as_basic_value()
296 /// .left()
297 /// .unwrap();
298 ///
299 /// builder.build_return(Some(&ret_val)).unwrap();
300 /// ```
301 #[llvm_versions(15..)]
302 pub fn build_direct_call(
303 &self,
304 function: FunctionValue<'ctx>,
305 args: &[BasicMetadataValueEnum<'ctx>],
306 name: &str,
307 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
308 if self.positioned.get() != PositionState::Set {
309 return Err(BuilderError::UnsetPosition);
310 }
311 self.build_call_help(function.get_type(), function.as_value_ref(), args, name)
312 }
313
314 /// Build a function call instruction, with attached operand bundles.
315 ///
316 /// # Example
317 ///
318 /// ```
319 /// use inkwell::context::Context;
320 /// use inkwell::values::OperandBundle;
321 ///
322 /// let context = Context::create();
323 /// let module = context.create_module("call_with_op_bundles");
324 /// let builder = context.create_builder();
325 /// let i32_type = context.i32_type();
326 ///
327 /// // declare i32 @func(i32)
328 /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
329 /// let fn_value = module.add_function("func", fn_type, None);
330 ///
331 /// let basic_block = context.append_basic_block(fn_value, "entry");
332 /// builder.position_at_end(basic_block);
333 ///
334 /// // %func_ret = call i32 @func(i32 0) [ "tag"(i32 0) ]
335 /// let ret_val = builder.build_direct_call_with_operand_bundles(
336 /// fn_value,
337 /// &[i32_type.const_zero().into()],
338 /// &[OperandBundle::create("tag", &[i32_type.const_zero().into()])],
339 /// "func_ret"
340 /// )
341 /// .unwrap()
342 /// .try_as_basic_value()
343 /// .unwrap_left();
344 /// builder.build_return(Some(&ret_val)).unwrap();
345 ///
346 /// # module.verify().unwrap();
347 /// ```
348 #[llvm_versions(18..)]
349 pub fn build_direct_call_with_operand_bundles(
350 &self,
351 function: FunctionValue<'ctx>,
352 args: &[BasicMetadataValueEnum<'ctx>],
353 operand_bundles: &[OperandBundle<'ctx>],
354 name: &str,
355 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
356 self.build_call_with_operand_bundles_help(
357 function.get_type(),
358 function.as_value_ref(),
359 args,
360 operand_bundles,
361 name,
362 )
363 }
364
365 /// Call a function pointer. Because a pointer does not carry a type, the type of the function
366 /// must be specified explicitly.
367 ///
368 /// See [Context::create_inline_asm] for a practical example. Basic usage looks like this:
369 ///
370 /// ```no_run
371 /// use inkwell::context::Context;
372 ///
373 /// // A simple function which calls itself:
374 /// let context = Context::create();
375 /// let module = context.create_module("ret");
376 /// let builder = context.create_builder();
377 /// let i32_type = context.i32_type();
378 /// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
379 /// let fn_value = module.add_function("ret", fn_type, None);
380 /// let entry = context.append_basic_block(fn_value, "entry");
381 /// let i32_arg = fn_value.get_first_param().unwrap();
382 /// let md_string = context.metadata_string("a metadata");
383 ///
384 /// builder.position_at_end(entry);
385 ///
386 /// let function_pointer = fn_value.as_global_value().as_pointer_value();
387 /// let ret_val = builder.build_indirect_call(fn_value.get_type(), function_pointer, &[i32_arg.into(), md_string.into()], "call").unwrap()
388 /// .try_as_basic_value()
389 /// .left()
390 /// .unwrap();
391 ///
392 /// builder.build_return(Some(&ret_val)).unwrap();
393 /// ```
394 ///
395 #[llvm_versions(15..)]
396 pub fn build_indirect_call(
397 &self,
398 function_type: FunctionType<'ctx>,
399 function_pointer: PointerValue<'ctx>,
400 args: &[BasicMetadataValueEnum<'ctx>],
401 name: &str,
402 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
403 if self.positioned.get() != PositionState::Set {
404 return Err(BuilderError::UnsetPosition);
405 }
406 self.build_call_help(function_type, function_pointer.as_value_ref(), args, name)
407 }
408
409 /// Build a call instruction to a function pointer, with attached operand bundles.
410 ///
411 /// See [Builder::build_direct_call_with_operand_bundles] for a usage example
412 /// with operand bundles.
413 #[llvm_versions(18..)]
414 pub fn build_indirect_call_with_operand_bundles(
415 &self,
416 function_type: FunctionType<'ctx>,
417 function_pointer: PointerValue<'ctx>,
418 args: &[BasicMetadataValueEnum<'ctx>],
419 operand_bundles: &[OperandBundle<'ctx>],
420 name: &str,
421 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
422 self.build_call_with_operand_bundles_help(
423 function_type,
424 function_pointer.as_value_ref(),
425 args,
426 operand_bundles,
427 name,
428 )
429 }
430
431 #[llvm_versions(15..)]
432 fn build_call_help(
433 &self,
434 function_type: FunctionType<'ctx>,
435 fn_val_ref: LLVMValueRef,
436 args: &[BasicMetadataValueEnum<'ctx>],
437 name: &str,
438 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
439 if self.positioned.get() != PositionState::Set {
440 return Err(BuilderError::UnsetPosition);
441 }
442 // LLVM gets upset when void return calls are named because they don't return anything
443 let name = match function_type.get_return_type() {
444 None => "",
445 Some(_) => name,
446 };
447
448 let fn_ty_ref = function_type.as_type_ref();
449
450 let c_string = to_c_str(name);
451 let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
452
453 let value = unsafe {
454 LLVMBuildCall2(
455 self.builder,
456 fn_ty_ref,
457 fn_val_ref,
458 args.as_mut_ptr(),
459 args.len() as u32,
460 c_string.as_ptr(),
461 )
462 };
463
464 unsafe { Ok(CallSiteValue::new(value)) }
465 }
466
467 #[llvm_versions(18..)]
468 fn build_call_with_operand_bundles_help(
469 &self,
470 function_type: FunctionType<'ctx>,
471 fn_val_ref: LLVMValueRef,
472 args: &[BasicMetadataValueEnum<'ctx>],
473 operand_bundles: &[OperandBundle<'ctx>],
474 name: &str,
475 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
476 use llvm_sys::prelude::LLVMOperandBundleRef;
477
478 if self.positioned.get() != PositionState::Set {
479 return Err(BuilderError::UnsetPosition);
480 }
481 // LLVM gets upset when void return calls are named because they don't return anything
482 let name = match function_type.get_return_type() {
483 None => "",
484 Some(_) => name,
485 };
486
487 let fn_ty_ref = function_type.as_type_ref();
488
489 let c_string = to_c_str(name);
490 let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
491 let mut operand_bundles: Vec<LLVMOperandBundleRef> =
492 operand_bundles.iter().map(|val| val.as_mut_ptr()).collect();
493
494 let value = unsafe {
495 LLVMBuildCallWithOperandBundles(
496 self.builder,
497 fn_ty_ref,
498 fn_val_ref,
499 args.as_mut_ptr(),
500 args.len() as u32,
501 operand_bundles.as_mut_ptr(),
502 operand_bundles.len() as u32,
503 c_string.as_ptr(),
504 )
505 };
506
507 unsafe { Ok(CallSiteValue::new(value)) }
508 }
509
510 /// An invoke is similar to a normal function call, but used to
511 /// call functions that may throw an exception, and then respond to the exception.
512 ///
513 /// When the called function returns normally, the `then` block is evaluated next. If instead
514 /// the function threw an exception, the `catch` block is entered. The first non-phi
515 /// instruction of the catch block must be a `landingpad` instruction. See also
516 /// [`Builder::build_landing_pad`].
517 ///
518 /// The [`add_prune_eh_pass`] turns an invoke into a call when the called function is
519 /// guaranteed to never throw an exception.
520 ///
521 /// [`add_prune_eh_pass`]: crate::passes::PassManager::add_prune_eh_pass
522 ///
523 /// This example catches C++ exceptions of type `int`, and returns `0` if an exceptions is thrown.
524 /// For usage of a cleanup landing pad and the `resume` instruction, see [`Builder::build_resume`]
525 /// ```no_run
526 /// use inkwell::context::Context;
527 /// use inkwell::AddressSpace;
528 /// use inkwell::module::Linkage;
529 ///
530 /// let context = Context::create();
531 /// let module = context.create_module("sum");
532 /// let builder = context.create_builder();
533 ///
534 /// let f32_type = context.f32_type();
535 /// let fn_type = f32_type.fn_type(&[], false);
536 ///
537 /// // we will pretend this function can throw an exception
538 /// let function = module.add_function("bomb", fn_type, None);
539 /// let basic_block = context.append_basic_block(function, "entry");
540 ///
541 /// builder.position_at_end(basic_block);
542 ///
543 /// let pi = f32_type.const_float(std::f64::consts::PI);
544 ///
545 /// builder.build_return(Some(&pi)).unwrap();
546 ///
547 /// let function2 = module.add_function("wrapper", fn_type, None);
548 /// let basic_block2 = context.append_basic_block(function2, "entry");
549 ///
550 /// builder.position_at_end(basic_block2);
551 ///
552 /// let then_block = context.append_basic_block(function2, "then_block");
553 /// let catch_block = context.append_basic_block(function2, "catch_block");
554 ///
555 /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();
556 ///
557 /// {
558 /// builder.position_at_end(then_block);
559 ///
560 /// // in the then_block, the `call_site` value is defined and can be used
561 /// let result = call_site.try_as_basic_value().left().unwrap();
562 ///
563 /// builder.build_return(Some(&result)).unwrap();
564 /// }
565 ///
566 /// {
567 /// builder.position_at_end(catch_block);
568 ///
569 /// // the personality function used by C++
570 /// let personality_function = {
571 /// let name = "__gxx_personality_v0";
572 /// let linkage = Some(Linkage::External);
573 ///
574 /// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
575 /// };
576 ///
577 /// // type of an exception in C++
578 /// #[cfg(feature = "typed-pointers")]
579 /// let i8_ptr_type = context.i32_type().ptr_type(AddressSpace::default());
580 /// #[cfg(not(feature = "typed-pointers"))]
581 /// let i32_ptr_ty = context.ptr_type(AddressSpace::default());
582 /// let i32_type = context.i32_type();
583 /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
584 ///
585 /// let null = i8_ptr_type.const_zero();
586 /// let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
587 ///
588 /// // we handle the exception by returning a default value
589 /// builder.build_return(Some(&f32_type.const_zero())).unwrap();
590 /// }
591 /// ```
592 #[llvm_versions(..=14)]
593 pub fn build_invoke<F>(
594 &self,
595 function: F,
596 args: &[BasicValueEnum<'ctx>],
597 then_block: BasicBlock<'ctx>,
598 catch_block: BasicBlock<'ctx>,
599 name: &str,
600 ) -> Result<CallSiteValue<'ctx>, BuilderError>
601 where
602 F: Into<CallableValue<'ctx>>,
603 {
604 if self.positioned.get() != PositionState::Set {
605 return Err(BuilderError::UnsetPosition);
606 }
607 let callable_value: CallableValue<'ctx> = function.into();
608 let fn_val_ref = callable_value.as_value_ref();
609
610 // LLVM gets upset when void return calls are named because they don't return anything
611 let name = if callable_value.returns_void() { "" } else { name };
612
613 let c_string = to_c_str(name);
614 let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
615
616 let value = unsafe {
617 LLVMBuildInvoke(
618 self.builder,
619 fn_val_ref,
620 args.as_mut_ptr(),
621 args.len() as u32,
622 then_block.basic_block,
623 catch_block.basic_block,
624 c_string.as_ptr(),
625 )
626 };
627
628 Ok(unsafe { CallSiteValue::new(value) })
629 }
630
631 /// An invoke is similar to a normal function call, but used to
632 /// call functions that may throw an exception, and then respond to the exception.
633 ///
634 /// When the called function returns normally, the `then` block is evaluated next. If instead
635 /// the function threw an exception, the `catch` block is entered. The first non-phi
636 /// instruction of the catch block must be a `landingpad` instruction. See also
637 /// [`Builder::build_landing_pad`].
638 ///
639 /// The [`add_prune_eh_pass`] turns an invoke into a call when the called function is
640 /// guaranteed to never throw an exception.
641 ///
642 /// [`add_prune_eh_pass`]: crate::passes::PassManager::add_prune_eh_pass
643 ///
644 /// This example catches C++ exceptions of type `int`, and returns `0` if an exceptions is thrown.
645 /// For usage of a cleanup landing pad and the `resume` instruction, see [`Builder::build_resume`]
646 /// ```no_run
647 /// use inkwell::context::Context;
648 /// use inkwell::AddressSpace;
649 /// use inkwell::module::Linkage;
650 ///
651 /// let context = Context::create();
652 /// let module = context.create_module("sum");
653 /// let builder = context.create_builder();
654 ///
655 /// let f32_type = context.f32_type();
656 /// let fn_type = f32_type.fn_type(&[], false);
657 ///
658 /// // we will pretend this function can throw an exception
659 /// let function = module.add_function("bomb", fn_type, None);
660 /// let basic_block = context.append_basic_block(function, "entry");
661 ///
662 /// builder.position_at_end(basic_block);
663 ///
664 /// let pi = f32_type.const_float(std::f64::consts::PI);
665 ///
666 /// builder.build_return(Some(&pi)).unwrap();
667 ///
668 /// let function2 = module.add_function("wrapper", fn_type, None);
669 /// let basic_block2 = context.append_basic_block(function2, "entry");
670 ///
671 /// builder.position_at_end(basic_block2);
672 ///
673 /// let then_block = context.append_basic_block(function2, "then_block");
674 /// let catch_block = context.append_basic_block(function2, "catch_block");
675 ///
676 /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();
677 ///
678 /// {
679 /// builder.position_at_end(then_block);
680 ///
681 /// // in the then_block, the `call_site` value is defined and can be used
682 /// let result = call_site.try_as_basic_value().left().unwrap();
683 ///
684 /// builder.build_return(Some(&result)).unwrap();
685 /// }
686 ///
687 /// {
688 /// builder.position_at_end(catch_block);
689 ///
690 /// // the personality function used by C++
691 /// let personality_function = {
692 /// let name = "__gxx_personality_v0";
693 /// let linkage = Some(Linkage::External);
694 ///
695 /// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
696 /// };
697 ///
698 /// // type of an exception in C++
699 /// #[cfg(feature = "typed-pointers")]
700 /// let ptr_type = context.i8_type().ptr_type(AddressSpace::default());
701 /// #[cfg(not(feature = "typed-pointers"))]
702 /// let ptr_type = context.ptr_type(AddressSpace::default());
703 /// let i32_type = context.i32_type();
704 /// let exception_type = context.struct_type(&[ptr_type.into(), i32_type.into()], false);
705 ///
706 /// let null = ptr_type.const_zero();
707 /// let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
708 ///
709 /// // we handle the exception by returning a default value
710 /// builder.build_return(Some(&f32_type.const_zero())).unwrap();
711 /// }
712 /// ```
713 #[llvm_versions(15..)]
714 pub fn build_invoke(
715 &self,
716 function: FunctionValue<'ctx>,
717 args: &[BasicValueEnum<'ctx>],
718 then_block: BasicBlock<'ctx>,
719 catch_block: BasicBlock<'ctx>,
720 name: &str,
721 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
722 if self.positioned.get() != PositionState::Set {
723 return Err(BuilderError::UnsetPosition);
724 }
725 self.build_direct_invoke(function, args, then_block, catch_block, name)
726 }
727
728 #[llvm_versions(15..)]
729 pub fn build_direct_invoke(
730 &self,
731 function: FunctionValue<'ctx>,
732 args: &[BasicValueEnum<'ctx>],
733 then_block: BasicBlock<'ctx>,
734 catch_block: BasicBlock<'ctx>,
735 name: &str,
736 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
737 if self.positioned.get() != PositionState::Set {
738 return Err(BuilderError::UnsetPosition);
739 }
740 self.build_invoke_help(
741 function.get_type(),
742 function.as_value_ref(),
743 args,
744 then_block,
745 catch_block,
746 name,
747 )
748 }
749
750 #[llvm_versions(15..)]
751 pub fn build_indirect_invoke(
752 &self,
753 function_type: FunctionType<'ctx>,
754 function_pointer: PointerValue<'ctx>,
755 args: &[BasicValueEnum<'ctx>],
756 then_block: BasicBlock<'ctx>,
757 catch_block: BasicBlock<'ctx>,
758 name: &str,
759 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
760 if self.positioned.get() != PositionState::Set {
761 return Err(BuilderError::UnsetPosition);
762 }
763 self.build_invoke_help(
764 function_type,
765 function_pointer.as_value_ref(),
766 args,
767 then_block,
768 catch_block,
769 name,
770 )
771 }
772
773 #[llvm_versions(15..)]
774 fn build_invoke_help(
775 &self,
776 fn_ty: FunctionType<'ctx>,
777 fn_val_ref: LLVMValueRef,
778 args: &[BasicValueEnum<'ctx>],
779 then_block: BasicBlock<'ctx>,
780 catch_block: BasicBlock<'ctx>,
781 name: &str,
782 ) -> Result<CallSiteValue<'ctx>, BuilderError> {
783 if self.positioned.get() != PositionState::Set {
784 return Err(BuilderError::UnsetPosition);
785 }
786 let fn_ty_ref = fn_ty.as_type_ref();
787
788 // LLVM gets upset when void return calls are named because they don't return anything
789 let name = if fn_ty.get_return_type().is_none() { "" } else { name };
790
791 let c_string = to_c_str(name);
792 let mut args: Vec<LLVMValueRef> = args.iter().map(|val| val.as_value_ref()).collect();
793
794 let value = unsafe {
795 LLVMBuildInvoke2(
796 self.builder,
797 fn_ty_ref,
798 fn_val_ref,
799 args.as_mut_ptr(),
800 args.len() as u32,
801 then_block.basic_block,
802 catch_block.basic_block,
803 c_string.as_ptr(),
804 )
805 };
806
807 unsafe { Ok(CallSiteValue::new(value)) }
808 }
809
810 /// Landing pads are places where control flow jumps to if a [`Builder::build_invoke`] triggered an exception.
811 /// The landing pad will match the exception against its `clauses`. Depending on the clause
812 /// that is matched, the exception can then be handled, or resumed after some optional cleanup,
813 /// causing the exception to bubble up.
814 ///
815 /// Exceptions in LLVM are designed based on the needs of a C++ compiler, but can be used more generally.
816 /// Here are some specific examples of landing pads. For a full example of handling an exception, see [`Builder::build_invoke`].
817 ///
818 /// * **cleanup**: a cleanup landing pad is always visited when unwinding the stack.
819 /// A cleanup is extra code that needs to be run when unwinding a scope. C++ destructors are a typical example.
820 /// In a language with reference counting, the cleanup block can decrement the refcount of values in scope.
821 /// The [`Builder::build_resume`] function has a full example using a cleanup lading pad.
822 ///
823 /// ```no_run
824 /// use inkwell::context::Context;
825 /// use inkwell::AddressSpace;
826 /// use inkwell::module::Linkage;
827 ///
828 /// let context = Context::create();
829 /// let module = context.create_module("sum");
830 /// let builder = context.create_builder();
831 ///
832 /// // type of an exception in C++
833 /// #[cfg(feature = "typed-pointers")]
834 /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
835 /// #[cfg(not(feature = "typed-pointers"))]
836 /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
837 /// let i32_type = context.i32_type();
838 /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
839 ///
840 /// // the personality function used by C++
841 /// let personality_function = {
842 /// let name = "__gxx_personality_v0";
843 /// let linkage = Some(Linkage::External);
844 ///
845 /// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
846 /// };
847 ///
848 /// // make the cleanup landing pad
849 /// let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res").unwrap();
850 /// ```
851 ///
852 /// * **catch all**: An implementation of the C++ `catch(...)`, which catches all exceptions.
853 /// A catch clause with a NULL pointer value will match anything.
854 ///
855 /// ```no_run
856 /// use inkwell::context::Context;
857 /// use inkwell::AddressSpace;
858 /// use inkwell::module::Linkage;
859 ///
860 /// let context = Context::create();
861 /// let module = context.create_module("sum");
862 /// let builder = context.create_builder();
863 ///
864 /// // type of an exception in C++
865 /// #[cfg(feature = "typed-pointers")]
866 /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
867 /// #[cfg(not(feature = "typed-pointers"))]
868 /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
869 /// let i32_type = context.i32_type();
870 /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
871 ///
872 /// // the personality function used by C++
873 /// let personality_function = {
874 /// let name = "__gxx_personality_v0";
875 /// let linkage = Some(Linkage::External);
876 ///
877 /// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
878 /// };
879 ///
880 /// // make a null pointer of type i8
881 /// let null = i8_ptr_type.const_zero();
882 ///
883 /// // make the catch all landing pad
884 /// let res = builder.build_landing_pad(exception_type, personality_function, &[null.into()], false, "res").unwrap();
885 /// ```
886 ///
887 /// * **catch a type of exception**: Catch a specific type of exception. The example uses C++'s type info.
888 ///
889 /// ```no_run
890 /// use inkwell::context::Context;
891 /// use inkwell::module::Linkage;
892 /// use inkwell::AddressSpace;
893 /// use inkwell::values::BasicValue;
894 ///
895 /// let context = Context::create();
896 /// let module = context.create_module("sum");
897 /// let builder = context.create_builder();
898 ///
899 /// // type of an exception in C++
900 /// #[cfg(feature = "typed-pointers")]
901 /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
902 /// #[cfg(not(feature = "typed-pointers"))]
903 /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
904 /// let i32_type = context.i32_type();
905 /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
906 ///
907 /// // the personality function used by C++
908 /// let personality_function = {
909 /// let name = "__gxx_personality_v0";
910 /// let linkage = Some(Linkage::External);
911 ///
912 /// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
913 /// };
914 ///
915 /// // link in the C++ type info for the `int` type
916 /// let type_info_int = module.add_global(i8_ptr_type, Some(AddressSpace::default()), "_ZTIi");
917 /// type_info_int.set_linkage(Linkage::External);
918 ///
919 /// // make the catch landing pad
920 /// let clause = type_info_int.as_basic_value_enum();
921 /// let res = builder.build_landing_pad(exception_type, personality_function, &[clause], false, "res").unwrap();
922 /// ```
923 ///
924 /// * **filter**: A filter clause encodes that only some types of exceptions are valid at this
925 /// point. A filter clause is made by constructing a clause from a constant array.
926 ///
927 /// ```no_run
928 /// use inkwell::context::Context;
929 /// use inkwell::module::Linkage;
930 /// use inkwell::values::AnyValue;
931 /// use inkwell::AddressSpace;
932 ///
933 /// let context = Context::create();
934 /// let module = context.create_module("sum");
935 /// let builder = context.create_builder();
936 ///
937 /// // type of an exception in C++
938 /// #[cfg(feature = "typed-pointers")]
939 /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
940 /// #[cfg(not(feature = "typed-pointers"))]
941 /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
942 /// let i32_type = context.i32_type();
943 /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
944 ///
945 /// // the personality function used by C++
946 /// let personality_function = {
947 /// let name = "__gxx_personality_v0";
948 /// let linkage = Some(Linkage::External);
949 ///
950 /// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
951 /// };
952 ///
953 /// // link in the C++ type info for the `int` type
954 /// let type_info_int = module.add_global(i8_ptr_type, Some(AddressSpace::default()), "_ZTIi");
955 /// type_info_int.set_linkage(Linkage::External);
956 ///
957 /// // make the filter landing pad
958 /// let filter_pattern = i8_ptr_type.const_array(&[type_info_int.as_any_value_enum().into_pointer_value()]);
959 /// let res = builder.build_landing_pad(exception_type, personality_function, &[filter_pattern.into()], false, "res").unwrap();
960 /// ```
961 pub fn build_landing_pad<T>(
962 &self,
963 exception_type: T,
964 personality_function: FunctionValue<'ctx>,
965 clauses: &[BasicValueEnum<'ctx>],
966 is_cleanup: bool,
967 name: &str,
968 ) -> Result<BasicValueEnum<'ctx>, BuilderError>
969 where
970 T: BasicType<'ctx>,
971 {
972 if self.positioned.get() != PositionState::Set {
973 return Err(BuilderError::UnsetPosition);
974 }
975 let c_string = to_c_str(name);
976 let num_clauses = clauses.len() as u32;
977
978 let value = unsafe {
979 LLVMBuildLandingPad(
980 self.builder,
981 exception_type.as_type_ref(),
982 personality_function.as_value_ref(),
983 num_clauses,
984 c_string.as_ptr(),
985 )
986 };
987
988 for clause in clauses {
989 unsafe {
990 LLVMAddClause(value, clause.as_value_ref());
991 }
992 }
993
994 unsafe {
995 LLVMSetCleanup(value, is_cleanup as _);
996 };
997
998 unsafe { Ok(BasicValueEnum::new(value)) }
999 }
1000
1001 /// Resume propagation of an existing (in-flight) exception whose unwinding was interrupted with a landingpad instruction.
1002 ///
1003 /// This example uses a cleanup landing pad. A cleanup is extra code that needs to be run when
1004 /// unwinding a scope. C++ destructors are a typical example. In a language with reference counting,
1005 /// the cleanup block can decrement the refcount of values in scope.
1006 ///
1007 /// ```no_run
1008 /// use inkwell::context::Context;
1009 /// use inkwell::AddressSpace;
1010 /// use inkwell::module::Linkage;
1011 ///
1012 /// let context = Context::create();
1013 /// let module = context.create_module("sum");
1014 /// let builder = context.create_builder();
1015 ///
1016 /// let f32_type = context.f32_type();
1017 /// let fn_type = f32_type.fn_type(&[], false);
1018 ///
1019 /// // we will pretend this function can throw an exception
1020 /// let function = module.add_function("bomb", fn_type, None);
1021 /// let basic_block = context.append_basic_block(function, "entry");
1022 ///
1023 /// builder.position_at_end(basic_block);
1024 ///
1025 /// let pi = f32_type.const_float(std::f64::consts::PI);
1026 ///
1027 /// builder.build_return(Some(&pi)).unwrap();
1028 ///
1029 /// let function2 = module.add_function("wrapper", fn_type, None);
1030 /// let basic_block2 = context.append_basic_block(function2, "entry");
1031 ///
1032 /// builder.position_at_end(basic_block2);
1033 ///
1034 /// let then_block = context.append_basic_block(function2, "then_block");
1035 /// let catch_block = context.append_basic_block(function2, "catch_block");
1036 ///
1037 /// let call_site = builder.build_invoke(function, &[], then_block, catch_block, "get_pi").unwrap();
1038 ///
1039 /// {
1040 /// builder.position_at_end(then_block);
1041 ///
1042 /// // in the then_block, the `call_site` value is defined and can be used
1043 /// let result = call_site.try_as_basic_value().left().unwrap();
1044 ///
1045 /// builder.build_return(Some(&result)).unwrap();
1046 /// }
1047 ///
1048 /// {
1049 /// builder.position_at_end(catch_block);
1050 ///
1051 /// // the personality function used by C++
1052 /// let personality_function = {
1053 /// let name = "__gxx_personality_v0";
1054 /// let linkage = Some(Linkage::External);
1055 ///
1056 /// module.add_function(name, context.i64_type().fn_type(&[], false), linkage)
1057 /// };
1058 ///
1059 /// // type of an exception in C++
1060 /// #[cfg(feature = "typed-pointers")]
1061 /// let i8_ptr_type = context.i8_type().ptr_type(AddressSpace::default());
1062 /// #[cfg(not(feature = "typed-pointers"))]
1063 /// let i8_ptr_type = context.ptr_type(AddressSpace::default());
1064 /// let i32_type = context.i32_type();
1065 /// let exception_type = context.struct_type(&[i8_ptr_type.into(), i32_type.into()], false);
1066 ///
1067 /// // make the landing pad; must give a concrete type to the slice
1068 /// let res = builder.build_landing_pad( exception_type, personality_function, &[], true, "res").unwrap();
1069 ///
1070 /// // do cleanup ...
1071 ///
1072 /// builder.build_resume(res).unwrap();
1073 /// }
1074 /// ```
1075 pub fn build_resume<V: BasicValue<'ctx>>(&self, value: V) -> Result<InstructionValue<'ctx>, BuilderError> {
1076 if self.positioned.get() != PositionState::Set {
1077 return Err(BuilderError::UnsetPosition);
1078 }
1079 let val = unsafe { LLVMBuildResume(self.builder, value.as_value_ref()) };
1080
1081 unsafe { Ok(InstructionValue::new(val)) }
1082 }
1083
1084 // REVIEW: Doesn't GEP work on array too?
1085 /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1086 #[cfg(feature = "typed-pointers")]
1087 pub unsafe fn build_gep(
1088 &self,
1089 ptr: PointerValue<'ctx>,
1090 ordered_indexes: &[IntValue<'ctx>],
1091 name: &str,
1092 ) -> Result<PointerValue<'ctx>, BuilderError> {
1093 if self.positioned.get() != PositionState::Set {
1094 return Err(BuilderError::UnsetPosition);
1095 }
1096 let c_string = to_c_str(name);
1097
1098 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1099
1100 #[cfg(not(feature = "llvm16-0"))]
1101 #[cfg_attr(feature = "llvm15-0", allow(deprecated))]
1102 let value = LLVMBuildGEP(
1103 self.builder,
1104 ptr.as_value_ref(),
1105 index_values.as_mut_ptr(),
1106 index_values.len() as u32,
1107 c_string.as_ptr(),
1108 );
1109 #[cfg(feature = "llvm16-0")]
1110 let value = LLVMBuildGEP2(
1111 self.builder,
1112 ptr.get_type().get_element_type().as_type_ref(),
1113 ptr.as_value_ref(),
1114 index_values.as_mut_ptr(),
1115 index_values.len() as u32,
1116 c_string.as_ptr(),
1117 );
1118
1119 Ok(PointerValue::new(value))
1120 }
1121
1122 // REVIEW: Doesn't GEP work on array too?
1123 /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1124 #[cfg(not(feature = "typed-pointers"))]
1125 pub unsafe fn build_gep<T: BasicType<'ctx>>(
1126 &self,
1127 pointee_ty: T,
1128 ptr: PointerValue<'ctx>,
1129 ordered_indexes: &[IntValue<'ctx>],
1130 name: &str,
1131 ) -> Result<PointerValue<'ctx>, BuilderError> {
1132 if self.positioned.get() != PositionState::Set {
1133 return Err(BuilderError::UnsetPosition);
1134 }
1135 let c_string = to_c_str(name);
1136
1137 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1138
1139 let value = LLVMBuildGEP2(
1140 self.builder,
1141 pointee_ty.as_type_ref(),
1142 ptr.as_value_ref(),
1143 index_values.as_mut_ptr(),
1144 index_values.len() as u32,
1145 c_string.as_ptr(),
1146 );
1147
1148 Ok(PointerValue::new(value))
1149 }
1150
1151 // REVIEW: Doesn't GEP work on array too?
1152 // REVIEW: This could be merge in with build_gep via a in_bounds: bool param
1153 /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1154 #[cfg(feature = "typed-pointers")]
1155 pub unsafe fn build_in_bounds_gep(
1156 &self,
1157 ptr: PointerValue<'ctx>,
1158 ordered_indexes: &[IntValue<'ctx>],
1159 name: &str,
1160 ) -> Result<PointerValue<'ctx>, BuilderError> {
1161 if self.positioned.get() != PositionState::Set {
1162 return Err(BuilderError::UnsetPosition);
1163 }
1164 let c_string = to_c_str(name);
1165
1166 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1167
1168 #[cfg(not(feature = "llvm16-0"))]
1169 #[cfg_attr(feature = "llvm15-0", allow(deprecated))]
1170 let value = LLVMBuildInBoundsGEP(
1171 self.builder,
1172 ptr.as_value_ref(),
1173 index_values.as_mut_ptr(),
1174 index_values.len() as u32,
1175 c_string.as_ptr(),
1176 );
1177 #[cfg(feature = "llvm16-0")]
1178 let value = LLVMBuildInBoundsGEP2(
1179 self.builder,
1180 ptr.get_type().get_element_type().as_type_ref(),
1181 ptr.as_value_ref(),
1182 index_values.as_mut_ptr(),
1183 index_values.len() as u32,
1184 c_string.as_ptr(),
1185 );
1186
1187 Ok(PointerValue::new(value))
1188 }
1189
1190 // REVIEW: Doesn't GEP work on array too?
1191 // REVIEW: This could be merge in with build_gep via a in_bounds: bool param
1192 /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future.
1193 #[cfg(not(feature = "typed-pointers"))]
1194 pub unsafe fn build_in_bounds_gep<T: BasicType<'ctx>>(
1195 &self,
1196 pointee_ty: T,
1197 ptr: PointerValue<'ctx>,
1198 ordered_indexes: &[IntValue<'ctx>],
1199 name: &str,
1200 ) -> Result<PointerValue<'ctx>, BuilderError> {
1201 if self.positioned.get() != PositionState::Set {
1202 return Err(BuilderError::UnsetPosition);
1203 }
1204 let c_string = to_c_str(name);
1205
1206 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
1207
1208 let value = LLVMBuildInBoundsGEP2(
1209 self.builder,
1210 pointee_ty.as_type_ref(),
1211 ptr.as_value_ref(),
1212 index_values.as_mut_ptr(),
1213 index_values.len() as u32,
1214 c_string.as_ptr(),
1215 );
1216
1217 Ok(PointerValue::new(value))
1218 }
1219
1220 /// Builds a GEP instruction on a struct pointer. Returns `Err(BuilderError::GEPError)` if input `PointerValue` doesn't
1221 /// point to a struct or if index is out of bounds.
1222 ///
1223 /// # Example
1224 ///
1225 /// ```no_run
1226 /// use inkwell::AddressSpace;
1227 /// use inkwell::context::Context;
1228 ///
1229 /// let context = Context::create();
1230 /// let builder = context.create_builder();
1231 /// let module = context.create_module("struct_gep");
1232 /// let void_type = context.void_type();
1233 /// let i32_ty = context.i32_type();
1234 /// #[cfg(feature = "typed-pointers")]
1235 /// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default());
1236 /// #[cfg(not(feature = "typed-pointers"))]
1237 /// let i32_ptr_ty = context.ptr_type(AddressSpace::default());
1238 /// let field_types = &[i32_ty.into(), i32_ty.into()];
1239 /// let struct_ty = context.struct_type(field_types, false);
1240 /// let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default());
1241 /// let fn_type = void_type.fn_type(&[i32_ptr_ty.into(), struct_ptr_ty.into()], false);
1242 /// let fn_value = module.add_function("", fn_type, None);
1243 /// let entry = context.append_basic_block(fn_value, "entry");
1244 ///
1245 /// builder.position_at_end(entry);
1246 ///
1247 /// let i32_ptr = fn_value.get_first_param().unwrap().into_pointer_value();
1248 /// let struct_ptr = fn_value.get_last_param().unwrap().into_pointer_value();
1249 ///
1250 /// assert!(builder.build_struct_gep(i32_ptr, 0, "struct_gep").is_err());
1251 /// assert!(builder.build_struct_gep(i32_ptr, 10, "struct_gep").is_err());
1252 /// assert!(builder.build_struct_gep(struct_ptr, 0, "struct_gep").is_ok());
1253 /// assert!(builder.build_struct_gep(struct_ptr, 1, "struct_gep").is_ok());
1254 /// assert!(builder.build_struct_gep(struct_ptr, 2, "struct_gep").is_err());
1255 /// ```
1256 #[cfg(feature = "typed-pointers")]
1257 pub fn build_struct_gep(
1258 &self,
1259 ptr: PointerValue<'ctx>,
1260 index: u32,
1261 name: &str,
1262 ) -> Result<PointerValue<'ctx>, BuilderError> {
1263 if self.positioned.get() != PositionState::Set {
1264 return Err(BuilderError::UnsetPosition);
1265 }
1266 let ptr_ty = ptr.get_type();
1267 let pointee_ty = ptr_ty.get_element_type();
1268
1269 if !pointee_ty.is_struct_type() {
1270 return Err(BuilderError::GEPPointee);
1271 }
1272
1273 let struct_ty = pointee_ty.into_struct_type();
1274
1275 if index >= struct_ty.count_fields() {
1276 return Err(BuilderError::GEPIndex);
1277 }
1278
1279 let c_string = to_c_str(name);
1280
1281 #[cfg(not(feature = "llvm16-0"))]
1282 #[cfg_attr(feature = "llvm15-0", allow(deprecated))]
1283 let value = unsafe { LLVMBuildStructGEP(self.builder, ptr.as_value_ref(), index, c_string.as_ptr()) };
1284 #[cfg(feature = "llvm16-0")]
1285 let value = unsafe {
1286 LLVMBuildStructGEP2(
1287 self.builder,
1288 ptr.get_type().get_element_type().as_type_ref(),
1289 ptr.as_value_ref(),
1290 index,
1291 c_string.as_ptr(),
1292 )
1293 };
1294
1295 unsafe { Ok(PointerValue::new(value)) }
1296 }
1297
1298 /// Builds a GEP instruction on a struct pointer. Returns `Err` `BuilderError::GEPPointee` or `BuilderError::GEPIndex` if input `PointerValue` doesn't
1299 /// point to a struct or if index is out of bounds.
1300 ///
1301 /// # Example
1302 ///
1303 /// ```no_run
1304 /// use inkwell::AddressSpace;
1305 /// use inkwell::context::Context;
1306 ///
1307 /// let context = Context::create();
1308 /// let builder = context.create_builder();
1309 /// let module = context.create_module("struct_gep");
1310 /// let void_type = context.void_type();
1311 /// let i32_ty = context.i32_type();
1312 /// #[cfg(feature = "typed-pointers")]
1313 /// let i32_ptr_ty = i32_ty.ptr_type(AddressSpace::default());
1314 /// #[cfg(not(feature = "typed-pointers"))]
1315 /// let i32_ptr_ty = context.ptr_type(AddressSpace::default());
1316 /// let field_types = &[i32_ty.into(), i32_ty.into()];
1317 /// let struct_ty = context.struct_type(field_types, false);
1318 /// let struct_ptr_ty = struct_ty.ptr_type(AddressSpace::default());
1319 /// let fn_type = void_type.fn_type(&[i32_ptr_ty.into(), struct_ptr_ty.into()], false);
1320 /// let fn_value = module.add_function("", fn_type, None);
1321 /// let entry = context.append_basic_block(fn_value, "entry");
1322 ///
1323 /// builder.position_at_end(entry);
1324 ///
1325 /// let i32_ptr = fn_value.get_first_param().unwrap().into_pointer_value();
1326 /// let struct_ptr = fn_value.get_last_param().unwrap().into_pointer_value();
1327 ///
1328 /// assert!(builder.build_struct_gep(i32_ty, i32_ptr, 0, "struct_gep").is_err());
1329 /// assert!(builder.build_struct_gep(i32_ty, i32_ptr, 10, "struct_gep").is_err());
1330 /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 0, "struct_gep").is_ok());
1331 /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 1, "struct_gep").is_ok());
1332 /// assert!(builder.build_struct_gep(struct_ty, struct_ptr, 2, "struct_gep").is_err());
1333 /// ```
1334 #[cfg(not(feature = "typed-pointers"))]
1335 pub fn build_struct_gep<T: BasicType<'ctx>>(
1336 &self,
1337 pointee_ty: T,
1338 ptr: PointerValue<'ctx>,
1339 index: u32,
1340 name: &str,
1341 ) -> Result<PointerValue<'ctx>, BuilderError> {
1342 if self.positioned.get() != PositionState::Set {
1343 return Err(BuilderError::UnsetPosition);
1344 }
1345 let pointee_ty = pointee_ty.as_any_type_enum();
1346
1347 if !pointee_ty.is_struct_type() {
1348 return Err(BuilderError::GEPPointee);
1349 }
1350
1351 let struct_ty = pointee_ty.into_struct_type();
1352
1353 if index >= struct_ty.count_fields() {
1354 return Err(BuilderError::GEPIndex);
1355 }
1356
1357 let c_string = to_c_str(name);
1358
1359 let value = unsafe {
1360 LLVMBuildStructGEP2(
1361 self.builder,
1362 pointee_ty.as_type_ref(),
1363 ptr.as_value_ref(),
1364 index,
1365 c_string.as_ptr(),
1366 )
1367 };
1368
1369 unsafe { Ok(PointerValue::new(value)) }
1370 }
1371
1372 /// Builds an instruction which calculates the difference of two pointers.
1373 ///
1374 /// # Example
1375 ///
1376 /// ```no_run
1377 /// use inkwell::context::Context;
1378 /// use inkwell::AddressSpace;
1379 ///
1380 /// // Builds a function which diffs two pointers
1381 /// let context = Context::create();
1382 /// let module = context.create_module("ret");
1383 /// let builder = context.create_builder();
1384 /// let void_type = context.void_type();
1385 /// let i32_type = context.i32_type();
1386 /// #[cfg(feature = "typed-pointers")]
1387 /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1388 /// #[cfg(not(feature = "typed-pointers"))]
1389 /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1390 /// let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_ptr_type.into()], false);
1391 /// let fn_value = module.add_function("ret", fn_type, None);
1392 /// let entry = context.append_basic_block(fn_value, "entry");
1393 /// let i32_ptr_param1 = fn_value.get_first_param().unwrap().into_pointer_value();
1394 /// let i32_ptr_param2 = fn_value.get_nth_param(1).unwrap().into_pointer_value();
1395 ///
1396 /// builder.position_at_end(entry);
1397 /// builder.build_ptr_diff(i32_ptr_param1, i32_ptr_param2, "diff").unwrap();
1398 /// builder.build_return(None).unwrap();
1399 /// ```
1400 #[cfg(feature = "typed-pointers")]
1401 pub fn build_ptr_diff(
1402 &self,
1403 lhs_ptr: PointerValue<'ctx>,
1404 rhs_ptr: PointerValue<'ctx>,
1405 name: &str,
1406 ) -> Result<IntValue<'ctx>, BuilderError> {
1407 if self.positioned.get() != PositionState::Set {
1408 return Err(BuilderError::UnsetPosition);
1409 }
1410 let c_string = to_c_str(name);
1411 #[cfg(not(feature = "llvm16-0"))]
1412 #[cfg_attr(feature = "llvm15-0", allow(deprecated))]
1413 let value = unsafe {
1414 LLVMBuildPtrDiff(
1415 self.builder,
1416 lhs_ptr.as_value_ref(),
1417 rhs_ptr.as_value_ref(),
1418 c_string.as_ptr(),
1419 )
1420 };
1421 #[cfg(feature = "llvm16-0")]
1422 let value = {
1423 if lhs_ptr.get_type().as_basic_type_enum() != rhs_ptr.get_type().as_basic_type_enum() {
1424 return Err(BuilderError::ValueTypeMismatch(
1425 "The values must have the same pointer type.",
1426 ));
1427 }
1428
1429 unsafe {
1430 LLVMBuildPtrDiff2(
1431 self.builder,
1432 lhs_ptr.get_type().get_element_type().as_type_ref(),
1433 lhs_ptr.as_value_ref(),
1434 rhs_ptr.as_value_ref(),
1435 c_string.as_ptr(),
1436 )
1437 }
1438 };
1439
1440 unsafe { Ok(IntValue::new(value)) }
1441 }
1442
1443 /// Builds an instruction which calculates the difference of two pointers.
1444 ///
1445 /// # Example
1446 ///
1447 /// ```no_run
1448 /// use inkwell::context::Context;
1449 /// use inkwell::AddressSpace;
1450 ///
1451 /// // Builds a function which diffs two pointers
1452 /// let context = Context::create();
1453 /// let module = context.create_module("ret");
1454 /// let builder = context.create_builder();
1455 /// let void_type = context.void_type();
1456 /// let i32_type = context.i32_type();
1457 /// #[cfg(feature = "typed-pointers")]
1458 /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1459 /// #[cfg(not(feature = "typed-pointers"))]
1460 /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1461 /// let fn_type = void_type.fn_type(&[i32_ptr_type.into(), i32_ptr_type.into()], false);
1462 /// let fn_value = module.add_function("ret", fn_type, None);
1463 /// let entry = context.append_basic_block(fn_value, "entry");
1464 /// let i32_ptr_param1 = fn_value.get_first_param().unwrap().into_pointer_value();
1465 /// let i32_ptr_param2 = fn_value.get_nth_param(1).unwrap().into_pointer_value();
1466 ///
1467 /// builder.position_at_end(entry);
1468 /// builder.build_ptr_diff(i32_ptr_type, i32_ptr_param1, i32_ptr_param2, "diff").unwrap();
1469 /// builder.build_return(None).unwrap();
1470 /// ```
1471 #[cfg(not(feature = "typed-pointers"))]
1472 pub fn build_ptr_diff<T: BasicType<'ctx>>(
1473 &self,
1474 pointee_ty: T,
1475 lhs_ptr: PointerValue<'ctx>,
1476 rhs_ptr: PointerValue<'ctx>,
1477 name: &str,
1478 ) -> Result<IntValue<'ctx>, BuilderError> {
1479 if self.positioned.get() != PositionState::Set {
1480 return Err(BuilderError::UnsetPosition);
1481 }
1482 let c_string = to_c_str(name);
1483
1484 let value = unsafe {
1485 LLVMBuildPtrDiff2(
1486 self.builder,
1487 pointee_ty.as_type_ref(),
1488 lhs_ptr.as_value_ref(),
1489 rhs_ptr.as_value_ref(),
1490 c_string.as_ptr(),
1491 )
1492 };
1493
1494 unsafe { Ok(IntValue::new(value)) }
1495 }
1496
1497 // SubTypes: Maybe this should return PhiValue<T>? That way we could force incoming values to be of T::Value?
1498 // That is, assuming LLVM complains about different phi types.. which I imagine it would. But this would get
1499 // tricky with VoidType since it has no instance value?
1500 // TODOC: Phi Instruction(s) must be first instruction(s) in a BasicBlock.
1501 // REVIEW: Not sure if we can enforce the above somehow via types.
1502 pub fn build_phi<T: BasicType<'ctx>>(&self, type_: T, name: &str) -> Result<PhiValue<'ctx>, BuilderError> {
1503 if self.positioned.get() != PositionState::Set {
1504 return Err(BuilderError::UnsetPosition);
1505 }
1506 let c_string = to_c_str(name);
1507 let value = unsafe { LLVMBuildPhi(self.builder, type_.as_type_ref(), c_string.as_ptr()) };
1508
1509 unsafe { Ok(PhiValue::new(value)) }
1510 }
1511
1512 /// Builds a store instruction. It allows you to store a value of type `T` in a pointer to a type `T`.
1513 ///
1514 /// # Example
1515 ///
1516 /// ```no_run
1517 /// use inkwell::context::Context;
1518 /// use inkwell::AddressSpace;
1519 ///
1520 /// // Builds a function which takes an i32 pointer and stores a 7 in it.
1521 /// let context = Context::create();
1522 /// let module = context.create_module("ret");
1523 /// let builder = context.create_builder();
1524 /// let void_type = context.void_type();
1525 /// let i32_type = context.i32_type();
1526 /// #[cfg(feature = "typed-pointers")]
1527 /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1528 /// #[cfg(not(feature = "typed-pointers"))]
1529 /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1530 /// let i32_seven = i32_type.const_int(7, false);
1531 /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
1532 /// let fn_value = module.add_function("ret", fn_type, None);
1533 /// let entry = context.append_basic_block(fn_value, "entry");
1534 /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
1535 ///
1536 /// builder.position_at_end(entry);
1537 /// builder.build_store(i32_ptr_param, i32_seven).unwrap();
1538 /// builder.build_return(None).unwrap();
1539 /// ```
1540 pub fn build_store<V: BasicValue<'ctx>>(
1541 &self,
1542 ptr: PointerValue<'ctx>,
1543 value: V,
1544 ) -> Result<InstructionValue<'ctx>, BuilderError> {
1545 if self.positioned.get() != PositionState::Set {
1546 return Err(BuilderError::UnsetPosition);
1547 }
1548 let value = unsafe { LLVMBuildStore(self.builder, value.as_value_ref(), ptr.as_value_ref()) };
1549
1550 unsafe { Ok(InstructionValue::new(value)) }
1551 }
1552
1553 /// Builds a load instruction. It allows you to retrieve a value of type `T` from a pointer to a type `T`.
1554 ///
1555 /// # Example
1556 ///
1557 /// ```no_run
1558 /// use inkwell::context::Context;
1559 /// use inkwell::AddressSpace;
1560 ///
1561 /// // Builds a function which takes an i32 pointer and returns the pointed at i32.
1562 /// let context = Context::create();
1563 /// let module = context.create_module("ret");
1564 /// let builder = context.create_builder();
1565 /// let i32_type = context.i32_type();
1566 /// #[cfg(feature = "typed-pointers")]
1567 /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1568 /// #[cfg(not(feature = "typed-pointers"))]
1569 /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1570 /// let fn_type = i32_type.fn_type(&[i32_ptr_type.into()], false);
1571 /// let fn_value = module.add_function("ret", fn_type, None);
1572 /// let entry = context.append_basic_block(fn_value, "entry");
1573 /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
1574 ///
1575 /// builder.position_at_end(entry);
1576 ///
1577 /// let pointee = builder.build_load(i32_ptr_param, "load").unwrap();
1578 ///
1579 /// builder.build_return(Some(&pointee)).unwrap();
1580 /// ```
1581 #[cfg(feature = "typed-pointers")]
1582 pub fn build_load(&self, ptr: PointerValue<'ctx>, name: &str) -> Result<BasicValueEnum<'ctx>, BuilderError> {
1583 if self.positioned.get() != PositionState::Set {
1584 return Err(BuilderError::UnsetPosition);
1585 }
1586 let c_string = to_c_str(name);
1587
1588 #[cfg(not(feature = "llvm16-0"))]
1589 #[cfg_attr(feature = "llvm15-0", allow(deprecated))]
1590 let value = unsafe { LLVMBuildLoad(self.builder, ptr.as_value_ref(), c_string.as_ptr()) };
1591 #[cfg(feature = "llvm16-0")]
1592 let value = unsafe {
1593 LLVMBuildLoad2(
1594 self.builder,
1595 ptr.get_type().get_element_type().as_type_ref(),
1596 ptr.as_value_ref(),
1597 c_string.as_ptr(),
1598 )
1599 };
1600
1601 unsafe { Ok(BasicValueEnum::new(value)) }
1602 }
1603
1604 /// Builds a load2 instruction. It allows you to retrieve a value of type `T` from a pointer to a type `T`.
1605 ///
1606 /// # Example
1607 ///
1608 /// ```no_run
1609 /// use inkwell::context::Context;
1610 /// use inkwell::AddressSpace;
1611 ///
1612 /// // Builds a function which takes an i32 pointer and returns the pointed at i32.
1613 /// let context = Context::create();
1614 /// let module = context.create_module("ret");
1615 /// let builder = context.create_builder();
1616 /// let i32_type = context.i32_type();
1617 /// #[cfg(feature = "typed-pointers")]
1618 /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
1619 /// #[cfg(not(feature = "typed-pointers"))]
1620 /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
1621 /// let fn_type = i32_type.fn_type(&[i32_ptr_type.into()], false);
1622 /// let fn_value = module.add_function("ret", fn_type, None);
1623 /// let entry = context.append_basic_block(fn_value, "entry");
1624 /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
1625 ///
1626 /// builder.position_at_end(entry);
1627 ///
1628 /// let pointee = builder.build_load(i32_type, i32_ptr_param, "load2").unwrap();
1629 ///
1630 /// builder.build_return(Some(&pointee)).unwrap();
1631 /// ```
1632 #[cfg(not(feature = "typed-pointers"))]
1633 pub fn build_load<T: BasicType<'ctx>>(
1634 &self,
1635 pointee_ty: T,
1636 ptr: PointerValue<'ctx>,
1637 name: &str,
1638 ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
1639 if self.positioned.get() != PositionState::Set {
1640 return Err(BuilderError::UnsetPosition);
1641 }
1642 let c_string = to_c_str(name);
1643
1644 let value = unsafe {
1645 LLVMBuildLoad2(
1646 self.builder,
1647 pointee_ty.as_type_ref(),
1648 ptr.as_value_ref(),
1649 c_string.as_ptr(),
1650 )
1651 };
1652
1653 unsafe { Ok(BasicValueEnum::new(value)) }
1654 }
1655
1656 // TODOC: Stack allocation
1657 pub fn build_alloca<T: BasicType<'ctx>>(&self, ty: T, name: &str) -> Result<PointerValue<'ctx>, BuilderError> {
1658 if self.positioned.get() != PositionState::Set {
1659 return Err(BuilderError::UnsetPosition);
1660 }
1661 let c_string = to_c_str(name);
1662 let value = unsafe { LLVMBuildAlloca(self.builder, ty.as_type_ref(), c_string.as_ptr()) };
1663
1664 unsafe { Ok(PointerValue::new(value)) }
1665 }
1666
1667 // TODOC: Stack allocation
1668 pub fn build_array_alloca<T: BasicType<'ctx>>(
1669 &self,
1670 ty: T,
1671 size: IntValue<'ctx>,
1672 name: &str,
1673 ) -> Result<PointerValue<'ctx>, BuilderError> {
1674 if self.positioned.get() != PositionState::Set {
1675 return Err(BuilderError::UnsetPosition);
1676 }
1677 let c_string = to_c_str(name);
1678 let value =
1679 unsafe { LLVMBuildArrayAlloca(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr()) };
1680
1681 unsafe { Ok(PointerValue::new(value)) }
1682 }
1683
1684 /// Build a [memcpy](https://llvm.org/docs/LangRef.html#llvm-memcpy-intrinsic) instruction.
1685 ///
1686 /// Alignment arguments are specified in bytes, and should always be
1687 /// both a power of 2 and under 2^64.
1688 ///
1689 /// The final argument should be a pointer-sized integer.
1690 ///
1691 /// Returns an `Err(BuilderError::AlignmentError)` if the source or destination alignments are not a power of 2.
1692 ///
1693 /// [`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.
1694 #[llvm_versions(8..)]
1695 pub fn build_memcpy(
1696 &self,
1697 dest: PointerValue<'ctx>,
1698 dest_align_bytes: u32,
1699 src: PointerValue<'ctx>,
1700 src_align_bytes: u32,
1701 size: IntValue<'ctx>,
1702 ) -> Result<PointerValue<'ctx>, BuilderError> {
1703 if self.positioned.get() != PositionState::Set {
1704 return Err(BuilderError::UnsetPosition);
1705 }
1706 if !is_alignment_ok(src_align_bytes) {
1707 return Err(BuilderError::AlignmentError(
1708 "The src_align_bytes argument to build_memcpy was not a power of 2.",
1709 ));
1710 }
1711
1712 if !is_alignment_ok(dest_align_bytes) {
1713 return Err(BuilderError::AlignmentError(
1714 "The dest_align_bytes argument to build_memcpy was not a power of 2.",
1715 ));
1716 }
1717
1718 let value = unsafe {
1719 LLVMBuildMemCpy(
1720 self.builder,
1721 dest.as_value_ref(),
1722 dest_align_bytes,
1723 src.as_value_ref(),
1724 src_align_bytes,
1725 size.as_value_ref(),
1726 )
1727 };
1728
1729 unsafe { Ok(PointerValue::new(value)) }
1730 }
1731
1732 /// Build a [memmove](http://llvm.org/docs/LangRef.html#llvm-memmove-intrinsic) instruction.
1733 ///
1734 /// Alignment arguments are specified in bytes, and should always be
1735 /// both a power of 2 and under 2^64.
1736 ///
1737 /// The final argument should be a pointer-sized integer.
1738 ///
1739 /// Returns an `Err(BuilderError::AlignmentError)` if the source or destination alignments are not a power of 2 under 2^64.
1740 ///
1741 /// [`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.
1742 #[llvm_versions(8..)]
1743 pub fn build_memmove(
1744 &self,
1745 dest: PointerValue<'ctx>,
1746 dest_align_bytes: u32,
1747 src: PointerValue<'ctx>,
1748 src_align_bytes: u32,
1749 size: IntValue<'ctx>,
1750 ) -> Result<PointerValue<'ctx>, BuilderError> {
1751 if self.positioned.get() != PositionState::Set {
1752 return Err(BuilderError::UnsetPosition);
1753 }
1754 if !is_alignment_ok(src_align_bytes) {
1755 return Err(BuilderError::AlignmentError(
1756 "The src_align_bytes argument to build_memmove was not a power of 2 under 2^64.",
1757 ));
1758 }
1759
1760 if !is_alignment_ok(dest_align_bytes) {
1761 return Err(BuilderError::AlignmentError(
1762 "The dest_align_bytes argument to build_memmove was not a power of 2 under 2^64.",
1763 ));
1764 }
1765
1766 let value = unsafe {
1767 LLVMBuildMemMove(
1768 self.builder,
1769 dest.as_value_ref(),
1770 dest_align_bytes,
1771 src.as_value_ref(),
1772 src_align_bytes,
1773 size.as_value_ref(),
1774 )
1775 };
1776
1777 unsafe { Ok(PointerValue::new(value)) }
1778 }
1779
1780 /// Build a [memset](http://llvm.org/docs/LangRef.html#llvm-memset-intrinsics) instruction.
1781 ///
1782 /// Alignment arguments are specified in bytes, and should always be
1783 /// both a power of 2 and under 2^64.
1784 ///
1785 /// The final argument should be a pointer-sized integer.
1786 ///
1787 /// Returns an `Err(BuilderError::AlignmentError)` if the source alignment is not a power of 2 under 2^64.
1788 ///
1789 /// [`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.
1790 #[llvm_versions(8..)]
1791 pub fn build_memset(
1792 &self,
1793 dest: PointerValue<'ctx>,
1794 dest_align_bytes: u32,
1795 val: IntValue<'ctx>,
1796 size: IntValue<'ctx>,
1797 ) -> Result<PointerValue<'ctx>, BuilderError> {
1798 if self.positioned.get() != PositionState::Set {
1799 return Err(BuilderError::UnsetPosition);
1800 }
1801 if !is_alignment_ok(dest_align_bytes) {
1802 return Err(BuilderError::AlignmentError(
1803 "The src_align_bytes argument to build_memmove was not a power of 2 under 2^64.",
1804 ));
1805 }
1806
1807 let value = unsafe {
1808 LLVMBuildMemSet(
1809 self.builder,
1810 dest.as_value_ref(),
1811 val.as_value_ref(),
1812 size.as_value_ref(),
1813 dest_align_bytes,
1814 )
1815 };
1816
1817 unsafe { Ok(PointerValue::new(value)) }
1818 }
1819
1820 // TODOC: Heap allocation
1821 /// Returns `Err(BuilderError::AlignmentError)` if the type is unsized.
1822 pub fn build_malloc<T: BasicType<'ctx>>(&self, ty: T, name: &str) -> Result<PointerValue<'ctx>, BuilderError> {
1823 if self.positioned.get() != PositionState::Set {
1824 return Err(BuilderError::UnsetPosition);
1825 }
1826 // LLVMBuildMalloc segfaults if ty is unsized
1827 if !ty.is_sized() {
1828 return Err(BuilderError::AlignmentError(
1829 "Cannot build malloc call for an unsized type",
1830 ));
1831 }
1832
1833 let c_string = to_c_str(name);
1834
1835 let value = unsafe { LLVMBuildMalloc(self.builder, ty.as_type_ref(), c_string.as_ptr()) };
1836
1837 unsafe { Ok(PointerValue::new(value)) }
1838 }
1839
1840 // TODOC: Heap allocation
1841 /// Returns `Err(BuilderError::AlignmentError)` if the type is unsized.
1842 pub fn build_array_malloc<T: BasicType<'ctx>>(
1843 &self,
1844 ty: T,
1845 size: IntValue<'ctx>,
1846 name: &str,
1847 ) -> Result<PointerValue<'ctx>, BuilderError> {
1848 if self.positioned.get() != PositionState::Set {
1849 return Err(BuilderError::UnsetPosition);
1850 }
1851 // LLVMBuildArrayMalloc segfaults if ty is unsized
1852 if !ty.is_sized() {
1853 return Err(BuilderError::AlignmentError(
1854 "Cannot build array malloc call for an unsized type",
1855 ));
1856 }
1857
1858 let c_string = to_c_str(name);
1859
1860 let value =
1861 unsafe { LLVMBuildArrayMalloc(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr()) };
1862
1863 unsafe { Ok(PointerValue::new(value)) }
1864 }
1865
1866 // SubType: <P>(&self, ptr: PointerValue<P>) -> InstructionValue {
1867 pub fn build_free(&self, ptr: PointerValue<'ctx>) -> Result<InstructionValue<'ctx>, BuilderError> {
1868 if self.positioned.get() != PositionState::Set {
1869 return Err(BuilderError::UnsetPosition);
1870 }
1871 unsafe { Ok(InstructionValue::new(LLVMBuildFree(self.builder, ptr.as_value_ref()))) }
1872 }
1873
1874 pub fn insert_instruction(&self, instruction: &InstructionValue<'ctx>, name: Option<&str>) {
1875 match name {
1876 Some(name) => {
1877 let c_string = to_c_str(name);
1878
1879 unsafe { LLVMInsertIntoBuilderWithName(self.builder, instruction.as_value_ref(), c_string.as_ptr()) }
1880 },
1881 None => unsafe {
1882 LLVMInsertIntoBuilder(self.builder, instruction.as_value_ref());
1883 },
1884 }
1885 }
1886
1887 pub fn get_insert_block(&self) -> Option<BasicBlock<'ctx>> {
1888 unsafe { BasicBlock::new(LLVMGetInsertBlock(self.builder)) }
1889 }
1890
1891 // TODO: Possibly make this generic over sign via struct metadata or subtypes
1892 // SubType: <I: IntSubType>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1893 // if I::sign() == Unsigned { LLVMBuildUDiv() } else { LLVMBuildSDiv() }
1894 pub fn build_int_unsigned_div<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1895 if self.positioned.get() != PositionState::Set {
1896 return Err(BuilderError::UnsetPosition);
1897 }
1898 let c_string = to_c_str(name);
1899 let value = unsafe { LLVMBuildUDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1900
1901 unsafe { Ok(T::new(value)) }
1902 }
1903
1904 // TODO: Possibly make this generic over sign via struct metadata or subtypes
1905 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1906 pub fn build_int_signed_div<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1907 if self.positioned.get() != PositionState::Set {
1908 return Err(BuilderError::UnsetPosition);
1909 }
1910 let c_string = to_c_str(name);
1911 let value = unsafe { LLVMBuildSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1912
1913 unsafe { Ok(T::new(value)) }
1914 }
1915
1916 // TODO: Possibly make this generic over sign via struct metadata or subtypes
1917 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1918 pub fn build_int_exact_signed_div<T: IntMathValue<'ctx>>(
1919 &self,
1920 lhs: T,
1921 rhs: T,
1922 name: &str,
1923 ) -> Result<T, BuilderError> {
1924 if self.positioned.get() != PositionState::Set {
1925 return Err(BuilderError::UnsetPosition);
1926 }
1927 let c_string = to_c_str(name);
1928 let value =
1929 unsafe { LLVMBuildExactSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1930
1931 unsafe { Ok(T::new(value)) }
1932 }
1933
1934 // TODO: Possibly make this generic over sign via struct metadata or subtypes
1935 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1936 pub fn build_int_unsigned_rem<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1937 if self.positioned.get() != PositionState::Set {
1938 return Err(BuilderError::UnsetPosition);
1939 }
1940 let c_string = to_c_str(name);
1941 let value = unsafe { LLVMBuildURem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1942
1943 unsafe { Ok(T::new(value)) }
1944 }
1945
1946 // TODO: Possibly make this generic over sign via struct metadata or subtypes
1947 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
1948 pub fn build_int_signed_rem<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
1949 if self.positioned.get() != PositionState::Set {
1950 return Err(BuilderError::UnsetPosition);
1951 }
1952 let c_string = to_c_str(name);
1953 let value = unsafe { LLVMBuildSRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
1954
1955 unsafe { Ok(T::new(value)) }
1956 }
1957
1958 pub fn build_int_s_extend<T: IntMathValue<'ctx>>(
1959 &self,
1960 int_value: T,
1961 int_type: T::BaseType,
1962 name: &str,
1963 ) -> Result<T, BuilderError> {
1964 if self.positioned.get() != PositionState::Set {
1965 return Err(BuilderError::UnsetPosition);
1966 }
1967 let c_string = to_c_str(name);
1968 let value = unsafe {
1969 LLVMBuildSExt(
1970 self.builder,
1971 int_value.as_value_ref(),
1972 int_type.as_type_ref(),
1973 c_string.as_ptr(),
1974 )
1975 };
1976
1977 unsafe { Ok(T::new(value)) }
1978 }
1979
1980 // REVIEW: Does this need vector support?
1981 pub fn build_address_space_cast(
1982 &self,
1983 ptr_val: PointerValue<'ctx>,
1984 ptr_type: PointerType<'ctx>,
1985 name: &str,
1986 ) -> Result<PointerValue<'ctx>, BuilderError> {
1987 if self.positioned.get() != PositionState::Set {
1988 return Err(BuilderError::UnsetPosition);
1989 }
1990 let c_string = to_c_str(name);
1991 let value = unsafe {
1992 LLVMBuildAddrSpaceCast(
1993 self.builder,
1994 ptr_val.as_value_ref(),
1995 ptr_type.as_type_ref(),
1996 c_string.as_ptr(),
1997 )
1998 };
1999
2000 unsafe { Ok(PointerValue::new(value)) }
2001 }
2002
2003 /// Builds a bitcast instruction. A bitcast reinterprets the bits of one value
2004 /// into a value of another type which has the same bit width.
2005 ///
2006 /// # Example
2007 ///
2008 /// ```no_run
2009 /// use inkwell::AddressSpace;
2010 /// use inkwell::context::Context;
2011 ///
2012 /// let context = Context::create();
2013 /// let module = context.create_module("bc");
2014 /// let void_type = context.void_type();
2015 /// let f32_type = context.f32_type();
2016 /// let i32_type = context.i32_type();
2017 /// let arg_types = [i32_type.into()];
2018 /// let fn_type = void_type.fn_type(&arg_types, false);
2019 /// let fn_value = module.add_function("bc", fn_type, None);
2020 /// let builder = context.create_builder();
2021 /// let entry = context.append_basic_block(fn_value, "entry");
2022 /// let i32_arg = fn_value.get_first_param().unwrap();
2023 ///
2024 /// builder.position_at_end(entry);
2025 ///
2026 /// builder.build_bit_cast(i32_arg, f32_type, "i32tof32").unwrap();
2027 /// builder.build_return(None).unwrap();
2028 ///
2029 /// assert!(module.verify().is_ok());
2030 /// ```
2031 pub fn build_bit_cast<T, V>(&self, val: V, ty: T, name: &str) -> Result<BasicValueEnum<'ctx>, BuilderError>
2032 where
2033 T: BasicType<'ctx>,
2034 V: BasicValue<'ctx>,
2035 {
2036 if self.positioned.get() != PositionState::Set {
2037 return Err(BuilderError::UnsetPosition);
2038 }
2039 let c_string = to_c_str(name);
2040 let value = unsafe { LLVMBuildBitCast(self.builder, val.as_value_ref(), ty.as_type_ref(), c_string.as_ptr()) };
2041
2042 unsafe { Ok(BasicValueEnum::new(value)) }
2043 }
2044
2045 pub fn build_int_s_extend_or_bit_cast<T: IntMathValue<'ctx>>(
2046 &self,
2047 int_value: T,
2048 int_type: T::BaseType,
2049 name: &str,
2050 ) -> Result<T, BuilderError> {
2051 if self.positioned.get() != PositionState::Set {
2052 return Err(BuilderError::UnsetPosition);
2053 }
2054 let c_string = to_c_str(name);
2055 let value = unsafe {
2056 LLVMBuildSExtOrBitCast(
2057 self.builder,
2058 int_value.as_value_ref(),
2059 int_type.as_type_ref(),
2060 c_string.as_ptr(),
2061 )
2062 };
2063
2064 unsafe { Ok(T::new(value)) }
2065 }
2066
2067 pub fn build_int_z_extend<T: IntMathValue<'ctx>>(
2068 &self,
2069 int_value: T,
2070 int_type: T::BaseType,
2071 name: &str,
2072 ) -> Result<T, BuilderError> {
2073 if self.positioned.get() != PositionState::Set {
2074 return Err(BuilderError::UnsetPosition);
2075 }
2076 let c_string = to_c_str(name);
2077 let value = unsafe {
2078 LLVMBuildZExt(
2079 self.builder,
2080 int_value.as_value_ref(),
2081 int_type.as_type_ref(),
2082 c_string.as_ptr(),
2083 )
2084 };
2085
2086 unsafe { Ok(T::new(value)) }
2087 }
2088
2089 pub fn build_int_z_extend_or_bit_cast<T: IntMathValue<'ctx>>(
2090 &self,
2091 int_value: T,
2092 int_type: T::BaseType,
2093 name: &str,
2094 ) -> Result<T, BuilderError> {
2095 if self.positioned.get() != PositionState::Set {
2096 return Err(BuilderError::UnsetPosition);
2097 }
2098 let c_string = to_c_str(name);
2099 let value = unsafe {
2100 LLVMBuildZExtOrBitCast(
2101 self.builder,
2102 int_value.as_value_ref(),
2103 int_type.as_type_ref(),
2104 c_string.as_ptr(),
2105 )
2106 };
2107
2108 unsafe { Ok(T::new(value)) }
2109 }
2110
2111 pub fn build_int_truncate<T: IntMathValue<'ctx>>(
2112 &self,
2113 int_value: T,
2114 int_type: T::BaseType,
2115 name: &str,
2116 ) -> Result<T, BuilderError> {
2117 if self.positioned.get() != PositionState::Set {
2118 return Err(BuilderError::UnsetPosition);
2119 }
2120 let c_string = to_c_str(name);
2121
2122 let value = unsafe {
2123 LLVMBuildTrunc(
2124 self.builder,
2125 int_value.as_value_ref(),
2126 int_type.as_type_ref(),
2127 c_string.as_ptr(),
2128 )
2129 };
2130
2131 unsafe { Ok(T::new(value)) }
2132 }
2133
2134 pub fn build_int_truncate_or_bit_cast<T: IntMathValue<'ctx>>(
2135 &self,
2136 int_value: T,
2137 int_type: T::BaseType,
2138 name: &str,
2139 ) -> Result<T, BuilderError> {
2140 if self.positioned.get() != PositionState::Set {
2141 return Err(BuilderError::UnsetPosition);
2142 }
2143 let c_string = to_c_str(name);
2144
2145 let value = unsafe {
2146 LLVMBuildTruncOrBitCast(
2147 self.builder,
2148 int_value.as_value_ref(),
2149 int_type.as_type_ref(),
2150 c_string.as_ptr(),
2151 )
2152 };
2153
2154 unsafe { Ok(T::new(value)) }
2155 }
2156
2157 pub fn build_float_rem<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2158 if self.positioned.get() != PositionState::Set {
2159 return Err(BuilderError::UnsetPosition);
2160 }
2161 let c_string = to_c_str(name);
2162 let value = unsafe { LLVMBuildFRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2163
2164 unsafe { Ok(T::new(value)) }
2165 }
2166
2167 // REVIEW: Consolidate these two casts into one via subtypes
2168 pub fn build_float_to_unsigned_int<T: FloatMathValue<'ctx>>(
2169 &self,
2170 float: T,
2171 int_type: <T::BaseType as FloatMathType<'ctx>>::MathConvType,
2172 name: &str,
2173 ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>
2174 {
2175 if self.positioned.get() != PositionState::Set {
2176 return Err(BuilderError::UnsetPosition);
2177 }
2178 let c_string = to_c_str(name);
2179 let value = unsafe {
2180 LLVMBuildFPToUI(
2181 self.builder,
2182 float.as_value_ref(),
2183 int_type.as_type_ref(),
2184 c_string.as_ptr(),
2185 )
2186 };
2187
2188 unsafe { Ok(<<T::BaseType as FloatMathType>::MathConvType as IntMathType>::ValueType::new(value)) }
2189 }
2190
2191 pub fn build_float_to_signed_int<T: FloatMathValue<'ctx>>(
2192 &self,
2193 float: T,
2194 int_type: <T::BaseType as FloatMathType<'ctx>>::MathConvType,
2195 name: &str,
2196 ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>
2197 {
2198 if self.positioned.get() != PositionState::Set {
2199 return Err(BuilderError::UnsetPosition);
2200 }
2201 let c_string = to_c_str(name);
2202 let value = unsafe {
2203 LLVMBuildFPToSI(
2204 self.builder,
2205 float.as_value_ref(),
2206 int_type.as_type_ref(),
2207 c_string.as_ptr(),
2208 )
2209 };
2210
2211 unsafe { Ok(<<T::BaseType as FloatMathType>::MathConvType as IntMathType>::ValueType::new(value)) }
2212 }
2213
2214 // REVIEW: Consolidate these two casts into one via subtypes
2215 pub fn build_unsigned_int_to_float<T: IntMathValue<'ctx>>(
2216 &self,
2217 int: T,
2218 float_type: <T::BaseType as IntMathType<'ctx>>::MathConvType,
2219 name: &str,
2220 ) -> Result<<<T::BaseType as IntMathType<'ctx>>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError>
2221 {
2222 if self.positioned.get() != PositionState::Set {
2223 return Err(BuilderError::UnsetPosition);
2224 }
2225 let c_string = to_c_str(name);
2226 let value = unsafe {
2227 LLVMBuildUIToFP(
2228 self.builder,
2229 int.as_value_ref(),
2230 float_type.as_type_ref(),
2231 c_string.as_ptr(),
2232 )
2233 };
2234
2235 unsafe { Ok(<<T::BaseType as IntMathType>::MathConvType as FloatMathType>::ValueType::new(value)) }
2236 }
2237
2238 pub fn build_signed_int_to_float<T: IntMathValue<'ctx>>(
2239 &self,
2240 int: T,
2241 float_type: <T::BaseType as IntMathType<'ctx>>::MathConvType,
2242 name: &str,
2243 ) -> Result<<<T::BaseType as IntMathType<'ctx>>::MathConvType as FloatMathType<'ctx>>::ValueType, BuilderError>
2244 {
2245 if self.positioned.get() != PositionState::Set {
2246 return Err(BuilderError::UnsetPosition);
2247 }
2248 let c_string = to_c_str(name);
2249 let value = unsafe {
2250 LLVMBuildSIToFP(
2251 self.builder,
2252 int.as_value_ref(),
2253 float_type.as_type_ref(),
2254 c_string.as_ptr(),
2255 )
2256 };
2257
2258 unsafe { Ok(<<T::BaseType as IntMathType>::MathConvType as FloatMathType>::ValueType::new(value)) }
2259 }
2260
2261 pub fn build_float_trunc<T: FloatMathValue<'ctx>>(
2262 &self,
2263 float: T,
2264 float_type: T::BaseType,
2265 name: &str,
2266 ) -> Result<T, BuilderError> {
2267 if self.positioned.get() != PositionState::Set {
2268 return Err(BuilderError::UnsetPosition);
2269 }
2270 let c_string = to_c_str(name);
2271 let value = unsafe {
2272 LLVMBuildFPTrunc(
2273 self.builder,
2274 float.as_value_ref(),
2275 float_type.as_type_ref(),
2276 c_string.as_ptr(),
2277 )
2278 };
2279
2280 unsafe { Ok(T::new(value)) }
2281 }
2282
2283 pub fn build_float_ext<T: FloatMathValue<'ctx>>(
2284 &self,
2285 float: T,
2286 float_type: T::BaseType,
2287 name: &str,
2288 ) -> Result<T, BuilderError> {
2289 if self.positioned.get() != PositionState::Set {
2290 return Err(BuilderError::UnsetPosition);
2291 }
2292 let c_string = to_c_str(name);
2293 let value = unsafe {
2294 LLVMBuildFPExt(
2295 self.builder,
2296 float.as_value_ref(),
2297 float_type.as_type_ref(),
2298 c_string.as_ptr(),
2299 )
2300 };
2301
2302 unsafe { Ok(T::new(value)) }
2303 }
2304
2305 pub fn build_float_cast<T: FloatMathValue<'ctx>>(
2306 &self,
2307 float: T,
2308 float_type: T::BaseType,
2309 name: &str,
2310 ) -> Result<T, BuilderError> {
2311 if self.positioned.get() != PositionState::Set {
2312 return Err(BuilderError::UnsetPosition);
2313 }
2314 let c_string = to_c_str(name);
2315 let value = unsafe {
2316 LLVMBuildFPCast(
2317 self.builder,
2318 float.as_value_ref(),
2319 float_type.as_type_ref(),
2320 c_string.as_ptr(),
2321 )
2322 };
2323
2324 unsafe { Ok(T::new(value)) }
2325 }
2326
2327 // SubType: <L, R>(&self, lhs: &IntValue<L>, rhs: &IntType<R>, name: &str) -> IntValue<R> {
2328 pub fn build_int_cast<T: IntMathValue<'ctx>>(
2329 &self,
2330 int: T,
2331 int_type: T::BaseType,
2332 name: &str,
2333 ) -> Result<T, BuilderError> {
2334 if self.positioned.get() != PositionState::Set {
2335 return Err(BuilderError::UnsetPosition);
2336 }
2337 let c_string = to_c_str(name);
2338 let value = unsafe {
2339 LLVMBuildIntCast(
2340 self.builder,
2341 int.as_value_ref(),
2342 int_type.as_type_ref(),
2343 c_string.as_ptr(),
2344 )
2345 };
2346
2347 unsafe { Ok(T::new(value)) }
2348 }
2349
2350 /// Like `build_int_cast`, but respects the signedness of the type being cast to.
2351 #[llvm_versions(8..)]
2352 pub fn build_int_cast_sign_flag<T: IntMathValue<'ctx>>(
2353 &self,
2354 int: T,
2355 int_type: T::BaseType,
2356 is_signed: bool,
2357 name: &str,
2358 ) -> Result<T, BuilderError> {
2359 if self.positioned.get() != PositionState::Set {
2360 return Err(BuilderError::UnsetPosition);
2361 }
2362 let c_string = to_c_str(name);
2363 let value = unsafe {
2364 LLVMBuildIntCast2(
2365 self.builder,
2366 int.as_value_ref(),
2367 int_type.as_type_ref(),
2368 is_signed.into(),
2369 c_string.as_ptr(),
2370 )
2371 };
2372
2373 unsafe { Ok(T::new(value)) }
2374 }
2375
2376 pub fn build_float_div<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2377 if self.positioned.get() != PositionState::Set {
2378 return Err(BuilderError::UnsetPosition);
2379 }
2380 let c_string = to_c_str(name);
2381 let value = unsafe { LLVMBuildFDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2382
2383 unsafe { Ok(T::new(value)) }
2384 }
2385
2386 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2387 pub fn build_int_add<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2388 if self.positioned.get() != PositionState::Set {
2389 return Err(BuilderError::UnsetPosition);
2390 }
2391 let c_string = to_c_str(name);
2392 let value = unsafe { LLVMBuildAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2393
2394 unsafe { Ok(T::new(value)) }
2395 }
2396
2397 // REVIEW: Possibly incorporate into build_int_add via flag param
2398 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2399 pub fn build_int_nsw_add<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2400 let c_string = to_c_str(name);
2401 let value = unsafe { LLVMBuildNSWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2402
2403 unsafe { Ok(T::new(value)) }
2404 }
2405
2406 // REVIEW: Possibly incorporate into build_int_add via flag param
2407 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2408 pub fn build_int_nuw_add<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2409 if self.positioned.get() != PositionState::Set {
2410 return Err(BuilderError::UnsetPosition);
2411 }
2412 let c_string = to_c_str(name);
2413 let value = unsafe { LLVMBuildNUWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2414
2415 unsafe { Ok(T::new(value)) }
2416 }
2417
2418 // SubType: <F>(&self, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name: &str) -> FloatValue<F> {
2419 pub fn build_float_add<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2420 if self.positioned.get() != PositionState::Set {
2421 return Err(BuilderError::UnsetPosition);
2422 }
2423 let c_string = to_c_str(name);
2424 let value = unsafe { LLVMBuildFAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2425
2426 unsafe { Ok(T::new(value)) }
2427 }
2428
2429 // SubType: (&self, lhs: &IntValue<bool>, rhs: &IntValue<bool>, name: &str) -> IntValue<bool> {
2430 pub fn build_xor<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2431 if self.positioned.get() != PositionState::Set {
2432 return Err(BuilderError::UnsetPosition);
2433 }
2434 let c_string = to_c_str(name);
2435 let value = unsafe { LLVMBuildXor(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2436
2437 unsafe { Ok(T::new(value)) }
2438 }
2439
2440 // SubType: (&self, lhs: &IntValue<bool>, rhs: &IntValue<bool>, name: &str) -> IntValue<bool> {
2441 pub fn build_and<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2442 if self.positioned.get() != PositionState::Set {
2443 return Err(BuilderError::UnsetPosition);
2444 }
2445 let c_string = to_c_str(name);
2446 let value = unsafe { LLVMBuildAnd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2447
2448 unsafe { Ok(T::new(value)) }
2449 }
2450
2451 // SubType: (&self, lhs: &IntValue<bool>, rhs: &IntValue<bool>, name: &str) -> IntValue<bool> {
2452 pub fn build_or<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2453 if self.positioned.get() != PositionState::Set {
2454 return Err(BuilderError::UnsetPosition);
2455 }
2456 let c_string = to_c_str(name);
2457 let value = unsafe { LLVMBuildOr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2458
2459 unsafe { Ok(T::new(value)) }
2460 }
2461
2462 /// Builds an `IntValue` containing the result of a logical left shift instruction.
2463 ///
2464 /// # Example
2465 /// A logical left shift is an operation in which an integer value's bits are shifted left by N number of positions.
2466 ///
2467 /// ```rust,no_run
2468 /// assert_eq!(0b0000_0001 << 0, 0b0000_0001);
2469 /// assert_eq!(0b0000_0001 << 1, 0b0000_0010);
2470 /// assert_eq!(0b0000_0011 << 2, 0b0000_1100);
2471 /// ```
2472 ///
2473 /// In Rust, a function that could do this for 8bit values looks like:
2474 ///
2475 /// ```rust,no_run
2476 /// fn left_shift(value: u8, n: u8) -> u8 {
2477 /// value << n
2478 /// }
2479 /// ```
2480 ///
2481 /// And in Inkwell, the corresponding function would look roughly like:
2482 ///
2483 /// ```rust,no_run
2484 /// use inkwell::context::Context;
2485 ///
2486 /// // Setup
2487 /// let context = Context::create();
2488 /// let module = context.create_module("my_module");
2489 /// let builder = context.create_builder();
2490 /// let i8_type = context.i8_type();
2491 /// let fn_type = i8_type.fn_type(&[i8_type.into(), i8_type.into()], false);
2492 ///
2493 /// // Function Definition
2494 /// let function = module.add_function("left_shift", fn_type, None);
2495 /// let value = function.get_first_param().unwrap().into_int_value();
2496 /// let n = function.get_nth_param(1).unwrap().into_int_value();
2497 /// let entry_block = context.append_basic_block(function, "entry");
2498 ///
2499 /// builder.position_at_end(entry_block);
2500 ///
2501 /// let shift = builder.build_left_shift(value, n, "left_shift").unwrap(); // value << n
2502 ///
2503 /// builder.build_return(Some(&shift)).unwrap();
2504 /// ```
2505 pub fn build_left_shift<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2506 if self.positioned.get() != PositionState::Set {
2507 return Err(BuilderError::UnsetPosition);
2508 }
2509 let c_string = to_c_str(name);
2510 let value = unsafe { LLVMBuildShl(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2511
2512 unsafe { Ok(T::new(value)) }
2513 }
2514
2515 /// Builds an `IntValue` containing the result of a right shift instruction.
2516 ///
2517 /// # Example
2518 /// A right shift is an operation in which an integer value's bits are shifted right by N number of positions.
2519 /// It may either be logical and have its leftmost N bit(s) filled with zeros or sign extended and filled with ones
2520 /// if the leftmost bit was one.
2521 ///
2522 /// ```rust,no_run
2523 /// //fix doc error about overflowing_literals
2524 /// //rendered rfc: https://github.com/rust-lang/rfcs/blob/master/text/2438-deny-integer-literal-overflow-lint.md
2525 /// //tracking issue: https://github.com/rust-lang/rust/issues/54502
2526 /// #![allow(overflowing_literals)]
2527 ///
2528 /// // Logical Right Shift
2529 /// assert_eq!(0b1100_0000u8 >> 2, 0b0011_0000);
2530 /// assert_eq!(0b0000_0010u8 >> 1, 0b0000_0001);
2531 /// assert_eq!(0b0000_1100u8 >> 2, 0b0000_0011);
2532 ///
2533 /// // Sign Extended Right Shift
2534 /// assert_eq!(0b0100_0000i8 >> 2, 0b0001_0000);
2535 /// assert_eq!(0b1110_0000u8 as i8 >> 1, 0b1111_0000u8 as i8);
2536 /// assert_eq!(0b1100_0000u8 as i8 >> 2, 0b1111_0000u8 as i8);
2537 /// ```
2538 ///
2539 /// In Rust, functions that could do this for 8bit values look like:
2540 ///
2541 /// ```rust,no_run
2542 /// fn logical_right_shift(value: u8, n: u8) -> u8 {
2543 /// value >> n
2544 /// }
2545 ///
2546 /// fn sign_extended_right_shift(value: i8, n: u8) -> i8 {
2547 /// value >> n
2548 /// }
2549 /// ```
2550 /// Notice that, in Rust (and most other languages), whether or not a value is sign extended depends wholly on whether
2551 /// or not the type is signed (ie an i8 is a signed 8 bit value). LLVM does not make this distinction for you.
2552 ///
2553 /// In Inkwell, the corresponding functions would look roughly like:
2554 ///
2555 /// ```rust,no_run
2556 /// use inkwell::context::Context;
2557 ///
2558 /// // Setup
2559 /// let context = Context::create();
2560 /// let module = context.create_module("my_module");
2561 /// let builder = context.create_builder();
2562 /// let i8_type = context.i8_type();
2563 /// let fn_type = i8_type.fn_type(&[i8_type.into(), i8_type.into()], false);
2564 ///
2565 /// // Function Definition
2566 /// let function = module.add_function("right_shift", fn_type, None);
2567 /// let value = function.get_first_param().unwrap().into_int_value();
2568 /// let n = function.get_nth_param(1).unwrap().into_int_value();
2569 /// let entry_block = context.append_basic_block(function, "entry");
2570 ///
2571 /// builder.position_at_end(entry_block);
2572 ///
2573 /// // Whether or not your right shift is sign extended (true) or logical (false) depends
2574 /// // on the boolean input parameter:
2575 /// let shift = builder.build_right_shift(value, n, false, "right_shift").unwrap(); // value >> n
2576 ///
2577 /// builder.build_return(Some(&shift)).unwrap();
2578 /// ```
2579 pub fn build_right_shift<T: IntMathValue<'ctx>>(
2580 &self,
2581 lhs: T,
2582 rhs: T,
2583 sign_extend: bool,
2584 name: &str,
2585 ) -> Result<T, BuilderError> {
2586 if self.positioned.get() != PositionState::Set {
2587 return Err(BuilderError::UnsetPosition);
2588 }
2589 let c_string = to_c_str(name);
2590 let value = unsafe {
2591 if sign_extend {
2592 LLVMBuildAShr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr())
2593 } else {
2594 LLVMBuildLShr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr())
2595 }
2596 };
2597
2598 unsafe { Ok(T::new(value)) }
2599 }
2600
2601 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2602 pub fn build_int_sub<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2603 if self.positioned.get() != PositionState::Set {
2604 return Err(BuilderError::UnsetPosition);
2605 }
2606 let c_string = to_c_str(name);
2607 let value = unsafe { LLVMBuildSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2608
2609 unsafe { Ok(T::new(value)) }
2610 }
2611
2612 // REVIEW: Possibly incorporate into build_int_sub via flag param
2613 pub fn build_int_nsw_sub<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2614 if self.positioned.get() != PositionState::Set {
2615 return Err(BuilderError::UnsetPosition);
2616 }
2617 let c_string = to_c_str(name);
2618 let value = unsafe { LLVMBuildNSWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2619
2620 unsafe { Ok(T::new(value)) }
2621 }
2622
2623 // REVIEW: Possibly incorporate into build_int_sub via flag param
2624 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2625 pub fn build_int_nuw_sub<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2626 if self.positioned.get() != PositionState::Set {
2627 return Err(BuilderError::UnsetPosition);
2628 }
2629 let c_string = to_c_str(name);
2630 let value = unsafe { LLVMBuildNUWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2631
2632 unsafe { Ok(T::new(value)) }
2633 }
2634
2635 // SubType: <F>(&self, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name: &str) -> FloatValue<F> {
2636 pub fn build_float_sub<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2637 if self.positioned.get() != PositionState::Set {
2638 return Err(BuilderError::UnsetPosition);
2639 }
2640 let c_string = to_c_str(name);
2641 let value = unsafe { LLVMBuildFSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2642
2643 unsafe { Ok(T::new(value)) }
2644 }
2645
2646 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2647 pub fn build_int_mul<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2648 if self.positioned.get() != PositionState::Set {
2649 return Err(BuilderError::UnsetPosition);
2650 }
2651 let c_string = to_c_str(name);
2652 let value = unsafe { LLVMBuildMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2653
2654 unsafe { Ok(T::new(value)) }
2655 }
2656
2657 // REVIEW: Possibly incorporate into build_int_mul via flag param
2658 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2659 pub fn build_int_nsw_mul<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2660 if self.positioned.get() != PositionState::Set {
2661 return Err(BuilderError::UnsetPosition);
2662 }
2663 let c_string = to_c_str(name);
2664 let value = unsafe { LLVMBuildNSWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2665
2666 unsafe { Ok(T::new(value)) }
2667 }
2668
2669 // REVIEW: Possibly incorporate into build_int_mul via flag param
2670 // SubType: <I>(&self, lhs: &IntValue<I>, rhs: &IntValue<I>, name: &str) -> IntValue<I> {
2671 pub fn build_int_nuw_mul<T: IntMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2672 if self.positioned.get() != PositionState::Set {
2673 return Err(BuilderError::UnsetPosition);
2674 }
2675 let c_string = to_c_str(name);
2676 let value = unsafe { LLVMBuildNUWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2677
2678 unsafe { Ok(T::new(value)) }
2679 }
2680
2681 // SubType: <F>(&self, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name: &str) -> FloatValue<F> {
2682 pub fn build_float_mul<T: FloatMathValue<'ctx>>(&self, lhs: T, rhs: T, name: &str) -> Result<T, BuilderError> {
2683 if self.positioned.get() != PositionState::Set {
2684 return Err(BuilderError::UnsetPosition);
2685 }
2686 let c_string = to_c_str(name);
2687 let value = unsafe { LLVMBuildFMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) };
2688
2689 unsafe { Ok(T::new(value)) }
2690 }
2691
2692 pub fn build_binop<T: BasicValue<'ctx>>(
2693 &self,
2694 op: InstructionOpcode,
2695 lhs: T,
2696 rhs: T,
2697 name: &str,
2698 ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
2699 if self.positioned.get() != PositionState::Set {
2700 return Err(BuilderError::UnsetPosition);
2701 }
2702 let c_string = to_c_str(name);
2703 let value = unsafe {
2704 LLVMBuildBinOp(
2705 self.builder,
2706 op.into(),
2707 lhs.as_value_ref(),
2708 rhs.as_value_ref(),
2709 c_string.as_ptr(),
2710 )
2711 };
2712
2713 unsafe { Ok(BasicValueEnum::new(value)) }
2714 }
2715
2716 pub fn build_cast<T: BasicType<'ctx>, V: BasicValue<'ctx>>(
2717 &self,
2718 op: InstructionOpcode,
2719 from_value: V,
2720 to_type: T,
2721 name: &str,
2722 ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
2723 if self.positioned.get() != PositionState::Set {
2724 return Err(BuilderError::UnsetPosition);
2725 }
2726 let c_string = to_c_str(name);
2727 let value = unsafe {
2728 LLVMBuildCast(
2729 self.builder,
2730 op.into(),
2731 from_value.as_value_ref(),
2732 to_type.as_type_ref(),
2733 c_string.as_ptr(),
2734 )
2735 };
2736
2737 unsafe { Ok(BasicValueEnum::new(value)) }
2738 }
2739
2740 // SubType: <F, T>(&self, from: &PointerValue<F>, to: &PointerType<T>, name: &str) -> PointerValue<T> {
2741 pub fn build_pointer_cast<T: PointerMathValue<'ctx>>(
2742 &self,
2743 from: T,
2744 to: T::BaseType,
2745 name: &str,
2746 ) -> Result<T, BuilderError> {
2747 if self.positioned.get() != PositionState::Set {
2748 return Err(BuilderError::UnsetPosition);
2749 }
2750 let c_string = to_c_str(name);
2751 let value =
2752 unsafe { LLVMBuildPointerCast(self.builder, from.as_value_ref(), to.as_type_ref(), c_string.as_ptr()) };
2753
2754 unsafe { Ok(T::new(value)) }
2755 }
2756
2757 // SubType: <I>(&self, op, lhs: &IntValue<I>, rhs: &IntValue<I>, name) -> IntValue<bool> { ?
2758 // Note: we need a way to get an appropriate return type, since this method's return value
2759 // is always a bool (or vector of bools), not necessarily the same as the input value
2760 // See https://github.com/TheDan64/inkwell/pull/47#discussion_r197599297
2761 pub fn build_int_compare<T: IntMathValue<'ctx>>(
2762 &self,
2763 op: IntPredicate,
2764 lhs: T,
2765 rhs: T,
2766 name: &str,
2767 ) -> Result<<T::BaseType as IntMathType<'ctx>>::ValueType, BuilderError> {
2768 if self.positioned.get() != PositionState::Set {
2769 return Err(BuilderError::UnsetPosition);
2770 }
2771 let c_string = to_c_str(name);
2772 let value = unsafe {
2773 LLVMBuildICmp(
2774 self.builder,
2775 op.into(),
2776 lhs.as_value_ref(),
2777 rhs.as_value_ref(),
2778 c_string.as_ptr(),
2779 )
2780 };
2781
2782 unsafe { Ok(<T::BaseType as IntMathType<'ctx>>::ValueType::new(value)) }
2783 }
2784
2785 // SubType: <F>(&self, op, lhs: &FloatValue<F>, rhs: &FloatValue<F>, name) -> IntValue<bool> { ?
2786 // Note: see comment on build_int_compare regarding return value type
2787 pub fn build_float_compare<T: FloatMathValue<'ctx>>(
2788 &self,
2789 op: FloatPredicate,
2790 lhs: T,
2791 rhs: T,
2792 name: &str,
2793 ) -> Result<<<T::BaseType as FloatMathType<'ctx>>::MathConvType as IntMathType<'ctx>>::ValueType, BuilderError>
2794 {
2795 if self.positioned.get() != PositionState::Set {
2796 return Err(BuilderError::UnsetPosition);
2797 }
2798 let c_string = to_c_str(name);
2799
2800 let value = unsafe {
2801 LLVMBuildFCmp(
2802 self.builder,
2803 op.into(),
2804 lhs.as_value_ref(),
2805 rhs.as_value_ref(),
2806 c_string.as_ptr(),
2807 )
2808 };
2809
2810 unsafe { Ok(<<T::BaseType as FloatMathType>::MathConvType as IntMathType>::ValueType::new(value)) }
2811 }
2812
2813 pub fn build_unconditional_branch(
2814 &self,
2815 destination_block: BasicBlock<'ctx>,
2816 ) -> Result<InstructionValue<'ctx>, BuilderError> {
2817 if self.positioned.get() != PositionState::Set {
2818 return Err(BuilderError::UnsetPosition);
2819 }
2820 let value = unsafe { LLVMBuildBr(self.builder, destination_block.basic_block) };
2821
2822 unsafe { Ok(InstructionValue::new(value)) }
2823 }
2824
2825 pub fn build_conditional_branch(
2826 &self,
2827 comparison: IntValue<'ctx>,
2828 then_block: BasicBlock<'ctx>,
2829 else_block: BasicBlock<'ctx>,
2830 ) -> Result<InstructionValue<'ctx>, BuilderError> {
2831 if self.positioned.get() != PositionState::Set {
2832 return Err(BuilderError::UnsetPosition);
2833 }
2834 let value = unsafe {
2835 LLVMBuildCondBr(
2836 self.builder,
2837 comparison.as_value_ref(),
2838 then_block.basic_block,
2839 else_block.basic_block,
2840 )
2841 };
2842
2843 unsafe { Ok(InstructionValue::new(value)) }
2844 }
2845
2846 pub fn build_indirect_branch<BV: BasicValue<'ctx>>(
2847 &self,
2848 address: BV,
2849 destinations: &[BasicBlock<'ctx>],
2850 ) -> Result<InstructionValue<'ctx>, BuilderError> {
2851 if self.positioned.get() != PositionState::Set {
2852 return Err(BuilderError::UnsetPosition);
2853 }
2854 let value = unsafe { LLVMBuildIndirectBr(self.builder, address.as_value_ref(), destinations.len() as u32) };
2855
2856 for destination in destinations {
2857 unsafe { LLVMAddDestination(value, destination.basic_block) }
2858 }
2859
2860 unsafe { Ok(InstructionValue::new(value)) }
2861 }
2862
2863 // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<I> {
2864 pub fn build_int_neg<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2865 if self.positioned.get() != PositionState::Set {
2866 return Err(BuilderError::UnsetPosition);
2867 }
2868 let c_string = to_c_str(name);
2869 let value = unsafe { LLVMBuildNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2870
2871 unsafe { Ok(T::new(value)) }
2872 }
2873
2874 // REVIEW: Possibly incorporate into build_int_neg via flag and subtypes
2875 // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<I> {
2876 pub fn build_int_nsw_neg<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2877 if self.positioned.get() != PositionState::Set {
2878 return Err(BuilderError::UnsetPosition);
2879 }
2880 let c_string = to_c_str(name);
2881 let value = unsafe { LLVMBuildNSWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2882
2883 unsafe { Ok(T::new(value)) }
2884 }
2885
2886 // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<I> {
2887 pub fn build_int_nuw_neg<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2888 if self.positioned.get() != PositionState::Set {
2889 return Err(BuilderError::UnsetPosition);
2890 }
2891 let c_string = to_c_str(name);
2892 let value = unsafe { LLVMBuildNUWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2893
2894 unsafe { Ok(T::new(value)) }
2895 }
2896
2897 // SubType: <F>(&self, value: &FloatValue<F>, name) -> FloatValue<F> {
2898 pub fn build_float_neg<T: FloatMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2899 if self.positioned.get() != PositionState::Set {
2900 return Err(BuilderError::UnsetPosition);
2901 }
2902 let c_string = to_c_str(name);
2903 let value = unsafe { LLVMBuildFNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2904
2905 unsafe { Ok(T::new(value)) }
2906 }
2907
2908 // SubType: <I>(&self, value: &IntValue<I>, name) -> IntValue<bool> { ?
2909 pub fn build_not<T: IntMathValue<'ctx>>(&self, value: T, name: &str) -> Result<T, BuilderError> {
2910 if self.positioned.get() != PositionState::Set {
2911 return Err(BuilderError::UnsetPosition);
2912 }
2913 let c_string = to_c_str(name);
2914 let value = unsafe { LLVMBuildNot(self.builder, value.as_value_ref(), c_string.as_ptr()) };
2915
2916 unsafe { Ok(T::new(value)) }
2917 }
2918
2919 // REVIEW: What if instruction and basic_block are completely unrelated?
2920 // It'd be great if we could get the BB from the instruction behind the scenes
2921 /// Set the position of the builder to after an instruction.
2922 ///
2923 /// Be sure to call one of the `position_*` methods or all `build_*` methods will return `Err(BuilderError::UnsetPosition)`.
2924 pub fn position_at(&self, basic_block: BasicBlock<'ctx>, instruction: &InstructionValue<'ctx>) {
2925 self.positioned.set(PositionState::Set);
2926
2927 unsafe { LLVMPositionBuilder(self.builder, basic_block.basic_block, instruction.as_value_ref()) }
2928 }
2929
2930 /// Set the position of the builder to before an instruction.
2931 ///
2932 /// Be sure to call one of the `position_*` methods or all `build_*` methods will return `Err(BuilderError::UnsetPosition)`.
2933 pub fn position_before(&self, instruction: &InstructionValue<'ctx>) {
2934 self.positioned.set(PositionState::Set);
2935
2936 unsafe { LLVMPositionBuilderBefore(self.builder, instruction.as_value_ref()) }
2937 }
2938
2939 /// Set the position of the builder to the end of a basic block.
2940 ///
2941 /// Be sure to call one of the `position_*` methods or all `build_*` methods will return `Err(BuilderError::UnsetPosition)`.
2942 pub fn position_at_end(&self, basic_block: BasicBlock<'ctx>) {
2943 self.positioned.set(PositionState::Set);
2944
2945 unsafe {
2946 LLVMPositionBuilderAtEnd(self.builder, basic_block.basic_block);
2947 }
2948 }
2949
2950 /// Builds an extract value instruction which extracts a `BasicValueEnum`
2951 /// from a struct or array.
2952 ///
2953 /// Returns `Err(BuilderError::ExtractOutOfRange)` if the provided index is out of bounds of the aggregate value length.
2954 ///
2955 /// # Example
2956 ///
2957 /// ```no_run
2958 /// use inkwell::context::Context;
2959 /// use inkwell::builder::BuilderError;
2960 ///
2961 /// let context = Context::create();
2962 /// let module = context.create_module("av");
2963 /// let void_type = context.void_type();
2964 /// let f32_type = context.f32_type();
2965 /// let i32_type = context.i32_type();
2966 /// let struct_type = context.struct_type(&[i32_type.into(), f32_type.into()], false);
2967 /// let array_type = i32_type.array_type(3);
2968 /// let fn_type = void_type.fn_type(&[], false);
2969 /// let fn_value = module.add_function("av_fn", fn_type, None);
2970 /// let builder = context.create_builder();
2971 /// let entry = context.append_basic_block(fn_value, "entry");
2972 ///
2973 /// builder.position_at_end(entry);
2974 ///
2975 /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap();
2976 ///
2977 /// #[cfg(feature = "typed-pointers")]
2978 /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value();
2979 /// #[cfg(not(feature = "typed-pointers"))]
2980 /// let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value();
2981 ///
2982 /// let const_int1 = i32_type.const_int(2, false);
2983 /// let const_int2 = i32_type.const_int(5, false);
2984 /// let const_int3 = i32_type.const_int(6, false);
2985 ///
2986 /// assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_ok());
2987 /// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_ok());
2988 /// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_ok());
2989 /// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
2990 ///
2991 /// assert!(builder.build_extract_value(array, 0, "extract").unwrap().is_int_value());
2992 /// assert!(builder.build_extract_value(array, 1, "extract").unwrap().is_int_value());
2993 /// assert!(builder.build_extract_value(array, 2, "extract").unwrap().is_int_value());
2994 /// assert!(builder.build_extract_value(array, 3, "extract").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
2995 /// ```
2996 pub fn build_extract_value<AV: AggregateValue<'ctx>>(
2997 &self,
2998 agg: AV,
2999 index: u32,
3000 name: &str,
3001 ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3002 if self.positioned.get() != PositionState::Set {
3003 return Err(BuilderError::UnsetPosition);
3004 }
3005 let size = match agg.as_aggregate_value_enum() {
3006 AggregateValueEnum::ArrayValue(av) => av.get_type().len(),
3007 AggregateValueEnum::StructValue(sv) => sv.get_type().count_fields(),
3008 };
3009
3010 if index >= size {
3011 return Err(BuilderError::ExtractOutOfRange);
3012 }
3013
3014 let c_string = to_c_str(name);
3015
3016 let value = unsafe { LLVMBuildExtractValue(self.builder, agg.as_value_ref(), index, c_string.as_ptr()) };
3017
3018 unsafe { Ok(BasicValueEnum::new(value)) }
3019 }
3020
3021 /// Builds an insert value instruction which inserts a `BasicValue` into a struct
3022 /// or array and returns the resulting aggregate value.
3023 ///
3024 /// Returns `Err(BuilderError::ExtractOutOfRange)` if the provided index is out of bounds of the aggregate value length.
3025 ///
3026 /// # Example
3027 ///
3028 /// ```no_run
3029 /// use inkwell::context::Context;
3030 /// use inkwell::builder::BuilderError;
3031 ///
3032 /// let context = Context::create();
3033 /// let module = context.create_module("av");
3034 /// let void_type = context.void_type();
3035 /// let f32_type = context.f32_type();
3036 /// let i32_type = context.i32_type();
3037 /// let struct_type = context.struct_type(&[i32_type.into(), f32_type.into()], false);
3038 /// let array_type = i32_type.array_type(3);
3039 /// let fn_type = void_type.fn_type(&[], false);
3040 /// let fn_value = module.add_function("av_fn", fn_type, None);
3041 /// let builder = context.create_builder();
3042 /// let entry = context.append_basic_block(fn_value, "entry");
3043 ///
3044 /// builder.position_at_end(entry);
3045 ///
3046 /// let array_alloca = builder.build_alloca(array_type, "array_alloca").unwrap();
3047 ///
3048 /// #[cfg(feature = "typed-pointers")]
3049 /// let array = builder.build_load(array_alloca, "array_load").unwrap().into_array_value();
3050 /// #[cfg(not(feature = "typed-pointers"))]
3051 /// let array = builder.build_load(i32_type, array_alloca, "array_load").unwrap().into_array_value();
3052 ///
3053 /// let const_int1 = i32_type.const_int(2, false);
3054 /// let const_int2 = i32_type.const_int(5, false);
3055 /// let const_int3 = i32_type.const_int(6, false);
3056 ///
3057 /// assert!(builder.build_insert_value(array, const_int1, 0, "insert").is_ok());
3058 /// assert!(builder.build_insert_value(array, const_int2, 1, "insert").is_ok());
3059 /// assert!(builder.build_insert_value(array, const_int3, 2, "insert").is_ok());
3060 /// assert!(builder.build_insert_value(array, const_int3, 3, "insert").is_err_and(|e| e == BuilderError::ExtractOutOfRange));
3061 /// ```
3062 pub fn build_insert_value<AV, BV>(
3063 &self,
3064 agg: AV,
3065 value: BV,
3066 index: u32,
3067 name: &str,
3068 ) -> Result<AggregateValueEnum<'ctx>, BuilderError>
3069 where
3070 AV: AggregateValue<'ctx>,
3071 BV: BasicValue<'ctx>,
3072 {
3073 if self.positioned.get() != PositionState::Set {
3074 return Err(BuilderError::UnsetPosition);
3075 }
3076 let size = match agg.as_aggregate_value_enum() {
3077 AggregateValueEnum::ArrayValue(av) => av.get_type().len(),
3078 AggregateValueEnum::StructValue(sv) => sv.get_type().count_fields(),
3079 };
3080
3081 if index >= size {
3082 return Err(BuilderError::ExtractOutOfRange);
3083 }
3084
3085 let c_string = to_c_str(name);
3086
3087 let value = unsafe {
3088 LLVMBuildInsertValue(
3089 self.builder,
3090 agg.as_value_ref(),
3091 value.as_value_ref(),
3092 index,
3093 c_string.as_ptr(),
3094 )
3095 };
3096
3097 unsafe { Ok(AggregateValueEnum::new(value)) }
3098 }
3099
3100 /// Builds an extract element instruction which extracts a `BasicValueEnum`
3101 /// from a vector.
3102 /// # Example
3103 ///
3104 /// ```no_run
3105 /// use inkwell::context::Context;
3106 ///
3107 /// let context = Context::create();
3108 /// let module = context.create_module("av");
3109 /// let i32_type = context.i32_type();
3110 /// let i32_zero = i32_type.const_int(0, false);
3111 /// let vec_type = i32_type.vec_type(2);
3112 /// let fn_type = i32_type.fn_type(&[vec_type.into()], false);
3113 /// let fn_value = module.add_function("vec_fn", fn_type, None);
3114 /// let builder = context.create_builder();
3115 /// let entry = context.append_basic_block(fn_value, "entry");
3116 /// let vector_param = fn_value.get_first_param().unwrap().into_vector_value();
3117 ///
3118 /// builder.position_at_end(entry);
3119 ///
3120 /// let extracted = builder.build_extract_element(vector_param, i32_zero, "insert").unwrap();
3121 ///
3122 /// builder.build_return(Some(&extracted)).unwrap();
3123 /// ```
3124 pub fn build_extract_element<V: VectorBaseValue<'ctx>>(
3125 &self,
3126 vector: V,
3127 index: IntValue<'ctx>,
3128 name: &str,
3129 ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3130 if self.positioned.get() != PositionState::Set {
3131 return Err(BuilderError::UnsetPosition);
3132 }
3133 let c_string = to_c_str(name);
3134
3135 let value = unsafe {
3136 LLVMBuildExtractElement(
3137 self.builder,
3138 vector.as_value_ref(),
3139 index.as_value_ref(),
3140 c_string.as_ptr(),
3141 )
3142 };
3143
3144 unsafe { Ok(BasicValueEnum::new(value)) }
3145 }
3146
3147 /// Builds an insert element instruction which inserts a `BasicValue` into a vector
3148 /// and returns the resulting vector.
3149 ///
3150 /// # Example
3151 ///
3152 /// ```no_run
3153 /// use inkwell::context::Context;
3154 ///
3155 /// let context = Context::create();
3156 /// let module = context.create_module("av");
3157 /// let void_type = context.void_type();
3158 /// let i32_type = context.i32_type();
3159 /// let i32_zero = i32_type.const_int(0, false);
3160 /// let i32_seven = i32_type.const_int(7, false);
3161 /// let vec_type = i32_type.vec_type(2);
3162 /// let fn_type = void_type.fn_type(&[vec_type.into()], false);
3163 /// let fn_value = module.add_function("vec_fn", fn_type, None);
3164 /// let builder = context.create_builder();
3165 /// let entry = context.append_basic_block(fn_value, "entry");
3166 /// let vector_param = fn_value.get_first_param().unwrap().into_vector_value();
3167 ///
3168 /// builder.position_at_end(entry);
3169 /// builder.build_insert_element(vector_param, i32_seven, i32_zero, "insert").unwrap();
3170 /// builder.build_return(None).unwrap();
3171 /// ```
3172 pub fn build_insert_element<V: BasicValue<'ctx>, W: VectorBaseValue<'ctx>>(
3173 &self,
3174 vector: W,
3175 element: V,
3176 index: IntValue<'ctx>,
3177 name: &str,
3178 ) -> Result<W, BuilderError> {
3179 if self.positioned.get() != PositionState::Set {
3180 return Err(BuilderError::UnsetPosition);
3181 }
3182 let c_string = to_c_str(name);
3183
3184 let value = unsafe {
3185 LLVMBuildInsertElement(
3186 self.builder,
3187 vector.as_value_ref(),
3188 element.as_value_ref(),
3189 index.as_value_ref(),
3190 c_string.as_ptr(),
3191 )
3192 };
3193
3194 unsafe { Ok(W::new(value)) }
3195 }
3196
3197 pub fn build_unreachable(&self) -> Result<InstructionValue<'ctx>, BuilderError> {
3198 if self.positioned.get() != PositionState::Set {
3199 return Err(BuilderError::UnsetPosition);
3200 }
3201 let val = unsafe { LLVMBuildUnreachable(self.builder) };
3202
3203 unsafe { Ok(InstructionValue::new(val)) }
3204 }
3205
3206 // REVIEW: Not sure if this should return InstructionValue or an actual value
3207 // TODO: Better name for num?
3208 pub fn build_fence(
3209 &self,
3210 atomic_ordering: AtomicOrdering,
3211 num: i32,
3212 name: &str,
3213 ) -> Result<InstructionValue<'ctx>, BuilderError> {
3214 if self.positioned.get() != PositionState::Set {
3215 return Err(BuilderError::UnsetPosition);
3216 }
3217 let c_string = to_c_str(name);
3218
3219 let val = unsafe { LLVMBuildFence(self.builder, atomic_ordering.into(), num, c_string.as_ptr()) };
3220
3221 unsafe { Ok(InstructionValue::new(val)) }
3222 }
3223
3224 // SubType: <P>(&self, ptr: &PointerValue<P>, name) -> IntValue<bool> {
3225 pub fn build_is_null<T: PointerMathValue<'ctx>>(
3226 &self,
3227 ptr: T,
3228 name: &str,
3229 ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>
3230 {
3231 if self.positioned.get() != PositionState::Set {
3232 return Err(BuilderError::UnsetPosition);
3233 }
3234 let c_string = to_c_str(name);
3235 let val = unsafe { LLVMBuildIsNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) };
3236
3237 unsafe { Ok(<<T::BaseType as PointerMathType>::PtrConvType as IntMathType>::ValueType::new(val)) }
3238 }
3239
3240 // SubType: <P>(&self, ptr: &PointerValue<P>, name) -> IntValue<bool> {
3241 pub fn build_is_not_null<T: PointerMathValue<'ctx>>(
3242 &self,
3243 ptr: T,
3244 name: &str,
3245 ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>
3246 {
3247 if self.positioned.get() != PositionState::Set {
3248 return Err(BuilderError::UnsetPosition);
3249 }
3250 let c_string = to_c_str(name);
3251 let val = unsafe { LLVMBuildIsNotNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) };
3252
3253 unsafe { Ok(<<T::BaseType as PointerMathType>::PtrConvType as IntMathType>::ValueType::new(val)) }
3254 }
3255
3256 // SubType: <I, P>(&self, int: &IntValue<I>, ptr_type: &PointerType<P>, name) -> PointerValue<P> {
3257 pub fn build_int_to_ptr<T: IntMathValue<'ctx>>(
3258 &self,
3259 int: T,
3260 ptr_type: <T::BaseType as IntMathType<'ctx>>::PtrConvType,
3261 name: &str,
3262 ) -> Result<<<T::BaseType as IntMathType<'ctx>>::PtrConvType as PointerMathType<'ctx>>::ValueType, BuilderError>
3263 {
3264 if self.positioned.get() != PositionState::Set {
3265 return Err(BuilderError::UnsetPosition);
3266 }
3267 let c_string = to_c_str(name);
3268
3269 let value = unsafe {
3270 LLVMBuildIntToPtr(
3271 self.builder,
3272 int.as_value_ref(),
3273 ptr_type.as_type_ref(),
3274 c_string.as_ptr(),
3275 )
3276 };
3277
3278 unsafe { Ok(<<T::BaseType as IntMathType>::PtrConvType as PointerMathType>::ValueType::new(value)) }
3279 }
3280
3281 // SubType: <I, P>(&self, ptr: &PointerValue<P>, int_type: &IntType<I>, name) -> IntValue<I> {
3282 pub fn build_ptr_to_int<T: PointerMathValue<'ctx>>(
3283 &self,
3284 ptr: T,
3285 int_type: <T::BaseType as PointerMathType<'ctx>>::PtrConvType,
3286 name: &str,
3287 ) -> Result<<<T::BaseType as PointerMathType<'ctx>>::PtrConvType as IntMathType<'ctx>>::ValueType, BuilderError>
3288 {
3289 if self.positioned.get() != PositionState::Set {
3290 return Err(BuilderError::UnsetPosition);
3291 }
3292 let c_string = to_c_str(name);
3293
3294 let value = unsafe {
3295 LLVMBuildPtrToInt(
3296 self.builder,
3297 ptr.as_value_ref(),
3298 int_type.as_type_ref(),
3299 c_string.as_ptr(),
3300 )
3301 };
3302
3303 unsafe { Ok(<<T::BaseType as PointerMathType>::PtrConvType as IntMathType>::ValueType::new(value)) }
3304 }
3305
3306 pub fn clear_insertion_position(&self) {
3307 self.positioned.set(PositionState::NotSet);
3308 unsafe { LLVMClearInsertionPosition(self.builder) }
3309 }
3310
3311 // REVIEW: Returning InstructionValue is the safe move here; but if the value means something
3312 // (IE the result of the switch) it should probably return BasicValueEnum?
3313 // SubTypes: I think value and case values must be the same subtype (maybe). Case value might need to be constants
3314 pub fn build_switch(
3315 &self,
3316 value: IntValue<'ctx>,
3317 else_block: BasicBlock<'ctx>,
3318 cases: &[(IntValue<'ctx>, BasicBlock<'ctx>)],
3319 ) -> Result<InstructionValue<'ctx>, BuilderError> {
3320 if self.positioned.get() != PositionState::Set {
3321 return Err(BuilderError::UnsetPosition);
3322 }
3323 let switch_value = unsafe {
3324 LLVMBuildSwitch(
3325 self.builder,
3326 value.as_value_ref(),
3327 else_block.basic_block,
3328 cases.len() as u32,
3329 )
3330 };
3331
3332 for &(value, basic_block) in cases {
3333 unsafe { LLVMAddCase(switch_value, value.as_value_ref(), basic_block.basic_block) }
3334 }
3335
3336 unsafe { Ok(InstructionValue::new(switch_value)) }
3337 }
3338
3339 // SubTypes: condition can only be IntValue<bool> or VectorValue<IntValue<Bool>>
3340 pub fn build_select<BV: BasicValue<'ctx>, IMV: IntMathValue<'ctx>>(
3341 &self,
3342 condition: IMV,
3343 then: BV,
3344 else_: BV,
3345 name: &str,
3346 ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3347 if self.positioned.get() != PositionState::Set {
3348 return Err(BuilderError::UnsetPosition);
3349 }
3350 let c_string = to_c_str(name);
3351 let value = unsafe {
3352 LLVMBuildSelect(
3353 self.builder,
3354 condition.as_value_ref(),
3355 then.as_value_ref(),
3356 else_.as_value_ref(),
3357 c_string.as_ptr(),
3358 )
3359 };
3360
3361 unsafe { Ok(BasicValueEnum::new(value)) }
3362 }
3363
3364 // The unsafety of this function should be fixable with subtypes. See GH #32
3365 pub unsafe fn build_global_string(&self, value: &str, name: &str) -> Result<GlobalValue<'ctx>, BuilderError> {
3366 if self.positioned.get() != PositionState::Set {
3367 return Err(BuilderError::UnsetPosition);
3368 }
3369 let c_string_value = to_c_str(value);
3370 let c_string_name = to_c_str(name);
3371 let value = LLVMBuildGlobalString(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr());
3372
3373 Ok(GlobalValue::new(value))
3374 }
3375
3376 // REVIEW: Does this similar fn have the same issue build_global_string does? If so, mark as unsafe
3377 // and fix with subtypes.
3378 pub fn build_global_string_ptr(&self, value: &str, name: &str) -> Result<GlobalValue<'ctx>, BuilderError> {
3379 if self.positioned.get() != PositionState::Set {
3380 return Err(BuilderError::UnsetPosition);
3381 }
3382 let c_string_value = to_c_str(value);
3383 let c_string_name = to_c_str(name);
3384 let value = unsafe { LLVMBuildGlobalStringPtr(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr()) };
3385
3386 unsafe { Ok(GlobalValue::new(value)) }
3387 }
3388
3389 // REVIEW: Do we need to constrain types here? subtypes?
3390 pub fn build_shuffle_vector<V: VectorBaseValue<'ctx>>(
3391 &self,
3392 left: V,
3393 right: V,
3394 mask: V,
3395 name: &str,
3396 ) -> Result<V, BuilderError> {
3397 if self.positioned.get() != PositionState::Set {
3398 return Err(BuilderError::UnsetPosition);
3399 }
3400 let c_string = to_c_str(name);
3401 let value = unsafe {
3402 LLVMBuildShuffleVector(
3403 self.builder,
3404 left.as_value_ref(),
3405 right.as_value_ref(),
3406 mask.as_value_ref(),
3407 c_string.as_ptr(),
3408 )
3409 };
3410
3411 unsafe { Ok(V::new(value)) }
3412 }
3413
3414 // REVIEW: Is return type correct?
3415 // SubTypes: I think this should be type: BT -> BT::Value
3416 // https://llvm.org/docs/LangRef.html#i-va-arg
3417 pub fn build_va_arg<BT: BasicType<'ctx>>(
3418 &self,
3419 list: PointerValue<'ctx>,
3420 type_: BT,
3421 name: &str,
3422 ) -> Result<BasicValueEnum<'ctx>, BuilderError> {
3423 if self.positioned.get() != PositionState::Set {
3424 return Err(BuilderError::UnsetPosition);
3425 }
3426 let c_string = to_c_str(name);
3427
3428 let value = unsafe {
3429 LLVMBuildVAArg(
3430 self.builder,
3431 list.as_value_ref(),
3432 type_.as_type_ref(),
3433 c_string.as_ptr(),
3434 )
3435 };
3436
3437 unsafe { Ok(BasicValueEnum::new(value)) }
3438 }
3439
3440 /// Builds an atomicrmw instruction. It allows you to atomically modify memory.
3441 ///
3442 /// May return of the following errors:
3443 /// - `Err(BuilderError::BitwidthError)` if the bitwidth of the value is not a power of 2 and less than 8
3444 /// - `Err(BuilderError:PointeeTypeMismatch)` if the pointee type does not match the value's type
3445 ///
3446 /// # Example
3447 ///
3448 /// ```
3449 /// use inkwell::context::Context;
3450 /// use inkwell::{AddressSpace, AtomicOrdering, AtomicRMWBinOp};
3451 /// let context = Context::create();
3452 /// let module = context.create_module("rmw");
3453 /// let void_type = context.void_type();
3454 /// let i32_type = context.i32_type();
3455 /// let i32_seven = i32_type.const_int(7, false);
3456 /// #[cfg(feature = "typed-pointers")]
3457 /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
3458 /// #[cfg(not(feature = "typed-pointers"))]
3459 /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
3460 /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
3461 /// let fn_value = module.add_function("rmw", fn_type, None);
3462 /// let entry = context.append_basic_block(fn_value, "entry");
3463 /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
3464 /// let builder = context.create_builder();
3465 /// builder.position_at_end(entry);
3466 /// builder.build_atomicrmw(AtomicRMWBinOp::Add, i32_ptr_param, i32_seven, AtomicOrdering::Unordered).unwrap();
3467 /// builder.build_return(None).unwrap();
3468 /// ```
3469 // https://llvm.org/docs/LangRef.html#atomicrmw-instruction
3470 pub fn build_atomicrmw(
3471 &self,
3472 op: AtomicRMWBinOp,
3473 ptr: PointerValue<'ctx>,
3474 value: IntValue<'ctx>,
3475 ordering: AtomicOrdering,
3476 ) -> Result<IntValue<'ctx>, BuilderError> {
3477 if self.positioned.get() != PositionState::Set {
3478 return Err(BuilderError::UnsetPosition);
3479 }
3480 // TODO: add support for fadd, fsub and xchg on floating point types in LLVM 9+.
3481
3482 // "The type of ‘<value>’ 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 ‘<pointer>’ operand must be a pointer to that type." -- https://releases.llvm.org/3.6.2/docs/LangRef.html#atomicrmw-instruction
3483 if value.get_type().get_bit_width() < 8 || !value.get_type().get_bit_width().is_power_of_two() {
3484 return Err(BuilderError::BitwidthError(
3485 "The bitwidth of value must be a power of 2 and greater than 8.",
3486 ));
3487 }
3488
3489 #[cfg(feature = "typed-pointers")]
3490 if ptr.get_type().get_element_type() != value.get_type().into() {
3491 return Err(BuilderError::PointeeTypeMismatch(
3492 "Pointer's pointee type must match the value's type.",
3493 ));
3494 }
3495
3496 let val = unsafe {
3497 LLVMBuildAtomicRMW(
3498 self.builder,
3499 op.into(),
3500 ptr.as_value_ref(),
3501 value.as_value_ref(),
3502 ordering.into(),
3503 false as i32,
3504 )
3505 };
3506
3507 unsafe { Ok(IntValue::new(val)) }
3508 }
3509
3510 /// Builds a [`cmpxchg`](https://llvm.org/docs/LangRef.html#cmpxchg-instruction) instruction.
3511 ///
3512 /// This instruction allows to atomically compare and replace memory.
3513 ///
3514 /// May return one of the following errors:
3515 /// - `Err(BuilderError::PointeeTypeMismatch)` if the pointer does not point to an element of the value type
3516 /// - `Err(BuilderError::ValueTypeMismatch)` if the value to compare and the new values are not of the same type, or if
3517 /// the value does not have a pointer or integer type
3518 /// - `Err(BuilderError::OrderingError)` if the following conditions are not satisfied:
3519 /// - Both success and failure orderings are not Monotonic or stronger
3520 /// - The failure ordering is stronger than the success ordering
3521 /// - The failure ordering is release or acquire release
3522 ///
3523 /// # Example
3524 ///
3525 /// ```
3526 /// use inkwell::context::Context;
3527 /// use inkwell::{AddressSpace, AtomicOrdering};
3528 /// let context = Context::create();
3529 /// let module = context.create_module("cmpxchg");
3530 /// let void_type = context.void_type();
3531 /// let i32_type = context.i32_type();
3532 /// #[cfg(feature = "typed-pointers")]
3533 /// let i32_ptr_type = i32_type.ptr_type(AddressSpace::default());
3534 /// #[cfg(not(feature = "typed-pointers"))]
3535 /// let i32_ptr_type = context.ptr_type(AddressSpace::default());
3536 /// let fn_type = void_type.fn_type(&[i32_ptr_type.into()], false);
3537 /// let fn_value = module.add_function("", fn_type, None);
3538 /// let i32_ptr_param = fn_value.get_first_param().unwrap().into_pointer_value();
3539 /// let i32_seven = i32_type.const_int(7, false);
3540 /// let i32_eight = i32_type.const_int(8, false);
3541 /// let entry = context.append_basic_block(fn_value, "entry");
3542 /// let builder = context.create_builder();
3543 /// builder.position_at_end(entry);
3544 /// builder.build_cmpxchg(i32_ptr_param, i32_seven, i32_eight, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic).unwrap();
3545 /// builder.build_return(None).unwrap();
3546 /// ```
3547 pub fn build_cmpxchg<V: BasicValue<'ctx>>(
3548 &self,
3549 ptr: PointerValue<'ctx>,
3550 cmp: V,
3551 new: V,
3552 success: AtomicOrdering,
3553 failure: AtomicOrdering,
3554 ) -> Result<StructValue<'ctx>, BuilderError> {
3555 if self.positioned.get() != PositionState::Set {
3556 return Err(BuilderError::UnsetPosition);
3557 }
3558 let cmp = cmp.as_basic_value_enum();
3559 let new = new.as_basic_value_enum();
3560 if cmp.get_type() != new.get_type() {
3561 return Err(BuilderError::ValueTypeMismatch(
3562 "The value to compare against and the value to replace with must have the same type.",
3563 ));
3564 }
3565 if !cmp.is_int_value() && !cmp.is_pointer_value() {
3566 return Err(BuilderError::ValueTypeMismatch(
3567 "The values must have pointer or integer type.",
3568 ));
3569 }
3570
3571 #[cfg(feature = "typed-pointers")]
3572 if ptr.get_type().get_element_type().as_basic_type_enum() != cmp.get_type() {
3573 return Err(BuilderError::PointeeTypeMismatch(
3574 "The pointer does not point to an element of the value type.",
3575 ));
3576 }
3577
3578 // "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
3579 if success < AtomicOrdering::Monotonic || failure < AtomicOrdering::Monotonic {
3580 return Err(BuilderError::OrderingError(
3581 "Both success and failure orderings must be Monotonic or stronger.",
3582 ));
3583 }
3584 if failure > success {
3585 return Err(BuilderError::OrderingError(
3586 "The failure ordering may not be stronger than the success ordering.",
3587 ));
3588 }
3589 if failure == AtomicOrdering::Release || failure == AtomicOrdering::AcquireRelease {
3590 return Err(BuilderError::OrderingError(
3591 "The failure ordering may not be release or acquire release.",
3592 ));
3593 }
3594
3595 let val = unsafe {
3596 LLVMBuildAtomicCmpXchg(
3597 self.builder,
3598 ptr.as_value_ref(),
3599 cmp.as_value_ref(),
3600 new.as_value_ref(),
3601 success.into(),
3602 failure.into(),
3603 false as i32,
3604 )
3605 };
3606
3607 unsafe { Ok(StructValue::new(val)) }
3608 }
3609
3610 /// Set the debug info source location of the instruction currently pointed at by the builder
3611 #[llvm_versions(7..=8)]
3612 pub fn set_current_debug_location(&self, context: impl AsContextRef<'ctx>, location: DILocation<'ctx>) {
3613 use llvm_sys::core::LLVMMetadataAsValue;
3614 use llvm_sys::core::LLVMSetCurrentDebugLocation;
3615 unsafe {
3616 LLVMSetCurrentDebugLocation(
3617 self.builder,
3618 LLVMMetadataAsValue(context.as_ctx_ref(), location.metadata_ref),
3619 );
3620 }
3621 }
3622
3623 /// Set the debug info source location of the instruction currently pointed at by the builder
3624 #[llvm_versions(9..)]
3625 pub fn set_current_debug_location(&self, location: DILocation<'ctx>) {
3626 use llvm_sys::core::LLVMSetCurrentDebugLocation2;
3627 unsafe {
3628 LLVMSetCurrentDebugLocation2(self.builder, location.metadata_ref);
3629 }
3630 }
3631
3632 /// Get the debug info source location of the instruction currently pointed at by the builder,
3633 /// if available.
3634 #[llvm_versions(7..)]
3635 pub fn get_current_debug_location(&self) -> Option<DILocation<'ctx>> {
3636 use llvm_sys::core::LLVMGetCurrentDebugLocation;
3637 use llvm_sys::core::LLVMValueAsMetadata;
3638 let metadata_ref = unsafe { LLVMGetCurrentDebugLocation(self.builder) };
3639 if metadata_ref.is_null() {
3640 return None;
3641 }
3642 Some(DILocation {
3643 metadata_ref: unsafe { LLVMValueAsMetadata(metadata_ref) },
3644 _marker: PhantomData,
3645 })
3646 }
3647
3648 /// Unset the debug info source location of the instruction currently pointed at by the
3649 /// builder. If there isn't any debug info, this is a no-op.
3650 #[llvm_versions(7..=8)]
3651 pub fn unset_current_debug_location(&self) {
3652 use llvm_sys::core::LLVMSetCurrentDebugLocation;
3653 unsafe {
3654 LLVMSetCurrentDebugLocation(self.builder, std::ptr::null_mut());
3655 }
3656 }
3657
3658 /// Unset the debug info source location of the instruction currently pointed at by the
3659 /// builder. If there isn't any debug info, this is a no-op.
3660 #[llvm_versions(9..)]
3661 pub fn unset_current_debug_location(&self) {
3662 use llvm_sys::core::LLVMSetCurrentDebugLocation2;
3663 unsafe {
3664 LLVMSetCurrentDebugLocation2(self.builder, std::ptr::null_mut());
3665 }
3666 }
3667}
3668
3669/// Used by build_memcpy and build_memmove
3670#[llvm_versions(8..)]
3671fn is_alignment_ok(align: u32) -> bool {
3672 // This replicates the assertions LLVM runs.
3673 //
3674 // See https://github.com/TheDan64/inkwell/issues/168
3675 align > 0 && align.is_power_of_two() && (align as f64).log2() < 64.0
3676}
3677
3678impl Drop for Builder<'_> {
3679 fn drop(&mut self) {
3680 unsafe {
3681 LLVMDisposeBuilder(self.builder);
3682 }
3683 }
3684}