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, 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    // function_map:HashMap<String,Function>,
34    // symbol_table:RefCell<HashMap<String,(LLVMType,LLVMValue)>>,
35    // current_function:Function
36}
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        // 创建字符串常量并获取其指针
84        // 这需要创建一个全局变量而不是使用构建指令
85        let string_const = Global::const_string(str0);
86
87        // 对于简单的情况,我们直接返回字符串常量
88        // 外部函数调用时LLVM会自动转换为指针
89        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(), // 指针元素类型,如果指针是*i8,这这里的类型应该是i8
224                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        // 获取ptr所指数组的类型
255        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        // 获取ptr所指数组的类型
277        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        // 获取ptr所指数组的类型
298        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}