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