11use libc:: { c_char, c_uint} ;
2- use ffi:: prelude:: { LLVMBuilderRef , LLVMValueRef } ;
2+ use ffi:: prelude:: { LLVMBasicBlockRef , LLVMBuilderRef , LLVMValueRef } ;
33use ffi:: { core, LLVMBuilder , LLVMRealPredicate , LLVMIntPredicate } ;
44use cbox:: CSemiBox ;
55use std:: marker:: PhantomData ;
@@ -11,6 +11,7 @@ use value::{Function, Value, Predicate};
1111
1212static NULL_NAME : [ c_char ; 1 ] = [ 0 ] ;
1313
14+
1415/// This provides a uniform API for creating instructions and inserting them into a basic block.
1516pub struct Builder ( PhantomData < [ u8 ] > ) ;
1617native_ref ! ( & Builder = LLVMBuilderRef ) ;
@@ -50,6 +51,24 @@ impl Builder {
5051 pub fn position_at_end ( & self , block : & BasicBlock ) {
5152 unsafe { core:: LLVMPositionBuilderAtEnd ( self . into ( ) , block. into ( ) ) }
5253 }
54+ /// Build a PHI instruction with no useful values
55+ pub fn build_phi ( & self , incoming : Vec < ( & BasicBlock , & Value ) > ) -> & Value {
56+ let count = incoming. len ( ) as u32 ;
57+ assert ! ( count > 0 ) ;
58+ let ty = incoming[ 0 ] . 1 . get_type ( ) ;
59+
60+ let mut incoming_values: Vec < LLVMValueRef > = Vec :: with_capacity ( incoming. len ( ) ) ;
61+ let mut incoming_blocks: Vec < LLVMBasicBlockRef > = Vec :: with_capacity ( incoming. len ( ) ) ;
62+ for ( bb, v) in incoming {
63+ incoming_values. push ( v. into ( ) ) ;
64+ incoming_blocks. push ( bb. into ( ) ) ;
65+ }
66+ unsafe {
67+ let phi = core:: LLVMBuildPhi ( self . into ( ) , ty. into ( ) , NULL_NAME . as_ptr ( ) ) ;
68+ core:: LLVMAddIncoming ( phi, incoming_values. as_mut_ptr ( ) , incoming_blocks. as_mut_ptr ( ) , count) ;
69+ phi
70+ } . into ( )
71+ }
5372 /// Build an instruction that returns from the function with void.
5473 pub fn build_ret_void ( & self ) -> & Value {
5574 unsafe { core:: LLVMBuildRetVoid ( self . into ( ) ) } . into ( )
@@ -73,6 +92,11 @@ impl Builder {
7392 pub fn build_free ( & self , val : & Value ) -> & Value {
7493 unsafe { core:: LLVMBuildFree ( self . into ( ) , val. into ( ) ) } . into ( )
7594 }
95+
96+ /// Build an unreachable instruction
97+ pub fn build_unreachable ( & self ) -> & Value {
98+ unsafe { core:: LLVMBuildUnreachable ( self . into ( ) ) . into ( ) }
99+ }
76100 /// Build an instruction that store the value `val` in the pointer `ptr`.
77101 pub fn build_store ( & self , val : & Value , ptr : & Value ) -> & Value {
78102 unsafe { core:: LLVMBuildStore ( self . into ( ) , val. into ( ) , ptr. into ( ) ) } . into ( )
@@ -95,6 +119,16 @@ impl Builder {
95119 call. into ( )
96120 }
97121 }
122+
123+ pub fn build_value_call ( & self , func : & Value , args : & [ & Value ] ) -> & Value {
124+ unsafe {
125+ let call = core:: LLVMBuildCall ( self . into ( ) , func. into ( ) , args. as_ptr ( ) as * mut LLVMValueRef , args. len ( ) as c_uint , NULL_NAME . as_ptr ( ) ) ;
126+ core:: LLVMSetTailCall ( call, 0 ) ;
127+ call. into ( )
128+ }
129+ }
130+
131+
98132 /// Build an instruction that calls the function `func` with the arguments `args`.
99133 ///
100134 /// This will return the return value of the function.
@@ -121,10 +155,42 @@ impl Builder {
121155 pub fn build_zext ( & self , value : & Value , dest : & Type ) -> & Value {
122156 unsafe { core:: LLVMBuildZExtOrBitCast ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
123157 }
158+
159+ /// Build an instruction that sign extends its operand to the type `dest`.
160+ pub fn build_sext ( & self , value : & Value , dest : & Type ) -> & Value {
161+ unsafe { core:: LLVMBuildSExtOrBitCast ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
162+ }
163+
124164 /// Build an instruction that truncates the high-order bits of value to fit into a certain type.
125165 pub fn build_trunc ( & self , value : & Value , dest : & Type ) -> & Value {
126166 unsafe { core:: LLVMBuildTrunc ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
127167 }
168+ /// Build an instruction that converts a floating point value to an signed int type
169+ pub fn build_fptosi ( & self , value : & Value , dest : & Type ) -> & Value {
170+ unsafe { core:: LLVMBuildFPToSI ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
171+ }
172+ /// Build an instruction that converts a floating point value to an unsigned int type
173+ pub fn build_fptoui ( & self , value : & Value , dest : & Type ) -> & Value {
174+ unsafe { core:: LLVMBuildFPToUI ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
175+ }
176+ /// Build an instruction that converts a signed int to an floating point type
177+ pub fn build_sitofp ( & self , value : & Value , dest : & Type ) -> & Value {
178+ unsafe { core:: LLVMBuildSIToFP ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
179+ }
180+ /// Build an instruction that converts a unsigned int to an floating point type
181+ pub fn build_uitofp ( & self , value : & Value , dest : & Type ) -> & Value {
182+ unsafe { core:: LLVMBuildUIToFP ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
183+ }
184+
185+ pub fn build_fpext ( & self , value : & Value , dest : & Type ) -> & Value {
186+ unsafe { core:: LLVMBuildFPExt ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
187+ }
188+
189+ pub fn build_fptrunc ( & self , value : & Value , dest : & Type ) -> & Value {
190+ unsafe { core:: LLVMBuildFPTrunc ( self . into ( ) , value. into ( ) , dest. into ( ) , NULL_NAME . as_ptr ( ) ) . into ( ) }
191+ }
192+
193+
128194 /// Build an instruction that inserts a value into an aggregate data value.
129195 pub fn build_insert_value ( & self , agg : & Value , elem : & Value , index : usize ) -> & Value {
130196 unsafe { core:: LLVMBuildInsertValue ( self . into ( ) , agg. into ( ) , elem. into ( ) , index as c_uint , NULL_NAME . as_ptr ( ) ) . into ( ) }
@@ -149,19 +215,26 @@ impl Builder {
149215 switch. into ( )
150216 }
151217 }
218+
152219 un_op ! { build_load, LLVMBuildLoad }
153220 un_op ! { build_neg, LLVMBuildNeg }
221+ un_op ! { build_fneg, LLVMBuildFNeg }
154222 un_op ! { build_not, LLVMBuildNot }
155223 bin_op ! { build_add, LLVMBuildAdd , LLVMBuildFAdd }
156224 bin_op ! { build_sub, LLVMBuildSub , LLVMBuildFSub }
157225 bin_op ! { build_mul, LLVMBuildMul , LLVMBuildFMul }
158226 bin_op ! { build_div, LLVMBuildSDiv , LLVMBuildFDiv }
227+ bin_op ! { build_udiv, LLVMBuildUDiv }
228+ bin_op ! { build_urem, LLVMBuildURem }
229+ bin_op ! { build_srem, LLVMBuildSRem }
159230 bin_op ! { build_shl, LLVMBuildShl }
160231 bin_op ! { build_ashr, LLVMBuildAShr }
232+ bin_op ! { build_lshr, LLVMBuildLShr }
161233 bin_op ! { build_and, LLVMBuildAnd }
162234 bin_op ! { build_or, LLVMBuildOr }
235+ bin_op ! { build_xor, LLVMBuildXor }
163236 /// Build an instruction to compare the values `a` and `b` with the predicate / comparative operator `pred`.
164- pub fn build_cmp ( & self , a : & Value , b : & Value , pred : Predicate ) -> & Value {
237+ pub fn build_signed_cmp ( & self , a : & Value , b : & Value , pred : Predicate ) -> & Value {
165238 let ( at, bt) = ( a. get_type ( ) , b. get_type ( ) ) ;
166239 assert_eq ! ( at, bt) ;
167240 if at. is_integer ( ) {
@@ -188,4 +261,22 @@ impl Builder {
188261 panic ! ( "expected numzextbers, got {:?}" , at)
189262 }
190263 }
264+
265+ pub fn build_unsigned_cmp ( & self , a : & Value , b : & Value , pred : Predicate ) -> & Value {
266+ let ( at, bt) = ( a. get_type ( ) , b. get_type ( ) ) ;
267+ assert_eq ! ( at, bt) ;
268+ assert ! ( at. is_integer( ) ) ;
269+
270+
271+ let pred = match pred {
272+ Predicate :: Equal => LLVMIntPredicate :: LLVMIntEQ ,
273+ Predicate :: NotEqual => LLVMIntPredicate :: LLVMIntNE ,
274+ Predicate :: GreaterThan => LLVMIntPredicate :: LLVMIntUGT ,
275+ Predicate :: GreaterThanOrEqual => LLVMIntPredicate :: LLVMIntUGE ,
276+ Predicate :: LessThan => LLVMIntPredicate :: LLVMIntULT ,
277+ Predicate :: LessThanOrEqual => LLVMIntPredicate :: LLVMIntULE
278+ } ;
279+ unsafe { core:: LLVMBuildICmp ( self . into ( ) , pred, a. into ( ) , b. into ( ) , NULL_NAME . as_ptr ( ) ) } . into ( )
280+ }
281+
191282}
0 commit comments