pipeline_script/llvm/builder/
ir.rs

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, LLVMBuildGlobalString, 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(Clone, Debug)]
30pub struct IRBuilder {
31    inner: LLVMBuilderRef,
32    strings: RefCell<HashMap<String, LLVMValue>>,
33    // function_map:HashMap<String,Function>,
34    // symbol_table:RefCell<HashMap<String,(LLVMType,LLVMValue)>>,
35    // current_function:Function
36}
37unsafe impl Send for IRBuilder {}
38unsafe impl Sync for IRBuilder {}
39impl IRBuilder {
40    pub(crate) fn new(builder: LLVMBuilderRef) -> Self {
41        Self {
42            inner: builder,
43            strings: HashMap::new().into(),
44        }
45    }
46
47    pub fn get_llvm_builder(&self) -> LLVMBuilderRef {
48        self.inner
49    }
50
51    pub fn build_return_void(&self) {
52        unsafe {
53            LLVMBuildRetVoid(self.inner);
54        }
55    }
56    pub fn build_return(&self, value: LLVMValue) {
57        if value.is_unit() {
58            self.build_return_void();
59            return;
60        }
61        unsafe {
62            LLVMBuildRet(self.inner, value.as_llvm_value_ref());
63        }
64    }
65
66    pub fn build_global_string_ptr(
67        &self,
68        name: impl AsRef<str>,
69        value: impl AsRef<str>,
70    ) -> LLVMValue {
71        let name = name.as_ref();
72        let name = CString::new(name).unwrap();
73        let str = value.as_ref();
74        let str = CString::new(str).unwrap();
75        let r = unsafe { LLVMBuildGlobalStringPtr(self.inner, str.as_ptr(), name.as_ptr()) };
76        r.into()
77    }
78    pub fn build_global_string(&self, name: impl AsRef<str>, value: impl AsRef<str>) -> LLVMValue {
79        let name0 = name.as_ref();
80        let name = CString::new(name0).unwrap();
81        let str0 = value.as_ref();
82        if self.strings.borrow().contains_key(str0) {
83            return self.strings.borrow().get(str0).unwrap().clone();
84        }
85        let str = CString::new(str0).unwrap();
86        let r = unsafe { LLVMBuildGlobalString(self.inner, str.as_ptr(), name.as_ptr()) };
87        let s = LLVMValue::String(r);
88        self.strings
89            .borrow_mut()
90            .insert(str0.to_string(), s.clone());
91        s
92    }
93    pub fn build_alloca(&self, name: impl AsRef<str>, ty: &LLVMType) -> ReferenceValue {
94        let name0 = name.as_ref();
95        let name = CString::new(name0).unwrap();
96        let local = unsafe { LLVMBuildAlloca(self.inner, ty.as_llvm_type_ref(), name.as_ptr()) };
97        ReferenceValue::new(local, ty.get_undef())
98    }
99
100    pub fn build_array(&self, el_ty: LLVMType, arr: Vec<LLVMValue>) -> LLVMValue {
101        let name = CString::new("").unwrap();
102        let array_address = unsafe {
103            LLVMBuildArrayAlloca(
104                self.inner,
105                el_ty.as_llvm_type_ref(),
106                Global::const_i64(arr.len() as i64).get_reference(),
107                name.as_ptr(),
108            )
109        };
110        let mut constant_vals = arr
111            .iter()
112            .map(|v| v.as_llvm_value_ref())
113            .collect::<Vec<_>>();
114        let constant_array = unsafe {
115            LLVMConstArray2(
116                el_ty.as_llvm_type_ref(),
117                constant_vals.as_mut_ptr(),
118                arr.len() as u64,
119            )
120        };
121        unsafe {
122            LLVMBuildStore(self.inner, constant_array, array_address);
123        }
124        LLVMValue::Array(ArrayValue::new(array_address, el_ty, arr.len()))
125    }
126    pub fn build_struct_get(&self, val: &StructValue, idx: usize) -> LLVMValue {
127        let name = CString::new("").unwrap();
128        let r = unsafe {
129            LLVMBuildExtractValue(
130                self.inner,
131                val.get_reference(),
132                idx as c_uint,
133                name.as_ptr(),
134            )
135        };
136        let field_type = val.simply_get_field_by_index(idx).unwrap();
137        match field_type {
138            LLVMValue::String(_) => LLVMValue::String(r),
139            LLVMValue::Struct(mut v) => {
140                v.set_reference(r);
141                v.into()
142            }
143            LLVMValue::Pointer(pointer_value) => {
144                let mut pointer_value = pointer_value.clone();
145                pointer_value.set_reference(r);
146                pointer_value.into()
147            }
148            LLVMValue::Function(f) => {
149                let mut function_value = f.clone();
150                function_value.set_reference(r);
151                function_value.into()
152            }
153            LLVMValue::Reference(reference_value) => {
154                let mut reference_value = reference_value.clone();
155                reference_value.set_reference(r);
156                reference_value.into()
157            }
158            _ => r.into(),
159        }
160    }
161
162    pub fn build_struct_insert(
163        &self,
164        val: &StructValue,
165        idx: usize,
166        value: &LLVMValue,
167    ) -> StructValue {
168        let name = CString::new("").unwrap();
169        let new_struct = unsafe {
170            LLVMBuildInsertValue(
171                self.inner,
172                val.get_reference(),
173                value.as_llvm_value_ref(),
174                idx as c_uint,
175                name.as_ptr(),
176            )
177        };
178        val.with_field(new_struct, idx, value.clone())
179    }
180    pub fn build_i64_to_ptr(&self, val: LLVMValue) -> LLVMValue {
181        let target = unsafe { LLVMPointerType(LLVMInt8Type(), 0) };
182        unsafe { LLVMConstIntToPtr(val.as_llvm_value_ref(), target) }.into()
183    }
184    pub fn build_struct_gep(&self, ty: &LLVMType, val: LLVMValue, idx: usize) -> LLVMValue {
185        let name = CString::new("").unwrap();
186        let r = unsafe {
187            LLVMBuildStructGEP2(
188                self.inner,
189                ty.as_llvm_type_ref(),
190                val.as_llvm_value_ref(),
191                idx as c_uint,
192                name.as_ptr(),
193            )
194        };
195        let ty = ty.get_struct_field_type(idx);
196        match &ty {
197            LLVMType::String(_) => ReferenceValue::new(r, ty.get_undef()).into(),
198            LLVMType::Struct(_, _, _) => ReferenceValue::new(r, ty.get_undef()).into(),
199            LLVMType::Pointer(element_type, _) => {
200                ReferenceValue::new(r, element_type.get_undef()).into()
201            }
202            LLVMType::Function(_, _, _) => ReferenceValue::new(r, ty.get_undef()).into(),
203            LLVMType::Ref(element_type, _) => {
204                ReferenceValue::new(r, element_type.get_undef()).into()
205            }
206            _ => ReferenceValue::new(r, ty.get_undef()).into(),
207        }
208    }
209    pub fn build_unreachable(&self) {
210        unsafe {
211            LLVMBuildUnreachable(self.inner);
212        }
213    }
214    pub fn build_store(&self, ptr: LLVMValueRef, val: &LLVMValue) {
215        unsafe { LLVMBuildStore(self.inner, val.as_llvm_value_ref(), ptr) };
216    }
217    pub fn build_load(&self, ty: LLVMType, ptr: LLVMValueRef) -> LLVMValue {
218        let name = CString::new("").unwrap();
219        let val = unsafe {
220            LLVMBuildLoad2(
221                self.inner,
222                ty.as_llvm_type_ref(), // 指针元素类型,如果指针是*i8,这这里的类型应该是i8
223                ptr,
224                name.as_ptr(),
225            )
226        };
227        unsafe {
228            match ty {
229                LLVMType::Pointer(_, _) => PointerValue::new(val, ty.get_undef()).into(),
230                LLVMType::String(_) => LLVMValue::String(val),
231                LLVMType::Array(element_type, array_type) => {
232                    let length = LLVMGetArrayLength2(array_type);
233                    ArrayValue::new(val, *element_type, length as usize).into()
234                }
235                LLVMType::Struct(name, fields, _) => {
236                    let mut field_index = HashMap::new();
237                    for (i, (name, _)) in fields.iter().enumerate() {
238                        field_index.insert(name.clone(), i);
239                    }
240                    StructValue::new(
241                        val,
242                        name,
243                        field_index,
244                        fields.iter().map(|(_, ty)| ty.get_undef()).collect(),
245                    )
246                    .into()
247                }
248                _ => val.into(),
249            }
250        }
251    }
252    pub fn build_array_get(&self, ty: LLVMType, ptr: LLVMValue, index: LLVMValue) -> LLVMValue {
253        // 获取ptr所指数组的类型
254        let name = CString::new("").unwrap();
255        let mut indices = [index.as_llvm_value_ref()];
256        let r = unsafe {
257            let ptr0 = LLVMBuildGEP2(
258                self.inner,
259                ty.as_llvm_type_ref(),
260                ptr.as_llvm_value_ref(),
261                indices.as_mut_ptr(),
262                1,
263                name.as_ptr(),
264            );
265            LLVMBuildLoad2(self.inner, ty.as_llvm_type_ref(), ptr0, name.as_ptr())
266        };
267        r.into()
268    }
269    pub fn build_array_get_in_bounds(
270        &self,
271        ty: LLVMType,
272        ptr: LLVMValue,
273        index: LLVMValue,
274    ) -> LLVMValue {
275        // 获取ptr所指数组的类型
276        let name = CString::new("").unwrap();
277        let mut indices = [index.as_llvm_value_ref()];
278        let r = unsafe {
279            let ptr0 = LLVMBuildInBoundsGEP2(
280                self.inner,
281                ty.as_llvm_type_ref(),
282                ptr.as_llvm_value_ref(),
283                indices.as_mut_ptr(),
284                1,
285                name.as_ptr(),
286            );
287            LLVMBuildLoad2(self.inner, ty.as_llvm_type_ref(), ptr0, name.as_ptr())
288        };
289        match ty {
290            LLVMType::Pointer(_, _) => PointerValue::new(r, ty.get_undef()).into(),
291            LLVMType::String(_) => LLVMValue::String(r),
292            _ => r.into(),
293        }
294    }
295    pub fn build_array_gep(&self, ty: LLVMType, ptr: LLVMValue, index: LLVMValue) -> LLVMValue {
296        // 获取ptr所指数组的类型
297        let name = CString::new("").unwrap();
298        let mut indices = [index.as_llvm_value_ref()];
299        let r = unsafe {
300            LLVMBuildGEP2(
301                self.inner,
302                ty.as_llvm_type_ref(),
303                ptr.as_llvm_value_ref(),
304                indices.as_mut_ptr(),
305                1,
306                name.as_ptr(),
307            )
308        };
309        ReferenceValue::new(r, ty.get_undef()).into()
310    }
311    pub fn position_at_end(&self, block: LLVMBasicBlockRef) {
312        unsafe { LLVMPositionBuilderAtEnd(self.inner, block) };
313    }
314    pub fn build_br(&self, block: LLVMBasicBlockRef) {
315        unsafe { LLVMBuildBr(self.inner, block) };
316    }
317    pub fn build_cond_br(
318        &self,
319        condition: &BoolValue,
320        then_block: LLVMBasicBlockRef,
321        else_block: LLVMBasicBlockRef,
322    ) {
323        unsafe {
324            LLVMBuildCondBr(
325                self.inner,
326                condition.get_reference(),
327                then_block,
328                else_block,
329            );
330        }
331    }
332
333    pub fn build_add(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
334        let name = CString::new("").unwrap();
335        let r = unsafe {
336            LLVMBuildAdd(
337                self.inner,
338                l.as_llvm_value_ref(),
339                r.as_llvm_value_ref(),
340                name.as_ptr(),
341            )
342        };
343        let r = r.into();
344        r
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 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 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}