use std::borrow::Cow;
use std::cell::Cell;
use std::convert::TryFrom;
use std::ops::Deref;

use gccjit::{
    BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type,
    UnaryOp,
};
use rustc_abi as abi;
use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange};
use rustc_apfloat::{Float, Round, Status, ieee};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::common::{
    AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{
    BackendTypes, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods,
    LayoutTypeCodegenMethods, OverflowOp, StaticBuilderMethods,
};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{
    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
    LayoutOfHelpers, TyAndLayout,
};
use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::callconv::FnAbi;
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};

use crate::abi::FnAbiGccExt;
use crate::common::{SignType, TypeReflection, type_is_pointer};
use crate::context::CodegenCx;
use crate::errors;
use crate::intrinsic::llvm;
use crate::type_of::LayoutGccExt;

// FIXME(antoyo)
type Funclet = ();

enum ExtremumOperation {
    Max,
    Min,
}

pub struct Builder<'a, 'gcc, 'tcx> {
    pub cx: &'a CodegenCx<'gcc, 'tcx>,
    pub block: Block<'gcc>,
    pub location: Option<Location<'gcc>>,
    value_counter: Cell<u64>,
}

impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
    fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
        Builder { cx, block, location: None, value_counter: Cell::new(0) }
    }

    fn next_value_counter(&self) -> u64 {
        self.value_counter.set(self.value_counter.get() + 1);
        self.value_counter.get()
    }

    fn atomic_extremum(
        &mut self,
        operation: ExtremumOperation,
        dst: RValue<'gcc>,
        src: RValue<'gcc>,
        order: AtomicOrdering,
    ) -> RValue<'gcc> {
        let size = get_maybe_pointer_size(src);

        let func = self.current_func();

        let load_ordering = match order {
            // FIXME(antoyo): does this make sense?
            AtomicOrdering::AcqRel | AtomicOrdering::Release => AtomicOrdering::Acquire,
            _ => order,
        };
        let previous_value =
            self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size));
        let previous_var =
            func.new_local(self.location, previous_value.get_type(), "previous_value");
        let return_value = func.new_local(self.location, previous_value.get_type(), "return_value");
        self.llbb().add_assignment(self.location, previous_var, previous_value);
        self.llbb().add_assignment(self.location, return_value, previous_var.to_rvalue());

        let while_block = func.new_block("while");
        let after_block = func.new_block("after_while");
        self.llbb().end_with_jump(self.location, while_block);

        // NOTE: since jumps were added and compare_exchange doesn't expect this, the current block in the
        // state need to be updated.
        self.switch_to_block(while_block);

        let comparison_operator = match operation {
            ExtremumOperation::Max => ComparisonOp::LessThan,
            ExtremumOperation::Min => ComparisonOp::GreaterThan,
        };

        let cond1 = self.context.new_comparison(
            self.location,
            comparison_operator,
            previous_var.to_rvalue(),
            self.context.new_cast(self.location, src, previous_value.get_type()),
        );
        let compare_exchange =
            self.compare_exchange(dst, previous_var, src, order, load_ordering, false);
        let cond2 = self.cx.context.new_unary_op(
            self.location,
            UnaryOp::LogicalNegate,
            compare_exchange.get_type(),
            compare_exchange,
        );
        let cond = self.cx.context.new_binary_op(
            self.location,
            BinaryOp::LogicalAnd,
            self.cx.bool_type,
            cond1,
            cond2,
        );

        while_block.end_with_conditional(self.location, cond, while_block, after_block);

        // NOTE: since jumps were added in a place rustc does not expect, the current block in the
        // state need to be updated.
        self.switch_to_block(after_block);

        return_value.to_rvalue()
    }

    fn compare_exchange(
        &self,
        dst: RValue<'gcc>,
        cmp: LValue<'gcc>,
        src: RValue<'gcc>,
        order: AtomicOrdering,
        failure_order: AtomicOrdering,
        weak: bool,
    ) -> RValue<'gcc> {
        let size = get_maybe_pointer_size(src);
        let compare_exchange =
            self.context.get_builtin_function(format!("__atomic_compare_exchange_{}", size));
        let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
        let failure_order = self.context.new_rvalue_from_int(self.i32_type, failure_order.to_gcc());
        let weak = self.context.new_rvalue_from_int(self.bool_type, weak as i32);

        let void_ptr_type = self.context.new_type::<*mut ()>();
        let volatile_void_ptr_type = void_ptr_type.make_volatile();
        let dst = self.context.new_cast(self.location, dst, volatile_void_ptr_type);
        let expected =
            self.context.new_cast(self.location, cmp.get_address(self.location), void_ptr_type);

        // NOTE: not sure why, but we have the wrong type here.
        let int_type = compare_exchange.get_param(2).to_rvalue().get_type();
        let src = self.context.new_bitcast(self.location, src, int_type);
        self.context.new_call(
            self.location,
            compare_exchange,
            &[dst, expected, src, weak, order, failure_order],
        )
    }

    pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) {
        self.llbb().add_assignment(self.location, lvalue, value);
    }

    fn check_call<'b>(
        &mut self,
        _typ: &str,
        func: Function<'gcc>,
        args: &'b [RValue<'gcc>],
    ) -> Cow<'b, [RValue<'gcc>]> {
        let mut all_args_match = true;
        let mut param_types = vec![];
        let param_count = func.get_param_count();
        for (index, arg) in args.iter().enumerate().take(param_count) {
            let param = func.get_param(index as i32);
            let param = param.to_rvalue().get_type();
            if param != arg.get_type() {
                all_args_match = false;
            }
            param_types.push(param);
        }

        if all_args_match {
            return Cow::Borrowed(args);
        }

        let casted_args: Vec<_> = param_types
            .into_iter()
            .zip(args.iter())
            .map(|(expected_ty, &actual_val)| {
                let actual_ty = actual_val.get_type();
                if expected_ty != actual_ty {
                    self.bitcast(actual_val, expected_ty)
                } else {
                    actual_val
                }
            })
            .collect();

        debug_assert_eq!(casted_args.len(), args.len());

        Cow::Owned(casted_args)
    }

    fn check_ptr_call<'b>(
        &mut self,
        _typ: &str,
        func_ptr: RValue<'gcc>,
        args: &'b [RValue<'gcc>],
        on_stack_param_indices: &FxHashSet<usize>,
    ) -> Cow<'b, [RValue<'gcc>]> {
        let mut all_args_match = true;
        let mut param_types = vec![];
        let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
        for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) {
            let param = gcc_func.get_param_type(index);
            if param != arg.get_type() {
                all_args_match = false;
            }
            param_types.push(param);
        }

        if all_args_match {
            return Cow::Borrowed(args);
        }

        let func_name = format!("{:?}", func_ptr);

        let mut casted_args: Vec<_> = param_types
            .into_iter()
            .zip(args.iter())
            .enumerate()
            .map(|(index, (expected_ty, &actual_val))| {
                if llvm::ignore_arg_cast(&func_name, index, args.len()) {
                    return actual_val;
                }

                let actual_ty = actual_val.get_type();
                if expected_ty != actual_ty {
                    if !actual_ty.is_vector()
                        && !expected_ty.is_vector()
                        && (actual_ty.is_integral() && expected_ty.is_integral())
                        || (actual_ty.get_pointee().is_some()
                            && expected_ty.get_pointee().is_some())
                    {
                        self.context.new_cast(self.location, actual_val, expected_ty)
                    } else if on_stack_param_indices.contains(&index) {
                        let ty = actual_val.get_type();
                        // It's possible that the value behind the pointer is actually not exactly
                        // the expected type, so to go around that, we add a cast before
                        // dereferencing the value.
                        if let Some(pointee_val) = ty.get_pointee()
                            && pointee_val != expected_ty
                        {
                            let new_val = self.context.new_cast(
                                self.location,
                                actual_val,
                                expected_ty.make_pointer(),
                            );
                            new_val.dereference(self.location).to_rvalue()
                        } else {
                            actual_val.dereference(self.location).to_rvalue()
                        }
                    } else {
                        // FIXME: this condition seems wrong: it will pass when both types are not
                        // a vector.
                        assert!(
                            (!expected_ty.is_vector() || actual_ty.is_vector())
                                && (expected_ty.is_vector() || !actual_ty.is_vector()),
                            "{:?} (is vector: {}) -> {:?} (is vector: {}), Function: {:?}[{}]",
                            actual_ty,
                            actual_ty.is_vector(),
                            expected_ty,
                            expected_ty.is_vector(),
                            func_ptr,
                            index
                        );
                        // FIXME(antoyo): perhaps use __builtin_convertvector for vector casting.
                        // FIXME: remove bitcast now that vector types can be compared?
                        // ==> We use bitcast to avoid having to do many manual casts from e.g. __m256i to __v32qi (in
                        // the case of _mm256_aesenc_epi128).
                        self.bitcast(actual_val, expected_ty)
                    }
                } else {
                    actual_val
                }
            })
            .collect();

        // NOTE: to take into account variadic functions.
        for arg in args.iter().skip(casted_args.len()) {
            casted_args.push(*arg);
        }

        Cow::Owned(casted_args)
    }

    fn check_store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
        let stored_ty = self.cx.val_ty(val);
        let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
        self.bitcast(ptr, stored_ptr_ty)
    }

    pub fn current_func(&self) -> Function<'gcc> {
        self.block.get_function()
    }

    pub fn function_call(
        &mut self,
        func: Function<'gcc>,
        args: &[RValue<'gcc>],
        _funclet: Option<&Funclet>,
    ) -> RValue<'gcc> {
        let args = self.check_call("call", func, args);

        // gccjit requires to use the result of functions, even when it's not used.
        // That's why we assign the result to a local or call add_eval().
        let return_type = func.get_return_type();
        let void_type = self.context.new_type::<()>();
        let current_func = self.block.get_function();
        if return_type != void_type {
            let result = current_func.new_local(
                self.location,
                return_type,
                format!("returnValue{}", self.next_value_counter()),
            );
            self.block.add_assignment(
                self.location,
                result,
                self.cx.context.new_call(self.location, func, &args),
            );
            result.to_rvalue()
        } else {
            self.block
                .add_eval(self.location, self.cx.context.new_call(self.location, func, &args));
            // Return dummy value when not having return value.
            self.context.new_rvalue_zero(self.isize_type)
        }
    }

    fn function_ptr_call(
        &mut self,
        typ: Type<'gcc>,
        fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
        mut func_ptr: RValue<'gcc>,
        args: &[RValue<'gcc>],
        _funclet: Option<&Funclet>,
    ) -> RValue<'gcc> {
        let func_ptr_type = {
            let func_ptr_type = func_ptr.get_type();
            if func_ptr_type != typ {
                func_ptr = self.context.new_cast(self.location, func_ptr, typ);
                typ
            } else {
                func_ptr_type
            }
        };
        let gcc_func = func_ptr_type.dyncast_function_ptr_type().expect("function ptr");
        let on_stack_param_indices = fn_abi
            .map(|fn_abi| fn_abi.gcc_type(self.cx).on_stack_param_indices)
            .unwrap_or_default();
        let func_name = format!("{:?}", func_ptr);
        let previous_arg_count = args.len();
        let orig_args = args;
        let args = {
            func_ptr = llvm::adjust_function(self.context, &func_name, func_ptr, args);
            llvm::adjust_intrinsic_arguments(self, gcc_func, args.into(), &func_name)
        };
        let args_adjusted = args.len() != previous_arg_count;
        let args = self.check_ptr_call("call", func_ptr, &args, &on_stack_param_indices);

        // gccjit requires to use the result of functions, even when it's not used.
        // That's why we assign the result to a local or call add_eval().
        let return_type = gcc_func.get_return_type();
        let void_type = self.context.new_type::<()>();
        let current_func = self.block.get_function();

        if return_type != void_type {
            let return_value = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args);
            let return_value = llvm::adjust_intrinsic_return_value(
                self,
                return_value,
                &func_name,
                &args,
                args_adjusted,
                orig_args,
            );
            let result = current_func.new_local(
                self.location,
                return_value.get_type(),
                format!("ptrReturnValue{}", self.next_value_counter()),
            );
            self.block.add_assignment(self.location, result, return_value);
            result.to_rvalue()
        } else {
            #[cfg(not(feature = "master"))]
            if gcc_func.get_param_count() == 0 {
                // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics.
                self.block.add_eval(
                    self.location,
                    self.cx.context.new_call_through_ptr(self.location, func_ptr, &[]),
                );
            } else {
                self.block.add_eval(
                    self.location,
                    self.cx.context.new_call_through_ptr(self.location, func_ptr, &args),
                );
            }
            #[cfg(feature = "master")]
            self.block.add_eval(
                self.location,
                self.cx.context.new_call_through_ptr(self.location, func_ptr, &args),
            );
            // Return dummy value when not having return value.
            self.context.new_rvalue_zero(self.isize_type)
        }
    }

    pub fn overflow_call(
        &self,
        func: Function<'gcc>,
        args: &[RValue<'gcc>],
        _funclet: Option<&Funclet>,
    ) -> RValue<'gcc> {
        // gccjit requires to use the result of functions, even when it's not used.
        // That's why we assign the result to a local.
        let return_type = self.context.new_type::<bool>();
        let current_func = self.block.get_function();
        // FIXME(antoyo): return the new_call() directly? Since the overflow function has no side-effects.
        let result = current_func.new_local(
            self.location,
            return_type,
            format!("overflowReturnValue{}", self.next_value_counter()),
        );
        self.block.add_assignment(
            self.location,
            result,
            self.cx.context.new_call(self.location, func, args),
        );
        result.to_rvalue()
    }
}

impl<'tcx> HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.cx.tcx()
    }
}

impl HasDataLayout for Builder<'_, '_, '_> {
    fn data_layout(&self) -> &TargetDataLayout {
        self.cx.data_layout()
    }
}

impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
    #[inline]
    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
        self.cx.handle_layout_err(err, span, ty)
    }
}

impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
    #[inline]
    fn handle_fn_abi_err(
        &self,
        err: FnAbiError<'tcx>,
        span: Span,
        fn_abi_request: FnAbiRequest<'tcx>,
    ) -> ! {
        self.cx.handle_fn_abi_err(err, span, fn_abi_request)
    }
}

impl<'a, 'gcc, 'tcx> Deref for Builder<'a, 'gcc, 'tcx> {
    type Target = CodegenCx<'gcc, 'tcx>;

    fn deref<'b>(&'b self) -> &'a Self::Target {
        self.cx
    }
}

impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
    type Function = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Function;
    type BasicBlock = <CodegenCx<'gcc, 'tcx> as BackendTypes>::BasicBlock;
    type Funclet = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Funclet;

    type Value = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Value;
    type Type = <CodegenCx<'gcc, 'tcx> as BackendTypes>::Type;
    type FunctionSignature = <CodegenCx<'gcc, 'tcx> as BackendTypes>::FunctionSignature;

    type DIScope = <CodegenCx<'gcc, 'tcx> as BackendTypes>::DIScope;
    type DILocation = <CodegenCx<'gcc, 'tcx> as BackendTypes>::DILocation;
    type DIVariable = <CodegenCx<'gcc, 'tcx> as BackendTypes>::DIVariable;
}

fn set_rvalue_location<'a, 'gcc, 'tcx>(
    _bx: &mut Builder<'a, 'gcc, 'tcx>,
    rvalue: RValue<'gcc>,
) -> RValue<'gcc> {
    #[cfg(feature = "master")]
    if let Some(location) = _bx.location {
        rvalue.set_location(location);
    }
    rvalue
}

impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
    type CodegenCx = CodegenCx<'gcc, 'tcx>;

    fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> {
        *cx.current_func.borrow_mut() = Some(block.get_function());
        Builder::with_cx(cx, block)
    }

    fn llbb(&self) -> Block<'gcc> {
        self.block
    }

    fn append_block(_: &'a CodegenCx<'gcc, 'tcx>, func: Function<'gcc>, name: &str) -> Block<'gcc> {
        func.new_block(name)
    }

    fn append_sibling_block(&mut self, name: &str) -> Block<'gcc> {
        let func = self.current_func();
        func.new_block(name)
    }

    fn switch_to_block(&mut self, block: Self::BasicBlock) {
        self.block = block;
    }

    fn ret_void(&mut self) {
        self.llbb().end_with_void_return(self.location)
    }

    fn ret(&mut self, mut value: RValue<'gcc>) {
        let expected_return_type = self.current_func().get_return_type();
        let value_type = value.get_type();
        if !expected_return_type.is_compatible_with(value_type) {
            // NOTE: due to opaque pointers now being used, we need to (bit)cast here.
            if self.is_native_int_type(value_type) && self.is_native_int_type(expected_return_type)
            {
                value = self.context.new_cast(self.location, value, expected_return_type);
            } else {
                value = self.context.new_bitcast(self.location, value, expected_return_type);
            }
        }
        self.llbb().end_with_return(self.location, value);
    }

    fn br(&mut self, dest: Block<'gcc>) {
        self.llbb().end_with_jump(self.location, dest)
    }

    fn cond_br(&mut self, cond: RValue<'gcc>, then_block: Block<'gcc>, else_block: Block<'gcc>) {
        self.llbb().end_with_conditional(self.location, cond, then_block, else_block)
    }

    fn switch(
        &mut self,
        value: RValue<'gcc>,
        default_block: Block<'gcc>,
        cases: impl ExactSizeIterator<Item = (u128, Block<'gcc>)>,
    ) {
        let mut gcc_cases = vec![];
        let typ = self.val_ty(value);
        // FIXME(FractalFir): This is a workaround for a libgccjit limitation.
        // Currently, libgccjit can't directly create 128 bit integers.
        // Since switch cases must be values, and casts are not constant, we can't use 128 bit switch cases.
        // In such a case, we will simply fall back to an if-ladder.
        // This *may* be slower than a native switch, but a slow working solution is better than none at all.
        if typ.is_i128(self) || typ.is_u128(self) {
            for (on_val, dest) in cases {
                let on_val = self.const_uint_big(typ, on_val);
                let is_case =
                    self.context.new_comparison(self.location, ComparisonOp::Equals, value, on_val);
                let next_block = self.current_func().new_block("case");
                self.block.end_with_conditional(self.location, is_case, dest, next_block);
                self.block = next_block;
            }
            self.block.end_with_jump(self.location, default_block);
        } else {
            for (on_val, dest) in cases {
                let on_val = self.const_uint_big(typ, on_val);
                gcc_cases.push(self.context.new_case(on_val, on_val, dest));
            }
            self.block.end_with_switch(self.location, value, default_block, &gcc_cases);
        }
    }

    #[cfg(feature = "master")]
    fn invoke(
        &mut self,
        typ: Type<'gcc>,
        fn_attrs: Option<&CodegenFnAttrs>,
        fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
        func: RValue<'gcc>,
        args: &[RValue<'gcc>],
        then: Block<'gcc>,
        catch: Block<'gcc>,
        _funclet: Option<&Funclet>,
        instance: Option<Instance<'tcx>>,
    ) -> RValue<'gcc> {
        let try_block = self.current_func().new_block("try");

        let current_block = self.block;
        self.block = try_block;
        let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here?
        self.block = current_block;

        let return_value =
            self.current_func().new_local(self.location, call.get_type(), "invokeResult");

        try_block.add_assignment(self.location, return_value, call);

        try_block.end_with_jump(self.location, then);

        if self.cleanup_blocks.borrow().contains(&catch) {
            self.block.add_try_finally(self.location, try_block, catch);
        } else {
            self.block.add_try_catch(self.location, try_block, catch);
        }

        self.block.end_with_jump(self.location, then);

        return_value.to_rvalue()
    }

    #[cfg(not(feature = "master"))]
    fn invoke(
        &mut self,
        typ: Type<'gcc>,
        fn_attrs: Option<&CodegenFnAttrs>,
        fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
        func: RValue<'gcc>,
        args: &[RValue<'gcc>],
        then: Block<'gcc>,
        catch: Block<'gcc>,
        _funclet: Option<&Funclet>,
        instance: Option<Instance<'tcx>>,
    ) -> RValue<'gcc> {
        let call_site = self.call(typ, fn_attrs, fn_abi, func, args, None, instance);
        let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
        self.llbb().end_with_conditional(self.location, condition, then, catch);
        if let Some(_fn_abi) = fn_abi {
            // FIXME(bjorn3): Apply function attributes
        }
        call_site
    }

    fn unreachable(&mut self) {
        let func = self.context.get_builtin_function("__builtin_unreachable");
        self.block.add_eval(self.location, self.context.new_call(self.location, func, &[]));
        let return_type = self.block.get_function().get_return_type();
        let void_type = self.context.new_type::<()>();
        if return_type == void_type {
            self.block.end_with_void_return(self.location)
        } else {
            let return_value =
                self.current_func().new_local(self.location, return_type, "unreachableReturn");
            self.block.end_with_return(self.location, return_value)
        }
    }

    fn add(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.gcc_add(a, b))
    }

    fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(a + b)
    }

    // FIXME(antoyo): should we also override the `unchecked_` versions?
    fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.gcc_sub(a, b))
    }

    fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(a - b)
    }

    fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.gcc_mul(a, b))
    }

    fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.cx.context.new_binary_op(
            self.location,
            BinaryOp::Mult,
            a.get_type(),
            a,
            b,
        ))
    }

    fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.gcc_udiv(a, b))
    }

    fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): poison if not exact.
        let a_type = a.get_type().to_unsigned(self);
        let a = self.gcc_int_cast(a, a_type);
        let b_type = b.get_type().to_unsigned(self);
        let b = self.gcc_int_cast(b, b_type);
        self.assign_to_var(self.gcc_udiv(a, b))
    }

    fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.gcc_sdiv(a, b))
    }

    fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): poison if not exact.
        // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they
        // should be the same.
        let typ = a.get_type().to_signed(self);
        let b = self.gcc_int_cast(b, typ);
        self.assign_to_var(self.gcc_sdiv(a, b))
    }

    fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(a / b)
    }

    fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.gcc_urem(a, b))
    }

    fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.assign_to_var(self.gcc_srem(a, b))
    }

    fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): add check in libgccjit since using the binary operator % causes the following error:
        // during RTL pass: expand
        // libgccjit.so: error: in expmed_mode_index, at expmed.h:240
        // 0x7f0101d58dc6 expmed_mode_index
        //     ../../../gcc/gcc/expmed.h:240
        // 0x7f0101d58e35 expmed_op_cost_ptr
        //     ../../../gcc/gcc/expmed.h:262
        // 0x7f0101d594a1 sdiv_cost_ptr
        //     ../../../gcc/gcc/expmed.h:531
        // 0x7f0101d594f3 sdiv_cost
        //     ../../../gcc/gcc/expmed.h:549
        // 0x7f0101d6af7e expand_divmod(int, tree_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, int, optab_methods)
        //     ../../../gcc/gcc/expmed.cc:4356
        // 0x7f0101d94f9e expand_expr_divmod
        //     ../../../gcc/gcc/expr.cc:8929
        // 0x7f0101d97a26 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier)
        //     ../../../gcc/gcc/expr.cc:9566
        // 0x7f0101bef6ef expand_gimple_stmt_1
        //     ../../../gcc/gcc/cfgexpand.cc:3967
        // 0x7f0101bef910 expand_gimple_stmt
        //     ../../../gcc/gcc/cfgexpand.cc:4028
        // 0x7f0101bf6ee7 expand_gimple_basic_block
        //     ../../../gcc/gcc/cfgexpand.cc:6069
        // 0x7f0101bf9194 execute
        //     ../../../gcc/gcc/cfgexpand.cc:6795
        let a_type = a.get_type();
        let a_type_unqualified = a_type.unqualified();
        if a_type.is_compatible_with(self.cx.float_type) {
            let fmodf = self.context.get_builtin_function("fmodf");
            // FIXME(antoyo): this seems to produce the wrong result.
            return self.context.new_call(self.location, fmodf, &[a, b]);
        }

        #[cfg(feature = "master")]
        match self.cx.type_kind(a_type) {
            TypeKind::Half => {
                let fmodf = self.context.get_builtin_function("fmodf");
                let f32_type = self.type_f32();
                let a = self.context.new_cast(self.location, a, f32_type);
                let b = self.context.new_cast(self.location, b, f32_type);
                let result = self.context.new_call(self.location, fmodf, &[a, b]);
                return self.context.new_cast(self.location, result, a_type);
            }
            TypeKind::Float => {
                let fmodf = self.context.get_builtin_function("fmodf");
                return self.context.new_call(self.location, fmodf, &[a, b]);
            }
            TypeKind::Double => {
                let fmod = self.context.get_builtin_function("fmod");
                return self.context.new_call(self.location, fmod, &[a, b]);
            }
            TypeKind::FP128 => {
                // FIXME(antoyo): use get_simple_function_f128_2args.
                let f128_type = self.type_f128();
                let fmodf128 = self.context.new_function(
                    None,
                    gccjit::FunctionType::Extern,
                    f128_type,
                    &[
                        self.context.new_parameter(None, f128_type, "a"),
                        self.context.new_parameter(None, f128_type, "b"),
                    ],
                    "fmodf128",
                    false,
                );
                return self.context.new_call(self.location, fmodf128, &[a, b]);
            }
            _ => (),
        }

        if let Some(vector_type) = a_type_unqualified.dyncast_vector() {
            assert_eq!(a_type_unqualified, b.get_type().unqualified());

            let num_units = vector_type.get_num_units();
            let new_elements: Vec<_> = (0..num_units)
                .map(|i| {
                    let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
                    let x = self.extract_element(a, index).to_rvalue();
                    let y = self.extract_element(b, index).to_rvalue();
                    self.frem(x, y)
                })
                .collect();

            return self.context.new_rvalue_from_vector(self.location, a_type, &new_elements);
        }
        assert_eq!(a_type_unqualified, self.cx.double_type);

        let fmod = self.context.get_builtin_function("fmod");
        self.context.new_call(self.location, fmod, &[a, b])
    }

    fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.gcc_shl(a, b)
    }

    fn lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.gcc_lshr(a, b)
    }

    fn ashr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): check whether behavior is an arithmetic shift for >> .
        // It seems to be if the value is signed.
        self.gcc_lshr(a, b)
    }

    fn and(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.gcc_and(a, b)
    }

    fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.cx.gcc_or(a, b, self.location)
    }

    fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.gcc_xor(a, b))
    }

    fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.gcc_neg(a))
    }

    fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(
            self,
            self.cx.context.new_unary_op(self.location, UnaryOp::Minus, a.get_type(), a),
        )
    }

    fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.gcc_not(a))
    }

    fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        let result = set_rvalue_location(self, lhs + rhs);
        self.assign_to_var(result)
    }

    fn fsub_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        let result = set_rvalue_location(self, lhs - rhs);
        self.assign_to_var(result)
    }

    fn fmul_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        let result = set_rvalue_location(self, lhs * rhs);
        self.assign_to_var(result)
    }

    fn fdiv_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        let result = set_rvalue_location(self, lhs / rhs);
        self.assign_to_var(result)
    }

    fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        let result = self.frem(lhs, rhs);
        set_rvalue_location(self, result);
        result
    }

    fn fadd_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        self.assign_to_var(lhs + rhs)
    }

    fn fsub_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        self.assign_to_var(lhs - rhs)
    }

    fn fmul_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        self.assign_to_var(lhs * rhs)
    }

    fn fdiv_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        self.assign_to_var(lhs / rhs)
    }

    fn frem_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
        self.frem(lhs, rhs)
    }

    fn checked_binop(
        &mut self,
        oop: OverflowOp,
        typ: Ty<'tcx>,
        lhs: Self::Value,
        rhs: Self::Value,
    ) -> (Self::Value, Self::Value) {
        self.gcc_checked_binop(oop, typ, lhs, rhs)
    }

    fn alloca(&mut self, size: Size, align: Align) -> RValue<'gcc> {
        let ty = self.cx.type_array(self.cx.type_i8(), size.bytes()).get_aligned(align.bytes());
        // FIXME(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial.
        self.current_func()
            .new_local(self.location, ty, format!("stack_var_{}", self.next_value_counter()))
            .get_address(self.location)
    }

    fn alloca_with_ty(&mut self, ty: TyAndLayout<'tcx>) -> RValue<'gcc> {
        self.alloca(ty.layout.size, ty.layout.align.abi)
    }

    fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
        let block = self.llbb();
        let function = block.get_function();
        // NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned.
        // For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned)
        // Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked"
        //
        // From GCCs perspective:
        // __int128_t  __attribute__((aligned(16)))  __attribute__((aligned(16)))
        // and:
        // __int128_t  __attribute__((aligned(16)))
        // are 2 distinct, incompatible types.
        //
        // So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types,
        // but the GCC APIs to facilitate this just aren't quite there yet.

        // This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment.
        // Otherwise, this may be an under-aligned load, so we will still call get_aligned.
        let mut can_skip_align = (pointee_ty == self.cx.u128_type
            || pointee_ty == self.cx.i128_type)
            && align == self.int128_align;
        // We can skip the call to `get_aligned` for byte-sized types with alignment of 1.
        can_skip_align = can_skip_align
            || (pointee_ty == self.cx.u8_type || pointee_ty == self.cx.i8_type)
                && align.bytes() == 1;
        // Skip the call to `get_aligned` when possible.
        let aligned_type =
            if can_skip_align { pointee_ty } else { pointee_ty.get_aligned(align.bytes()) };

        let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
        // NOTE: instead of returning the dereference here, we have to assign it to a variable in
        // the current basic block. Otherwise, it could be used in another basic block, causing a
        // dereference after a drop, for instance.
        let deref = ptr.dereference(self.location).to_rvalue();
        let loaded_value = function.new_local(
            self.location,
            aligned_type,
            format!("loadedValue{}", self.next_value_counter()),
        );
        block.add_assignment(self.location, loaded_value, deref);
        loaded_value.to_rvalue()
    }

    fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
        let ptr = self.context.new_cast(self.location, ptr, ty.make_volatile().make_pointer());
        // (FractalFir): We insert a local here, to ensure this volatile load can't move across
        // blocks.
        let local = self.current_func().new_local(self.location, ty, "volatile_tmp");
        self.block.add_assignment(self.location, local, ptr.dereference(self.location).to_rvalue());
        local.to_rvalue()
    }

    fn atomic_load(
        &mut self,
        _ty: Type<'gcc>,
        ptr: RValue<'gcc>,
        order: AtomicOrdering,
        size: Size,
    ) -> RValue<'gcc> {
        // FIXME(antoyo): use ty.
        // FIXME(antoyo): handle alignment.
        let atomic_load =
            self.context.get_builtin_function(format!("__atomic_load_{}", size.bytes()));
        let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());

        let volatile_const_void_ptr_type =
            self.context.new_type::<()>().make_const().make_volatile().make_pointer();
        let ptr = self.context.new_cast(self.location, ptr, volatile_const_void_ptr_type);
        self.context.new_call(self.location, atomic_load, &[ptr, ordering])
    }

    fn load_operand(
        &mut self,
        place: PlaceRef<'tcx, RValue<'gcc>>,
    ) -> OperandRef<'tcx, RValue<'gcc>> {
        assert_eq!(place.val.llextra.is_some(), place.layout.is_unsized());

        if place.layout.is_zst() {
            return OperandRef::zero_sized(place.layout);
        }

        fn scalar_load_metadata<'a, 'gcc, 'tcx>(
            bx: &mut Builder<'a, 'gcc, 'tcx>,
            load: RValue<'gcc>,
            scalar: &abi::Scalar,
        ) {
            let vr = scalar.valid_range(bx);
            match scalar.primitive() {
                abi::Primitive::Int(..) => {
                    if !scalar.is_always_valid(bx) {
                        bx.range_metadata(load, vr);
                    }
                }
                abi::Primitive::Pointer(_) if vr.start < vr.end && !vr.contains(0) => {
                    bx.nonnull_metadata(load);
                }
                _ => {}
            }
        }

        let val = if place.val.llextra.is_some() {
            // FIXME: Merge with the `else` below?
            OperandValue::Ref(place.val)
        } else if place.layout.is_gcc_immediate() {
            let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align);
            OperandValue::Immediate(
                if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr {
                    scalar_load_metadata(self, load, scalar);
                    self.to_immediate_scalar(load, *scalar)
                } else {
                    load
                },
            )
        } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr {
            let b_offset = a.size(self).align_to(b.align(self).abi);

            let mut load = |i, scalar: &abi::Scalar, align| {
                let ptr = if i == 0 {
                    place.val.llval
                } else {
                    self.inbounds_ptradd(place.val.llval, self.const_usize(b_offset.bytes()))
                };
                let llty = place.layout.scalar_pair_element_gcc_type(self, i);
                let load = self.load(llty, ptr, align);
                scalar_load_metadata(self, load, scalar);
                if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
            };

            OperandValue::Pair(
                load(0, a, place.val.align),
                load(1, b, place.val.align.restrict_for_offset(b_offset)),
            )
        } else {
            OperandValue::Ref(place.val)
        };

        OperandRef { val, layout: place.layout, move_annotation: None }
    }

    fn write_operand_repeatedly(
        &mut self,
        cg_elem: OperandRef<'tcx, RValue<'gcc>>,
        count: u64,
        dest: PlaceRef<'tcx, RValue<'gcc>>,
    ) {
        let zero = self.const_usize(0);
        let count = self.const_usize(count);
        let start = dest.project_index(self, zero).val.llval;
        let end = dest.project_index(self, count).val.llval;

        let header_bb = self.append_sibling_block("repeat_loop_header");
        let body_bb = self.append_sibling_block("repeat_loop_body");
        let next_bb = self.append_sibling_block("repeat_loop_next");

        let ptr_type = start.get_type();
        let current = self.llbb().get_function().new_local(self.location, ptr_type, "loop_var");
        let current_val = current.to_rvalue();
        self.assign(current, start);

        self.br(header_bb);

        self.switch_to_block(header_bb);
        let keep_going = self.icmp(IntPredicate::IntNE, current_val, end);
        self.cond_br(keep_going, body_bb, next_bb);

        self.switch_to_block(body_bb);
        let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
        cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align));

        let next = self.inbounds_gep(
            self.backend_type(cg_elem.layout),
            current.to_rvalue(),
            &[self.const_usize(1)],
        );
        self.llbb().add_assignment(self.location, current, next);
        self.br(header_bb);

        self.switch_to_block(next_bb);
    }

    fn range_metadata(&mut self, _load: RValue<'gcc>, _range: WrappingRange) {
        // FIXME(antoyo)
    }

    fn nonnull_metadata(&mut self, _load: RValue<'gcc>) {
        // FIXME(antoyo)
    }

    fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
        self.store_with_flags(val, ptr, align, MemFlags::empty())
    }

    fn store_with_flags(
        &mut self,
        val: RValue<'gcc>,
        ptr: RValue<'gcc>,
        align: Align,
        flags: MemFlags,
    ) -> RValue<'gcc> {
        let ptr = self.check_store(val, ptr);
        let destination = ptr.dereference(self.location);
        // NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast
        // to type so it gets the proper alignment.
        let destination_type = destination.to_rvalue().get_type().unqualified();
        let align = if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() };
        let mut modified_destination_type = destination_type.get_aligned(align);
        if flags.contains(MemFlags::VOLATILE) {
            modified_destination_type = modified_destination_type.make_volatile();
        }

        let modified_ptr =
            self.cx.context.new_cast(self.location, ptr, modified_destination_type.make_pointer());
        let modified_destination = modified_ptr.dereference(self.location);
        self.llbb().add_assignment(self.location, modified_destination, val);
        // FIXME(antoyo): handle `MemFlags::NONTEMPORAL`.
        // NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
        // When adding support for NONTEMPORAL, make sure to not just emit MOVNT on x86; see the
        // LLVM backend for details.
        self.cx.context.new_rvalue_zero(self.type_i32())
    }

    fn atomic_store(
        &mut self,
        value: RValue<'gcc>,
        ptr: RValue<'gcc>,
        order: AtomicOrdering,
        size: Size,
    ) {
        // FIXME(antoyo): handle alignment.
        let atomic_store =
            self.context.get_builtin_function(format!("__atomic_store_{}", size.bytes()));
        let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
        let volatile_const_void_ptr_type =
            self.context.new_type::<()>().make_volatile().make_pointer();
        let ptr = self.context.new_cast(self.location, ptr, volatile_const_void_ptr_type);

        // FIXME(antoyo): fix libgccjit to allow comparing an integer type with an aligned integer type because
        // the following cast is required to avoid this error:
        // 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))))
        let int_type = atomic_store.get_param(1).to_rvalue().get_type();
        let value = self.context.new_bitcast(self.location, value, int_type);
        self.llbb().add_eval(
            self.location,
            self.context.new_call(self.location, atomic_store, &[ptr, value, ordering]),
        );
    }

    fn gep(
        &mut self,
        typ: Type<'gcc>,
        ptr: RValue<'gcc>,
        indices: &[RValue<'gcc>],
    ) -> RValue<'gcc> {
        // NOTE: due to opaque pointers now being used, we need to cast here.
        let ptr = self.context.new_cast(self.location, ptr, typ.make_pointer());
        let ptr_type = ptr.get_type();
        let mut pointee_type = ptr.get_type();
        // NOTE: we cannot use array indexing here like in inbounds_gep because array indexing is
        // always considered in bounds in GCC (FIXME(antoyo): to be verified).
        // So, we have to cast to a number.
        let mut result = self.context.new_bitcast(self.location, ptr, self.sizet_type);
        // FIXME(antoyo): if there were more than 1 index, this code is probably wrong and would
        // require dereferencing the pointer.
        for index in indices {
            pointee_type = pointee_type.get_pointee().expect("pointee type");
            #[cfg(feature = "master")]
            let pointee_size = {
                let size = self.cx.context.new_sizeof(pointee_type);
                self.context.new_cast(self.location, size, index.get_type())
            };
            #[cfg(not(feature = "master"))]
            let pointee_size =
                self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32);
            result = result + self.gcc_int_cast(*index * pointee_size, self.sizet_type);
        }
        self.context.new_bitcast(self.location, result, ptr_type)
    }

    fn inbounds_gep(
        &mut self,
        typ: Type<'gcc>,
        ptr: RValue<'gcc>,
        indices: &[RValue<'gcc>],
    ) -> RValue<'gcc> {
        // NOTE: due to opaque pointers now being used, we need to cast here.
        let ptr = self.context.new_cast(self.location, ptr, typ.make_pointer());
        // NOTE: array indexing is always considered in bounds in GCC (FIXME(antoyo): to be verified).
        let mut indices = indices.iter();
        let index = indices.next().expect("first index in inbounds_gep");
        let mut result = self.context.new_array_access(self.location, ptr, *index);
        for index in indices {
            result = self.context.new_array_access(self.location, result, *index);
        }
        result.get_address(self.location)
    }

    /* Casts */
    fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): check that it indeed truncate the value.
        self.gcc_int_cast(value, dest_ty)
    }

    fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): check that it indeed sign extend the value.
        if dest_ty.dyncast_vector().is_some() {
            // FIXME(antoyo): nothing to do as it is only for LLVM?
            return value;
        }
        self.context.new_cast(self.location, value, dest_ty)
    }

    fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.gcc_float_to_uint_cast(value, dest_ty))
    }

    fn fptosi(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.gcc_float_to_int_cast(value, dest_ty))
    }

    fn uitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.gcc_uint_to_float_cast(value, dest_ty))
    }

    fn sitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.gcc_int_to_float_cast(value, dest_ty))
    }

    fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): make sure it truncates.
        set_rvalue_location(self, self.context.new_cast(self.location, value, dest_ty))
    }

    fn fpext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        set_rvalue_location(self, self.context.new_cast(self.location, value, dest_ty))
    }

    fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        let usize_value = self.cx.context.new_cast(None, value, self.cx.type_isize());
        self.intcast(usize_value, dest_ty, false)
    }

    fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        let usize_value = self.intcast(value, self.cx.type_isize(), false);
        self.cx.context.new_cast(None, usize_value, dest_ty)
    }

    fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        self.cx.const_bitcast(value, dest_ty)
    }

    fn intcast(
        &mut self,
        mut value: RValue<'gcc>,
        dest_typ: Type<'gcc>,
        is_signed: bool,
    ) -> RValue<'gcc> {
        let value_type = value.get_type();
        if is_signed && !value_type.is_signed(self.cx) {
            let signed_type = value_type.to_signed(self.cx);
            value = self.gcc_int_cast(value, signed_type);
        } else if !is_signed && value_type.is_signed(self.cx) {
            let unsigned_type = value_type.to_unsigned(self.cx);
            value = self.gcc_int_cast(value, unsigned_type);
        }

        self.gcc_int_cast(value, dest_typ)
    }

    fn pointercast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        let val_type = value.get_type();
        match (type_is_pointer(val_type), type_is_pointer(dest_ty)) {
            (false, true) => {
                // NOTE: Projecting a field of a pointer type will attempt a cast from a signed char to
                // a pointer, which is not supported by gccjit.
                self.cx.context.new_cast(
                    self.location,
                    self.inttoptr(value, val_type.make_pointer()),
                    dest_ty,
                )
            }
            (false, false) => {
                // When they are not pointers, we want a transmute (or reinterpret_cast).
                self.bitcast(value, dest_ty)
            }
            (true, true) => self.cx.context.new_cast(self.location, value, dest_ty),
            (true, false) => unimplemented!(),
        }
    }

    /* Comparisons */
    fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        self.gcc_icmp(op, lhs, rhs)
    }

    fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
        // LLVM has a concept of "unordered compares", where eg ULT returns true if either the two
        // arguments are unordered (i.e. either is NaN), or the lhs is less than the rhs. GCC does
        // not natively have this concept, so in some cases we must manually handle NaNs
        let must_handle_nan = match op {
            RealPredicate::RealPredicateFalse => unreachable!(),
            RealPredicate::RealOEQ => false,
            RealPredicate::RealOGT => false,
            RealPredicate::RealOGE => false,
            RealPredicate::RealOLT => false,
            RealPredicate::RealOLE => false,
            RealPredicate::RealONE => false,
            RealPredicate::RealORD => unreachable!(),
            RealPredicate::RealUNO => unreachable!(),
            RealPredicate::RealUEQ => false,
            RealPredicate::RealUGT => true,
            RealPredicate::RealUGE => true,
            RealPredicate::RealULT => true,
            RealPredicate::RealULE => true,
            RealPredicate::RealUNE => false,
            RealPredicate::RealPredicateTrue => unreachable!(),
        };

        let cmp = self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs);

        if must_handle_nan {
            let is_nan = self.context.new_binary_op(
                self.location,
                BinaryOp::LogicalOr,
                self.cx.bool_type,
                // compare a value to itself to check whether it is NaN
                self.context.new_comparison(self.location, ComparisonOp::NotEquals, lhs, lhs),
                self.context.new_comparison(self.location, ComparisonOp::NotEquals, rhs, rhs),
            );

            self.context.new_binary_op(
                self.location,
                BinaryOp::LogicalOr,
                self.cx.bool_type,
                is_nan,
                cmp,
            )
        } else {
            cmp
        }
    }

    /* Miscellaneous instructions */
    fn memcpy(
        &mut self,
        dst: RValue<'gcc>,
        _dst_align: Align,
        src: RValue<'gcc>,
        _src_align: Align,
        size: RValue<'gcc>,
        flags: MemFlags,
        _tt: Option<rustc_ast::expand::typetree::FncTree>, // Autodiff TypeTrees are LLVM-only, ignored in GCC backend
    ) {
        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
        let size = self.intcast(size, self.type_size_t(), false);
        let _is_volatile = flags.contains(MemFlags::VOLATILE);
        let dst = self.pointercast(dst, self.type_i8p());
        let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
        let memcpy = self.context.get_builtin_function("memcpy");
        // FIXME(antoyo): handle aligns and is_volatile.
        self.block.add_eval(
            self.location,
            self.context.new_call(self.location, memcpy, &[dst, src, size]),
        );
    }

    fn memmove(
        &mut self,
        dst: RValue<'gcc>,
        _dst_align: Align,
        src: RValue<'gcc>,
        _src_align: Align,
        size: RValue<'gcc>,
        flags: MemFlags,
    ) {
        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported");
        let size = self.intcast(size, self.type_size_t(), false);
        let _is_volatile = flags.contains(MemFlags::VOLATILE);
        let dst = self.pointercast(dst, self.type_i8p());
        let src = self.pointercast(src, self.type_ptr_to(self.type_void()));

        let memmove = self.context.get_builtin_function("memmove");
        // FIXME(antoyo): handle is_volatile.
        self.block.add_eval(
            self.location,
            self.context.new_call(self.location, memmove, &[dst, src, size]),
        );
    }

    fn memset(
        &mut self,
        ptr: RValue<'gcc>,
        fill_byte: RValue<'gcc>,
        size: RValue<'gcc>,
        _align: Align,
        flags: MemFlags,
    ) {
        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memset not supported");
        let _is_volatile = flags.contains(MemFlags::VOLATILE);
        let ptr = self.pointercast(ptr, self.type_i8p());
        let memset = self.context.get_builtin_function("memset");
        // FIXME(antoyo): handle align and is_volatile.
        let fill_byte = self.context.new_cast(self.location, fill_byte, self.i32_type);
        let size = self.intcast(size, self.type_size_t(), false);
        self.block.add_eval(
            self.location,
            self.context.new_call(self.location, memset, &[ptr, fill_byte, size]),
        );
    }

    fn select(
        &mut self,
        cond: RValue<'gcc>,
        then_val: RValue<'gcc>,
        mut else_val: RValue<'gcc>,
    ) -> RValue<'gcc> {
        let func = self.current_func();
        let variable = func.new_local(self.location, then_val.get_type(), "selectVar");
        let then_block = func.new_block("then");
        let else_block = func.new_block("else");
        let after_block = func.new_block("after");
        self.llbb().end_with_conditional(self.location, cond, then_block, else_block);

        then_block.add_assignment(self.location, variable, then_val);
        then_block.end_with_jump(self.location, after_block);

        if !then_val.get_type().is_compatible_with(else_val.get_type()) {
            else_val = self.context.new_cast(self.location, else_val, then_val.get_type());
        }
        else_block.add_assignment(self.location, variable, else_val);
        else_block.end_with_jump(self.location, after_block);

        // NOTE: since jumps were added in a place rustc does not expect, the current block in the
        // state need to be updated.
        self.switch_to_block(after_block);

        variable.to_rvalue()
    }

    fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> {
        unimplemented!();
    }

    #[cfg(feature = "master")]
    fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> {
        self.context.new_vector_access(self.location, vec, idx).to_rvalue()
    }

    #[cfg(not(feature = "master"))]
    fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> {
        use crate::context::new_array_type;

        let vector_type = vec
            .get_type()
            .unqualified()
            .dyncast_vector()
            .expect("Called extract_element on a non-vector type");
        let element_type = vector_type.get_element_type();
        let vec_num_units = vector_type.get_num_units();
        let array_type =
            new_array_type(self.context, self.location, element_type, vec_num_units as u64);
        let array = self.context.new_bitcast(self.location, vec, array_type).to_rvalue();
        self.context.new_array_access(self.location, array, idx).to_rvalue()
    }

    fn vector_splat(&mut self, _num_elts: usize, _elt: RValue<'gcc>) -> RValue<'gcc> {
        unimplemented!();
    }

    fn extract_value(&mut self, aggregate_value: RValue<'gcc>, idx: u64) -> RValue<'gcc> {
        // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays.
        assert_eq!(idx as usize as u64, idx);
        let value_type = aggregate_value.get_type();

        if value_type.dyncast_array().is_some() {
            let index = self
                .context
                .new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
            let element = self.context.new_array_access(self.location, aggregate_value, index);
            element.get_address(self.location)
        } else if value_type.dyncast_vector().is_some() {
            panic!();
        } else if let Some(struct_type) = value_type.is_struct() {
            aggregate_value
                .access_field(self.location, struct_type.get_field(idx as i32))
                .to_rvalue()
        } else {
            panic!("Unexpected type {:?}", value_type);
        }
    }

    fn insert_value(
        &mut self,
        aggregate_value: RValue<'gcc>,
        value: RValue<'gcc>,
        idx: u64,
    ) -> RValue<'gcc> {
        // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays.
        assert_eq!(idx as usize as u64, idx);
        let value_type = aggregate_value.get_type();

        let new_val = self.current_func().new_local(None, value_type, "aggregate_value");
        self.block.add_assignment(None, new_val, aggregate_value);

        let lvalue = if value_type.dyncast_array().is_some() {
            let index = self
                .context
                .new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
            self.context.new_array_access(self.location, new_val, index)
        } else if value_type.dyncast_vector().is_some() {
            panic!();
        } else if let Some(struct_type) = value_type.is_struct() {
            new_val.access_field(None, struct_type.get_field(idx as i32))
        } else {
            panic!("Unexpected type {:?}", value_type);
        };

        let lvalue_type = lvalue.to_rvalue().get_type();
        let value =
            // NOTE: sometimes, rustc will create a value with the wrong type.
            if lvalue_type != value.get_type() {
                self.context.new_cast(self.location, value, lvalue_type)
            }
            else {
                value
            };

        self.llbb().add_assignment(self.location, lvalue, value);

        new_val.to_rvalue()
    }

    fn set_personality_fn(&mut self, _personality: Function<'gcc>) {
        #[cfg(feature = "master")]
        self.current_func().set_personality_function(_personality);
    }

    #[cfg(feature = "master")]
    fn cleanup_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
        self.set_personality_fn(pers_fn);

        // NOTE: insert the current block in a variable so that a later call to invoke knows to
        // generate a try/finally instead of a try/catch for this block.
        self.cleanup_blocks.borrow_mut().insert(self.block);

        let eh_pointer_builtin =
            self.cx.context.get_target_builtin_function("__builtin_eh_pointer");
        let zero = self.cx.context.new_rvalue_zero(self.int_type);
        let ptr = self.cx.context.new_call(self.location, eh_pointer_builtin, &[zero]);

        let value1_type = self.u8_type.make_pointer();
        let ptr = self.cx.context.new_cast(self.location, ptr, value1_type);
        let value1 = ptr;
        let value2 = zero; // FIXME(antoyo): set the proper value here (the type of exception?).

        (value1, value2)
    }

    #[cfg(not(feature = "master"))]
    fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
        let value1 = self
            .current_func()
            .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0")
            .to_rvalue();
        let value2 =
            self.current_func().new_local(self.location, self.i32_type, "landing_pad1").to_rvalue();
        (value1, value2)
    }

    fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) {
        // FIXME(antoyo): generate the correct landing pad
        self.cleanup_landing_pad(pers_fn);
    }

    #[cfg(feature = "master")]
    fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
        let exn_type = exn0.get_type();
        let exn = self.context.new_cast(self.location, exn0, exn_type);
        let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume");
        self.llbb()
            .add_eval(self.location, self.context.new_call(self.location, unwind_resume, &[exn]));
        self.unreachable();
    }

    #[cfg(not(feature = "master"))]
    fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
        self.unreachable();
    }

    fn cleanup_pad(&mut self, _parent: Option<RValue<'gcc>>, _args: &[RValue<'gcc>]) -> Funclet {
        unimplemented!();
    }

    fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option<Block<'gcc>>) {
        unimplemented!();
    }

    fn catch_pad(&mut self, _parent: RValue<'gcc>, _args: &[RValue<'gcc>]) -> Funclet {
        unimplemented!();
    }

    fn catch_switch(
        &mut self,
        _parent: Option<RValue<'gcc>>,
        _unwind: Option<Block<'gcc>>,
        _handlers: &[Block<'gcc>],
    ) -> RValue<'gcc> {
        unimplemented!();
    }

    fn get_funclet_cleanuppad(&self, _funclet: &Funclet) -> RValue<'gcc> {
        unimplemented!();
    }

    // Atomic Operations
    fn atomic_cmpxchg(
        &mut self,
        dst: RValue<'gcc>,
        cmp: RValue<'gcc>,
        src: RValue<'gcc>,
        order: AtomicOrdering,
        failure_order: AtomicOrdering,
        weak: bool,
    ) -> (RValue<'gcc>, RValue<'gcc>) {
        let expected = self.current_func().new_local(None, cmp.get_type(), "expected");
        self.llbb().add_assignment(None, expected, cmp);
        // NOTE: gcc doesn't support a failure memory model that is stronger than the success
        // memory model.
        let order = if failure_order as i32 > order as i32 { failure_order } else { order };
        let success = self.compare_exchange(dst, expected, src, order, failure_order, weak);

        // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before
        // expected so that we store expected after the call.
        let success_var = self.current_func().new_local(self.location, self.bool_type, "success");
        self.llbb().add_assignment(self.location, success_var, success);

        (expected.to_rvalue(), success_var.to_rvalue())
    }

    fn atomic_rmw(
        &mut self,
        op: AtomicRmwBinOp,
        dst: RValue<'gcc>,
        src: RValue<'gcc>,
        order: AtomicOrdering,
        ret_ptr: bool,
    ) -> RValue<'gcc> {
        let size = get_maybe_pointer_size(src);
        let name = match op {
            AtomicRmwBinOp::AtomicXchg => format!("__atomic_exchange_{}", size),
            AtomicRmwBinOp::AtomicAdd => format!("__atomic_fetch_add_{}", size),
            AtomicRmwBinOp::AtomicSub => format!("__atomic_fetch_sub_{}", size),
            AtomicRmwBinOp::AtomicAnd => format!("__atomic_fetch_and_{}", size),
            AtomicRmwBinOp::AtomicNand => format!("__atomic_fetch_nand_{}", size),
            AtomicRmwBinOp::AtomicOr => format!("__atomic_fetch_or_{}", size),
            AtomicRmwBinOp::AtomicXor => format!("__atomic_fetch_xor_{}", size),
            AtomicRmwBinOp::AtomicMax => {
                return self.atomic_extremum(ExtremumOperation::Max, dst, src, order);
            }
            AtomicRmwBinOp::AtomicMin => {
                return self.atomic_extremum(ExtremumOperation::Min, dst, src, order);
            }
            AtomicRmwBinOp::AtomicUMax => {
                return self.atomic_extremum(ExtremumOperation::Max, dst, src, order);
            }
            AtomicRmwBinOp::AtomicUMin => {
                return self.atomic_extremum(ExtremumOperation::Min, dst, src, order);
            }
        };

        let atomic_function = self.context.get_builtin_function(name);
        let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());

        // FIXME: If `ret_ptr` is true and `src` is an integer, we should really tell GCC
        // that this is a pointer operation that needs to preserve provenance -- but like LLVM,
        // GCC does not currently seems to support that.
        let void_ptr_type = self.context.new_type::<*mut ()>();
        let volatile_void_ptr_type = void_ptr_type.make_volatile();
        let dst = self.context.new_cast(self.location, dst, volatile_void_ptr_type);
        // FIXME(antoyo): not sure why, but we have the wrong type here.
        let new_src_type = atomic_function.get_param(1).to_rvalue().get_type();
        let src = self.context.new_bitcast(self.location, src, new_src_type);
        let res = self.context.new_call(self.location, atomic_function, &[dst, src, order]);
        let res_type = if ret_ptr { void_ptr_type } else { src.get_type() };
        self.context.new_cast(self.location, res, res_type)
    }

    fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) {
        let name = match scope {
            SynchronizationScope::SingleThread => "__atomic_signal_fence",
            SynchronizationScope::CrossThread => "__atomic_thread_fence",
        };
        let thread_fence = self.context.get_builtin_function(name);
        let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
        self.llbb()
            .add_eval(self.location, self.context.new_call(self.location, thread_fence, &[order]));
    }

    fn set_invariant_load(&mut self, load: RValue<'gcc>) {
        // NOTE: Hack to consider vtable function pointer as non-global-variable function pointer.
        self.normal_function_addresses.borrow_mut().insert(load);
        // FIXME(antoyo)
    }

    fn lifetime_start(&mut self, _ptr: RValue<'gcc>, _size: Size) {
        // FIXME(antoyo)
    }

    fn lifetime_end(&mut self, _ptr: RValue<'gcc>, _size: Size) {
        // FIXME(antoyo)
    }

    fn call(
        &mut self,
        typ: Type<'gcc>,
        _fn_attrs: Option<&CodegenFnAttrs>,
        fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
        func: RValue<'gcc>,
        args: &[RValue<'gcc>],
        funclet: Option<&Funclet>,
        _instance: Option<Instance<'tcx>>,
    ) -> RValue<'gcc> {
        // FIXME(antoyo): remove when having a proper API.
        let gcc_func = unsafe { std::mem::transmute::<RValue<'gcc>, Function<'gcc>>(func) };
        let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
            // FIXME(antoyo): remove when the API supports a different type for functions.
            let func: Function<'gcc> = self.cx.rvalue_as_function(func);
            self.function_call(func, args, funclet)
        } else {
            // If it's a not function that was defined, it's a function pointer.
            self.function_ptr_call(typ, fn_abi, func, args, funclet)
        };
        if let Some(_fn_abi) = fn_abi {
            // FIXME(bjorn3): Apply function attributes
        }
        call
    }

    fn tail_call(
        &mut self,
        _llty: Self::Type,
        _fn_attrs: Option<&CodegenFnAttrs>,
        _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
        _llfn: Self::Value,
        _args: &[Self::Value],
        _funclet: Option<&Self::Funclet>,
        _instance: Option<Instance<'tcx>>,
    ) {
        // FIXME: implement support for explicit tail calls like rustc_codegen_llvm.
        self.tcx.dcx().emit_fatal(errors::ExplicitTailCallsUnsupported);
    }

    fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
        // FIXME(antoyo): this does not zero-extend.
        self.gcc_int_cast(value, dest_typ)
    }

    fn cx(&self) -> &CodegenCx<'gcc, 'tcx> {
        self.cx
    }

    fn apply_attrs_to_cleanup_callsite(&mut self, _llret: RValue<'gcc>) {
        // FIXME(bjorn3): implement
    }

    fn set_span(&mut self, _span: Span) {}

    fn from_immediate(&mut self, val: Self::Value) -> Self::Value {
        if self.cx().val_ty(val) == self.cx().type_i1() {
            self.zext(val, self.cx().type_i8())
        } else {
            val
        }
    }

    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
        if scalar.is_bool() {
            return self.unchecked_utrunc(val, self.cx().type_i1());
        }
        val
    }

    fn fptoui_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        self.fptoint_sat(false, val, dest_ty)
    }

    fn fptosi_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
        self.fptoint_sat(true, val, dest_ty)
    }
}

impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
    fn fptoint_sat(
        &mut self,
        signed: bool,
        val: RValue<'gcc>,
        dest_ty: Type<'gcc>,
    ) -> RValue<'gcc> {
        let src_ty = self.cx.val_ty(val);
        let (float_ty, int_ty) = if self.cx.type_kind(src_ty) == TypeKind::Vector {
            assert_eq!(self.cx.vector_length(src_ty), self.cx.vector_length(dest_ty));
            (self.cx.element_type(src_ty), self.cx.element_type(dest_ty))
        } else {
            (src_ty, dest_ty)
        };

        // FIXME(jistone): the following was originally the fallback SSA implementation, before LLVM 13
        // added native `fptosi.sat` and `fptoui.sat` conversions, but it was used by GCC as well.
        // Now that LLVM always relies on its own, the code has been moved to GCC, but the comments are
        // still LLVM-specific. This should be updated, and use better GCC specifics if possible.

        let int_width = self.cx.int_width(int_ty);
        let float_width = self.cx.float_width(float_ty);
        // LLVM's fpto[su]i returns undef when the input val is infinite, NaN, or does not fit into the
        // destination integer type after rounding towards zero. This `undef` value can cause UB in
        // safe code (see issue #10184), so we implement a saturating conversion on top of it:
        // Semantically, the mathematical value of the input is rounded towards zero to the next
        // mathematical integer, and then the result is clamped into the range of the destination
        // integer type. Positive and negative infinity are mapped to the maximum and minimum value of
        // the destination integer type. NaN is mapped to 0.
        //
        // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
        // a value representable in int_ty.
        // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
        // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
        // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
        // representable. Note that this only works if float_ty's exponent range is sufficiently large.
        // f16 or 256 bit integers would break this property. Right now the smallest float type is f32
        // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
        // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
        // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
        // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
        fn int_max(signed: bool, int_width: u64) -> u128 {
            let shift_amount = 128 - int_width;
            if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
        }
        fn int_min(signed: bool, int_width: u64) -> i128 {
            if signed { i128::MIN >> (128 - int_width) } else { 0 }
        }

        // FIXME: rewrite using a generic function with <F: Float>.
        let compute_clamp_bounds_half = |signed: bool, int_width: u64| -> (u128, u128) {
            let rounded_min =
                ieee::Half::from_i128_r(int_min(signed, int_width), Round::TowardZero);
            //assert_eq!(rounded_min.status, Status::OK);
            let rounded_max =
                ieee::Half::from_u128_r(int_max(signed, int_width), Round::TowardZero);
            assert!(rounded_max.value.is_finite());
            (rounded_min.value.to_bits(), rounded_max.value.to_bits())
        };
        fn compute_clamp_bounds<F: Float>(signed: bool, int_width: u64) -> (u128, u128) {
            let rounded_min = F::from_i128_r(int_min(signed, int_width), Round::TowardZero);
            assert_eq!(rounded_min.status, Status::OK);
            let rounded_max = F::from_u128_r(int_max(signed, int_width), Round::TowardZero);
            assert!(rounded_max.value.is_finite());
            (rounded_min.value.to_bits(), rounded_max.value.to_bits())
        }
        // To implement saturation, we perform the following steps:
        //
        // 1. Cast val to an integer with fpto[su]i. This may result in undef.
        // 2. Compare val to f_min and f_max, and use the comparison results to select:
        //  a) int_ty::MIN if val < f_min or val is NaN
        //  b) int_ty::MAX if val > f_max
        //  c) the result of fpto[su]i otherwise
        // 3. If val is NaN, return 0.0, otherwise return the result of step 2.
        //
        // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
        // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
        // undef does not introduce any non-determinism either.
        // More importantly, the above procedure correctly implements saturating conversion.
        // Proof (sketch):
        // If val is NaN, 0 is returned by definition.
        // Otherwise, val is finite or infinite and thus can be compared with f_min and f_max.
        // This yields three cases to consider:
        // (1) if val in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
        //     saturating conversion for inputs in that range.
        // (2) if val > f_max, then val is larger than int_ty::MAX. This holds even if f_max is rounded
        //     (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
        //     than int_ty::MAX. Because val is larger than int_ty::MAX, the return value of int_ty::MAX
        //     is correct.
        // (3) if val < f_min, then val is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
        //     int_ty::MIN and therefore the return value of int_ty::MIN is correct.
        // QED.

        let float_bits_to_llval = |bx: &mut Self, bits| {
            let bits_llval = match float_width {
                16 => bx.cx().const_u16(bits as u16),
                32 => bx.cx().const_u32(bits as u32),
                64 => bx.cx().const_u64(bits as u64),
                128 => bx.cx().const_u128(bits),
                n => bug!("unsupported float width {}", n),
            };
            bx.bitcast(bits_llval, float_ty)
        };
        let (f_min, f_max) = match float_width {
            16 => compute_clamp_bounds_half(signed, int_width),
            32 => compute_clamp_bounds::<ieee::Single>(signed, int_width),
            64 => compute_clamp_bounds::<ieee::Double>(signed, int_width),
            128 => compute_clamp_bounds::<ieee::Quad>(signed, int_width),
            n => bug!("unsupported float width {}", n),
        };
        let f_min = float_bits_to_llval(self, f_min);
        let f_max = float_bits_to_llval(self, f_max);
        let int_max = self.cx.const_uint_big(int_ty, int_max(signed, int_width));
        let int_min = self.cx.const_uint_big(int_ty, int_min(signed, int_width) as u128);
        let zero = self.cx.const_uint(int_ty, 0);

        // If we're working with vectors, constants must be "splatted": the constant is duplicated
        // into each lane of the vector.  The algorithm stays the same, we are just using the
        // same constant across all lanes.
        let maybe_splat = |bx: &mut Self, val| {
            if bx.cx().type_kind(dest_ty) == TypeKind::Vector {
                bx.vector_splat(bx.vector_length(dest_ty), val)
            } else {
                val
            }
        };
        let f_min = maybe_splat(self, f_min);
        let f_max = maybe_splat(self, f_max);
        let int_max = maybe_splat(self, int_max);
        let int_min = maybe_splat(self, int_min);
        let zero = maybe_splat(self, zero);

        // Step 1 ...
        let fptosui_result =
            if signed { self.fptosi(val, dest_ty) } else { self.fptoui(val, dest_ty) };
        let less_or_nan = self.fcmp(RealPredicate::RealULT, val, f_min);
        let greater = self.fcmp(RealPredicate::RealOGT, val, f_max);

        // Step 2: We use two comparisons and two selects, with %s1 being the
        // result:
        //     %less_or_nan = fcmp ult %val, %f_min
        //     %greater = fcmp olt %val, %f_max
        //     %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
        //     %s1 = select %greater, int_ty::MAX, %s0
        // Note that %less_or_nan uses an *unordered* comparison. This
        // comparison is true if the operands are not comparable (i.e., if val is
        // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if
        // val is NaN.
        //
        // Performance note: Unordered comparison can be lowered to a "flipped"
        // comparison and a negation, and the negation can be merged into the
        // select. Therefore, it not necessarily any more expensive than an
        // ordered ("normal") comparison. Whether these optimizations will be
        // performed is ultimately up to the backend, but at least x86 does
        // perform them.
        let s0 = self.select(less_or_nan, int_min, fptosui_result);
        let s1 = self.select(greater, int_max, s0);

        // Step 3: NaN replacement.
        // For unsigned types, the above step already yielded int_ty::MIN == 0 if val is NaN.
        // Therefore we only need to execute this step for signed integer types.
        if signed {
            // LLVM has no isNaN predicate, so we use (val == val) instead
            let cmp = self.fcmp(RealPredicate::RealOEQ, val, val);
            self.select(cmp, s1, zero)
        } else {
            s1
        }
    }

    #[cfg(feature = "master")]
    pub fn shuffle_vector(
        &mut self,
        v1: RValue<'gcc>,
        v2: RValue<'gcc>,
        mask: RValue<'gcc>,
    ) -> RValue<'gcc> {
        // NOTE: if the `mask` is a constant value, the following code will copy it in many places,
        // which will make GCC create a lot (+4000) local variables in some cases.
        // So we assign it to an explicit local variable once to avoid this.
        let func = self.current_func();
        let mask_var = func.new_local(self.location, mask.get_type(), "mask");
        let block = self.block;
        block.add_assignment(self.location, mask_var, mask);
        let mask = mask_var.to_rvalue();

        // FIXME(antoyo): use a recursive unqualified() here.
        let vector_type = v1.get_type().unqualified().dyncast_vector().expect("vector type");
        let element_type = vector_type.get_element_type();
        let vec_num_units = vector_type.get_num_units();

        let mask_element_type = if element_type.is_integral() {
            element_type
        } else {
            #[cfg(feature = "master")]
            {
                self.cx.type_ix(element_type.get_size() as u64 * 8)
            }
            #[cfg(not(feature = "master"))]
            self.int_type
        };

        // NOTE: this condition is needed because we call shuffle_vector in the implementation of
        // simd_gather.
        let mut mask_elements = if let Some(vector_type) = mask.get_type().dyncast_vector() {
            let mask_num_units = vector_type.get_num_units();
            let mut mask_elements = vec![];
            for i in 0..mask_num_units {
                let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
                mask_elements.push(self.context.new_cast(
                    self.location,
                    self.extract_element(mask, index).to_rvalue(),
                    mask_element_type,
                ));
            }
            mask_elements
        } else {
            let struct_type = mask.get_type().is_struct().expect("mask should be of struct type");
            let mask_num_units = struct_type.get_field_count();
            let mut mask_elements = vec![];
            for i in 0..mask_num_units {
                let field = struct_type.get_field(i as i32);
                mask_elements.push(self.context.new_cast(
                    self.location,
                    mask.access_field(self.location, field).to_rvalue(),
                    mask_element_type,
                ));
            }
            mask_elements
        };
        let mask_num_units = mask_elements.len();

        // NOTE: the mask needs to be the same length as the input vectors, so add the missing
        // elements in the mask if needed.
        for _ in mask_num_units..vec_num_units {
            mask_elements.push(self.context.new_rvalue_zero(mask_element_type));
        }

        let result_type = self.context.new_vector_type(element_type, mask_num_units as u64);
        let (v1, v2) = if vec_num_units < mask_num_units {
            // NOTE: the mask needs to be the same length as the input vectors, so join the 2
            // vectors and create a dummy second vector.
            let mut elements = vec![];
            for i in 0..vec_num_units {
                elements.push(
                    self.context
                        .new_vector_access(
                            self.location,
                            v1,
                            self.context.new_rvalue_from_int(self.int_type, i as i32),
                        )
                        .to_rvalue(),
                );
            }
            for i in 0..(mask_num_units - vec_num_units) {
                elements.push(
                    self.context
                        .new_vector_access(
                            self.location,
                            v2,
                            self.context.new_rvalue_from_int(self.int_type, i as i32),
                        )
                        .to_rvalue(),
                );
            }
            let v1 = self.context.new_rvalue_from_vector(self.location, result_type, &elements);
            let zero = self.context.new_rvalue_zero(element_type);
            let v2 = self.context.new_rvalue_from_vector(
                self.location,
                result_type,
                &vec![zero; mask_num_units],
            );
            (v1, v2)
        } else {
            (v1, v2)
        };

        let new_mask_num_units = std::cmp::max(mask_num_units, vec_num_units);
        let mask_type = self.context.new_vector_type(mask_element_type, new_mask_num_units as u64);
        let mask = self.context.new_rvalue_from_vector(self.location, mask_type, &mask_elements);
        let result = self.context.new_rvalue_vector_perm(self.location, v1, v2, mask);

        if vec_num_units != mask_num_units {
            // NOTE: if padding was added, only select the number of elements of the masks to
            // remove that padding in the result.
            let mut elements = vec![];
            for i in 0..mask_num_units {
                elements.push(
                    self.context
                        .new_vector_access(
                            self.location,
                            result,
                            self.context.new_rvalue_from_int(self.int_type, i as i32),
                        )
                        .to_rvalue(),
                );
            }
            self.context.new_rvalue_from_vector(self.location, result_type, &elements)
        } else {
            result
        }
    }

    #[cfg(not(feature = "master"))]
    pub fn shuffle_vector(
        &mut self,
        _v1: RValue<'gcc>,
        _v2: RValue<'gcc>,
        _mask: RValue<'gcc>,
    ) -> RValue<'gcc> {
        unimplemented!();
    }

    #[cfg(feature = "master")]
    pub fn vector_reduce<F>(&mut self, src: RValue<'gcc>, op: F) -> RValue<'gcc>
    where
        F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>,
    {
        let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
        let element_type = vector_type.get_element_type();
        let mask_element_type = self.type_ix(element_type.get_size() as u64 * 8);
        let element_count = vector_type.get_num_units();
        let mut vector_elements = vec![];
        for i in 0..element_count {
            vector_elements.push(i);
        }
        let mask_type = self.context.new_vector_type(mask_element_type, element_count as u64);
        let mut shift = 1;
        let mut res = src;
        while shift < element_count {
            let vector_elements: Vec<_> = vector_elements
                .iter()
                .map(|i| {
                    self.context.new_rvalue_from_int(
                        mask_element_type,
                        ((i + shift) % element_count) as i32,
                    )
                })
                .collect();
            let mask =
                self.context.new_rvalue_from_vector(self.location, mask_type, &vector_elements);
            let shifted = self.context.new_rvalue_vector_perm(self.location, res, res, mask);
            shift *= 2;
            res = op(res, shifted, self.context);
        }
        self.context
            .new_vector_access(self.location, res, self.context.new_rvalue_zero(self.int_type))
            .to_rvalue()
    }

    #[cfg(not(feature = "master"))]
    pub fn vector_reduce<F>(&mut self, _src: RValue<'gcc>, _op: F) -> RValue<'gcc>
    where
        F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>,
    {
        unimplemented!();
    }

    pub fn vector_reduce_op(&mut self, src: RValue<'gcc>, op: BinaryOp) -> RValue<'gcc> {
        let loc = self.location;
        self.vector_reduce(src, |a, b, context| context.new_binary_op(loc, op, a.get_type(), a, b))
    }

    pub fn vector_reduce_fadd_reassoc(
        &mut self,
        _acc: RValue<'gcc>,
        _src: RValue<'gcc>,
    ) -> RValue<'gcc> {
        unimplemented!();
    }

    #[cfg(feature = "master")]
    pub fn vector_reduce_fadd(&mut self, acc: RValue<'gcc>, src: RValue<'gcc>) -> RValue<'gcc> {
        let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
        let element_count = vector_type.get_num_units();
        (0..element_count)
            .map(|i| {
                self.context
                    .new_vector_access(
                        self.location,
                        src,
                        self.context.new_rvalue_from_int(self.int_type, i as _),
                    )
                    .to_rvalue()
            })
            .fold(acc, |x, i| x + i)
    }

    #[cfg(not(feature = "master"))]
    pub fn vector_reduce_fadd(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
        unimplemented!();
    }

    pub fn vector_reduce_fmul_reassoc(
        &mut self,
        _acc: RValue<'gcc>,
        _src: RValue<'gcc>,
    ) -> RValue<'gcc> {
        unimplemented!();
    }

    #[cfg(feature = "master")]
    pub fn vector_reduce_fmul(&mut self, acc: RValue<'gcc>, src: RValue<'gcc>) -> RValue<'gcc> {
        let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
        let element_count = vector_type.get_num_units();
        (0..element_count)
            .map(|i| {
                self.context
                    .new_vector_access(
                        self.location,
                        src,
                        self.context.new_rvalue_from_int(self.int_type, i as _),
                    )
                    .to_rvalue()
            })
            .fold(acc, |x, i| x * i)
    }

    #[cfg(not(feature = "master"))]
    pub fn vector_reduce_fmul(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
        unimplemented!()
    }

    // Inspired by Hacker's Delight min implementation.
    pub fn vector_reduce_min(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
        let loc = self.location;
        self.vector_reduce(src, |a, b, context| {
            let differences_or_zeros = difference_or_zero(loc, a, b, context);
            context.new_binary_op(loc, BinaryOp::Plus, b.get_type(), b, differences_or_zeros)
        })
    }

    // Inspired by Hacker's Delight max implementation.
    pub fn vector_reduce_max(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
        let loc = self.location;
        self.vector_reduce(src, |a, b, context| {
            let differences_or_zeros = difference_or_zero(loc, a, b, context);
            context.new_binary_op(loc, BinaryOp::Minus, a.get_type(), a, differences_or_zeros)
        })
    }

    /// Emits a SIMD min/max operation for floats. The semantics for each lane are: if one
    /// side is NaN (QNaN or SNaN), the other side is returned.
    fn vector_extremum(
        &mut self,
        a: RValue<'gcc>,
        b: RValue<'gcc>,
        direction: ExtremumOperation,
    ) -> RValue<'gcc> {
        let vector_type = a.get_type();

        // Mask out the NaNs (both QNaN and SNaN) in b and replace them with the corresponding lane
        // in a, so when a and b get compared & spliced together, we get the numeric values instead
        // of NaNs.
        let b_nan_mask = self.context.new_comparison(self.location, ComparisonOp::NotEquals, b, b);
        let mask_type = b_nan_mask.get_type();
        let b_nan_mask_inverted =
            self.context.new_unary_op(self.location, UnaryOp::BitwiseNegate, mask_type, b_nan_mask);
        let a_cast = self.context.new_bitcast(self.location, a, mask_type);
        let b_cast = self.context.new_bitcast(self.location, b, mask_type);
        let res = (b_nan_mask & a_cast) | (b_nan_mask_inverted & b_cast);
        let b = self.context.new_bitcast(self.location, res, vector_type);

        // now do the actual comparison
        let comparison_op = match direction {
            ExtremumOperation::Min => ComparisonOp::LessThan,
            ExtremumOperation::Max => ComparisonOp::GreaterThan,
        };
        let cmp = self.context.new_comparison(self.location, comparison_op, a, b);
        let cmp_inverted =
            self.context.new_unary_op(self.location, UnaryOp::BitwiseNegate, cmp.get_type(), cmp);
        let res = (cmp & a_cast) | (cmp_inverted & res);
        self.context.new_bitcast(self.location, res, vector_type)
    }

    pub fn vector_minimum_number_nsz(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.vector_extremum(a, b, ExtremumOperation::Min)
    }

    pub fn vector_maximum_number_nsz(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
        self.vector_extremum(a, b, ExtremumOperation::Max)
    }

    pub fn vector_select(
        &mut self,
        cond: RValue<'gcc>,
        then_val: RValue<'gcc>,
        else_val: RValue<'gcc>,
    ) -> RValue<'gcc> {
        // cond is a vector of integers, not of bools.
        let vector_type = cond.get_type().unqualified().dyncast_vector().expect("vector type");
        let num_units = vector_type.get_num_units();
        let element_type = vector_type.get_element_type();

        #[cfg(feature = "master")]
        let (cond, element_type) = {
            // FIXME(antoyo): dyncast_vector should not require a call to unqualified.
            let then_val_vector_type =
                then_val.get_type().unqualified().dyncast_vector().expect("vector type");
            let then_val_element_type = then_val_vector_type.get_element_type();
            let then_val_element_size = then_val_element_type.get_size();

            // NOTE: the mask needs to be of the same size as the other arguments in order for the &
            // operation to work.
            if then_val_element_size != element_type.get_size() {
                let new_element_type = self.type_ix(then_val_element_size as u64 * 8);
                let new_vector_type =
                    self.context.new_vector_type(new_element_type, num_units as u64);
                let cond = self.context.convert_vector(self.location, cond, new_vector_type);
                (cond, new_element_type)
            } else {
                (cond, element_type)
            }
        };

        let cond_type = cond.get_type();

        let zeros = vec![self.context.new_rvalue_zero(element_type); num_units];
        let zeros = self.context.new_rvalue_from_vector(self.location, cond_type, &zeros);

        let result_type = then_val.get_type();

        let masks =
            self.context.new_comparison(self.location, ComparisonOp::NotEquals, cond, zeros);
        // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make
        // the & operation work.
        let then_val = self.bitcast_if_needed(then_val, masks.get_type());
        let then_vals = masks & then_val;

        let minus_ones = vec![self.context.new_rvalue_from_int(element_type, -1); num_units];
        let minus_ones = self.context.new_rvalue_from_vector(self.location, cond_type, &minus_ones);
        let inverted_masks = masks ^ minus_ones;
        // NOTE: sometimes, the type of else_val can be different than the type of then_val in
        // libgccjit (vector of int vs vector of int32_t), but they should be the same for the AND
        // operation to work.
        // FIXME: remove bitcast now that vector types can be compared?
        let else_val = self.context.new_bitcast(self.location, else_val, then_val.get_type());
        let else_vals = inverted_masks & else_val;

        let res = then_vals | else_vals;
        self.bitcast_if_needed(res, result_type)
    }

    // GCC doesn't like deeply nested expressions.
    // By assigning intermediate expressions to a variable, this allow us to avoid deeply nested
    // expressions and GCC will use much less RAM.
    fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> {
        let var = self.current_func().new_local(self.location, value.get_type(), "opResult");
        self.llbb().add_assignment(self.location, var, value);
        var.to_rvalue()
    }
}

fn difference_or_zero<'gcc>(
    loc: Option<Location<'gcc>>,
    a: RValue<'gcc>,
    b: RValue<'gcc>,
    context: &'gcc Context<'gcc>,
) -> RValue<'gcc> {
    let difference = a - b;
    let masks = context.new_comparison(loc, ComparisonOp::GreaterThanEquals, b, a);
    // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make
    // the & operation work.
    let a_type = a.get_type();
    let masks =
        if masks.get_type() != a_type { context.new_bitcast(loc, masks, a_type) } else { masks };
    difference & masks
}

impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> {
    fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> {
        // Forward to the `get_static` method of `CodegenCx`
        self.cx().get_static(def_id).get_address(self.location)
    }
}

impl<'tcx> HasTypingEnv<'tcx> for Builder<'_, '_, 'tcx> {
    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
        self.cx.typing_env()
    }
}

impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> {
    fn target_spec(&self) -> &Target {
        self.cx.target_spec()
    }
}

impl<'tcx> HasX86AbiOpt for Builder<'_, '_, 'tcx> {
    fn x86_abi_opt(&self) -> X86Abi {
        self.cx.x86_abi_opt()
    }
}

pub trait ToGccComp {
    fn to_gcc_comparison(&self) -> ComparisonOp;
}

impl ToGccComp for IntPredicate {
    fn to_gcc_comparison(&self) -> ComparisonOp {
        match *self {
            IntPredicate::IntEQ => ComparisonOp::Equals,
            IntPredicate::IntNE => ComparisonOp::NotEquals,
            IntPredicate::IntUGT => ComparisonOp::GreaterThan,
            IntPredicate::IntUGE => ComparisonOp::GreaterThanEquals,
            IntPredicate::IntULT => ComparisonOp::LessThan,
            IntPredicate::IntULE => ComparisonOp::LessThanEquals,
            IntPredicate::IntSGT => ComparisonOp::GreaterThan,
            IntPredicate::IntSGE => ComparisonOp::GreaterThanEquals,
            IntPredicate::IntSLT => ComparisonOp::LessThan,
            IntPredicate::IntSLE => ComparisonOp::LessThanEquals,
        }
    }
}

impl ToGccComp for RealPredicate {
    fn to_gcc_comparison(&self) -> ComparisonOp {
        // FIXME(antoyo): check that ordered vs non-ordered is respected.
        match *self {
            RealPredicate::RealPredicateFalse => unreachable!(),
            RealPredicate::RealOEQ => ComparisonOp::Equals,
            RealPredicate::RealOGT => ComparisonOp::GreaterThan,
            RealPredicate::RealOGE => ComparisonOp::GreaterThanEquals,
            RealPredicate::RealOLT => ComparisonOp::LessThan,
            RealPredicate::RealOLE => ComparisonOp::LessThanEquals,
            RealPredicate::RealONE => ComparisonOp::NotEquals,
            RealPredicate::RealORD => unreachable!(),
            RealPredicate::RealUNO => unreachable!(),
            RealPredicate::RealUEQ => ComparisonOp::Equals,
            RealPredicate::RealUGT => ComparisonOp::GreaterThan,
            RealPredicate::RealUGE => ComparisonOp::GreaterThan,
            RealPredicate::RealULT => ComparisonOp::LessThan,
            RealPredicate::RealULE => ComparisonOp::LessThan,
            RealPredicate::RealUNE => ComparisonOp::NotEquals,
            RealPredicate::RealPredicateTrue => unreachable!(),
        }
    }
}

#[repr(C)]
#[expect(non_camel_case_types)]
enum MemOrdering {
    __ATOMIC_RELAXED,
    __ATOMIC_CONSUME,
    __ATOMIC_ACQUIRE,
    __ATOMIC_RELEASE,
    __ATOMIC_ACQ_REL,
    __ATOMIC_SEQ_CST,
}

trait ToGccOrdering {
    fn to_gcc(self) -> i32;
}

impl ToGccOrdering for AtomicOrdering {
    fn to_gcc(self) -> i32 {
        use MemOrdering::*;

        let ordering = match self {
            AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // FIXME(antoyo): check if that's the same.
            AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
            AtomicOrdering::Release => __ATOMIC_RELEASE,
            AtomicOrdering::AcqRel => __ATOMIC_ACQ_REL,
            AtomicOrdering::SeqCst => __ATOMIC_SEQ_CST,
        };
        ordering as i32
    }
}

// Needed because gcc 12 `get_size()` doesn't work on pointers.
#[cfg(feature = "master")]
fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
    value.get_type().get_size()
}

#[cfg(not(feature = "master"))]
fn get_maybe_pointer_size(value: RValue<'_>) -> u32 {
    let type_ = value.get_type();
    if type_.get_pointee().is_some() { size_of::<*const ()>() as _ } else { type_.get_size() }
}
