remir_llvm 1.0.0

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

use remir::{block::BlockInstruction, insts::Instruction};

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

pub fn bridge_llvm_branch_instruction(
    instruction: BlockInstruction,
    bridge: &mut LLVMBridge,
) -> Result<Option<LLVMBasicValue>, ()> {
    let res = match &instruction.instruction {
        Instruction::UncondBr { branch } => {
            let block = &bridge.blocks[branch];

            llvm_to_base_returnless!(
                bridge
                    .builder
                    .build_unconditional_branch(block.inner.clone())
            );

            None
        }

        Instruction::Condbr {
            cond,
            true_label,
            false_label,
        } => {
            let cond = bridge.values[&cond.base.inst_ind].into_int_value();

            let true_label = bridge.blocks[true_label].inner.clone();
            let false_label = bridge.blocks[false_label].inner.clone();

            llvm_to_base_returnless!(bridge.builder.build_conditional_branch(
                cond,
                true_label,
                false_label
            ));

            None
        }

        Instruction::IndirectBranch {
            target,
            destinations,
        } => {
            let target = bridge.values[&target.base.inst_ind].into_pointer_value();
            let mut dests = vec![];

            for destination in destinations {
                dests.push(bridge.blocks[destination].inner.clone());
            }

            llvm_to_base_returnless!(bridge.builder.build_indirect_branch(target, &dests));
            None
        }

        Instruction::Phi { label_set } => {
            let ty = bridge
                .type_storage
                .convert(label_set[0].1.value_type.clone());

            let phi = llvm_to_base!(bridge.builder.build_phi(ty.inner, ""));

            for choice in label_set {
                let block = bridge.blocks[&choice.0].clone();
                let value = bridge.values[&choice.1.inst_ind].clone();

                phi.add_incoming(&[(&value.inner, block.inner)]);
            }

            Some(phi.as_basic_value())
        }

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

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

    return Ok(None);
}