@@ -47,9 +47,9 @@ fn test_null_checked_ptr_ops() {
47
47
// Here we're going to create a function that looks roughly like:
48
48
// fn check_null_index1(ptr: *const i8) -> i8 {
49
49
// if ptr.is_null() {
50
- // return -1;
50
+ // -1
51
51
// } else {
52
- // return ptr[1];
52
+ // ptr[1]
53
53
// }
54
54
// }
55
55
@@ -98,3 +98,151 @@ fn test_null_checked_ptr_ops() {
98
98
99
99
assert_eq ! ( check_null_index1( array. as_ptr( ) ) , 42i8 ) ;
100
100
}
101
+
102
+ #[ test]
103
+ fn test_binary_ops ( ) {
104
+ Target :: initialize_native ( & InitializationConfig :: default ( ) ) . expect ( "Failed to initialize native target" ) ;
105
+
106
+ let context = Context :: create ( ) ;
107
+ let module = context. create_module ( "unsafe" ) ;
108
+ let builder = context. create_builder ( ) ;
109
+ let execution_engine = module. create_jit_execution_engine ( 0 ) . unwrap ( ) ;
110
+ let module = execution_engine. get_module_at ( 0 ) ;
111
+
112
+ // Here we're going to create an and function which looks roughly like:
113
+ // fn and(left: bool, right: bool) -> bool {
114
+ // left && right
115
+ // }
116
+
117
+ let bool_type = context. bool_type ( ) ;
118
+ let fn_type = bool_type. fn_type ( & [ & bool_type, & bool_type] , false ) ;
119
+ let fn_value = module. add_function ( "and" , & fn_type, None ) ;
120
+ let entry = fn_value. append_basic_block ( "entry" ) ;
121
+
122
+ builder. position_at_end ( & entry) ;
123
+
124
+ let left = fn_value. get_first_param ( ) . unwrap ( ) . into_int_value ( ) ;
125
+ let right = fn_value. get_last_param ( ) . unwrap ( ) . into_int_value ( ) ;
126
+
127
+ let and = builder. build_and ( & left, & right, "and_op" ) ;
128
+
129
+ builder. build_return ( Some ( & and) ) ;
130
+
131
+ // Here we're going to create an or function which looks roughly like:
132
+ // fn or(left: bool, right: bool) -> bool {
133
+ // left || right
134
+ // }
135
+
136
+ let fn_value = module. add_function ( "or" , & fn_type, None ) ;
137
+ let entry = fn_value. append_basic_block ( "entry" ) ;
138
+
139
+ builder. position_at_end ( & entry) ;
140
+
141
+ let left = fn_value. get_first_param ( ) . unwrap ( ) . into_int_value ( ) ;
142
+ let right = fn_value. get_last_param ( ) . unwrap ( ) . into_int_value ( ) ;
143
+
144
+ let or = builder. build_or ( & left, & right, "or_op" ) ;
145
+
146
+ builder. build_return ( Some ( & or) ) ;
147
+
148
+ // Here we're going to create a xor function which looks roughly like:
149
+ // fn xor(left: bool, right: bool) -> bool {
150
+ // left || right
151
+ // }
152
+
153
+ let fn_value = module. add_function ( "xor" , & fn_type, None ) ;
154
+ let entry = fn_value. append_basic_block ( "entry" ) ;
155
+
156
+ builder. position_at_end ( & entry) ;
157
+
158
+ let left = fn_value. get_first_param ( ) . unwrap ( ) . into_int_value ( ) ;
159
+ let right = fn_value. get_last_param ( ) . unwrap ( ) . into_int_value ( ) ;
160
+
161
+ let xor = builder. build_xor ( & left, & right, "xor_op" ) ;
162
+
163
+ builder. build_return ( Some ( & xor) ) ;
164
+
165
+ let addr = execution_engine. get_function_address ( "and" ) . unwrap ( ) ;
166
+ let and: extern "C" fn ( bool , bool ) -> bool = unsafe { transmute ( addr) } ;
167
+ let addr = execution_engine. get_function_address ( "or" ) . unwrap ( ) ;
168
+ let or: extern "C" fn ( bool , bool ) -> bool = unsafe { transmute ( addr) } ;
169
+ let addr = execution_engine. get_function_address ( "xor" ) . unwrap ( ) ;
170
+ let xor: extern "C" fn ( bool , bool ) -> bool = unsafe { transmute ( addr) } ;
171
+
172
+ assert ! ( !and( false , false ) ) ;
173
+ assert ! ( !and( true , false ) ) ;
174
+ assert ! ( !and( false , true ) ) ;
175
+ assert ! ( and( true , true ) ) ;
176
+
177
+ assert ! ( !or( false , false ) ) ;
178
+ assert ! ( or( true , false ) ) ;
179
+ assert ! ( or( false , true ) ) ;
180
+ assert ! ( or( true , true ) ) ;
181
+
182
+ assert ! ( !xor( false , false ) ) ;
183
+ assert ! ( xor( true , false ) ) ;
184
+ assert ! ( xor( false , true ) ) ;
185
+ assert ! ( !xor( true , true ) ) ;
186
+ }
187
+
188
+ #[ test]
189
+ fn test_switch ( ) {
190
+ Target :: initialize_native ( & InitializationConfig :: default ( ) ) . expect ( "Failed to initialize native target" ) ;
191
+
192
+ let context = Context :: create ( ) ;
193
+ let module = context. create_module ( "unsafe" ) ;
194
+ let builder = context. create_builder ( ) ;
195
+ let execution_engine = module. create_jit_execution_engine ( 0 ) . unwrap ( ) ;
196
+ let module = execution_engine. get_module_at ( 0 ) ;
197
+
198
+ // Here we're going to create a function which looks roughly like:
199
+ // fn switch(val: u8) -> u8 {
200
+ // if val == 0 {
201
+ // 1
202
+ // }
203
+ // else if val == 42 {
204
+ // 255
205
+ // }
206
+ // else {
207
+ // val * 2
208
+ // }
209
+ // }
210
+
211
+ let i8_type = context. i8_type ( ) ;
212
+ let fn_type = i8_type. fn_type ( & [ & i8_type] , false ) ;
213
+ let fn_value = module. add_function ( "switch" , & fn_type, None ) ;
214
+ let i8_zero = i8_type. const_int ( 0 , false ) ;
215
+ let i8_one = i8_type. const_int ( 1 , false ) ;
216
+ let i8_two = i8_type. const_int ( 2 , false ) ;
217
+ let i8_42 = i8_type. const_int ( 42 , false ) ;
218
+ let i8_255 = i8_type. const_int ( 255 , false ) ;
219
+ let entry = fn_value. append_basic_block ( "entry" ) ;
220
+ let check = fn_value. append_basic_block ( "check" ) ;
221
+ let elif = fn_value. append_basic_block ( "elif" ) ;
222
+ let else_ = fn_value. append_basic_block ( "else" ) ;
223
+ let value = fn_value. get_first_param ( ) . unwrap ( ) . into_int_value ( ) ;
224
+
225
+ builder. position_at_end ( & entry) ;
226
+ builder. build_switch ( & value, & else_, & [ ( & i8_zero, & check) , ( & i8_42, & elif) ] ) ;
227
+
228
+ builder. position_at_end ( & check) ;
229
+ builder. build_return ( Some ( & i8_one) ) ;
230
+
231
+ builder. position_at_end ( & elif) ;
232
+ builder. build_return ( Some ( & i8_255) ) ;
233
+
234
+ builder. position_at_end ( & else_) ;
235
+
236
+ let double = builder. build_int_mul ( & value, & i8_two, "double" ) ;
237
+
238
+ builder. build_return ( Some ( & double) ) ;
239
+
240
+ let addr = execution_engine. get_function_address ( "switch" ) . unwrap ( ) ;
241
+ let switch: extern "C" fn ( u8 ) -> u8 = unsafe { transmute ( addr) } ;
242
+
243
+ assert_eq ! ( switch( 0 ) , 1 ) ;
244
+ assert_eq ! ( switch( 1 ) , 2 ) ;
245
+ assert_eq ! ( switch( 3 ) , 6 ) ;
246
+ assert_eq ! ( switch( 10 ) , 20 ) ;
247
+ assert_eq ! ( switch( 42 ) , 255 ) ;
248
+ }
0 commit comments