remir_llvm 1.0.0

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

use inkwell::{
    module::Linkage,
    types::StringRadix,
    values::{BasicValueEnum, IntValue},
};
use remir::{block::BlockInstruction, insts::Instruction, module::Module, values::ValueType};

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

pub fn bridge_llvm_const_instruction(
    instruction: BlockInstruction,
    bridge: &mut LLVMBridge,
    module: &mut Module,
) -> Result<Option<LLVMBasicValue>, ()> {
    let res: Option<BasicValueEnum<'static>> = match &instruction.instruction {
        Instruction::ConstInt { val, size, signed } => {
            let ty = bridge
                .type_storage
                .convert(ValueType::Int(*signed, *size))
                .into_int_type();

            let res = ty
                .const_int_from_string(&val.to_string(), StringRadix::Decimal)
                .unwrap();

            Some(res.into())
        }

        Instruction::ConstFloat { val, size } => {
            let ty = bridge
                .type_storage
                .convert(ValueType::Float(*size))
                .into_float_type();

            let res = unsafe { ty.const_float_from_string(&val.to_string()) };

            Some(res.into())
        }

        Instruction::ConstPointer { addr } => {
            let int_ty = bridge
                .type_storage
                .convert(ValueType::Int(false, 64))
                .into_int_type();

            let ty = bridge
                .type_storage
                .convert(ValueType::Pointer(Box::new(ValueType::Unknown)))
                .into_pointer_type();

            let addr = int_ty.const_int(*addr as u64, false);

            let ptr = llvm_to_base!(bridge.builder.build_int_to_ptr(addr, ty, ""));

            Some(ptr.into())
        }

        Instruction::ConstString { str } => {
            let bytes = str.as_bytes();
            let byte_type = bridge
                .type_storage
                .convert(ValueType::Int(false, 8))
                .into_int_type();

            let arr_type = byte_type.array_type((bytes.len() + 1) as u32);

            let global = bridge.modules[&module.name].add_global(arr_type, None, "");

            global.set_linkage(Linkage::Private);
            global.set_constant(true);
            global.set_unnamed_addr(true);

            let mut vals: Vec<IntValue> = bytes
                .iter()
                .map(|b| byte_type.const_int(*b as u64, false))
                .collect();

            vals.push(byte_type.const_zero());

            global.set_initializer(&byte_type.const_array(&vals));

            Some(global.as_pointer_value().into())
        }

        Instruction::ConstStruct { ty, values } => {
            let ty = bridge.type_storage.convert(ty.clone()).into_struct_type();
            let mut vals = vec![];

            for value in values {
                vals.push(bridge.values[&value.inst_ind].clone().inner);
            }

            let val = ty.const_named_struct(&vals).into();

            Some(val)
        }

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

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

    return Ok(None);
}