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