]> git.lizzy.rs Git - rust.git/blob - src/builder.rs
Initial commit
[rust.git] / src / builder.rs
1 use std::borrow::Cow;
2 use std::cell::Cell;
3 use std::convert::TryFrom;
4 use std::ops::{Deref, Range};
5
6 use gccjit::FunctionType;
7 use gccjit::{
8     BinaryOp,
9     Block,
10     ComparisonOp,
11     Function,
12     LValue,
13     RValue,
14     ToRValue,
15     Type,
16     UnaryOp,
17 };
18 use rustc_codegen_ssa::MemFlags;
19 use rustc_codegen_ssa::common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope};
20 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
21 use rustc_codegen_ssa::mir::place::PlaceRef;
22 use rustc_codegen_ssa::traits::{
23     BackendTypes,
24     BaseTypeMethods,
25     BuilderMethods,
26     ConstMethods,
27     DerivedTypeMethods,
28     HasCodegen,
29     OverflowOp,
30     StaticBuilderMethods,
31 };
32 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
33 use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, TyAndLayout};
34 use rustc_span::Span;
35 use rustc_span::def_id::DefId;
36 use rustc_target::abi::{
37     self,
38     Align,
39     HasDataLayout,
40     LayoutOf,
41     Size,
42     TargetDataLayout,
43 };
44 use rustc_target::spec::{HasTargetSpec, Target};
45
46 use crate::common::{SignType, TypeReflection, type_is_pointer};
47 use crate::context::CodegenCx;
48 use crate::type_of::LayoutGccExt;
49
50 // TODO
51 type Funclet = ();
52
53 // TODO: remove this variable.
54 static mut RETURN_VALUE_COUNT: usize = 0;
55
56 enum ExtremumOperation {
57     Max,
58     Min,
59 }
60
61 trait EnumClone {
62     fn clone(&self) -> Self;
63 }
64
65 impl EnumClone for AtomicOrdering {
66     fn clone(&self) -> Self {
67         match *self {
68             AtomicOrdering::NotAtomic => AtomicOrdering::NotAtomic,
69             AtomicOrdering::Unordered => AtomicOrdering::Unordered,
70             AtomicOrdering::Monotonic => AtomicOrdering::Monotonic,
71             AtomicOrdering::Acquire => AtomicOrdering::Acquire,
72             AtomicOrdering::Release => AtomicOrdering::Release,
73             AtomicOrdering::AcquireRelease => AtomicOrdering::AcquireRelease,
74             AtomicOrdering::SequentiallyConsistent => AtomicOrdering::SequentiallyConsistent,
75         }
76     }
77 }
78
79 pub struct Builder<'a: 'gcc, 'gcc, 'tcx> {
80     pub cx: &'a CodegenCx<'gcc, 'tcx>,
81     pub block: Option<Block<'gcc>>,
82     stack_var_count: Cell<usize>,
83 }
84
85 impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
86     fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>) -> Self {
87         Builder {
88             cx,
89             block: None,
90             stack_var_count: Cell::new(0),
91         }
92     }
93
94     fn atomic_extremum(&mut self, operation: ExtremumOperation, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> {
95         let size = self.cx.int_width(src.get_type()) / 8;
96
97         let func = self.current_func();
98
99         let load_ordering =
100             match order {
101                 // TODO: does this make sense?
102                 AtomicOrdering::AcquireRelease | AtomicOrdering::Release => AtomicOrdering::Acquire,
103                 _ => order.clone(),
104             };
105         let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering.clone(), Size::from_bytes(size));
106         let previous_var = func.new_local(None, previous_value.get_type(), "previous_value");
107         let return_value = func.new_local(None, previous_value.get_type(), "return_value");
108         self.llbb().add_assignment(None, previous_var, previous_value);
109         self.llbb().add_assignment(None, return_value, previous_var.to_rvalue());
110
111         let while_block = func.new_block("while");
112         let after_block = func.new_block("after_while");
113         self.llbb().end_with_jump(None, while_block);
114
115         // NOTE: since jumps were added and compare_exchange doesn't expect this, the current blocks in the
116         // state need to be updated.
117         self.block = Some(while_block);
118         *self.cx.current_block.borrow_mut() = Some(while_block);
119
120         let comparison_operator =
121             match operation {
122                 ExtremumOperation::Max => ComparisonOp::LessThan,
123                 ExtremumOperation::Min => ComparisonOp::GreaterThan,
124             };
125
126         let cond1 = self.context.new_comparison(None, comparison_operator, previous_var.to_rvalue(), self.context.new_cast(None, src, previous_value.get_type()));
127         let compare_exchange = self.compare_exchange(dst, previous_var, src, order, load_ordering, false);
128         let cond2 = self.cx.context.new_unary_op(None, UnaryOp::LogicalNegate, compare_exchange.get_type(), compare_exchange);
129         let cond = self.cx.context.new_binary_op(None, BinaryOp::LogicalAnd, self.cx.bool_type, cond1, cond2);
130
131         while_block.end_with_conditional(None, cond, while_block, after_block);
132
133         // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the
134         // state need to be updated.
135         self.block = Some(after_block);
136         *self.cx.current_block.borrow_mut() = Some(after_block);
137
138         return_value.to_rvalue()
139     }
140
141     fn compare_exchange(&self, dst: RValue<'gcc>, cmp: LValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> {
142         let size = self.cx.int_width(src.get_type());
143         let compare_exchange = self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size / 8));
144         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
145         let failure_order = self.context.new_rvalue_from_int(self.i32_type, failure_order.to_gcc());
146         let weak = self.context.new_rvalue_from_int(self.bool_type, weak as i32);
147
148         let void_ptr_type = self.context.new_type::<*mut ()>();
149         let volatile_void_ptr_type = void_ptr_type.make_volatile();
150         let dst = self.context.new_cast(None, dst, volatile_void_ptr_type);
151         let expected = self.context.new_cast(None, cmp.get_address(None), void_ptr_type);
152
153         // NOTE: not sure why, but we have the wrong type here.
154         let int_type = compare_exchange.get_param(2).to_rvalue().get_type();
155         let src = self.context.new_cast(None, src, int_type);
156         self.context.new_call(None, compare_exchange, &[dst, expected, src, weak, order, failure_order])
157     }
158
159     pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) {
160         self.llbb().add_assignment(None, lvalue, value);
161     }
162
163     fn check_call<'b>(&mut self, _typ: &str, func: Function<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> {
164         //let mut fn_ty = self.cx.val_ty(func);
165         // Strip off pointers
166         /*while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
167             fn_ty = self.cx.element_type(fn_ty);
168         }*/
169
170         /*assert!(
171             self.cx.type_kind(fn_ty) == TypeKind::Function,
172             "builder::{} not passed a function, but {:?}",
173             typ,
174             fn_ty
175         );
176
177         let param_tys = self.cx.func_params_types(fn_ty);
178
179         let all_args_match = param_tys
180             .iter()
181             .zip(args.iter().map(|&v| self.val_ty(v)))
182             .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);*/
183
184         let mut all_args_match = true;
185         let mut param_types = vec![];
186         let param_count = func.get_param_count();
187         for (index, arg) in args.iter().enumerate().take(param_count) {
188             let param = func.get_param(index as i32);
189             let param = param.to_rvalue().get_type();
190             if param != arg.get_type() {
191                 all_args_match = false;
192             }
193             param_types.push(param);
194         }
195
196         if all_args_match {
197             return Cow::Borrowed(args);
198         }
199
200         let casted_args: Vec<_> = param_types
201             .into_iter()
202             .zip(args.iter())
203             .enumerate()
204             .map(|(_i, (expected_ty, &actual_val))| {
205                 let actual_ty = actual_val.get_type();
206                 if expected_ty != actual_ty {
207                     /*debug!(
208                         "type mismatch in function call of {:?}. \
209                             Expected {:?} for param {}, got {:?}; injecting bitcast",
210                         func, expected_ty, i, actual_ty
211                     );*/
212                     /*println!(
213                         "type mismatch in function call of {:?}. \
214                             Expected {:?} for param {}, got {:?}; injecting bitcast",
215                         func, expected_ty, i, actual_ty
216                     );*/
217                     self.bitcast(actual_val, expected_ty)
218                 }
219                 else {
220                     actual_val
221                 }
222             })
223             .collect();
224
225         Cow::Owned(casted_args)
226     }
227
228     fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> {
229         //let mut fn_ty = self.cx.val_ty(func);
230         // Strip off pointers
231         /*while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
232             fn_ty = self.cx.element_type(fn_ty);
233         }*/
234
235         /*assert!(
236             self.cx.type_kind(fn_ty) == TypeKind::Function,
237             "builder::{} not passed a function, but {:?}",
238             typ,
239             fn_ty
240         );
241
242         let param_tys = self.cx.func_params_types(fn_ty);
243
244         let all_args_match = param_tys
245             .iter()
246             .zip(args.iter().map(|&v| self.val_ty(v)))
247             .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);*/
248
249         let mut all_args_match = true;
250         let mut param_types = vec![];
251         let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr");
252         for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) {
253             let param = gcc_func.get_param_type(index);
254             if param != arg.get_type() {
255                 all_args_match = false;
256             }
257             param_types.push(param);
258         }
259
260         if all_args_match {
261             return Cow::Borrowed(args);
262         }
263
264         let casted_args: Vec<_> = param_types
265             .into_iter()
266             .zip(args.iter())
267             .enumerate()
268             .map(|(_i, (expected_ty, &actual_val))| {
269                 let actual_ty = actual_val.get_type();
270                 if expected_ty != actual_ty {
271                     /*debug!(
272                         "type mismatch in function call of {:?}. \
273                             Expected {:?} for param {}, got {:?}; injecting bitcast",
274                         func, expected_ty, i, actual_ty
275                     );*/
276                     /*println!(
277                         "type mismatch in function call of {:?}. \
278                             Expected {:?} for param {}, got {:?}; injecting bitcast",
279                         func, expected_ty, i, actual_ty
280                     );*/
281                     self.bitcast(actual_val, expected_ty)
282                 }
283                 else {
284                     actual_val
285                 }
286             })
287             .collect();
288
289         Cow::Owned(casted_args)
290     }
291
292     fn check_store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
293         let dest_ptr_ty = self.cx.val_ty(ptr).make_pointer(); // TODO: make sure make_pointer() is okay here.
294         let stored_ty = self.cx.val_ty(val);
295         let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
296
297         //assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
298
299         if dest_ptr_ty == stored_ptr_ty {
300             ptr
301         }
302         else {
303             /*debug!(
304                 "type mismatch in store. \
305                     Expected {:?}, got {:?}; inserting bitcast",
306                 dest_ptr_ty, stored_ptr_ty
307             );*/
308             /*println!(
309                 "type mismatch in store. \
310                     Expected {:?}, got {:?}; inserting bitcast",
311                 dest_ptr_ty, stored_ptr_ty
312             );*/
313             //ptr
314             self.bitcast(ptr, stored_ptr_ty)
315         }
316     }
317
318     pub fn current_func(&self) -> Function<'gcc> {
319         self.block.expect("block").get_function()
320     }
321
322     fn function_call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
323         //debug!("call {:?} with args ({:?})", func, args);
324
325         // TODO: remove when the API supports a different type for functions.
326         let func: Function<'gcc> = self.cx.rvalue_as_function(func);
327         let args = self.check_call("call", func, args);
328         //let bundle = funclet.map(|funclet| funclet.bundle());
329         //let bundle = bundle.as_ref().map(|b| &*b.raw);
330
331         // gccjit requires to use the result of functions, even when it's not used.
332         // That's why we assign the result to a local or call add_eval().
333         let return_type = func.get_return_type();
334         let current_block = self.current_block.borrow().expect("block");
335         let void_type = self.context.new_type::<()>();
336         let current_func = current_block.get_function();
337         if return_type != void_type {
338             unsafe { RETURN_VALUE_COUNT += 1 };
339             let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
340             current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
341             result.to_rvalue()
342         }
343         else {
344             current_block.add_eval(None, self.cx.context.new_call(None, func, &args));
345             // Return dummy value when not having return value.
346             self.context.new_rvalue_from_long(self.isize_type, 0)
347         }
348     }
349
350     fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
351         //debug!("func ptr call {:?} with args ({:?})", func, args);
352
353         let args = self.check_ptr_call("call", func_ptr, args);
354         //let bundle = funclet.map(|funclet| funclet.bundle());
355         //let bundle = bundle.as_ref().map(|b| &*b.raw);
356
357         // gccjit requires to use the result of functions, even when it's not used.
358         // That's why we assign the result to a local or call add_eval().
359         let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr");
360         let mut return_type = gcc_func.get_return_type();
361         let current_block = self.current_block.borrow().expect("block");
362         let void_type = self.context.new_type::<()>();
363         let current_func = current_block.get_function();
364
365         // FIXME: As a temporary workaround for unsupported LLVM intrinsics.
366         if gcc_func.get_param_count() == 0 && format!("{:?}", func_ptr) == "__builtin_ia32_pmovmskb128" {
367             return_type = self.int_type;
368         }
369
370         if return_type != void_type {
371             unsafe { RETURN_VALUE_COUNT += 1 };
372             let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
373             current_block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
374             result.to_rvalue()
375         }
376         else {
377             if gcc_func.get_param_count() == 0 {
378                 // FIXME: As a temporary workaround for unsupported LLVM intrinsics.
379                 current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[]));
380             }
381             else {
382                 current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
383             }
384             // Return dummy value when not having return value.
385             let result = current_func.new_local(None, self.isize_type, "dummyValueThatShouldNeverBeUsed");
386             current_block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0));
387             result.to_rvalue()
388         }
389     }
390
391     pub fn overflow_call(&mut self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
392         //debug!("overflow_call {:?} with args ({:?})", func, args);
393
394         //let bundle = funclet.map(|funclet| funclet.bundle());
395         //let bundle = bundle.as_ref().map(|b| &*b.raw);
396
397         // gccjit requires to use the result of functions, even when it's not used.
398         // That's why we assign the result to a local.
399         let return_type = self.context.new_type::<bool>();
400         let current_block = self.current_block.borrow().expect("block");
401         let current_func = current_block.get_function();
402         // TODO: return the new_call() directly? Since the overflow function has no side-effects.
403         unsafe { RETURN_VALUE_COUNT += 1 };
404         let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
405         current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
406         result.to_rvalue()
407     }
408 }
409
410 impl<'gcc, 'tcx> HasCodegen<'tcx> for Builder<'_, 'gcc, 'tcx> {
411     type CodegenCx = CodegenCx<'gcc, 'tcx>;
412 }
413
414 impl<'tcx> HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
415     fn tcx(&self) -> TyCtxt<'tcx> {
416         self.cx.tcx()
417     }
418 }
419
420 impl HasDataLayout for Builder<'_, '_, '_> {
421     fn data_layout(&self) -> &TargetDataLayout {
422         self.cx.data_layout()
423     }
424 }
425
426 impl<'tcx> LayoutOf for Builder<'_, '_, 'tcx> {
427     type Ty = Ty<'tcx>;
428     type TyAndLayout = TyAndLayout<'tcx>;
429
430     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
431         self.cx.layout_of(ty)
432     }
433 }
434
435 impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> {
436     type Target = CodegenCx<'gcc, 'tcx>;
437
438     fn deref(&self) -> &Self::Target {
439         self.cx
440     }
441 }
442
443 impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
444     type Value = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Value;
445     type Function = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Function;
446     type BasicBlock = <CodegenCx<'gcc, 'tcx> as BackendTypes>::BasicBlock;
447     type Type = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Type;
448     type Funclet = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Funclet;
449
450     type DIScope = <CodegenCx<'gcc, 'tcx> as BackendTypes>::DIScope;
451     type DILocation = <CodegenCx<'gcc, 'tcx> as BackendTypes>::DILocation;
452     type DIVariable = <CodegenCx<'gcc, 'tcx> as BackendTypes>::DIVariable;
453 }
454
455 impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
456     fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
457         let mut bx = Builder::with_cx(cx);
458         *cx.current_block.borrow_mut() = Some(block);
459         bx.block = Some(block);
460         bx
461     }
462
463     fn build_sibling_block(&mut self, name: &str) -> Self {
464         let block = self.append_sibling_block(name);
465         Self::build(self.cx, block)
466     }
467
468     fn llbb(&self) -> Block<'gcc> {
469         self.block.expect("block")
470     }
471
472     fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
473         let func = cx.rvalue_as_function(func);
474         func.new_block(name)
475     }
476
477     fn append_sibling_block(&mut self, name: &str) -> Block<'gcc> {
478         let func = self.current_func();
479         func.new_block(name)
480     }
481
482     fn ret_void(&mut self) {
483         self.llbb().end_with_void_return(None)
484     }
485
486     fn ret(&mut self, value: RValue<'gcc>) {
487         let value =
488             if self.structs_as_pointer.borrow().contains(&value) {
489                 // NOTE: hack to workaround a limitation of the rustc API: see comment on
490                 // CodegenCx.structs_as_pointer
491                 value.dereference(None).to_rvalue()
492             }
493             else {
494                 value
495             };
496         self.llbb().end_with_return(None, value);
497     }
498
499     fn br(&mut self, dest: Block<'gcc>) {
500         self.llbb().end_with_jump(None, dest)
501     }
502
503     fn cond_br(&mut self, cond: RValue<'gcc>, then_block: Block<'gcc>, else_block: Block<'gcc>) {
504         self.llbb().end_with_conditional(None, cond, then_block, else_block)
505     }
506
507     fn switch(&mut self, value: RValue<'gcc>, default_block: Block<'gcc>, cases: impl ExactSizeIterator<Item = (u128, Block<'gcc>)>) {
508         let mut gcc_cases = vec![];
509         let typ = self.val_ty(value);
510         for (on_val, dest) in cases {
511             let on_val = self.const_uint_big(typ, on_val);
512             gcc_cases.push(self.context.new_case(on_val, on_val, dest));
513         }
514         self.block.expect("block").end_with_switch(None, value, default_block, &gcc_cases);
515     }
516
517     fn invoke(&mut self, _func: RValue<'gcc>, _args: &[RValue<'gcc>], _then: Block<'gcc>, _catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
518         unimplemented!();
519         /*debug!("invoke {:?} with args ({:?})", func, args);
520
521         let args = self.check_call("invoke", func, args);
522         let bundle = funclet.map(|funclet| funclet.bundle());
523         let bundle = bundle.as_ref().map(|b| &*b.raw);
524
525         unsafe {
526             llvm::LLVMRustBuildInvoke(
527                 self.llbuilder,
528                 func,
529                 args.as_ptr(),
530                 args.len() as c_uint,
531                 then,
532                 catch,
533                 bundle,
534                 UNNAMED,
535             )
536         }*/
537     }
538
539     fn unreachable(&mut self) {
540         let func = self.context.get_builtin_function("__builtin_unreachable");
541         let block = self.block.expect("block");
542         block.add_eval(None, self.context.new_call(None, func, &[]));
543         let return_type = block.get_function().get_return_type();
544         let void_type = self.context.new_type::<()>();
545         if return_type == void_type {
546             block.end_with_void_return(None)
547         }
548         else {
549             let return_value = self.current_func()
550                 .new_local(None, return_type, "unreachableReturn");
551             block.end_with_return(None, return_value)
552         }
553     }
554
555     fn add(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
556         // FIXME: this should not be required.
557         if format!("{:?}", a.get_type()) != format!("{:?}", b.get_type()) {
558             b = self.context.new_cast(None, b, a.get_type());
559         }
560         a + b
561     }
562
563     fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
564         a + b
565     }
566
567     fn sub(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
568         if a.get_type() != b.get_type() {
569             b = self.context.new_cast(None, b, a.get_type());
570         }
571         a - b
572     }
573
574     fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
575         a - b
576     }
577
578     fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
579         a * b
580     }
581
582     fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
583         a * b
584     }
585
586     fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
587         // TODO: convert the arguments to unsigned?
588         a / b
589     }
590
591     fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
592         // TODO: convert the arguments to unsigned?
593         // TODO: poison if not exact.
594         a / b
595     }
596
597     fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
598         // TODO: convert the arguments to signed?
599         a / b
600     }
601
602     fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
603         // TODO: posion if not exact.
604         // FIXME: rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they
605         // should be the same.
606         let typ = a.get_type().to_signed(self);
607         let a = self.context.new_cast(None, a, typ);
608         let b = self.context.new_cast(None, b, typ);
609         a / b
610     }
611
612     fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
613         a / b
614     }
615
616     fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
617         a % b
618     }
619
620     fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
621         a % b
622     }
623
624     fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
625         if a.get_type() == self.cx.float_type {
626             let fmodf = self.context.get_builtin_function("fmodf");
627             // FIXME: this seems to produce the wrong result.
628             return self.context.new_call(None, fmodf, &[a, b]);
629         }
630         assert_eq!(a.get_type(), self.cx.double_type);
631
632         let fmod = self.context.get_builtin_function("fmod");
633         return self.context.new_call(None, fmod, &[a, b]);
634     }
635
636     fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
637         // FIXME: remove the casts when libgccjit can shift an unsigned number by an unsigned number.
638         let a_type = a.get_type();
639         let b_type = b.get_type();
640         if a_type.is_unsigned(self) && b_type.is_signed(self) {
641             //println!("shl: {:?} -> {:?}", a, b_type);
642             let a = self.context.new_cast(None, a, b_type);
643             let result = a << b;
644             //println!("shl: {:?} -> {:?}", result, a_type);
645             self.context.new_cast(None, result, a_type)
646         }
647         else if a_type.is_signed(self) && b_type.is_unsigned(self) {
648             //println!("shl: {:?} -> {:?}", b, a_type);
649             let b = self.context.new_cast(None, b, a_type);
650             a << b
651         }
652         else {
653             a << b
654         }
655     }
656
657     fn lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
658         // FIXME: remove the casts when libgccjit can shift an unsigned number by an unsigned number.
659         // TODO: cast to unsigned to do a logical shift if that does not work.
660         let a_type = a.get_type();
661         let b_type = b.get_type();
662         if a_type.is_unsigned(self) && b_type.is_signed(self) {
663             //println!("lshl: {:?} -> {:?}", a, b_type);
664             let a = self.context.new_cast(None, a, b_type);
665             let result = a >> b;
666             //println!("lshl: {:?} -> {:?}", result, a_type);
667             self.context.new_cast(None, result, a_type)
668         }
669         else if a_type.is_signed(self) && b_type.is_unsigned(self) {
670             //println!("lshl: {:?} -> {:?}", b, a_type);
671             let b = self.context.new_cast(None, b, a_type);
672             a >> b
673         }
674         else {
675             a >> b
676         }
677     }
678
679     fn ashr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
680         // TODO: check whether behavior is an arithmetic shift for >> .
681         // FIXME: remove the casts when libgccjit can shift an unsigned number by an unsigned number.
682         let a_type = a.get_type();
683         let b_type = b.get_type();
684         if a_type.is_unsigned(self) && b_type.is_signed(self) {
685             //println!("ashl: {:?} -> {:?}", a, b_type);
686             let a = self.context.new_cast(None, a, b_type);
687             let result = a >> b;
688             //println!("ashl: {:?} -> {:?}", result, a_type);
689             self.context.new_cast(None, result, a_type)
690         }
691         else if a_type.is_signed(self) && b_type.is_unsigned(self) {
692             //println!("ashl: {:?} -> {:?}", b, a_type);
693             let b = self.context.new_cast(None, b, a_type);
694             a >> b
695         }
696         else {
697             a >> b
698         }
699     }
700
701     fn and(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
702         // FIXME: hack by putting the result in a variable to workaround this bug:
703         // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498
704         if a.get_type() != b.get_type() {
705             b = self.context.new_cast(None, b, a.get_type());
706         }
707         let res = self.current_func().new_local(None, b.get_type(), "andResult");
708         self.llbb().add_assignment(None, res, a & b);
709         res.to_rvalue()
710     }
711
712     fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
713         // FIXME: hack by putting the result in a variable to workaround this bug:
714         // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498
715         let res = self.current_func().new_local(None, b.get_type(), "orResult");
716         self.llbb().add_assignment(None, res, a | b);
717         res.to_rvalue()
718     }
719
720     fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
721         a ^ b
722     }
723
724     fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
725         // TODO: use new_unary_op()?
726         self.cx.context.new_rvalue_from_long(a.get_type(), 0) - a
727     }
728
729     fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
730         self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
731     }
732
733     fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
734         let operation =
735             if a.get_type().is_bool() {
736                 UnaryOp::LogicalNegate
737             }
738             else {
739                 UnaryOp::BitwiseNegate
740             };
741         self.cx.context.new_unary_op(None, operation, a.get_type(), a)
742     }
743
744     fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
745         a + b
746     }
747
748     fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
749         a + b
750     }
751
752     fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
753         a - b
754     }
755
756     fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
757         // TODO: should generate poison value?
758         a - b
759     }
760
761     fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
762         a * b
763     }
764
765     fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
766         a * b
767     }
768
769     fn fadd_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
770         unimplemented!();
771         /*unsafe {
772             let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED);
773             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
774             instr
775         }*/
776     }
777
778     fn fsub_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
779         unimplemented!();
780         /*unsafe {
781             let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED);
782             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
783             instr
784         }*/
785     }
786
787     fn fmul_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
788         unimplemented!();
789         /*unsafe {
790             let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED);
791             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
792             instr
793         }*/
794     }
795
796     fn fdiv_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
797         unimplemented!();
798         /*unsafe {
799             let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED);
800             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
801             instr
802         }*/
803     }
804
805     fn frem_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
806         unimplemented!();
807         /*unsafe {
808             let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED);
809             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
810             instr
811         }*/
812     }
813
814     fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) {
815         use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*};
816
817         let new_kind =
818             match typ.kind() {
819                 Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
820                 Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
821                 t @ (Uint(_) | Int(_)) => t.clone(),
822                 _ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
823             };
824
825         // TODO: remove duplication with intrinsic?
826         let name =
827             match oop {
828                 OverflowOp::Add =>
829                     match new_kind {
830                         Int(I8) => "__builtin_add_overflow",
831                         Int(I16) => "__builtin_add_overflow",
832                         Int(I32) => "__builtin_sadd_overflow",
833                         Int(I64) => "__builtin_saddll_overflow",
834                         Int(I128) => "__builtin_add_overflow",
835
836                         Uint(U8) => "__builtin_add_overflow",
837                         Uint(U16) => "__builtin_add_overflow",
838                         Uint(U32) => "__builtin_uadd_overflow",
839                         Uint(U64) => "__builtin_uaddll_overflow",
840                         Uint(U128) => "__builtin_add_overflow",
841
842                         _ => unreachable!(),
843                     },
844                 OverflowOp::Sub =>
845                     match new_kind {
846                         Int(I8) => "__builtin_sub_overflow",
847                         Int(I16) => "__builtin_sub_overflow",
848                         Int(I32) => "__builtin_ssub_overflow",
849                         Int(I64) => "__builtin_ssubll_overflow",
850                         Int(I128) => "__builtin_sub_overflow",
851
852                         Uint(U8) => "__builtin_sub_overflow",
853                         Uint(U16) => "__builtin_sub_overflow",
854                         Uint(U32) => "__builtin_usub_overflow",
855                         Uint(U64) => "__builtin_usubll_overflow",
856                         Uint(U128) => "__builtin_sub_overflow",
857
858                         _ => unreachable!(),
859                     },
860                 OverflowOp::Mul =>
861                     match new_kind {
862                         Int(I8) => "__builtin_mul_overflow",
863                         Int(I16) => "__builtin_mul_overflow",
864                         Int(I32) => "__builtin_smul_overflow",
865                         Int(I64) => "__builtin_smulll_overflow",
866                         Int(I128) => "__builtin_mul_overflow",
867
868                         Uint(U8) => "__builtin_mul_overflow",
869                         Uint(U16) => "__builtin_mul_overflow",
870                         Uint(U32) => "__builtin_umul_overflow",
871                         Uint(U64) => "__builtin_umulll_overflow",
872                         Uint(U128) => "__builtin_mul_overflow",
873
874                         _ => unreachable!(),
875                     },
876             };
877
878         let intrinsic = self.context.get_builtin_function(&name);
879         let res = self.current_func()
880             // TODO: is it correct to use rhs type instead of the parameter typ?
881             .new_local(None, rhs.get_type(), "binopResult")
882             .get_address(None);
883         let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None);
884         (res.dereference(None).to_rvalue(), overflow)
885     }
886
887     fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> {
888         // FIXME: this check that we don't call get_aligned() a second time on a time.
889         // Ideally, we shouldn't need to do this check.
890         let aligned_type =
891             if ty == self.cx.u128_type || ty == self.cx.i128_type {
892                 ty
893             }
894             else {
895                 ty.get_aligned(align.bytes())
896             };
897         // TODO: It might be better to return a LValue, but fixing the rustc API is non-trivial.
898         self.stack_var_count.set(self.stack_var_count.get() + 1);
899         self.current_func().new_local(None, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None)
900     }
901
902     fn dynamic_alloca(&mut self, _ty: Type<'gcc>, _align: Align) -> RValue<'gcc> {
903         unimplemented!();
904         /*unsafe {
905             let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED);
906             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
907             alloca
908         }*/
909     }
910
911     fn array_alloca(&mut self, _ty: Type<'gcc>, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
912         unimplemented!();
913         /*unsafe {
914             let alloca = llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED);
915             llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
916             alloca
917         }*/
918     }
919
920     fn load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
921         // TODO: use ty.
922         let block = self.llbb();
923         let function = block.get_function();
924         // NOTE: instead of returning the dereference here, we have to assign it to a variable in
925         // the current basic block. Otherwise, it could be used in another basic block, causing a
926         // dereference after a drop, for instance.
927         // TODO: handle align.
928         let deref = ptr.dereference(None).to_rvalue();
929         let value_type = deref.get_type();
930         unsafe { RETURN_VALUE_COUNT += 1 };
931         let loaded_value = function.new_local(None, value_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
932         block.add_assignment(None, loaded_value, deref);
933         loaded_value.to_rvalue()
934     }
935
936     fn volatile_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
937         // TODO: use ty.
938         //println!("5: volatile load: {:?} to {:?}", ptr, ptr.get_type().make_volatile());
939         let ptr = self.context.new_cast(None, ptr, ptr.get_type().make_volatile());
940         //println!("6");
941         ptr.dereference(None).to_rvalue()
942     }
943
944     fn atomic_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, size: Size) -> RValue<'gcc> {
945         // TODO: use ty.
946         // TODO: handle alignment.
947         let atomic_load = self.context.get_builtin_function(&format!("__atomic_load_{}", size.bytes()));
948         let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
949
950         let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile();
951         let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type);
952         self.context.new_call(None, atomic_load, &[ptr, ordering])
953     }
954
955     fn load_operand(&mut self, place: PlaceRef<'tcx, RValue<'gcc>>) -> OperandRef<'tcx, RValue<'gcc>> {
956         //debug!("PlaceRef::load: {:?}", place);
957
958         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
959
960         if place.layout.is_zst() {
961             return OperandRef::new_zst(self, place.layout);
962         }
963
964         fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) {
965             let vr = scalar.valid_range.clone();
966             match scalar.value {
967                 abi::Int(..) => {
968                     let range = scalar.valid_range_exclusive(bx);
969                     if range.start != range.end {
970                         bx.range_metadata(load, range);
971                     }
972                 }
973                 abi::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
974                     bx.nonnull_metadata(load);
975                 }
976                 _ => {}
977             }
978         }
979
980         let val =
981             if let Some(llextra) = place.llextra {
982                 OperandValue::Ref(place.llval, Some(llextra), place.align)
983             }
984             else if place.layout.is_gcc_immediate() {
985                 let const_llval = None;
986                 /*unsafe {
987                     if let Some(global) = llvm::LLVMIsAGlobalVariable(place.llval) {
988                         if llvm::LLVMIsGlobalConstant(global) == llvm::True {
989                             const_llval = llvm::LLVMGetInitializer(global);
990                         }
991                     }
992                 }*/
993                 let llval = const_llval.unwrap_or_else(|| {
994                     let load = self.load(place.llval.get_type(), place.llval, place.align);
995                     if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
996                         scalar_load_metadata(self, load, scalar);
997                     }
998                     load
999                 });
1000                 OperandValue::Immediate(self.to_immediate(llval, place.layout))
1001             }
1002             else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
1003                 let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
1004
1005                 let mut load = |i, scalar: &abi::Scalar, align| {
1006                     let llptr = self.struct_gep(place.llval, i as u64);
1007                     let load = self.load(llptr.get_type(), llptr, align);
1008                     scalar_load_metadata(self, load, scalar);
1009                     if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
1010                 };
1011
1012                 OperandValue::Pair(
1013                     load(0, a, place.align),
1014                     load(1, b, place.align.restrict_for_offset(b_offset)),
1015                 )
1016             }
1017             else {
1018                 OperandValue::Ref(place.llval, None, place.align)
1019             };
1020
1021         OperandRef { val, layout: place.layout }
1022     }
1023
1024     fn write_operand_repeatedly(mut self, cg_elem: OperandRef<'tcx, RValue<'gcc>>, count: u64, dest: PlaceRef<'tcx, RValue<'gcc>>) -> Self {
1025         let zero = self.const_usize(0);
1026         let count = self.const_usize(count);
1027         let start = dest.project_index(&mut self, zero).llval;
1028         let end = dest.project_index(&mut self, count).llval;
1029
1030         let mut header_bx = self.build_sibling_block("repeat_loop_header");
1031         let mut body_bx = self.build_sibling_block("repeat_loop_body");
1032         let next_bx = self.build_sibling_block("repeat_loop_next");
1033
1034         let ptr_type = start.get_type();
1035         let current = self.llbb().get_function().new_local(None, ptr_type, "loop_var");
1036         let current_val = current.to_rvalue();
1037         self.assign(current, start);
1038
1039         self.br(header_bx.llbb());
1040
1041         let keep_going = header_bx.icmp(IntPredicate::IntNE, current_val, end);
1042         header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
1043
1044         let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
1045         cg_elem.val.store(&mut body_bx, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align));
1046
1047         let next = body_bx.inbounds_gep(current.to_rvalue(), &[self.const_usize(1)]);
1048         body_bx.llbb().add_assignment(None, current, next);
1049         body_bx.br(header_bx.llbb());
1050
1051         next_bx
1052     }
1053
1054     fn range_metadata(&mut self, _load: RValue<'gcc>, _range: Range<u128>) {
1055         // TODO
1056         /*if self.sess().target.target.arch == "amdgpu" {
1057             // amdgpu/LLVM does something weird and thinks a i64 value is
1058             // split into a v2i32, halving the bitwidth LLVM expects,
1059             // tripping an assertion. So, for now, just disable this
1060             // optimization.
1061             return;
1062         }
1063
1064         unsafe {
1065             let llty = self.cx.val_ty(load);
1066             let v = [
1067                 self.cx.const_uint_big(llty, range.start),
1068                 self.cx.const_uint_big(llty, range.end),
1069             ];
1070
1071             llvm::LLVMSetMetadata(
1072                 load,
1073                 llvm::MD_range as c_uint,
1074                 llvm::LLVMMDNodeInContext(self.cx.llcx, v.as_ptr(), v.len() as c_uint),
1075             );
1076         }*/
1077     }
1078
1079     fn nonnull_metadata(&mut self, _load: RValue<'gcc>) {
1080         // TODO
1081         /*unsafe {
1082             llvm::LLVMSetMetadata(
1083                 load,
1084                 llvm::MD_nonnull as c_uint,
1085                 llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0),
1086             );
1087         }*/
1088     }
1089
1090     fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
1091         self.store_with_flags(val, ptr, align, MemFlags::empty())
1092     }
1093
1094     fn store_with_flags(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, _align: Align, _flags: MemFlags) -> RValue<'gcc> {
1095         //debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
1096         let ptr = self.check_store(val, ptr);
1097         self.llbb().add_assignment(None, ptr.dereference(None), val);
1098         /*let align =
1099             if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() as c_uint };
1100         llvm::LLVMSetAlignment(store, align);
1101         if flags.contains(MemFlags::VOLATILE) {
1102             llvm::LLVMSetVolatile(store, llvm::True);
1103         }
1104         if flags.contains(MemFlags::NONTEMPORAL) {
1105             // According to LLVM [1] building a nontemporal store must
1106             // *always* point to a metadata value of the integer 1.
1107             //
1108             // [1]: http://llvm.org/docs/LangRef.html#store-instruction
1109             let one = self.cx.const_i32(1);
1110             let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
1111             llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
1112         }*/
1113         // NOTE: dummy value here since it's never used. FIXME: API should not return a value here?
1114         self.cx.context.new_rvalue_zero(self.type_i32())
1115     }
1116
1117     fn atomic_store(&mut self, value: RValue<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, size: Size) {
1118         // TODO: handle alignment.
1119         let atomic_store = self.context.get_builtin_function(&format!("__atomic_store_{}", size.bytes()));
1120         let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
1121         let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile();
1122         let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type);
1123
1124         // FIXME: fix libgccjit to allow comparing an integer type with an aligned integer type because
1125         // the following cast is required to avoid this error:
1126         // gcc_jit_context_new_call: mismatching types for argument 2 of function "__atomic_store_4": assignment to param arg1 (type: int) from loadedValue3577 (type: unsigned int  __attribute__((aligned(4))))
1127         let int_type = atomic_store.get_param(1).to_rvalue().get_type();
1128         let value = self.context.new_cast(None, value, int_type);
1129         self.llbb()
1130             .add_eval(None, self.context.new_call(None, atomic_store, &[ptr, value, ordering]));
1131     }
1132
1133     fn gep(&mut self, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
1134         let mut result = ptr;
1135         for index in indices {
1136             result = self.context.new_array_access(None, result, *index).get_address(None).to_rvalue();
1137         }
1138         result
1139     }
1140
1141     fn inbounds_gep(&mut self, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
1142         // FIXME: would be safer if doing the same thing (loop) as gep.
1143         // TODO: specify inbounds somehow.
1144         match indices.len() {
1145             1 => {
1146                 self.context.new_array_access(None, ptr, indices[0]).get_address(None)
1147             },
1148             2 => {
1149                 let array = ptr.dereference(None); // TODO: assert that first index is 0?
1150                 self.context.new_array_access(None, array, indices[1]).get_address(None)
1151             },
1152             _ => unimplemented!(),
1153         }
1154     }
1155
1156     fn struct_gep(&mut self, ptr: RValue<'gcc>, idx: u64) -> RValue<'gcc> {
1157         // FIXME: it would be better if the API only called this on struct, not on arrays.
1158         assert_eq!(idx as usize as u64, idx);
1159         let value = ptr.dereference(None).to_rvalue();
1160         let value_type = value.get_type();
1161
1162         if value_type.is_array().is_some() {
1163             let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
1164             let element = self.context.new_array_access(None, value, index);
1165             element.get_address(None)
1166         }
1167         else if let Some(vector_type) = value_type.is_vector() {
1168             let array_type = vector_type.get_element_type().make_pointer();
1169             let array = self.bitcast(ptr, array_type);
1170             let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
1171             let element = self.context.new_array_access(None, array, index);
1172             element.get_address(None)
1173         }
1174         else if let Some(struct_type) = value_type.is_struct() {
1175             ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None)
1176         }
1177         else {
1178             panic!("Unexpected type {:?}", value_type);
1179         }
1180     }
1181
1182     /* Casts */
1183     fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1184         // TODO: check that it indeed truncate the value.
1185         //println!("trunc: {:?} -> {:?}", value, dest_ty);
1186         self.context.new_cast(None, value, dest_ty)
1187     }
1188
1189     fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1190         // TODO: check that it indeed sign extend the value.
1191         //println!("Sext {:?} to {:?}", value, dest_ty);
1192         //if let Some(vector_type) = value.get_type().is_vector() {
1193         if dest_ty.is_vector().is_some() {
1194             // TODO: nothing to do as it is only for LLVM?
1195             return value;
1196             /*let dest_type = self.context.new_vector_type(dest_ty, vector_type.get_num_units() as u64);
1197             println!("Casting {:?} to {:?}", value, dest_type);
1198             return self.context.new_cast(None, value, dest_type);*/
1199         }
1200         self.context.new_cast(None, value, dest_ty)
1201     }
1202
1203     fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1204         //println!("7: fptoui: {:?} to {:?}", value, dest_ty);
1205         let ret = self.context.new_cast(None, value, dest_ty);
1206         //println!("8");
1207         ret
1208         //unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED) }
1209     }
1210
1211     fn fptosi(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1212         self.context.new_cast(None, value, dest_ty)
1213     }
1214
1215     fn uitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1216         //println!("1: uitofp: {:?} -> {:?}", value, dest_ty);
1217         let ret = self.context.new_cast(None, value, dest_ty);
1218         //println!("2");
1219         ret
1220     }
1221
1222     fn sitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1223         //println!("3: sitofp: {:?} -> {:?}", value, dest_ty);
1224         let ret = self.context.new_cast(None, value, dest_ty);
1225         //println!("4");
1226         ret
1227     }
1228
1229     fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1230         // TODO: make sure it trancates.
1231         self.context.new_cast(None, value, dest_ty)
1232     }
1233
1234     fn fpext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1235         self.context.new_cast(None, value, dest_ty)
1236     }
1237
1238     fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1239         self.cx.ptrtoint(self.block.expect("block"), value, dest_ty)
1240     }
1241
1242     fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1243         self.cx.inttoptr(self.block.expect("block"), value, dest_ty)
1244     }
1245
1246     fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1247         self.cx.const_bitcast(value, dest_ty)
1248     }
1249
1250     fn intcast(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>, _is_signed: bool) -> RValue<'gcc> {
1251         // NOTE: is_signed is for value, not dest_typ.
1252         //println!("intcast: {:?} ({:?}) -> {:?}", value, value.get_type(), dest_typ);
1253         self.cx.context.new_cast(None, value, dest_typ)
1254     }
1255
1256     fn pointercast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
1257         //println!("pointercast: {:?} ({:?}) -> {:?}", value, value.get_type(), dest_ty);
1258         let val_type = value.get_type();
1259         match (type_is_pointer(val_type), type_is_pointer(dest_ty)) {
1260             (false, true) => {
1261                 // NOTE: Projecting a field of a pointer type will attemp a cast from a signed char to
1262                 // a pointer, which is not supported by gccjit.
1263                 return self.cx.context.new_cast(None, self.inttoptr(value, val_type.make_pointer()), dest_ty);
1264             },
1265             (false, false) => {
1266                 // When they are not pointers, we want a transmute (or reinterpret_cast).
1267                 //self.cx.context.new_cast(None, value, dest_ty)
1268                 self.bitcast(value, dest_ty)
1269             },
1270             (true, true) => self.cx.context.new_cast(None, value, dest_ty),
1271             (true, false) => unimplemented!(),
1272         }
1273     }
1274
1275     /* Comparisons */
1276     fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
1277         if lhs.get_type() != rhs.get_type() {
1278             // NOTE: hack because we try to cast a vector type to the same vector type.
1279             if format!("{:?}", lhs.get_type()) != format!("{:?}", rhs.get_type()) {
1280                 rhs = self.context.new_cast(None, rhs, lhs.get_type());
1281             }
1282         }
1283         self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
1284     }
1285
1286     fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
1287         self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
1288     }
1289
1290     /* Miscellaneous instructions */
1291     fn memcpy(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
1292         if flags.contains(MemFlags::NONTEMPORAL) {
1293             // HACK(nox): This is inefficient but there is no nontemporal memcpy.
1294             let val = self.load(src.get_type(), src, src_align);
1295             let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
1296             self.store_with_flags(val, ptr, dst_align, flags);
1297             return;
1298         }
1299         let size = self.intcast(size, self.type_size_t(), false);
1300         let _is_volatile = flags.contains(MemFlags::VOLATILE);
1301         let dst = self.pointercast(dst, self.type_i8p());
1302         let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
1303         let memcpy = self.context.get_builtin_function("memcpy");
1304         let block = self.block.expect("block");
1305         // TODO: handle aligns and is_volatile.
1306         block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
1307     }
1308
1309     fn memmove(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
1310         if flags.contains(MemFlags::NONTEMPORAL) {
1311             // HACK(nox): This is inefficient but there is no nontemporal memmove.
1312             let val = self.load(src.get_type(), src, src_align);
1313             let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
1314             self.store_with_flags(val, ptr, dst_align, flags);
1315             return;
1316         }
1317         let size = self.intcast(size, self.type_size_t(), false);
1318         let _is_volatile = flags.contains(MemFlags::VOLATILE);
1319         let dst = self.pointercast(dst, self.type_i8p());
1320         let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
1321
1322         let memmove = self.context.get_builtin_function("memmove");
1323         let block = self.block.expect("block");
1324         // TODO: handle is_volatile.
1325         block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size]));
1326     }
1327
1328     fn memset(&mut self, ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, _align: Align, flags: MemFlags) {
1329         let _is_volatile = flags.contains(MemFlags::VOLATILE);
1330         let ptr = self.pointercast(ptr, self.type_i8p());
1331         let memset = self.context.get_builtin_function("memset");
1332         let block = self.block.expect("block");
1333         // TODO: handle aligns and is_volatile.
1334         //println!("memset: {:?} -> {:?}", fill_byte, self.i32_type);
1335         let fill_byte = self.context.new_cast(None, fill_byte, self.i32_type);
1336         let size = self.intcast(size, self.type_size_t(), false);
1337         block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size]));
1338     }
1339
1340     fn select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, mut else_val: RValue<'gcc>) -> RValue<'gcc> {
1341         let func = self.current_func();
1342         let variable = func.new_local(None, then_val.get_type(), "selectVar");
1343         let then_block = func.new_block("then");
1344         let else_block = func.new_block("else");
1345         let after_block = func.new_block("after");
1346         self.llbb().end_with_conditional(None, cond, then_block, else_block);
1347
1348         then_block.add_assignment(None, variable, then_val);
1349         then_block.end_with_jump(None, after_block);
1350
1351         if then_val.get_type() != else_val.get_type() {
1352             else_val = self.context.new_cast(None, else_val, then_val.get_type());
1353         }
1354         else_block.add_assignment(None, variable, else_val);
1355         else_block.end_with_jump(None, after_block);
1356
1357         // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the
1358         // state need to be updated.
1359         self.block = Some(after_block);
1360         *self.cx.current_block.borrow_mut() = Some(after_block);
1361
1362         variable.to_rvalue()
1363     }
1364
1365     #[allow(dead_code)]
1366     fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> {
1367         unimplemented!();
1368         //unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
1369     }
1370
1371     fn extract_element(&mut self, _vec: RValue<'gcc>, _idx: RValue<'gcc>) -> RValue<'gcc> {
1372         unimplemented!();
1373         //unsafe { llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, UNNAMED) }
1374     }
1375
1376     fn vector_splat(&mut self, _num_elts: usize, _elt: RValue<'gcc>) -> RValue<'gcc> {
1377         unimplemented!();
1378         /*unsafe {
1379             let elt_ty = self.cx.val_ty(elt);
1380             let undef = llvm::LLVMGetUndef(self.type_vector(elt_ty, num_elts as u64));
1381             let vec = self.insert_element(undef, elt, self.cx.const_i32(0));
1382             let vec_i32_ty = self.type_vector(self.type_i32(), num_elts as u64);
1383             self.shuffle_vector(vec, undef, self.const_null(vec_i32_ty))
1384         }*/
1385     }
1386
1387     fn extract_value(&mut self, aggregate_value: RValue<'gcc>, idx: u64) -> RValue<'gcc> {
1388         // FIXME: it would be better if the API only called this on struct, not on arrays.
1389         assert_eq!(idx as usize as u64, idx);
1390         let value_type = aggregate_value.get_type();
1391
1392         if value_type.is_array().is_some() {
1393             let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
1394             let element = self.context.new_array_access(None, aggregate_value, index);
1395             element.get_address(None)
1396         }
1397         else if value_type.is_vector().is_some() {
1398             panic!();
1399         }
1400         else if let Some(pointer_type) = value_type.get_pointee() {
1401             if let Some(struct_type) = pointer_type.is_struct() {
1402                 // NOTE: hack to workaround a limitation of the rustc API: see comment on
1403                 // CodegenCx.structs_as_pointer
1404                 aggregate_value.dereference_field(None, struct_type.get_field(idx as i32)).to_rvalue()
1405             }
1406             else {
1407                 panic!("Unexpected type {:?}", value_type);
1408             }
1409         }
1410         else if let Some(struct_type) = value_type.is_struct() {
1411             aggregate_value.access_field(None, struct_type.get_field(idx as i32)).to_rvalue()
1412         }
1413         else {
1414             panic!("Unexpected type {:?}", value_type);
1415         }
1416         /*assert_eq!(idx as c_uint as u64, idx);
1417         unsafe { llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, UNNAMED) }*/
1418     }
1419
1420     fn insert_value(&mut self, aggregate_value: RValue<'gcc>, value: RValue<'gcc>, idx: u64) -> RValue<'gcc> {
1421         // FIXME: it would be better if the API only called this on struct, not on arrays.
1422         assert_eq!(idx as usize as u64, idx);
1423         let value_type = aggregate_value.get_type();
1424
1425         let lvalue =
1426             if value_type.is_array().is_some() {
1427                 let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
1428                 self.context.new_array_access(None, aggregate_value, index)
1429             }
1430             else if value_type.is_vector().is_some() {
1431                 panic!();
1432             }
1433             else if let Some(pointer_type) = value_type.get_pointee() {
1434                 if let Some(struct_type) = pointer_type.is_struct() {
1435                     // NOTE: hack to workaround a limitation of the rustc API: see comment on
1436                     // CodegenCx.structs_as_pointer
1437                     aggregate_value.dereference_field(None, struct_type.get_field(idx as i32))
1438                 }
1439                 else {
1440                     panic!("Unexpected type {:?}", value_type);
1441                 }
1442             }
1443             else {
1444                 panic!("Unexpected type {:?}", value_type);
1445             };
1446         self.llbb().add_assignment(None, lvalue, value);
1447
1448         aggregate_value
1449     }
1450
1451     fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: usize) -> RValue<'gcc> {
1452         unimplemented!();
1453         /*unsafe {
1454             llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, num_clauses as c_uint, UNNAMED)
1455         }*/
1456     }
1457
1458     fn set_cleanup(&mut self, _landing_pad: RValue<'gcc>) {
1459         unimplemented!();
1460         /*unsafe {
1461             llvm::LLVMSetCleanup(landing_pad, llvm::True);
1462         }*/
1463     }
1464
1465     fn resume(&mut self, _exn: RValue<'gcc>) -> RValue<'gcc> {
1466         unimplemented!();
1467         //unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) }
1468     }
1469
1470     fn cleanup_pad(&mut self, _parent: Option<RValue<'gcc>>, _args: &[RValue<'gcc>]) -> Funclet {
1471         unimplemented!();
1472         /*let name = const_cstr!("cleanuppad");
1473         let ret = unsafe {
1474             llvm::LLVMRustBuildCleanupPad(
1475                 self.llbuilder,
1476                 parent,
1477                 args.len() as c_uint,
1478                 args.as_ptr(),
1479                 name.as_ptr(),
1480             )
1481         };
1482         Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))*/
1483     }
1484
1485     fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option<Block<'gcc>>) -> RValue<'gcc> {
1486         unimplemented!();
1487         /*let ret =
1488             unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) };
1489         ret.expect("LLVM does not have support for cleanupret")*/
1490     }
1491
1492     fn catch_pad(&mut self, _parent: RValue<'gcc>, _args: &[RValue<'gcc>]) -> Funclet {
1493         unimplemented!();
1494         /*let name = const_cstr!("catchpad");
1495         let ret = unsafe {
1496             llvm::LLVMRustBuildCatchPad(
1497                 self.llbuilder,
1498                 parent,
1499                 args.len() as c_uint,
1500                 args.as_ptr(),
1501                 name.as_ptr(),
1502             )
1503         };
1504         Funclet::new(ret.expect("LLVM does not have support for catchpad"))*/
1505     }
1506
1507     fn catch_switch(&mut self, _parent: Option<RValue<'gcc>>, _unwind: Option<Block<'gcc>>, _num_handlers: usize) -> RValue<'gcc> {
1508         unimplemented!();
1509         /*let name = const_cstr!("catchswitch");
1510         let ret = unsafe {
1511             llvm::LLVMRustBuildCatchSwitch(
1512                 self.llbuilder,
1513                 parent,
1514                 unwind,
1515                 num_handlers as c_uint,
1516                 name.as_ptr(),
1517             )
1518         };
1519         ret.expect("LLVM does not have support for catchswitch")*/
1520     }
1521
1522     fn add_handler(&mut self, _catch_switch: RValue<'gcc>, _handler: Block<'gcc>) {
1523         unimplemented!();
1524         /*unsafe {
1525             llvm::LLVMRustAddHandler(catch_switch, handler);
1526         }*/
1527     }
1528
1529     fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
1530         unimplemented!();
1531         /*unsafe {
1532             llvm::LLVMSetPersonalityFn(self.llfn(), personality);
1533         }*/
1534     }
1535
1536     // Atomic Operations
1537     fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> {
1538         let expected = self.current_func().new_local(None, cmp.get_type(), "expected");
1539         self.llbb().add_assignment(None, expected, cmp);
1540         let success = self.compare_exchange(dst, expected, src, order, failure_order, weak);
1541
1542         let pair_type = self.cx.type_struct(&[src.get_type(), self.bool_type], false);
1543         let result = self.current_func().new_local(None, pair_type, "atomic_cmpxchg_result");
1544         let align = Align::from_bits(64).expect("align"); // TODO: use good align.
1545
1546         let value_type = result.to_rvalue().get_type();
1547         if let Some(struct_type) = value_type.is_struct() {
1548             self.store(success, result.access_field(None, struct_type.get_field(1)).get_address(None), align);
1549             // NOTE: since success contains the call to the intrinsic, it must be stored before
1550             // expected so that we store expected after the call.
1551             self.store(expected.to_rvalue(), result.access_field(None, struct_type.get_field(0)).get_address(None), align);
1552         }
1553         // TODO: handle when value is not a struct.
1554
1555         result.to_rvalue()
1556     }
1557
1558     fn atomic_rmw(&mut self, op: AtomicRmwBinOp, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> {
1559         let size = self.cx.int_width(src.get_type()) / 8;
1560         let name =
1561             match op {
1562                 AtomicRmwBinOp::AtomicXchg => format!("__atomic_exchange_{}", size),
1563                 AtomicRmwBinOp::AtomicAdd => format!("__atomic_fetch_add_{}", size),
1564                 AtomicRmwBinOp::AtomicSub => format!("__atomic_fetch_sub_{}", size),
1565                 AtomicRmwBinOp::AtomicAnd => format!("__atomic_fetch_and_{}", size),
1566                 AtomicRmwBinOp::AtomicNand => format!("__atomic_fetch_nand_{}", size),
1567                 AtomicRmwBinOp::AtomicOr => format!("__atomic_fetch_or_{}", size),
1568                 AtomicRmwBinOp::AtomicXor => format!("__atomic_fetch_xor_{}", size),
1569                 AtomicRmwBinOp::AtomicMax => return self.atomic_extremum(ExtremumOperation::Max, dst, src, order),
1570                 AtomicRmwBinOp::AtomicMin => return self.atomic_extremum(ExtremumOperation::Min, dst, src, order),
1571                 AtomicRmwBinOp::AtomicUMax => return self.atomic_extremum(ExtremumOperation::Max, dst, src, order),
1572                 AtomicRmwBinOp::AtomicUMin => return self.atomic_extremum(ExtremumOperation::Min, dst, src, order),
1573             };
1574
1575
1576         let atomic_function = self.context.get_builtin_function(name);
1577         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
1578
1579         let void_ptr_type = self.context.new_type::<*mut ()>();
1580         let volatile_void_ptr_type = void_ptr_type.make_volatile();
1581         let dst = self.context.new_cast(None, dst, volatile_void_ptr_type);
1582         // NOTE: not sure why, but we have the wrong type here.
1583         let new_src_type = atomic_function.get_param(1).to_rvalue().get_type();
1584         let src = self.context.new_cast(None, src, new_src_type);
1585         let res = self.context.new_call(None, atomic_function, &[dst, src, order]);
1586         self.context.new_cast(None, res, src.get_type())
1587     }
1588
1589     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) {
1590         let name =
1591             match scope {
1592                 SynchronizationScope::SingleThread => "__atomic_signal_fence",
1593                 SynchronizationScope::CrossThread => "__atomic_thread_fence",
1594             };
1595         let thread_fence = self.context.get_builtin_function(name);
1596         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
1597         self.llbb().add_eval(None, self.context.new_call(None, thread_fence, &[order]));
1598     }
1599
1600     fn set_invariant_load(&mut self, load: RValue<'gcc>) {
1601         // NOTE: Hack to consider vtable function pointer as non-global-variable function pointer.
1602         self.normal_function_addresses.borrow_mut().insert(load);
1603         // TODO
1604         /*unsafe {
1605             llvm::LLVMSetMetadata(
1606                 load,
1607                 llvm::MD_invariant_load as c_uint,
1608                 llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0),
1609             );
1610         }*/
1611     }
1612
1613     fn lifetime_start(&mut self, _ptr: RValue<'gcc>, _size: Size) {
1614         // TODO
1615         //self.call_lifetime_intrinsic("llvm.lifetime.start.p0i8", ptr, size);
1616     }
1617
1618     fn lifetime_end(&mut self, _ptr: RValue<'gcc>, _size: Size) {
1619         // TODO
1620         //self.call_lifetime_intrinsic("llvm.lifetime.end.p0i8", ptr, size);
1621     }
1622
1623     fn call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], funclet: Option<&Funclet>) -> RValue<'gcc> {
1624         // FIXME: remove when having a proper API.
1625         let gcc_func = unsafe { std::mem::transmute(func) };
1626         if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() {
1627             self.function_call(func, args, funclet)
1628         }
1629         else {
1630             // If it's a not function that was defined, it's a function pointer.
1631             self.function_ptr_call(func, args, funclet)
1632         }
1633     }
1634
1635     fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
1636         // FIXME: this does not zero-extend.
1637         if value.get_type().is_bool() && dest_typ.is_i8(&self.cx) {
1638             // FIXME: hack because base::from_immediate converts i1 to i8.
1639             // Fix the code in codegen_ssa::base::from_immediate.
1640             return value;
1641         }
1642         //println!("zext: {:?} -> {:?}", value, dest_typ);
1643         self.context.new_cast(None, value, dest_typ)
1644     }
1645
1646     fn cx(&self) -> &CodegenCx<'gcc, 'tcx> {
1647         self.cx
1648     }
1649
1650     fn do_not_inline(&mut self, _llret: RValue<'gcc>) {
1651         unimplemented!();
1652         //llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret);
1653     }
1654
1655     fn set_span(&mut self, _span: Span) {}
1656
1657     fn from_immediate(&mut self, val: Self::Value) -> Self::Value {
1658         if self.cx().val_ty(val) == self.cx().type_i1() {
1659             self.zext(val, self.cx().type_i8())
1660         }
1661         else {
1662             val
1663         }
1664     }
1665
1666     fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &abi::Scalar) -> Self::Value {
1667         if scalar.is_bool() {
1668             return self.trunc(val, self.cx().type_i1());
1669         }
1670         val
1671     }
1672
1673     fn fptoui_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option<RValue<'gcc>> {
1674         None
1675     }
1676
1677     fn fptosi_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option<RValue<'gcc>> {
1678         None
1679     }
1680
1681     fn instrprof_increment(&mut self, _fn_name: RValue<'gcc>, _hash: RValue<'gcc>, _num_counters: RValue<'gcc>, _index: RValue<'gcc>) {
1682         unimplemented!();
1683         /*debug!(
1684             "instrprof_increment() with args ({:?}, {:?}, {:?}, {:?})",
1685             fn_name, hash, num_counters, index
1686         );
1687
1688         let llfn = unsafe { llvm::LLVMRustGetInstrProfIncrementIntrinsic(self.cx().llmod) };
1689         let args = &[fn_name, hash, num_counters, index];
1690         let args = self.check_call("call", llfn, args);
1691
1692         unsafe {
1693             let _ = llvm::LLVMRustBuildCall(
1694                 self.llbuilder,
1695                 llfn,
1696                 args.as_ptr() as *const &llvm::Value,
1697                 args.len() as c_uint,
1698                 None,
1699             );
1700         }*/
1701     }
1702 }
1703
1704 impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
1705     pub fn shuffle_vector(&mut self, v1: RValue<'gcc>, v2: RValue<'gcc>, mask: RValue<'gcc>) -> RValue<'gcc> {
1706         let return_type = v1.get_type();
1707         let params = [
1708             self.context.new_parameter(None, return_type, "v1"),
1709             self.context.new_parameter(None, return_type, "v2"),
1710             self.context.new_parameter(None, mask.get_type(), "mask"),
1711         ];
1712         let shuffle = self.context.new_function(None, FunctionType::Extern, return_type, &params, "_mm_shuffle_epi8", false);
1713         self.context.new_call(None, shuffle, &[v1, v2, mask])
1714     }
1715 }
1716
1717 impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> {
1718     fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> {
1719         // Forward to the `get_static` method of `CodegenCx`
1720         self.cx().get_static(def_id)
1721     }
1722 }
1723
1724 impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
1725     fn param_env(&self) -> ParamEnv<'tcx> {
1726         self.cx.param_env()
1727     }
1728 }
1729
1730 impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> {
1731     fn target_spec(&self) -> &Target {
1732         &self.cx.target_spec()
1733     }
1734 }
1735
1736 trait ToGccComp {
1737     fn to_gcc_comparison(&self) -> ComparisonOp;
1738 }
1739
1740 impl ToGccComp for IntPredicate {
1741     fn to_gcc_comparison(&self) -> ComparisonOp {
1742         match *self {
1743             IntPredicate::IntEQ => ComparisonOp::Equals,
1744             IntPredicate::IntNE => ComparisonOp::NotEquals,
1745             IntPredicate::IntUGT => ComparisonOp::GreaterThan,
1746             IntPredicate::IntUGE => ComparisonOp::GreaterThanEquals,
1747             IntPredicate::IntULT => ComparisonOp::LessThan,
1748             IntPredicate::IntULE => ComparisonOp::LessThanEquals,
1749             IntPredicate::IntSGT => ComparisonOp::GreaterThan,
1750             IntPredicate::IntSGE => ComparisonOp::GreaterThanEquals,
1751             IntPredicate::IntSLT => ComparisonOp::LessThan,
1752             IntPredicate::IntSLE => ComparisonOp::LessThanEquals,
1753         }
1754     }
1755 }
1756
1757 impl ToGccComp for RealPredicate {
1758     fn to_gcc_comparison(&self) -> ComparisonOp {
1759         // TODO: check that ordered vs non-ordered is respected.
1760         match *self {
1761             RealPredicate::RealPredicateFalse => unreachable!(),
1762             RealPredicate::RealOEQ => ComparisonOp::Equals,
1763             RealPredicate::RealOGT => ComparisonOp::GreaterThan,
1764             RealPredicate::RealOGE => ComparisonOp::GreaterThanEquals,
1765             RealPredicate::RealOLT => ComparisonOp::LessThan,
1766             RealPredicate::RealOLE => ComparisonOp::LessThanEquals,
1767             RealPredicate::RealONE => ComparisonOp::NotEquals,
1768             RealPredicate::RealORD => unreachable!(),
1769             RealPredicate::RealUNO => unreachable!(),
1770             RealPredicate::RealUEQ => ComparisonOp::Equals,
1771             RealPredicate::RealUGT => ComparisonOp::GreaterThan,
1772             RealPredicate::RealUGE => ComparisonOp::GreaterThan,
1773             RealPredicate::RealULT => ComparisonOp::LessThan,
1774             RealPredicate::RealULE => ComparisonOp::LessThan,
1775             RealPredicate::RealUNE => ComparisonOp::NotEquals,
1776             RealPredicate::RealPredicateTrue => unreachable!(),
1777         }
1778     }
1779 }
1780
1781 #[repr(C)]
1782 #[allow(non_camel_case_types)]
1783 enum MemOrdering {
1784     __ATOMIC_RELAXED,
1785     __ATOMIC_CONSUME,
1786     __ATOMIC_ACQUIRE,
1787     __ATOMIC_RELEASE,
1788     __ATOMIC_ACQ_REL,
1789     __ATOMIC_SEQ_CST,
1790 }
1791
1792 trait ToGccOrdering {
1793     fn to_gcc(self) -> i32;
1794 }
1795
1796 impl ToGccOrdering for AtomicOrdering {
1797     fn to_gcc(self) -> i32 {
1798         use MemOrdering::*;
1799
1800         let ordering =
1801             match self {
1802                 AtomicOrdering::NotAtomic => __ATOMIC_RELAXED, // TODO: check if that's the same.
1803                 AtomicOrdering::Unordered => __ATOMIC_RELAXED,
1804                 AtomicOrdering::Monotonic => __ATOMIC_RELAXED, // TODO: check if that's the same.
1805                 AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
1806                 AtomicOrdering::Release => __ATOMIC_RELEASE,
1807                 AtomicOrdering::AcquireRelease => __ATOMIC_ACQ_REL,
1808                 AtomicOrdering::SequentiallyConsistent => __ATOMIC_SEQ_CST,
1809             };
1810         ordering as i32
1811     }
1812 }