Skip to content

Commit

Permalink
feat: WIP: impl if statement
Browse files Browse the repository at this point in the history
  • Loading branch information
sbwtw committed Jun 29, 2024
1 parent 27a1197 commit 6a94129
Show file tree
Hide file tree
Showing 12 changed files with 438 additions and 319 deletions.
498 changes: 249 additions & 249 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions lib/src/backend/llvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ impl CodeGenBackend for LLVMBackend {
todo!()
}

fn get_module_bytes(&mut self, w: &mut dyn Write) -> io::Result<()> {
fn gen_function(&mut self, func: usize) -> Result<Box<dyn CompiledCode>, CodeGenError> {
todo!()
}

fn gen_function(&mut self, func: usize) -> Result<Box<dyn CompiledCode>, CodeGenError> {
fn create_label<S: AsRef<str>>(&mut self, label: S) -> Self::Label {
todo!()
}

fn define_label<S: AsRef<str>>(&mut self, label: Option<S>) -> Self::Label {
fn insert_label<S: AsRef<str>>(&mut self, label: S) {
todo!()
}

Expand All @@ -38,4 +38,8 @@ impl CodeGenBackend for LLVMBackend {
fn gen_operator(&mut self, operator: &mut OperatorExpression) {
todo!()
}

fn get_module_bytes(&mut self, w: &mut dyn Write) -> io::Result<()> {
todo!()
}
}
84 changes: 48 additions & 36 deletions lib/src/backend/lua/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use super::register::{Reg, RK};
use super::{ConstIdx, LuaType, LuaVarKind};

macro_rules! excess_k {
($v: expr, $k: expr) => {
($v: expr, $k: literal) => {
($v as u32).wrapping_add(((2u32.pow($k) - 1) / 2)) & (2u32.pow($k) - 1)
};
}
Expand All @@ -19,6 +19,12 @@ macro_rules! excess_sbx {
};
}

macro_rules! excess_sj {
($v: expr) => {
excess_k!($v, 25)
};
}

#[repr(u8)]
#[allow(non_camel_case_types)]
enum LuaOpCode {
Expand Down Expand Up @@ -228,11 +234,15 @@ pub enum LuaByteCode {
/// A B C k call C metamethod over R[A] and K[B]
MMBinK(Reg, ConstIdx, ConstIdx),

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

/// A sB k if ((R[A] == sB) ~= k) then pc++
Eqi(Reg, i8, bool),
/// A sB k: if ((R[A] > sB) ~= k) then pc++
Gti(Reg, u8, u8),
Gti(Reg, i32, ConstIdx),
/// A sB k: if ((R[A] >= sB) ~= k) then pc++
Gei(Reg, u8, u8),

Expand Down Expand Up @@ -261,8 +271,10 @@ impl LuaByteCode {
LuaByteCode::MMBin(..) => "MMBIN",
LuaByteCode::MMBinI(..) => "MMBINI",
LuaByteCode::MMBinK(..) => "MMBINK",
LuaByteCode::Eqi(..) => "EQI",
LuaByteCode::Gei(..) => "GEI",
LuaByteCode::Gti(..) => "GTI",
LuaByteCode::Jmp(..) => "JMP",
LuaByteCode::Eq(..) => "EQ",
LuaByteCode::Return(..) => "RETURN",
LuaByteCode::VarArgPrep(..) => "VARARGPREP",
Expand All @@ -282,8 +294,10 @@ impl LuaByteCode {
LuaByteCode::MMBinI(..) => LuaOpCode::OP_MMBINI,
LuaByteCode::MMBinK(..) => LuaOpCode::OP_MMBINK,
LuaByteCode::Add(..) => LuaOpCode::OP_ADD,
LuaByteCode::Eqi(..) => LuaOpCode::OP_EQI,
LuaByteCode::Gei(..) => LuaOpCode::OP_GEI,
LuaByteCode::Gti(..) => LuaOpCode::OP_GTI,
LuaByteCode::Jmp(..) => LuaOpCode::OP_JMP,
LuaByteCode::Eq(..) => LuaOpCode::OP_EQ,
LuaByteCode::Return(..) => LuaOpCode::OP_RETURN,
LuaByteCode::VarArgPrep(..) => LuaOpCode::OP_VARARGPREP,
Expand All @@ -298,10 +312,17 @@ impl LuaByteCode {
}
// A B k
LuaByteCode::Eq(a, b, k) => (k as u32) << 17 | (b.num() as u32) << 9 | a.num() as u32,
// A sB8 K(flag)
LuaByteCode::Eqi(a, sb8, k) => {
(excess_k!(sb8, 8)) << 9 | a.num() as u32 | (k as u32) << 8
}
// A sB k
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,
LuaByteCode::Gti(a, sb, k) => {
(k as u32) << 17 | excess_sbx!(sb) << 9 | a.num() as u32 | 1u32 << 8
}
LuaByteCode::Gei(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
Expand Down Expand Up @@ -338,6 +359,8 @@ impl LuaByteCode {
LuaByteCode::Move(a, b) => (b.num() as u32) << 9 | a.num() as u32,
// A only
LuaByteCode::VarArgPrep(a) => (a as u32) << 8,
// sJ
LuaByteCode::Jmp(sj) => excess_sj!(sj),
};

let op = self.opcode() as u32;
Expand Down Expand Up @@ -372,32 +395,29 @@ impl LuaCompiledCode {
match code {
// ABC
LuaByteCode::Add(a, b, c) => {
write!(s, "R{} R{} R{}", a.num(), b.num(), c.num()).unwrap();
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 sB8 K(flag)
LuaByteCode::Eqi(a, sb8, k) => {
write!(s, "R{} {sb8} {}", a.num(), *k as usize).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();
}
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) => {
write!(s, "R{} {b} {c}", a.num()).unwrap();
LuaByteCode::Gti(a, b, c) => write!(s, "R{} {b} {c}", a.num()).unwrap(),
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();
}
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();
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();
}
LuaByteCode::GetTabUp(reg, upv, k) => write!(s, "R{} {upv} {k}", reg.num()).unwrap(),
// Reg, Upv, RK
LuaByteCode::SetTabUp(reg, upv, rk) => {
write!(s, "R{} {upv} ", reg.num()).unwrap();
Expand All @@ -409,25 +429,17 @@ impl LuaCompiledCode {
.unwrap();
}
// ABC with k
LuaByteCode::Return(a, b, c) => {
write!(s, "{a} {b} {c}").unwrap();
}
LuaByteCode::Return(a, b, c) => write!(s, "{a} {b} {c}").unwrap(),
// ABx
LuaByteCode::LoadK(a, bx) => {
write!(s, "R{} {bx}", a.num()).unwrap();
}
LuaByteCode::LoadK(a, bx) => write!(s, "R{} {bx}", a.num()).unwrap(),
// AsBx
LuaByteCode::LoadI(a, sbx) => {
write!(s, "R{} {sbx}", a.num()).unwrap();
}
LuaByteCode::LoadI(a, sbx) => write!(s, "R{} {sbx}", a.num()).unwrap(),
// A B
LuaByteCode::Move(a, b) => {
write!(s, "R{} R{}", a.num(), b.num()).unwrap();
}
LuaByteCode::Move(a, b) => write!(s, "R{} R{}", a.num(), b.num()).unwrap(),
// A only
LuaByteCode::VarArgPrep(a) => {
write!(s, "{a}").unwrap();
}
LuaByteCode::VarArgPrep(a) => write!(s, "{a}").unwrap(),
// sJ
LuaByteCode::Jmp(sj) => write!(s, "{sj}").unwrap(),
}

match code {
Expand Down
25 changes: 25 additions & 0 deletions lib/src/backend/lua/label.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use smallvec::smallvec;
use crate::ast::SmallVec8;
use crate::parser::StString;

/// Unresolved offset placeholder
#[derive(Default, Debug, Clone)]
pub struct InstLabel {
/// The instruction position of label
pub inst_index: Option<usize>,
/// The name of this label
pub name: StString,
/// Record all patch needed instructions
pub fixup_instructions: SmallVec8<usize>,
}

impl InstLabel {
pub fn new(name: StString) -> Self {
Self {
inst_index: None,
name,
fixup_instructions: smallvec![],
}
}
}

73 changes: 55 additions & 18 deletions lib/src/backend/lua/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@ mod bytecode;
use bytecode::*;

mod dump;
use dump::lua_dump_module;

mod register;
#[cfg(test)]
mod test;
use register::*;

mod utils;
use utils::*;

mod vm;
mod label;
use label::InstLabel;

#[cfg(test)]
mod test;

use crate::backend::*;
use crate::parser::{LiteralValue, Operator};
use crate::parser::{BitValue, LiteralValue, Operator};
use crate::prelude::*;

use self::dump::lua_dump_module;
use self::register::*;
use self::utils::*;

use indexmap::{IndexMap, IndexSet};
use log::*;
use smallvec::{smallvec, SmallVec};
use std::mem;
use std::rc::Rc;
use std::collections::HashMap;

type ConstIdx = u8;

Expand All @@ -44,7 +50,7 @@ bitflags! {

bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct LuaVarKind: u8 {
pub(crate) struct LuaVarKind: u8 {
// regular
const VDKREG = 0;
// constant
Expand Down Expand Up @@ -72,7 +78,7 @@ enum LuaAccessMode {
}

#[derive(Clone)]
pub struct LuaBackendStates {
struct LuaBackendStates {
variable: Option<Rc<Variable>>,
registers: SmallVec8<Reg>,
const_idx: Option<ConstIdx>,
Expand Down Expand Up @@ -118,6 +124,7 @@ pub struct LuaBackend {
// tmp values for generating function
upvalue_table: IndexMap<StString, LuaUpValue>,
constants: IndexSet<LuaConstants>,
labels: HashMap<StString, InstLabel>,
}

impl LuaBackend {
Expand Down Expand Up @@ -181,13 +188,16 @@ impl LuaBackend {

#[inline]
fn code_eq(&mut self, dst: Reg, op0: RK, op1: RK) {
todo!()
self.code_load(Reg::R(1), &LiteralValue::Byte(1));
self.push_code(LuaByteCode::Eqi(Reg::R(1), 1, false));
}

#[inline]
fn add_constant(&mut self, v: &LiteralValue) -> ConstIdx {
match v {
LiteralValue::String(s) => self.add_string_constant(s),
LiteralValue::Bit(BitValue::Zero) => self.add_integer_constant(0),
LiteralValue::Bit(BitValue::One) => self.add_integer_constant(1),
LiteralValue::DInt(i) => self.add_integer_constant(*i as i64),
LiteralValue::UInt(i) => self.add_integer_constant(*i as i64),
LiteralValue::Real(s) | LiteralValue::LReal(s) => {
Expand Down Expand Up @@ -270,19 +280,20 @@ impl LuaBackend {
}

impl CodeGenBackend for LuaBackend {
type Label = usize;
type Label = InstLabel;

fn new(mgr: UnitsManager, app: ModuleContext) -> Self {
Self {
mgr,
app,
byte_codes: vec![],
byte_codes: Vec::with_capacity(1024 * 2), // 2KiB
states: smallvec![],
local_function: None,
local_proto: None,
constants: IndexSet::new(),
upvalue_table: IndexMap::new(),
reg_mgr: RegisterManager::new(),
labels: HashMap::new(),
}
}

Expand Down Expand Up @@ -346,8 +357,26 @@ impl CodeGenBackend for LuaBackend {
}))
}

fn define_label<S: AsRef<str>>(&mut self, label: Option<S>) -> Self::Label {
0
/// create a new label
fn create_label<S: AsRef<str>>(&mut self, label: S) -> InstLabel {
let label_name: StString = label.as_ref().into();
let lbl = InstLabel::new(label_name.clone());

self.labels.entry(label_name).or_insert(lbl).clone()
}

/// insert label, record current insert position
fn insert_label<S: AsRef<str>>(&mut self, label: S) {
let label_name: StString = label.as_ref().into();

let label = self.labels.entry(label_name.clone()).or_insert(InstLabel::new(label_name));

// ensure label is not inserted
debug_assert!(label.inst_index.is_some());

// record insert location
let inst_index = self.byte_codes.len();
label.inst_index = Some(inst_index)
}

fn gen_variable_load(&mut self, variable: &mut Variable) {
Expand Down Expand Up @@ -484,14 +513,18 @@ impl AstVisitorMut for LuaBackend {
fn visit_if_statement_mut(&mut self, ifst: &mut IfStatement) {
trace!("LuaGen: if statement: {}", ifst.condition());

let cond_true = self.define_label(Some("if-true"));
let cond_false = self.define_label(Some("if-false"));
let cond_true = self.create_label("if-true");
let cond_false = self.create_label("if-false");

self.push_default_attribute();
self.visit_expression_mut(ifst.condition_mut());
let attr = self.pop_attribute();

if let Some(then_ctrl) = ifst.then_controlled_mut() {
self.visit_statement_mut(then_ctrl);
}

self.reg_mgr.free(&attr.registers[0]);
}

fn visit_operator_expression_mut(&mut self, operator: &mut OperatorExpression) {
Expand Down Expand Up @@ -531,8 +564,12 @@ impl AstVisitorMut for LuaBackend {
_ => unreachable!(),
}

// self.reg_mgr.free(&rk0);
// self.reg_mgr.free(&rk1);
if let RK::R(r0) = rk0 {
self.reg_mgr.free(&r0);
}
if let RK::R(r1) = rk1 {
self.reg_mgr.free(&r1);
}
self.top_attribute().registers = smallvec![dest_reg];
}

Expand Down
Loading

0 comments on commit 6a94129

Please sign in to comment.