1use crate::context::Context;
2use crate::llvm::global::Global;
3use crate::llvm::types::LLVMType;
4use crate::llvm::value::array::ArrayValue;
5use crate::llvm::value::bool::BoolValue;
6use crate::llvm::value::fucntion::FunctionValue;
7use crate::llvm::value::pointer::PointerValue;
8use crate::llvm::value::pstruct::StructValue;
9use crate::llvm::value::reference::ReferenceValue;
10use crate::llvm::value::LLVMValue;
11use llvm_sys::core::{
12 LLVMBuildAdd, LLVMBuildAlloca, LLVMBuildAnd, LLVMBuildArrayAlloca, LLVMBuildBr, LLVMBuildCall2,
13 LLVMBuildCondBr, LLVMBuildExtractValue, LLVMBuildFAdd, LLVMBuildFMul, LLVMBuildFNeg,
14 LLVMBuildGEP2, LLVMBuildGlobalStringPtr, LLVMBuildICmp,
15 LLVMBuildInBoundsGEP2, LLVMBuildInsertValue, LLVMBuildLoad2, LLVMBuildMul, LLVMBuildNeg,
16 LLVMBuildNot, LLVMBuildOr, LLVMBuildRet, LLVMBuildRetVoid, LLVMBuildSDiv, LLVMBuildStore,
17 LLVMBuildStructGEP2, LLVMBuildSub, LLVMBuildUnreachable, LLVMBuildZExt, LLVMConstArray2,
18 LLVMConstIntToPtr, LLVMDisposeBuilder, LLVMGetArrayLength2, LLVMInt8Type, LLVMPointerType,
19 LLVMPositionBuilderAtEnd,
20};
21use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMBuilderRef, LLVMValueRef};
22use llvm_sys::LLVMIntPredicate::{
23 LLVMIntEQ, LLVMIntNE, LLVMIntSGE, LLVMIntSGT, LLVMIntSLE, LLVMIntSLT,
24};
25use std::cell::RefCell;
26use std::collections::HashMap;
27use std::ffi::{c_uint, CString};
28
29#[derive(Debug)]
30pub struct IRBuilder {
31 inner: LLVMBuilderRef,
32 strings: RefCell<HashMap<String, LLVMValue>>,
33 }
37
38impl IRBuilder {
39 pub(crate) fn new(builder: LLVMBuilderRef) -> Self {
40 Self {
41 inner: builder,
42 strings: HashMap::new().into(),
43 }
44 }
45
46 pub fn get_llvm_builder(&self) -> LLVMBuilderRef {
47 self.inner
48 }
49
50 pub fn build_return_void(&self) {
51 unsafe {
52 LLVMBuildRetVoid(self.inner);
53 }
54 }
55 pub fn build_return(&self, value: LLVMValue) {
56 if value.is_unit() {
57 self.build_return_void();
58 return;
59 }
60 unsafe {
61 LLVMBuildRet(self.inner, value.as_llvm_value_ref());
62 }
63 }
64
65 pub fn build_global_string_ptr(
66 &self,
67 name: impl AsRef<str>,
68 value: impl AsRef<str>,
69 ) -> LLVMValue {
70 let name = name.as_ref();
71 let name = CString::new(name).unwrap();
72 let str = value.as_ref();
73 let str = CString::new(str).unwrap();
74 let r = unsafe { LLVMBuildGlobalStringPtr(self.inner, str.as_ptr(), name.as_ptr()) };
75 r.into()
76 }
77 pub fn build_global_string(&self, value: impl AsRef<str>) -> LLVMValue {
78 let str0 = value.as_ref();
79 if self.strings.borrow().contains_key(str0) {
80 return self.strings.borrow().get(str0).unwrap().clone();
81 }
82
83 let string_const = Global::const_string(str0);
86
87 self.strings
90 .borrow_mut()
91 .insert(str0.to_string(), string_const.clone());
92 string_const
93 }
94 pub fn build_alloca(&self, name: impl AsRef<str>, ty: &LLVMType) -> ReferenceValue {
95 let name0 = name.as_ref();
96 let name = CString::new(name0).unwrap();
97 let local = unsafe { LLVMBuildAlloca(self.inner, ty.as_llvm_type_ref(), name.as_ptr()) };
98 ReferenceValue::new(local, ty.get_undef())
99 }
100
101 pub fn build_array(&self, el_ty: LLVMType, arr: Vec<LLVMValue>) -> LLVMValue {
102 let name = CString::new("").unwrap();
103 let array_address = unsafe {
104 LLVMBuildArrayAlloca(
105 self.inner,
106 el_ty.as_llvm_type_ref(),
107 Global::const_i64(arr.len() as i64).get_reference(),
108 name.as_ptr(),
109 )
110 };
111 let mut constant_vals = arr
112 .iter()
113 .map(|v| v.as_llvm_value_ref())
114 .collect::<Vec<_>>();
115 let constant_array = unsafe {
116 LLVMConstArray2(
117 el_ty.as_llvm_type_ref(),
118 constant_vals.as_mut_ptr(),
119 arr.len() as u64,
120 )
121 };
122 unsafe {
123 LLVMBuildStore(self.inner, constant_array, array_address);
124 }
125 LLVMValue::Array(ArrayValue::new(array_address, el_ty, arr.len()))
126 }
127 pub fn build_struct_get(&self, val: &StructValue, idx: usize) -> LLVMValue {
128 let name = CString::new("").unwrap();
129 let r = unsafe {
130 LLVMBuildExtractValue(
131 self.inner,
132 val.get_reference(),
133 idx as c_uint,
134 name.as_ptr(),
135 )
136 };
137 let field_type = val.simply_get_field_by_index(idx).unwrap();
138 match field_type {
139 LLVMValue::String(_) => LLVMValue::String(r),
140 LLVMValue::Struct(mut v) => {
141 v.set_reference(r);
142 v.into()
143 }
144 LLVMValue::Pointer(pointer_value) => {
145 let mut pointer_value = pointer_value.clone();
146 pointer_value.set_reference(r);
147 pointer_value.into()
148 }
149 LLVMValue::Function(f) => {
150 let mut function_value = f.clone();
151 function_value.set_reference(r);
152 function_value.into()
153 }
154 LLVMValue::Reference(reference_value) => {
155 let mut reference_value = reference_value.clone();
156 reference_value.set_reference(r);
157 reference_value.into()
158 }
159 _ => r.into(),
160 }
161 }
162
163 pub fn build_struct_insert(
164 &self,
165 val: &StructValue,
166 idx: usize,
167 value: &LLVMValue,
168 ) -> StructValue {
169 let name = CString::new("").unwrap();
170 let new_struct = unsafe {
171 LLVMBuildInsertValue(
172 self.inner,
173 val.get_reference(),
174 value.as_llvm_value_ref(),
175 idx as c_uint,
176 name.as_ptr(),
177 )
178 };
179 val.with_field(new_struct, idx, value.clone())
180 }
181 pub fn build_i64_to_ptr(&self, val: LLVMValue) -> LLVMValue {
182 let target = unsafe { LLVMPointerType(LLVMInt8Type(), 0) };
183 unsafe { LLVMConstIntToPtr(val.as_llvm_value_ref(), target) }.into()
184 }
185 pub fn build_struct_gep(&self, ty: &LLVMType, val: LLVMValue, idx: usize) -> LLVMValue {
186 let name = CString::new("").unwrap();
187 let r = unsafe {
188 LLVMBuildStructGEP2(
189 self.inner,
190 ty.as_llvm_type_ref(),
191 val.as_llvm_value_ref(),
192 idx as c_uint,
193 name.as_ptr(),
194 )
195 };
196 let ty = ty.get_struct_field_type(idx);
197 match &ty {
198 LLVMType::String(_) => ReferenceValue::new(r, ty.get_undef()).into(),
199 LLVMType::Struct(_, _, _) => ReferenceValue::new(r, ty.get_undef()).into(),
200 LLVMType::Pointer(element_type, _) => {
201 ReferenceValue::new(r, element_type.get_undef()).into()
202 }
203 LLVMType::Function(_, _, _) => ReferenceValue::new(r, ty.get_undef()).into(),
204 LLVMType::Ref(element_type, _) => {
205 ReferenceValue::new(r, element_type.get_undef()).into()
206 }
207 _ => ReferenceValue::new(r, ty.get_undef()).into(),
208 }
209 }
210 pub fn build_unreachable(&self) {
211 unsafe {
212 LLVMBuildUnreachable(self.inner);
213 }
214 }
215 pub(crate) fn build_store(&self, ptr: LLVMValueRef, val: &LLVMValue) {
216 unsafe { LLVMBuildStore(self.inner, val.as_llvm_value_ref(), ptr) };
217 }
218 pub(crate) fn build_load(&self, ty: LLVMType, ptr: LLVMValueRef) -> LLVMValue {
219 let name = CString::new("").unwrap();
220 let val = unsafe {
221 LLVMBuildLoad2(
222 self.inner,
223 ty.as_llvm_type_ref(), ptr,
225 name.as_ptr(),
226 )
227 };
228 unsafe {
229 match ty {
230 LLVMType::Pointer(_, _) => PointerValue::new(val, ty.get_undef()).into(),
231 LLVMType::String(_) => LLVMValue::String(val),
232 LLVMType::Array(element_type, array_type) => {
233 let length = LLVMGetArrayLength2(array_type);
234 ArrayValue::new(val, *element_type, length as usize).into()
235 }
236 LLVMType::Struct(name, fields, _) => {
237 let mut field_index = HashMap::new();
238 for (i, (name, _)) in fields.iter().enumerate() {
239 field_index.insert(name.clone(), i);
240 }
241 StructValue::new(
242 val,
243 name,
244 field_index,
245 fields.iter().map(|(_, ty)| ty.get_undef()).collect(),
246 )
247 .into()
248 }
249 _ => val.into(),
250 }
251 }
252 }
253 pub fn build_array_get(&self, ty: LLVMType, ptr: LLVMValue, index: LLVMValue) -> LLVMValue {
254 let name = CString::new("").unwrap();
256 let mut indices = [index.as_llvm_value_ref()];
257 let r = unsafe {
258 let ptr0 = LLVMBuildGEP2(
259 self.inner,
260 ty.as_llvm_type_ref(),
261 ptr.as_llvm_value_ref(),
262 indices.as_mut_ptr(),
263 1,
264 name.as_ptr(),
265 );
266 LLVMBuildLoad2(self.inner, ty.as_llvm_type_ref(), ptr0, name.as_ptr())
267 };
268 r.into()
269 }
270 pub fn build_array_get_in_bounds(
271 &self,
272 ty: LLVMType,
273 ptr: LLVMValue,
274 index: LLVMValue,
275 ) -> LLVMValue {
276 let name = CString::new("").unwrap();
278 let mut indices = [index.as_llvm_value_ref()];
279 let r = unsafe {
280 let ptr0 = LLVMBuildInBoundsGEP2(
281 self.inner,
282 ty.as_llvm_type_ref(),
283 ptr.as_llvm_value_ref(),
284 indices.as_mut_ptr(),
285 1,
286 name.as_ptr(),
287 );
288 LLVMBuildLoad2(self.inner, ty.as_llvm_type_ref(), ptr0, name.as_ptr())
289 };
290 match ty {
291 LLVMType::Pointer(_, _) => PointerValue::new(r, ty.get_undef()).into(),
292 LLVMType::String(_) => LLVMValue::String(r),
293 _ => r.into(),
294 }
295 }
296 pub fn build_array_gep(&self, ty: LLVMType, ptr: LLVMValue, index: LLVMValue) -> LLVMValue {
297 let name = CString::new("").unwrap();
299 let mut indices = [index.as_llvm_value_ref()];
300 let r = unsafe {
301 LLVMBuildGEP2(
302 self.inner,
303 ty.as_llvm_type_ref(),
304 ptr.as_llvm_value_ref(),
305 indices.as_mut_ptr(),
306 1,
307 name.as_ptr(),
308 )
309 };
310 ReferenceValue::new(r, ty.get_undef()).into()
311 }
312 pub(crate) fn position_at_end(&self, block: LLVMBasicBlockRef) {
313 unsafe { LLVMPositionBuilderAtEnd(self.inner, block) };
314 }
315 pub(crate) fn build_br(&self, block: LLVMBasicBlockRef) {
316 unsafe { LLVMBuildBr(self.inner, block) };
317 }
318 pub(crate) fn build_cond_br(
319 &self,
320 condition: &BoolValue,
321 then_block: LLVMBasicBlockRef,
322 else_block: LLVMBasicBlockRef,
323 ) {
324 unsafe {
325 LLVMBuildCondBr(
326 self.inner,
327 condition.get_reference(),
328 then_block,
329 else_block,
330 );
331 }
332 }
333
334 pub fn build_add(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
335 let name = CString::new("").unwrap();
336 let r = unsafe {
337 LLVMBuildAdd(
338 self.inner,
339 l.as_llvm_value_ref(),
340 r.as_llvm_value_ref(),
341 name.as_ptr(),
342 )
343 };
344 r.into()
345 }
346 pub fn build_fadd(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
347 let name = CString::new("").unwrap();
348 unsafe {
349 LLVMBuildFAdd(
350 self.inner,
351 l.as_llvm_value_ref(),
352 r.as_llvm_value_ref(),
353 name.as_ptr(),
354 )
355 }
356 .into()
357 }
358 pub fn build_fmul(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
359 let name = CString::new("").unwrap();
360 unsafe {
361 LLVMBuildFMul(
362 self.inner,
363 l.as_llvm_value_ref(),
364 r.as_llvm_value_ref(),
365 name.as_ptr(),
366 )
367 }
368 .into()
369 }
370 pub fn build_mul(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
371 let name = CString::new("").unwrap();
372 let r = unsafe {
373 LLVMBuildMul(
374 self.inner,
375 l.as_llvm_value_ref(),
376 r.as_llvm_value_ref(),
377 name.as_ptr(),
378 )
379 };
380 r.into()
381 }
382 pub fn build_sub(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
383 let name = CString::new("").unwrap();
384 let r = unsafe {
385 LLVMBuildSub(
386 self.inner,
387 l.as_llvm_value_ref(),
388 r.as_llvm_value_ref(),
389 name.as_ptr(),
390 )
391 };
392 r.into()
393 }
394 pub(crate) fn build_div(&self, l: LLVMValueRef, r: LLVMValueRef) -> LLVMValue {
395 let name = CString::new("").unwrap();
396 unsafe { LLVMBuildSDiv(self.inner, l, r, name.as_ptr()) }.into()
397 }
398 pub fn build_fsub(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
399 let name = CString::new("").unwrap();
400 unsafe {
401 llvm_sys::core::LLVMBuildFSub(
402 self.inner,
403 l.as_llvm_value_ref(),
404 r.as_llvm_value_ref(),
405 name.as_ptr(),
406 )
407 }
408 .into()
409 }
410 pub fn build_fdiv(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
411 let name = CString::new("").unwrap();
412 unsafe {
413 llvm_sys::core::LLVMBuildFDiv(
414 self.inner,
415 l.as_llvm_value_ref(),
416 r.as_llvm_value_ref(),
417 name.as_ptr(),
418 )
419 }
420 .into()
421 }
422 pub fn build_si_to_fp(&self, val: LLVMValue, dest_ty: LLVMType) -> LLVMValue {
423 let name = CString::new("").unwrap();
424 unsafe {
425 llvm_sys::core::LLVMBuildSIToFP(
426 self.inner,
427 val.as_llvm_value_ref(),
428 dest_ty.as_llvm_type_ref(),
429 name.as_ptr(),
430 )
431 }
432 .into()
433 }
434 pub fn build_fp_to_si(&self, val: LLVMValue, dest_ty: LLVMType) -> LLVMValue {
435 let name = CString::new("").unwrap();
436 unsafe {
437 llvm_sys::core::LLVMBuildFPToSI(
438 self.inner,
439 val.as_llvm_value_ref(),
440 dest_ty.as_llvm_type_ref(),
441 name.as_ptr(),
442 )
443 }
444 .into()
445 }
446 pub(crate) fn build_eq(&self, l: LLVMValueRef, r: LLVMValueRef) -> BoolValue {
447 let name = CString::new("").unwrap();
448 let r = unsafe { LLVMBuildICmp(self.inner, LLVMIntEQ, l, r, name.as_ptr()) };
449 BoolValue::new(r)
450 }
451 pub fn build_neq(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
452 let name = CString::new("").unwrap();
453 unsafe {
454 LLVMBuildICmp(
455 self.inner,
456 LLVMIntNE,
457 l.as_llvm_value_ref(),
458 r.as_llvm_value_ref(),
459 name.as_ptr(),
460 )
461 }
462 .into()
463 }
464 pub fn build_greater(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
465 let name = CString::new("").unwrap();
466 unsafe {
467 LLVMBuildICmp(
468 self.inner,
469 LLVMIntSGT,
470 l.as_llvm_value_ref(),
471 r.as_llvm_value_ref(),
472 name.as_ptr(),
473 )
474 }
475 .into()
476 }
477 pub fn build_less(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
478 let name = CString::new("").unwrap();
479 unsafe {
480 LLVMBuildICmp(
481 self.inner,
482 LLVMIntSLT,
483 l.as_llvm_value_ref(),
484 r.as_llvm_value_ref(),
485 name.as_ptr(),
486 )
487 }
488 .into()
489 }
490 pub fn build_call(
491 &self,
492 ctx: &Context,
493 function: &FunctionValue,
494 params: &mut [LLVMValue],
495 var_name: impl AsRef<str>,
496 ) -> LLVMValue {
497 let dec = function
498 .get_llvm_type(ctx)
499 .get_element_type()
500 .as_llvm_type_ref();
501 let var_name = CString::new(var_name.as_ref()).unwrap();
502 let mut params = params
503 .iter()
504 .map(|e| e.as_llvm_value_ref())
505 .collect::<Vec<LLVMValueRef>>();
506 let call_res = unsafe {
507 LLVMBuildCall2(
508 self.inner,
509 dec,
510 function.get_reference(),
511 params.as_mut_ptr(),
512 params.len() as c_uint,
513 var_name.as_ptr(),
514 )
515 };
516 let return_value = function.get_return_value();
517 if return_value.is_struct() {
518 let mut struct_value = return_value.as_struct().unwrap().clone();
519 struct_value.set_reference(call_res);
520 return struct_value.clone().into();
521 }
522 match return_value {
523 LLVMValue::String(_) => LLVMValue::String(call_res),
524 LLVMValue::Pointer(pointer_value) => {
525 let mut pointer_value = pointer_value.clone();
526 pointer_value.set_reference(call_res);
527 pointer_value.into()
528 }
529 LLVMValue::Struct(mut v) => {
530 v.set_reference(call_res);
531 v.into()
532 }
533 _ => call_res.into(),
534 }
535 }
536 pub fn build_call_fn_ptr(
537 &self,
538 fn_type: LLVMType,
539 ptr: LLVMValue,
540 params: &mut [LLVMValue],
541 var_name: impl AsRef<str>,
542 ) -> LLVMValue {
543 let name = CString::new(var_name.as_ref()).unwrap();
544 let mut params = params
545 .iter()
546 .map(|e| e.as_llvm_value_ref())
547 .collect::<Vec<LLVMValueRef>>();
548 unsafe {
549 LLVMBuildCall2(
550 self.inner,
551 fn_type.as_llvm_type_ref(),
552 ptr.as_llvm_value_ref(),
553 params.as_mut_ptr(),
554 params.len() as c_uint,
555 name.as_ptr(),
556 )
557 }
558 .into()
559 }
560 pub fn build_zext(&self, value: LLVMValue, ty: LLVMType) -> LLVMValue {
561 let name = CString::new("").unwrap();
562 unsafe {
563 LLVMBuildZExt(
564 self.inner,
565 value.as_llvm_value_ref(),
566 ty.as_llvm_type_ref(),
567 name.as_ptr(),
568 )
569 }
570 .into()
571 }
572 pub fn build_extract_value(&self, ctx: &Context, val: &StructValue, idx: usize) -> LLVMValue {
573 let name = CString::new("").unwrap();
574 let r = unsafe {
575 LLVMBuildExtractValue(
576 self.inner,
577 val.get_reference(),
578 idx as c_uint,
579 name.as_ptr(),
580 )
581 };
582
583 let field_type = val.get_field_by_index(ctx, idx).unwrap();
584 match field_type {
585 LLVMValue::String(_) => LLVMValue::String(r),
586 LLVMValue::Struct(mut v) => {
587 v.set_reference(r);
588 v.into()
589 }
590 LLVMValue::Pointer(pointer_value) => {
591 let mut pointer_value = pointer_value.clone();
592 pointer_value.set_reference(r);
593 pointer_value.into()
594 }
595 LLVMValue::Function(f) => {
596 let mut function_value = f.clone();
597 function_value.set_reference(r);
598 function_value.into()
599 }
600 _ => r.into(),
601 }
602 }
603 pub fn build_less_equal(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
604 let name = CString::new("").unwrap();
605 unsafe {
606 LLVMBuildICmp(
607 self.inner,
608 LLVMIntSLE,
609 l.as_llvm_value_ref(),
610 r.as_llvm_value_ref(),
611 name.as_ptr(),
612 )
613 }
614 .into()
615 }
616
617 pub fn build_greater_equal(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
618 let name = CString::new("").unwrap();
619 unsafe {
620 LLVMBuildICmp(
621 self.inner,
622 LLVMIntSGE,
623 l.as_llvm_value_ref(),
624 r.as_llvm_value_ref(),
625 name.as_ptr(),
626 )
627 }
628 .into()
629 }
630
631 pub fn build_and(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
632 let name = CString::new("").unwrap();
633 unsafe {
634 LLVMBuildAnd(
635 self.inner,
636 l.as_llvm_value_ref(),
637 r.as_llvm_value_ref(),
638 name.as_ptr(),
639 )
640 }
641 .into()
642 }
643
644 pub fn build_or(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
645 let name = CString::new("").unwrap();
646 unsafe {
647 LLVMBuildOr(
648 self.inner,
649 l.as_llvm_value_ref(),
650 r.as_llvm_value_ref(),
651 name.as_ptr(),
652 )
653 }
654 .into()
655 }
656
657 pub fn build_fneg(&self, val: LLVMValue) -> LLVMValue {
658 let name = CString::new("").unwrap();
659 unsafe { LLVMBuildFNeg(self.inner, val.as_llvm_value_ref(), name.as_ptr()) }.into()
660 }
661
662 pub fn build_neg(&self, val: LLVMValue) -> LLVMValue {
663 let name = CString::new("").unwrap();
664 unsafe { LLVMBuildNeg(self.inner, val.as_llvm_value_ref(), name.as_ptr()) }.into()
665 }
666
667 pub fn build_fcmp(
668 &self,
669 pred: llvm_sys::LLVMRealPredicate,
670 l: LLVMValue,
671 r: LLVMValue,
672 ) -> LLVMValue {
673 let name = CString::new("").unwrap();
674 unsafe {
675 llvm_sys::core::LLVMBuildFCmp(
676 self.inner,
677 pred,
678 l.as_llvm_value_ref(),
679 r.as_llvm_value_ref(),
680 name.as_ptr(),
681 )
682 }
683 .into()
684 }
685
686 pub fn build_fcmp_oeq(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
687 self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOEQ, l, r)
688 }
689
690 pub fn build_fcmp_one(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
691 self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealONE, l, r)
692 }
693
694 pub fn build_fcmp_ogt(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
695 self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOGT, l, r)
696 }
697
698 pub fn build_fcmp_oge(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
699 self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOGE, l, r)
700 }
701
702 pub fn build_fcmp_olt(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
703 self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOLT, l, r)
704 }
705
706 pub fn build_fcmp_ole(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
707 self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOLE, l, r)
708 }
709
710 pub fn build_not(&self, val: LLVMValue) -> LLVMValue {
711 let name = CString::new("").unwrap();
712 unsafe { LLVMBuildNot(self.inner, val.as_llvm_value_ref(), name.as_ptr()) }.into()
713 }
714}
715
716impl Drop for IRBuilder {
717 fn drop(&mut self) {
718 unsafe { LLVMDisposeBuilder(self.inner) };
719 }
720}