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