1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::{
    cell::RefCell,
    collections::HashMap,
    ops::{AddAssign, DerefMut},
};

use crate::insts::ImmByte;

/*
#[derive(Debug, Clone, Default)]
pub struct CallInst(pub JumpInst);

*/

#[derive(Debug, Clone, Default)]
pub struct JumpInst {
    pub opcodes: Vec<u8>,
    pub label: String,
    pub modify_range: (usize, usize),
}

impl JumpInst {
    pub fn from(opcodes: Vec<u8>, imm_byte: ImmByte, label: String) -> Self {
        let right = opcodes.len();
        let left = right
            - match imm_byte {
                ImmByte::Bit8 => 1,
                ImmByte::Bit16 => 2,
                ImmByte::Bit32 => 4,
                ImmByte::Bit64 => 8,
            };
        JumpInst {
            opcodes,
            label,
            modify_range: (left, right),
        }
    }
    pub fn len(&self) -> usize {
        self.opcodes.len()
    }
}

#[derive(Debug, Clone)]
pub struct LinkError(pub String);

#[derive(Debug, Clone)]
pub enum InstUnit {
    Inst(Vec<u8>),
    JumpInst(JumpInst),
    // CallInst(CallInst),
}

impl InstUnit {
    pub fn len(&self) -> usize {
        match self {
            InstUnit::Inst(inst) => inst.len(),
            InstUnit::JumpInst(jump_inst) => jump_inst.len(),
            // InstUnit::CallInst(call_inst) => call_inst.0.len(),
        }
    }
}

#[derive(Debug, Clone, Default)]
pub struct InstBuffer {
    pub buf: RefCell<Vec<InstUnit>>,
    pub label_buf: RefCell<HashMap<String, u32>>,
    pub offset: RefCell<u32>,
}

impl InstBuffer {
    pub fn len(&self) -> usize {
        self.buf.borrow().len()
    }

    pub fn inst(&self, i: Vec<u8>) {
        self.offset
            .borrow_mut()
            .deref_mut()
            .add_assign(i.len() as u32);
        self.buf.borrow_mut().push(InstUnit::Inst(i));
    }

    pub fn jump(&self, i: JumpInst) {
        self.offset
            .borrow_mut()
            .deref_mut()
            .add_assign(i.len() as u32);
        self.buf.borrow_mut().push(InstUnit::JumpInst(i));
    }

    pub fn label(&self, label: String) {
        self.label_buf
            .borrow_mut()
            .insert(label, self.offset.borrow().clone());
    }

    pub fn dump(&self, base_addr: u32, buf: &mut Vec<u8>) -> Result<(), LinkError> {
        for inst in self.buf.borrow().iter() {
            match inst {
                InstUnit::Inst(i) => {
                    buf.extend(i.iter());
                }
                InstUnit::JumpInst(j) => {
                    let obj = self
                        .label_buf
                        .borrow()
                        .get(&j.label)
                        .cloned()
                        .ok_or(LinkError(j.label.clone()))?;
                    let obj = base_addr + obj;
                    buf.extend(j.opcodes[..j.modify_range.0].iter());
                    buf.extend(obj.to_ne_bytes());
                    buf.extend(j.opcodes[j.modify_range.1..].iter());
                } /*
                  InstUnit::CallInst(j) => {
                      let j = &j.0;
                      let obj = fun_table.get(&j.label).ok_or(LinkError::FunctionNotFound(j.label.clone()))?;
                      buf.extend(j.opcodes[..j.modify_range.0].iter());
                      buf.extend(obj.to_ne_bytes());
                      buf.extend(j.opcodes[j.modify_range.1..].iter());
                  }
                   */
            }
        }
        Ok(())
    }
}