Skip to content

Commit eac2a60

Browse files
authored
Merge pull request #9 from rbartlensky/lua-ir
SSA intermediate representation
2 parents fec1a20 + d053638 commit eac2a60

File tree

16 files changed

+386
-107
lines changed

16 files changed

+386
-107
lines changed

.rustfmt.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
indent_style="Block"
2-
imports_indent="Block"
31
use_try_shorthand=true
42
use_field_init_shorthand=true
5-
merge_imports=true

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
language: rust
2-
rust: nightly
32
before_script:
43
- rustup component add rustfmt-preview
54
script:

luacompiler/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use lrlex::LexerBuilder;
55
use lrpar::CTParserBuilder;
66

77
fn main() -> Result<(), Box<std::error::Error>> {
8-
let lex_rule_ids_map = CTParserBuilder::<u8>::new().process_file_in_src("lua5_3/lua5_3.y")?;
8+
let lex_rule_ids_map =
9+
CTParserBuilder::<u8>::new_with_storaget().process_file_in_src("lua5_3/lua5_3.y")?;
910
LexerBuilder::new()
1011
.rule_ids_map(lex_rule_ids_map)
1112
.process_file_in_src("lua5_3/lua5_3.l")?;

luacompiler/src/lib/bytecode/instructions.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,26 @@ pub fn make_instr(opcode: Opcode, arg1: u8, arg2: u8, arg3: u8) -> u32 {
2525
opcode as u32 + ((arg1 as u32) << 4) + ((arg2 as u32) << 8) + ((arg3 as u32) << 12)
2626
}
2727

28+
/// Represents a high level instruction whose operands have a size of usize.
29+
/// This is used by the frontend to create an SSA IR, which later gets translated
30+
/// into smaller instructions that fit in 32 bits.
31+
#[derive(PartialEq, Eq, Debug)]
32+
pub struct HLInstr(pub Opcode, pub usize, pub usize, pub usize);
33+
34+
impl HLInstr {
35+
pub fn as_32bit(&self) -> u32 {
36+
if self.1 > 255 || self.2 > 255 || self.3 > 255 {
37+
panic!("Value is truncated!");
38+
}
39+
make_instr(self.0, self.1 as u8, self.2 as u8, self.3 as u8)
40+
}
41+
}
42+
2843
/// Represents the supported operations of the bytecode.
2944
/// Each operation can have at most 3 arguments.
3045
/// There are 256 available registers, and load operations (LDI, LDF, LDS) can only
3146
/// refer to at most 256 constants.
47+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
3248
pub enum Opcode {
3349
MOV = 0, // R(1) = R(2)
3450
LDI = 1, // R(1) = I(1); load integer from the constant table

luacompiler/src/lib/bytecode/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ impl LuaBytecode {
8484

8585
impl fmt::Display for LuaBytecode {
8686
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87-
write!(f, "{{\n");
87+
write!(f, "{{\n")?;
8888
for instr in &self.block {
89-
write!(f, " {}\n", instr);
89+
write!(f, " {}\n", instr)?;
9090
}
9191
write!(f, "}}")
9292
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use bytecode::LuaBytecode;
2+
use irgen::lua_ir::LuaIR;
3+
4+
pub fn compile_to_bytecode(ir: LuaIR) -> LuaBytecode {
5+
LuaIRToLuaBc::new(ir).compile()
6+
}
7+
8+
struct LuaIRToLuaBc {
9+
ir: LuaIR,
10+
}
11+
12+
impl LuaIRToLuaBc {
13+
/// Compile the given LuaIR to LuaBytecode.
14+
fn new(ir: LuaIR) -> LuaIRToLuaBc {
15+
LuaIRToLuaBc { ir }
16+
}
17+
18+
fn compile(self) -> LuaBytecode {
19+
assert!(self.ir.lifetimes.len() < 256);
20+
LuaBytecode::new(
21+
self.ir.instrs.iter().map(|i| i.as_32bit()).collect(),
22+
self.ir.const_map,
23+
self.ir.lifetimes.len() as u8,
24+
)
25+
}
26+
}

luacompiler/src/lib/errors.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
use lrpar::{Node, ParseError};
1+
use lrpar::{LexParseError, Node, ParseError};
22
use std::io;
33

44
type ParseErr = (Option<Node<u8>>, Vec<ParseError<u8>>);
55

66
#[derive(Debug)]
77
pub enum CliError {
88
Io(io::Error),
9-
LexError(lrpar::LexParseError<u8>),
9+
LexError(Vec<LexParseError<u8>>),
1010
ParseError(ParseErr),
1111
}
1212

13-
impl From<lrpar::LexParseError<u8>> for CliError {
14-
fn from(err: lrpar::LexParseError<u8>) -> CliError {
13+
impl From<Vec<LexParseError<u8>>> for CliError {
14+
fn from(err: Vec<LexParseError<u8>>) -> CliError {
1515
CliError::LexError(err)
1616
}
1717
}

luacompiler/src/lib/irgen/constants_map.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use std::collections::HashMap;
99
/// For instance, if '1.0' is used in Lua, then an entry from 1.0 to 0 is created in the
1010
/// <float_map> member.
1111
pub struct ConstantsMap {
12-
int_map: HashMap<i64, u8>,
13-
float_map: HashMap<String, u8>,
14-
str_map: HashMap<String, u8>,
12+
int_map: HashMap<i64, usize>,
13+
float_map: HashMap<String, usize>,
14+
str_map: HashMap<String, usize>,
1515
}
1616

1717
impl ConstantsMap {
@@ -25,8 +25,8 @@ impl ConstantsMap {
2525
}
2626

2727
/// Get the corresponding index of the given integer in the constant table.
28-
pub fn get_int(&mut self, int: i64) -> u8 {
29-
let len = self.int_map.len() as u8;
28+
pub fn get_int(&mut self, int: i64) -> usize {
29+
let len = self.int_map.len();
3030
*self.int_map.entry(int).or_insert(len)
3131
}
3232

@@ -41,8 +41,8 @@ impl ConstantsMap {
4141
}
4242

4343
/// Get the corresponding index of the given float in the constant table.
44-
pub fn get_float(&mut self, float: String) -> u8 {
45-
let len = self.float_map.len() as u8;
44+
pub fn get_float(&mut self, float: String) -> usize {
45+
let len = self.float_map.len();
4646
*self.float_map.entry(float).or_insert(len)
4747
}
4848

@@ -57,8 +57,8 @@ impl ConstantsMap {
5757
}
5858

5959
/// Get the corresponding index of the given string in the constant table.
60-
pub fn get_str(&mut self, string: String) -> u8 {
61-
let len = self.str_map.len() as u8;
60+
pub fn get_str(&mut self, string: String) -> usize {
61+
let len = self.str_map.len();
6262
*self.str_map.entry(string).or_insert(len)
6363
}
6464

luacompiler/src/lib/irgen/lua_ir.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use bytecode::instructions::HLInstr;
2+
use irgen::{constants_map::ConstantsMap, register_map::Lifetime};
3+
4+
/// Represents an IR in which all instructions are in SSA form.
5+
pub struct LuaIR {
6+
pub instrs: Vec<HLInstr>,
7+
pub const_map: ConstantsMap,
8+
pub lifetimes: Vec<Lifetime>,
9+
}
10+
11+
impl LuaIR {
12+
pub fn new(
13+
instrs: Vec<HLInstr>,
14+
const_map: ConstantsMap,
15+
mut lifetimes: Vec<Lifetime>,
16+
) -> LuaIR {
17+
lifetimes.sort_by(|x, y| x.start_point().cmp(&y.start_point()));
18+
LuaIR {
19+
instrs,
20+
const_map,
21+
lifetimes,
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)