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 }
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(), 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 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 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 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}