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