vicis 0.1.0

Manipulate LLVM-IR in Pure Rust
Documentation
use crate::ir::{
    function::{
        instruction::{InstructionId, Opcode},
        Data, Function,
    },
    module::Module,
    value::Value,
};

pub fn run_on_module(module: &mut Module) {
    for (_, function) in module.functions_mut().iter_mut() {
        run_on_function(function);
    }
}

pub fn run_on_function(func: &mut Function) {
    let mut worklist = vec![];
    let mut elimination_list = vec![];

    for block in func.layout.block_iter() {
        for inst in func.layout.inst_iter(block) {
            check_if_elimination_possible(&func.data, inst, &mut elimination_list, &mut worklist)
        }
    }

    while let Some(inst) = elimination_list.pop() {
        func.remove_inst(inst).unwrap();
    }

    while let Some(inst) = worklist.pop() {
        check_if_elimination_possible(&func.data, inst, &mut elimination_list, &mut worklist);
        while let Some(inst) = elimination_list.pop() {
            func.remove_inst(inst).unwrap();
        }
    }
}

fn check_if_elimination_possible(
    data: &Data,
    inst: InstructionId,
    elimination_list: &mut Vec<InstructionId>,
    worklist: &mut Vec<InstructionId>,
) {
    let inst = data.inst_ref(inst);
    let do_not_eliminate =
        matches!(inst.opcode, Opcode::Store | Opcode::Call) || inst.opcode.is_terminator();
    if do_not_eliminate {
        return;
    }
    if inst.users.len() == 0 {
        elimination_list.push(inst.id.unwrap());
        for arg in inst
            .operand
            .args()
            .iter()
            .filter_map(|&arg| match data.value_ref(arg) {
                Value::Instruction(id) => Some(*id),
                _ => None,
            })
        {
            worklist.push(arg)
        }
    }
}