Skip to content

Commit

Permalink
Lua: implements simple Add instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
sbwtw committed May 26, 2024
1 parent 91309c1 commit 788cfe8
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 100 deletions.
64 changes: 54 additions & 10 deletions lib/src/backend/lua/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,19 @@ pub enum LuaByteCode {
/// A B C: UpValue[A][K[B]:string] := RK(C)
SetTabUp(Reg, u8, RK),

/// A B C: R[A] := R[B] + K[C]:number
AddK(Reg, Reg, ConstIdx),

/// A B C: R[A] := R[B] + R[C]
Add(Reg, Reg, Reg),

/// A B C call C metamethod over R[A] and R[B]
MMBin(Reg, Reg, ConstIdx),
/// A sB C k call C metamethod over R[A] and sB
MMBinI(Reg, i32, ConstIdx),
/// A B C k call C metamethod over R[A] and K[B]
MMBinK(Reg, ConstIdx, ConstIdx),

/// A B k: if ((R[A] == R[B]) ~= k) then pc++
Eq(Reg, Reg, u8),

Expand Down Expand Up @@ -247,6 +257,10 @@ impl LuaByteCode {
LuaByteCode::Move(..) => "MOVE",
LuaByteCode::LoadI(..) => "LOADI",
LuaByteCode::Add(..) => "ADD",
LuaByteCode::AddK(..) => "ADDK",
LuaByteCode::MMBin(..) => "MMBIN",
LuaByteCode::MMBinI(..) => "MMBINI",
LuaByteCode::MMBinK(..) => "MMBINK",
LuaByteCode::Gei(..) => "GEI",
LuaByteCode::Gti(..) => "GTI",
LuaByteCode::Eq(..) => "EQ",
Expand All @@ -263,6 +277,10 @@ impl LuaByteCode {
LuaByteCode::LoadK(..) => LuaOpCode::OP_LOADK,
LuaByteCode::Move(..) => LuaOpCode::OP_MOVE,
LuaByteCode::LoadI(..) => LuaOpCode::OP_LOADI,
LuaByteCode::AddK(..) => LuaOpCode::OP_ADDK,
LuaByteCode::MMBin(..) => LuaOpCode::OP_MMBIN,
LuaByteCode::MMBinI(..) => LuaOpCode::OP_MMBINI,
LuaByteCode::MMBinK(..) => LuaOpCode::OP_MMBINK,
LuaByteCode::Add(..) => LuaOpCode::OP_ADD,
LuaByteCode::Gei(..) => LuaOpCode::OP_GEI,
LuaByteCode::Gti(..) => LuaOpCode::OP_GTI,
Expand All @@ -281,13 +299,25 @@ impl LuaByteCode {
// A B k
LuaByteCode::Eq(a, b, k) => (k as u32) << 17 | (b.num() as u32) << 9 | a.num() as u32,
// A sB k
| LuaByteCode::Gei(a, sb, c)
LuaByteCode::Gei(a, sb, c)
| LuaByteCode::Gti(a, sb, c)
| LuaByteCode::Call(a, sb, c) => (c as u32) << 17 | (sb as u32) << 9 | a.num() as u32,
// A B K
LuaByteCode::GetTabUp(a, upv, k) => {
(k as u32) << 17 | (upv as u32) << 9 | a.num() as u32
}
// RA, KB, KC with k
LuaByteCode::MMBinK(ra, kb, kc) => {
(kc as u32) << 17 | (kb as u32) << 9 | ra.num() as u32 | 1u32 << 8
}
// RA, sB, KC with k
LuaByteCode::MMBinI(ra, sb, k) => {
(k as u32) << 17 | excess_sbx!(sb) << 9 | ra.num() as u32 | 1u32 << 8
}
// RA, RB, KC
LuaByteCode::AddK(ra, rb, k) | LuaByteCode::MMBin(ra, rb, k) => {
(k as u32) << 17 | (rb.num() as u32) << 9 | ra.num() as u32
}
// A B RK
LuaByteCode::SetTabUp(a, upv, rk) => {
let c = match rk {
Expand All @@ -297,11 +327,9 @@ impl LuaByteCode {
};

c | (upv as u32) << 9 | a.num() as u32
},
// A B C all literal
LuaByteCode::Return(a, b, c) => {
(c as u32) << 17 | (b as u32) << 9 | a as u32
}
// A B C all literal
LuaByteCode::Return(a, b, c) => (c as u32) << 17 | (b as u32) << 9 | a as u32,
// ABx
LuaByteCode::LoadK(a, bx) => (bx as u32) << 8 | a.num() as u32,
// AsBx
Expand Down Expand Up @@ -346,16 +374,26 @@ impl LuaCompiledCode {
LuaByteCode::Add(a, b, c) => {
write!(s, "R{} R{} R{}", a.num(), b.num(), c.num()).unwrap();
}
// RA, KB, KC with k
LuaByteCode::MMBinK(ra, kb, kc) => {
write!(s, "R{} {kb} {kc}", ra.num()).unwrap();
}
// A B k
LuaByteCode::Eq(a, b, k) => {
write!(s, "R{} R{} {k}", a.num(), b.num()).unwrap();
}
// A sB k
LuaByteCode::Gti(a, b, c)
| LuaByteCode::Gei(a, b, c)
| LuaByteCode::Call(a, b, c) => {
LuaByteCode::Gti(a, b, c) | LuaByteCode::Gei(a, b, c) | LuaByteCode::Call(a, b, c) => {
write!(s, "R{} {b} {c}", a.num()).unwrap();
}
// RA sB KC with k
LuaByteCode::MMBinI(ra, sb, kc) => {
write!(s, "R{} {sb} {kc}", ra.num()).unwrap();
}
// RegA, RegB, K
LuaByteCode::AddK(ra, rb, k) | LuaByteCode::MMBin(ra, rb, k) => {
write!(s, "R{} R{} {k}", ra.num(), rb.num()).unwrap();
}
// Reg, Upv, K
LuaByteCode::GetTabUp(reg, upv, k) => {
write!(s, "R{} {upv} {k}", reg.num()).unwrap();
Expand All @@ -367,8 +405,9 @@ impl LuaCompiledCode {
match rk {
RK::R(r) => write!(s, "{}", r.num()),
RK::K(k) => write!(s, "{}k", k),
}.unwrap();
},
}
.unwrap();
}
// ABC with k
LuaByteCode::Return(a, b, c) => {
write!(s, "{a} {b} {c}").unwrap();
Expand All @@ -392,6 +431,11 @@ impl LuaCompiledCode {
}

match code {
LuaByteCode::MMBin(_, _, k)
| LuaByteCode::MMBinI(_, _, k)
| LuaByteCode::MMBinK(_, _, k) => {
write!(s, " ; {}", self.constants[*k as usize]).unwrap();
}
LuaByteCode::LoadK(a, bx) => {
write!(s, " ; K[{}] = {}", bx, self.constants[*bx as usize]).unwrap();
}
Expand Down
123 changes: 81 additions & 42 deletions lib/src/backend/lua/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use log::*;
use smallvec::{smallvec, SmallVec};
use std::mem;
use std::rc::Rc;
use crate::backend::lua::register::Reg::R;

type ConstIdx = u8;

Expand Down Expand Up @@ -82,6 +81,18 @@ pub struct LuaBackendStates {
access_mode: LuaAccessMode,
}

impl LuaBackendStates {
fn rk(&self) -> RK {
if !self.registers.is_empty() {
RK::R(self.registers[0])
} else if let Some(k) = self.const_idx {
RK::K(k)
} else {
unreachable!()
}
}
}

impl Default for LuaBackendStates {
fn default() -> Self {
Self {
Expand Down Expand Up @@ -117,7 +128,7 @@ impl LuaBackend {

#[inline]
fn code_settabup(&mut self, up_idx: u8, rk: RK) {
self.push_code(LuaByteCode::SetTabUp(R(0), up_idx, rk));
self.push_code(LuaByteCode::SetTabUp(Reg::R(0), up_idx, rk));
}

#[inline]
Expand Down Expand Up @@ -147,6 +158,32 @@ impl LuaBackend {
self.byte_codes.push(code)
}

#[inline]
fn code_add(&mut self, dst: Reg, op0: RK, op1: RK) {
let addk = self.add_string_constant("__add");

match (op0, op1) {
(RK::K(k), RK::R(r)) | (RK::R(r), RK::K(k)) => {
self.push_code(LuaByteCode::AddK(dst, r, k));
self.push_code(LuaByteCode::MMBinK(dst, k, addk));
}
(RK::K(k1), RK::K(k2)) => {
self.push_code(LuaByteCode::LoadK(dst, k1));
self.push_code(LuaByteCode::AddK(dst, dst, k2));
self.push_code(LuaByteCode::MMBinK(dst, k2, addk));
}
(RK::R(r1), RK::R(r2)) => {
self.push_code(LuaByteCode::Add(dst, r1, r2));
self.push_code(LuaByteCode::MMBin(r1, r2, addk));
}
}
}

#[inline]
fn code_eq(&mut self, dst: Reg, op0: RK, op1: RK) {
todo!()
}

#[inline]
fn add_constant(&mut self, v: &LiteralValue) -> ConstIdx {
match v {
Expand Down Expand Up @@ -278,11 +315,14 @@ impl CodeGenBackend for LuaBackend {
// index: 0,
// kind: 0,
// });
self.upvalue_table.insert(StString::empty(), LuaUpValue {
stack: 1,
index: 0,
kind: LuaVarKind::VDKREG,
});
self.upvalue_table.insert(
StString::empty(),
LuaUpValue {
stack: 1,
index: 0,
kind: LuaVarKind::VDKREG,
},
);

let mut fun = f.write();
self.push_attribute_with_scope(fun_scope);
Expand Down Expand Up @@ -329,22 +369,21 @@ impl AstVisitorMut for LuaBackend {
fn visit_literal_mut(&mut self, literal: &mut LiteralExpression) {
trace!("LuaGen: literal expression: {:?}", literal);

// // Literals can't WRITE
// assert!(!self.top_attribute().access_mode != LuaAccessMode::Write);
let access = self.top_attribute().access_mode;

if matches!(
self.top_attribute().access_mode,
LuaAccessMode::ReadRegisterOnly
) {
let r = match self.top_attribute().registers.first() {
Some(r) => *r,
_ => self.reg_mgr.alloc_hard(),
};
// Literals can't WRITE
assert!(!matches!(access, LuaAccessMode::Write));

self.code_load(r, literal.literal());
} else {
self.top_attribute().const_idx = Some(self.add_constant(literal.literal()))
}
self.top_attribute().const_idx = Some(self.add_constant(literal.literal()))
// if matches!(access, LuaAccessMode::ReadRegisterOnly) {
// let r = match self.top_attribute().registers.first() {
// Some(r) => *r,
// _ => self.reg_mgr.alloc_hard(),
// };

// self.code_load(r, literal.literal());
// } else {
// }
}

fn visit_variable_expression_mut(&mut self, var_expr: &mut VariableExpression) {
Expand All @@ -365,11 +404,13 @@ impl AstVisitorMut for LuaBackend {

let arg_regs = self.reg_mgr.alloc_hard_batch(arg_cnt);
self.top_attribute().registers = arg_regs.into();
self.top_attribute().const_idx = Some(self.add_string_constant(var_expr.org_name()));
self.top_attribute().const_idx =
Some(self.add_string_constant(var_expr.org_name()));
}
// Read Symbol
LuaAccessMode::ReadSymbol => {
self.top_attribute().const_idx = Some(self.add_string_constant(var_expr.org_name()));
self.top_attribute().const_idx =
Some(self.add_string_constant(var_expr.org_name()));
}
LuaAccessMode::WriteRegister => {
let dst = self.top_attribute().registers[0];
Expand All @@ -382,14 +423,11 @@ impl AstVisitorMut for LuaBackend {
LuaAccessMode::LoadNewRegister => {
let scope = self.top_attribute().scope.as_ref().unwrap();
if let Some(variable) = scope.find_variable(var_expr.name()) {
self.top_attribute().registers =
smallvec![self.reg_mgr.alloc_local_variable(variable.name())];

// let reg = self.reg_mgr.alloc_hard();
// self.top_attribute().register = Some(reg);
//
// // TODO: initialize
// self.push_code(LuaByteCode::LoadI(reg, 0));
let const_idx = self.add_string_constant(var_expr.org_name());
let reg = self.reg_mgr.alloc_local_variable(variable.name());

self.code_gettabup(reg, const_idx);
self.top_attribute().registers = smallvec![reg];
} else {
// TODO: variable not found error
}
Expand All @@ -415,7 +453,11 @@ impl AstVisitorMut for LuaBackend {
let callee_reg = arg_regs[0];

// Load Callee from constant table into callee_reg
self.push_code(LuaByteCode::GetTabUp(callee_reg, 0, callee_attr.const_idx.unwrap()));
self.push_code(LuaByteCode::GetTabUp(
callee_reg,
0,
callee_attr.const_idx.unwrap(),
));

// visit all arguments
for (idx, arg) in call.arguments_mut().iter_mut().enumerate() {
Expand Down Expand Up @@ -474,26 +516,23 @@ impl AstVisitorMut for LuaBackend {

self.push_access_attribute(LuaAccessMode::LoadNewRegister);
self.visit_expression_mut(&mut operands[0]);
let op0_reg = self.pop_attribute().registers[0];
let rk0 = self.pop_attribute().rk();

self.push_access_attribute(LuaAccessMode::LoadNewRegister);
self.visit_expression_mut(&mut operands[1]);
let op1_reg = self.pop_attribute().registers[0];
let rk1 = self.pop_attribute().rk();

// generate operators
match op {
// a + b
Operator::Plus => self.push_code(LuaByteCode::Add(dest_reg, op0_reg, op1_reg)),
Operator::Plus => self.code_add(dest_reg, rk0, rk1),
// a = b
Operator::Equal => {
// (op0 == op1) != 1
self.push_code(LuaByteCode::Eq(op0_reg, op1_reg, 1))
}
Operator::Equal => self.code_eq(dest_reg, rk0, rk1),
_ => unreachable!(),
}

self.reg_mgr.free(&op0_reg);
self.reg_mgr.free(&op1_reg);
// self.reg_mgr.free(&rk0);
// self.reg_mgr.free(&rk1);
self.top_attribute().registers = smallvec![dest_reg];
}

Expand Down Expand Up @@ -523,7 +562,7 @@ impl AstVisitorMut for LuaBackend {
// assert_ne!(lhs_reg, rhs.registers[0]);

self.reg_mgr.free(&rhs.registers[0]);
// self.code_move(rhs.registers[0], lhs_reg);
self.code_settabup(lhs_constant_index, RK::R(rhs.registers[0]));
}
}
}
Loading

0 comments on commit 788cfe8

Please sign in to comment.