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) -> LLVMValue {
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        LLVMValue::Reference(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(&self, val: LLVMValue, idx: usize, value: &LLVMValue) -> LLVMValue {
163        let name = CString::new("").unwrap();
164        let new_struct = unsafe {
165            LLVMBuildInsertValue(
166                self.inner,
167                val.as_llvm_value_ref(),
168                value.as_llvm_value_ref(),
169                idx as c_uint,
170                name.as_ptr(),
171            )
172        };
173        let struct_value = val.as_struct().unwrap();
174        LLVMValue::Struct(struct_value.with_field(new_struct, idx, value.clone()))
175    }
176    pub fn build_i64_to_ptr(&self, val: LLVMValue) -> LLVMValue {
177        let target = unsafe { LLVMPointerType(LLVMInt8Type(), 0) };
178        unsafe { LLVMConstIntToPtr(val.as_llvm_value_ref(), target) }.into()
179    }
180    pub fn build_struct_gep(&self, ty: &LLVMType, val: LLVMValue, idx: usize) -> LLVMValue {
181        let name = CString::new("").unwrap();
182        let r = unsafe {
183            LLVMBuildStructGEP2(
184                self.inner,
185                ty.as_llvm_type_ref(),
186                val.as_llvm_value_ref(),
187                idx as c_uint,
188                name.as_ptr(),
189            )
190        };
191        let ty = ty.get_struct_field_type(idx);
192        match &ty {
193            LLVMType::String(_) => ReferenceValue::new(r, ty.get_undef()).into(),
194            LLVMType::Struct(_, _, _) => ReferenceValue::new(r, ty.get_undef()).into(),
195            LLVMType::Pointer(element_type, _) => {
196                ReferenceValue::new(r, element_type.get_undef()).into()
197            }
198            LLVMType::Function(_, _, _) => ReferenceValue::new(r, ty.get_undef()).into(),
199            LLVMType::Ref(element_type, _) => {
200                ReferenceValue::new(r, element_type.get_undef()).into()
201            }
202            _ => ReferenceValue::new(r, ty.get_undef()).into(),
203        }
204    }
205    pub fn build_unreachable(&self) {
206        unsafe {
207            LLVMBuildUnreachable(self.inner);
208        }
209    }
210    pub fn build_store(&self, ptr: LLVMValueRef, val: LLVMValue) {
211        unsafe { LLVMBuildStore(self.inner, val.as_llvm_value_ref(), ptr) };
212    }
213    pub fn build_load(&self, ty: LLVMType, ptr: LLVMValueRef) -> LLVMValue {
214        let name = CString::new("").unwrap();
215        let val = unsafe {
216            LLVMBuildLoad2(
217                self.inner,
218                ty.as_llvm_type_ref(), // 指针元素类型,如果指针是*i8,这这里的类型应该是i8
219                ptr,
220                name.as_ptr(),
221            )
222        };
223        unsafe {
224            match ty {
225                LLVMType::Pointer(_, _) => PointerValue::new(val, ty.get_undef()).into(),
226                LLVMType::String(_) => LLVMValue::String(val),
227                LLVMType::Array(element_type, array_type) => {
228                    let length = LLVMGetArrayLength2(array_type);
229                    ArrayValue::new(val, *element_type, length as usize).into()
230                }
231                LLVMType::Struct(name, fields, _) => {
232                    let mut field_index = HashMap::new();
233                    for (i, (name, _)) in fields.iter().enumerate() {
234                        field_index.insert(name.clone(), i);
235                    }
236                    StructValue::new(
237                        val,
238                        name,
239                        field_index,
240                        fields.iter().map(|(_, ty)| ty.get_undef()).collect(),
241                    )
242                    .into()
243                }
244                _ => val.into(),
245            }
246        }
247    }
248    pub fn build_array_get(&self, ty: LLVMType, ptr: LLVMValue, index: LLVMValue) -> LLVMValue {
249        // 获取ptr所指数组的类型
250        let name = CString::new("").unwrap();
251        let mut indices = [index.as_llvm_value_ref()];
252        let r = unsafe {
253            let ptr0 = LLVMBuildGEP2(
254                self.inner,
255                ty.as_llvm_type_ref(),
256                ptr.as_llvm_value_ref(),
257                indices.as_mut_ptr(),
258                1,
259                name.as_ptr(),
260            );
261            LLVMBuildLoad2(self.inner, ty.as_llvm_type_ref(), ptr0, name.as_ptr())
262        };
263        r.into()
264    }
265    pub fn build_array_get_in_bounds(
266        &self,
267        ty: LLVMType,
268        ptr: LLVMValue,
269        index: LLVMValue,
270    ) -> LLVMValue {
271        // 获取ptr所指数组的类型
272        let name = CString::new("").unwrap();
273        let mut indices = [index.as_llvm_value_ref()];
274        let r = unsafe {
275            let ptr0 = LLVMBuildInBoundsGEP2(
276                self.inner,
277                ty.as_llvm_type_ref(),
278                ptr.as_llvm_value_ref(),
279                indices.as_mut_ptr(),
280                1,
281                name.as_ptr(),
282            );
283            LLVMBuildLoad2(self.inner, ty.as_llvm_type_ref(), ptr0, name.as_ptr())
284        };
285        match ty {
286            LLVMType::Pointer(_, _) => PointerValue::new(r, ty.get_undef()).into(),
287            LLVMType::String(_) => LLVMValue::String(r),
288            _ => r.into(),
289        }
290    }
291    pub fn build_array_gep(&self, ty: LLVMType, ptr: LLVMValue, index: LLVMValue) -> LLVMValue {
292        // 获取ptr所指数组的类型
293        let name = CString::new("").unwrap();
294        let mut indices = [index.as_llvm_value_ref()];
295        let r = unsafe {
296            LLVMBuildGEP2(
297                self.inner,
298                ty.as_llvm_type_ref(),
299                ptr.as_llvm_value_ref(),
300                indices.as_mut_ptr(),
301                1,
302                name.as_ptr(),
303            )
304        };
305        ReferenceValue::new(r, ty.get_undef()).into()
306    }
307    pub fn position_at_end(&self, block: LLVMBasicBlockRef) {
308        unsafe { LLVMPositionBuilderAtEnd(self.inner, block) };
309    }
310    pub fn build_br(&self, block: LLVMBasicBlockRef) {
311        unsafe { LLVMBuildBr(self.inner, block) };
312    }
313    pub fn build_cond_br(
314        &self,
315        condition: &BoolValue,
316        then_block: LLVMBasicBlockRef,
317        else_block: LLVMBasicBlockRef,
318    ) {
319        unsafe {
320            LLVMBuildCondBr(
321                self.inner,
322                condition.get_reference(),
323                then_block,
324                else_block,
325            );
326        }
327    }
328
329    pub fn build_add(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
330        let name = CString::new("").unwrap();
331        let r = unsafe {
332            LLVMBuildAdd(
333                self.inner,
334                l.as_llvm_value_ref(),
335                r.as_llvm_value_ref(),
336                name.as_ptr(),
337            )
338        };
339        let r = r.into();
340        r
341    }
342    pub fn build_fadd(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
343        let name = CString::new("").unwrap();
344        unsafe {
345            LLVMBuildFAdd(
346                self.inner,
347                l.as_llvm_value_ref(),
348                r.as_llvm_value_ref(),
349                name.as_ptr(),
350            )
351        }
352        .into()
353    }
354    pub fn build_fmul(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
355        let name = CString::new("").unwrap();
356        unsafe {
357            LLVMBuildFMul(
358                self.inner,
359                l.as_llvm_value_ref(),
360                r.as_llvm_value_ref(),
361                name.as_ptr(),
362            )
363        }
364        .into()
365    }
366    pub fn build_mul(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
367        let name = CString::new("").unwrap();
368        let r = unsafe {
369            LLVMBuildMul(
370                self.inner,
371                l.as_llvm_value_ref(),
372                r.as_llvm_value_ref(),
373                name.as_ptr(),
374            )
375        };
376        r.into()
377    }
378    pub fn build_sub(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
379        let name = CString::new("").unwrap();
380        let r = unsafe {
381            LLVMBuildSub(
382                self.inner,
383                l.as_llvm_value_ref(),
384                r.as_llvm_value_ref(),
385                name.as_ptr(),
386            )
387        };
388        r.into()
389    }
390    pub fn build_div(&self, l: LLVMValueRef, r: LLVMValueRef) -> LLVMValue {
391        let name = CString::new("").unwrap();
392        unsafe { LLVMBuildSDiv(self.inner, l, r, name.as_ptr()) }.into()
393    }
394    pub fn build_fsub(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
395        let name = CString::new("").unwrap();
396        unsafe {
397            llvm_sys::core::LLVMBuildFSub(
398                self.inner,
399                l.as_llvm_value_ref(),
400                r.as_llvm_value_ref(),
401                name.as_ptr(),
402            )
403        }
404        .into()
405    }
406    pub fn build_fdiv(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
407        let name = CString::new("").unwrap();
408        unsafe {
409            llvm_sys::core::LLVMBuildFDiv(
410                self.inner,
411                l.as_llvm_value_ref(),
412                r.as_llvm_value_ref(),
413                name.as_ptr(),
414            )
415        }
416        .into()
417    }
418    pub fn build_si_to_fp(&self, val: LLVMValue, dest_ty: LLVMType) -> LLVMValue {
419        let name = CString::new("").unwrap();
420        unsafe {
421            llvm_sys::core::LLVMBuildSIToFP(
422                self.inner,
423                val.as_llvm_value_ref(),
424                dest_ty.as_llvm_type_ref(),
425                name.as_ptr(),
426            )
427        }
428        .into()
429    }
430    pub fn build_fp_to_si(&self, val: LLVMValue, dest_ty: LLVMType) -> LLVMValue {
431        let name = CString::new("").unwrap();
432        unsafe {
433            llvm_sys::core::LLVMBuildFPToSI(
434                self.inner,
435                val.as_llvm_value_ref(),
436                dest_ty.as_llvm_type_ref(),
437                name.as_ptr(),
438            )
439        }
440        .into()
441    }
442    pub fn build_eq(&self, l: LLVMValueRef, r: LLVMValueRef) -> BoolValue {
443        let name = CString::new("").unwrap();
444        let r = unsafe { LLVMBuildICmp(self.inner, LLVMIntEQ, l, r, name.as_ptr()) };
445        BoolValue::new(r)
446    }
447    pub fn build_neq(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
448        let name = CString::new("").unwrap();
449        unsafe {
450            LLVMBuildICmp(
451                self.inner,
452                LLVMIntNE,
453                l.as_llvm_value_ref(),
454                r.as_llvm_value_ref(),
455                name.as_ptr(),
456            )
457        }
458        .into()
459    }
460    pub fn build_greater(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
461        let name = CString::new("").unwrap();
462        unsafe {
463            LLVMBuildICmp(
464                self.inner,
465                LLVMIntSGT,
466                l.as_llvm_value_ref(),
467                r.as_llvm_value_ref(),
468                name.as_ptr(),
469            )
470        }
471        .into()
472    }
473    pub fn build_less(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
474        let name = CString::new("").unwrap();
475        unsafe {
476            LLVMBuildICmp(
477                self.inner,
478                LLVMIntSLT,
479                l.as_llvm_value_ref(),
480                r.as_llvm_value_ref(),
481                name.as_ptr(),
482            )
483        }
484        .into()
485    }
486    pub fn build_call(
487        &self,
488        ctx: &Context,
489        function: &FunctionValue,
490        params: &mut [LLVMValue],
491        var_name: impl AsRef<str>,
492    ) -> LLVMValue {
493        let dec = function
494            .get_llvm_type(ctx)
495            .get_element_type()
496            .as_llvm_type_ref();
497        let var_name = CString::new(var_name.as_ref()).unwrap();
498        let mut params = params
499            .iter()
500            .map(|e| e.as_llvm_value_ref())
501            .collect::<Vec<LLVMValueRef>>();
502        let call_res = unsafe {
503            LLVMBuildCall2(
504                self.inner,
505                dec,
506                function.get_reference(),
507                params.as_mut_ptr(),
508                params.len() as c_uint,
509                var_name.as_ptr(),
510            )
511        };
512        let return_value = function.get_return_value();
513        if return_value.is_struct() {
514            let mut struct_value = return_value.as_struct().unwrap().clone();
515            struct_value.set_reference(call_res);
516            return struct_value.clone().into();
517        }
518        match return_value {
519            LLVMValue::String(_) => LLVMValue::String(call_res),
520            LLVMValue::Pointer(pointer_value) => {
521                let mut pointer_value = pointer_value.clone();
522                pointer_value.set_reference(call_res);
523                pointer_value.into()
524            }
525            LLVMValue::Struct(mut v) => {
526                v.set_reference(call_res);
527                v.into()
528            }
529            _ => call_res.into(),
530        }
531    }
532    pub fn build_call_fn_ptr(
533        &self,
534        fn_type: LLVMType,
535        ptr: LLVMValue,
536        params: &mut [LLVMValue],
537        var_name: impl AsRef<str>,
538    ) -> LLVMValue {
539        let name = CString::new(var_name.as_ref()).unwrap();
540        let mut params = params
541            .iter()
542            .map(|e| e.as_llvm_value_ref())
543            .collect::<Vec<LLVMValueRef>>();
544        unsafe {
545            LLVMBuildCall2(
546                self.inner,
547                fn_type.as_llvm_type_ref(),
548                ptr.as_llvm_value_ref(),
549                params.as_mut_ptr(),
550                params.len() as c_uint,
551                name.as_ptr(),
552            )
553        }
554        .into()
555    }
556    pub fn build_zext(&self, value: LLVMValue, ty: LLVMType) -> LLVMValue {
557        let name = CString::new("").unwrap();
558        unsafe {
559            LLVMBuildZExt(
560                self.inner,
561                value.as_llvm_value_ref(),
562                ty.as_llvm_type_ref(),
563                name.as_ptr(),
564            )
565        }
566        .into()
567    }
568    pub fn build_extract_value(&self, ctx: &Context, val: &StructValue, idx: usize) -> LLVMValue {
569        let name = CString::new("").unwrap();
570        let r = unsafe {
571            LLVMBuildExtractValue(
572                self.inner,
573                val.get_reference(),
574                idx as c_uint,
575                name.as_ptr(),
576            )
577        };
578
579        let field_type = val.get_field_by_index(ctx, idx).unwrap();
580        match field_type {
581            LLVMValue::String(_) => LLVMValue::String(r),
582            LLVMValue::Struct(mut v) => {
583                v.set_reference(r);
584                v.into()
585            }
586            LLVMValue::Pointer(pointer_value) => {
587                let mut pointer_value = pointer_value.clone();
588                pointer_value.set_reference(r);
589                pointer_value.into()
590            }
591            LLVMValue::Function(f) => {
592                let mut function_value = f.clone();
593                function_value.set_reference(r);
594                function_value.into()
595            }
596            _ => r.into(),
597        }
598    }
599    pub fn build_less_equal(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
600        let name = CString::new("").unwrap();
601        unsafe {
602            LLVMBuildICmp(
603                self.inner,
604                LLVMIntSLE,
605                l.as_llvm_value_ref(),
606                r.as_llvm_value_ref(),
607                name.as_ptr(),
608            )
609        }
610        .into()
611    }
612
613    pub fn build_greater_equal(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
614        let name = CString::new("").unwrap();
615        unsafe {
616            LLVMBuildICmp(
617                self.inner,
618                LLVMIntSGE,
619                l.as_llvm_value_ref(),
620                r.as_llvm_value_ref(),
621                name.as_ptr(),
622            )
623        }
624        .into()
625    }
626
627    pub fn build_and(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
628        let name = CString::new("").unwrap();
629        unsafe {
630            LLVMBuildAnd(
631                self.inner,
632                l.as_llvm_value_ref(),
633                r.as_llvm_value_ref(),
634                name.as_ptr(),
635            )
636        }
637        .into()
638    }
639
640    pub fn build_or(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
641        let name = CString::new("").unwrap();
642        unsafe {
643            LLVMBuildOr(
644                self.inner,
645                l.as_llvm_value_ref(),
646                r.as_llvm_value_ref(),
647                name.as_ptr(),
648            )
649        }
650        .into()
651    }
652
653    pub fn build_fneg(&self, val: LLVMValue) -> LLVMValue {
654        let name = CString::new("").unwrap();
655        unsafe { LLVMBuildFNeg(self.inner, val.as_llvm_value_ref(), name.as_ptr()) }.into()
656    }
657
658    pub fn build_neg(&self, val: LLVMValue) -> LLVMValue {
659        let name = CString::new("").unwrap();
660        unsafe { LLVMBuildNeg(self.inner, val.as_llvm_value_ref(), name.as_ptr()) }.into()
661    }
662
663    pub fn build_fcmp(
664        &self,
665        pred: llvm_sys::LLVMRealPredicate,
666        l: LLVMValue,
667        r: LLVMValue,
668    ) -> LLVMValue {
669        let name = CString::new("").unwrap();
670        unsafe {
671            llvm_sys::core::LLVMBuildFCmp(
672                self.inner,
673                pred,
674                l.as_llvm_value_ref(),
675                r.as_llvm_value_ref(),
676                name.as_ptr(),
677            )
678        }
679        .into()
680    }
681
682    pub fn build_fcmp_oeq(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
683        self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOEQ, l, r)
684    }
685
686    pub fn build_fcmp_one(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
687        self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealONE, l, r)
688    }
689
690    pub fn build_fcmp_ogt(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
691        self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOGT, l, r)
692    }
693
694    pub fn build_fcmp_oge(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
695        self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOGE, l, r)
696    }
697
698    pub fn build_fcmp_olt(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
699        self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOLT, l, r)
700    }
701
702    pub fn build_fcmp_ole(&self, l: LLVMValue, r: LLVMValue) -> LLVMValue {
703        self.build_fcmp(llvm_sys::LLVMRealPredicate::LLVMRealOLE, l, r)
704    }
705
706    pub fn build_not(&self, val: LLVMValue) -> LLVMValue {
707        let name = CString::new("").unwrap();
708        unsafe { LLVMBuildNot(self.inner, val.as_llvm_value_ref(), name.as_ptr()) }.into()
709    }
710}
711
712impl Drop for IRBuilder {
713    fn drop(&mut self) {
714        unsafe { LLVMDisposeBuilder(self.inner) };
715    }
716}