remir_llvm 1.0.0

The LLVM binding for the Remir library
use std::hint::unreachable_unchecked;

use inkwell::intrinsics::Intrinsic;
use remir::{block::BlockInstruction, insts::Instruction, module::Module};

use crate::{LLVMBridge, llvm_to_base, llvm_to_base_returnless, utils::LLVMBasicValue};

pub fn bridge_llvm_hints_instruction(
    instruction: BlockInstruction,
    bridge: &mut LLVMBridge,
    module: &mut Module,
) -> Result<Option<LLVMBasicValue>, ()> {
    let res = match &instruction.instruction {
        Instruction::Unreachable => {
            llvm_to_base_returnless!(bridge.builder.build_unreachable());

            None
        }

        Instruction::BitCast { src, into } => {
            let src = bridge.values[&src.inst_ind].inner.clone();
            let into = bridge.type_storage.convert(into.clone()).inner;

            let res = llvm_to_base!(bridge.builder.build_bit_cast(src, into, ""));

            Some(res)
        }

        Instruction::Crash { message: _ } => {
            let trap_fn = Intrinsic::find("llvm.trap")
                .unwrap()
                .get_declaration(&bridge.modules[&module.name], &[])
                .unwrap();

            llvm_to_base_returnless!(bridge.builder.build_call(trap_fn, &[], ""));
            llvm_to_base_returnless!(bridge.builder.build_unreachable());

            None
        }

        Instruction::Assume { val } => {
            let val = bridge.values[&val.base.inst_ind].into_int_value();

            let assume_fn = Intrinsic::find("llvm.assume")
                .unwrap()
                .get_declaration(&bridge.modules[&module.name], &[])
                .unwrap();

            llvm_to_base_returnless!(bridge.builder.build_call(assume_fn, &[val.into()], ""));

            None
        }

        _ => unsafe { unreachable_unchecked() },
    };

    if res.is_some() {
        return Ok(Some(LLVMBasicValue::new(res.unwrap(), &bridge.ctx)));
    }

    return Ok(None);
}