diff --git a/tiger/gc_test.sh b/tiger/gc_test.sh index 8548eb1..4c7d1c1 100755 --- a/tiger/gc_test.sh +++ b/tiger/gc_test.sh @@ -2,7 +2,7 @@ (( i = 1 )) -files=(array array_assignment comments conditions escapes functions gc hello hello1 hello2 hello3 hello5 integers lib loops merge nested prettyprint queens record spill strings vars) +files=(comments conditions escapes functional functions gc hello hello1 hello2 hello3 hello5 integers lib merge nested pure pureClosure pureTree record spill strings vars) while true; do echo "******************************" diff --git a/tiger/src/asm_gen.rs b/tiger/src/asm_gen.rs index 3f31dfe..e0486ec 100644 --- a/tiger/src/asm_gen.rs +++ b/tiger/src/asm_gen.rs @@ -263,14 +263,6 @@ impl Gen { self.emit(instruction); }, Exp::BinOp { op: BinOp::Div, left: expr, right: box Exp::Const(num) } => { - let instruction = Instruction::Move { - assembly: "mov 'd0, 0".to_string(), - source: vec![], - destination: vec![X86_64::rdx()], - stack_destination: vec![], - stack_source: vec![], - }; - self.emit(instruction); let instruction = Instruction::Move { assembly: "mov 'd0, 's0".to_string(), source: vec![self.munch_expression(*expr)], @@ -288,6 +280,14 @@ impl Gen { stack_source: vec![], }; self.emit(instruction); + let instruction = Instruction::Move { + assembly: "cqo".to_string(), + source: vec![X86_64::rax()], + destination: vec![X86_64::rdx()], + stack_destination: vec![], + stack_source: vec![], + }; + self.emit(instruction); let instruction = Instruction::Operation { assembly: "idiv 's0".to_string(), source: vec![immediate, X86_64::rax(), X86_64::rdx()], @@ -308,17 +308,17 @@ impl Gen { }, Exp::BinOp { op: BinOp::Div, left: box Exp::Const(num), right: expr } => { let instruction = Instruction::Move { - assembly: "mov 'd0, 0".to_string(), + assembly: format!("mov 'd0, {}", num), source: vec![], - destination: vec![X86_64::rdx()], + destination: vec![X86_64::rax()], stack_destination: vec![], stack_source: vec![], }; self.emit(instruction); let instruction = Instruction::Move { - assembly: format!("mov 'd0, {}", num), - source: vec![], - destination: vec![X86_64::rax()], + assembly: "cqo".to_string(), + source: vec![X86_64::rax()], + destination: vec![X86_64::rdx()], stack_destination: vec![], stack_source: vec![], }; @@ -546,17 +546,17 @@ impl Gen { }, Exp::BinOp { op: BinOp::Div, left, right } => { let instruction = Instruction::Move { - assembly: "mov 'd0, 0".to_string(), - source: vec![], - destination: vec![X86_64::rdx()], + assembly: "mov 'd0, 's0".to_string(), + source: vec![self.munch_expression(*left)], + destination: vec![X86_64::rax()], stack_destination: vec![], stack_source: vec![], }; self.emit(instruction); let instruction = Instruction::Move { - assembly: "mov 'd0, 's0".to_string(), - source: vec![self.munch_expression(*left)], - destination: vec![X86_64::rax()], + assembly: "cqo".to_string(), + source: vec![X86_64::rax()], + destination: vec![X86_64::rdx()], stack_destination: vec![], stack_source: vec![], }; diff --git a/tiger/src/ast.rs b/tiger/src/ast.rs index dfcefcd..069ae61 100644 --- a/tiger/src/ast.rs +++ b/tiger/src/ast.rs @@ -21,16 +21,10 @@ use position::WithPos; use symbol::{Symbol, SymbolWithPos}; -use temp::Label; #[allow(clippy::enum_variant_names)] #[derive(Clone, Debug, PartialEq)] pub enum Declaration { - ClassDeclaration { - declarations: Vec, - name: SymbolWithPos, - parent_class: SymbolWithPos, - }, Function(Vec), Type(Vec), VariableDeclaration { @@ -50,19 +44,14 @@ pub enum Expr { size: Box, typ: SymbolWithPos, }, - Assign { - expr: Box, - var: Box, - }, - Break, Call { args: Vec, function: Box, }, Closure { body: Box, + name: SymbolWithPos, params: Vec, - pure: bool, result: Option, }, ClosureParamField { @@ -76,9 +65,6 @@ pub enum Expr { ident: SymbolWithPos, this: Box, }, - FunctionPointer { - label: Label, - }, FunctionPointerCall { args: Vec, closure_name: Symbol, @@ -96,14 +82,6 @@ pub enum Expr { body: Box, declarations: Vec, }, - MethodCall { - args: Vec, - method: SymbolWithPos, - this: Box, - }, - New { - class_name: SymbolWithPos, - }, Nil, Oper { left: Box, @@ -123,10 +101,6 @@ pub enum Expr { this: Box, }, Variable(SymbolWithPos), - While { - body: Box, - test: Box, - }, } pub type ExprWithPos = WithPos; @@ -145,7 +119,6 @@ pub struct FuncDeclaration { pub body: ExprWithPos, pub name: SymbolWithPos, pub params: Vec, - pub pure: bool, pub result: Option, } @@ -204,7 +177,3 @@ pub struct TypeDec { pub type TypeDecWithPos = WithPos; pub type TyWithPos = WithPos; - -pub fn dummy_var_expr(symbol: Symbol) -> ExprWithPos { - WithPos::dummy(Expr::Variable(WithPos::dummy(symbol))) -} diff --git a/tiger/src/collector.rs b/tiger/src/collector.rs index 3020b1a..633ab1f 100644 --- a/tiger/src/collector.rs +++ b/tiger/src/collector.rs @@ -30,7 +30,6 @@ use std::ptr; use data_layout::{ ARRAY_DATA_LAYOUT_SIZE, - CLASS_DATA_LAYOUT_SIZE, RECORD_DATA_LAYOUT_SIZE, STRING_DATA_LAYOUT_SIZE, STRING_TYPE, @@ -42,14 +41,12 @@ const SHOW_STATS: bool = false; #[derive(Debug)] pub enum Layout { Array(usize, bool), - Class(*const c_char), Record(*const c_char), String(usize), } const ARRAY_TYPE: usize = 0; const RECORD_TYPE: usize = 1; -const CLASS_TYPE: usize = 3; impl Layout { fn write_repr(&self, mut ptr: *mut usize) { @@ -62,11 +59,6 @@ impl Layout { ptr = ptr.offset(1); ptr::write(ptr, is_pointer as usize); }, - Layout::Class(data_layout) => { - ptr::write(ptr, CLASS_TYPE); - ptr = ptr.offset(1); - ptr::write(ptr, data_layout as usize) - }, Layout::Record(data_layout) => { ptr::write(ptr, RECORD_TYPE); ptr = ptr.offset(1); @@ -84,12 +76,6 @@ impl Layout { fn size(&self) -> usize { match *self { Layout::Array(length, _) => (length + ARRAY_DATA_LAYOUT_SIZE) * WORD_SIZE, - Layout::Class(data_layout) => { - let string_ptr = string_offset(data_layout); - let fields = unsafe { CStr::from_ptr(string_ptr) }; - let field_count = fields.to_bytes().len() + CLASS_DATA_LAYOUT_SIZE; - field_count * WORD_SIZE - }, Layout::Record(data_layout) => { let string_ptr = string_offset(data_layout); let fields = unsafe { CStr::from_ptr(string_ptr) }; @@ -233,14 +219,6 @@ impl Collector { } } }, - CLASS_TYPE => { - for (i, &field_layout) in record_layout(pointer).iter().enumerate() { - if field_layout == b'p' { - let field = class_field(pointer, i); - self.dfs(field); - } - } - }, RECORD_TYPE => { for (i, &field_layout) in record_layout(pointer).iter().enumerate() { if field_layout == b'p' { @@ -281,17 +259,6 @@ impl Collector { } } }, - CLASS_TYPE => { - for (i, &field_layout) in record_layout(pointer).iter().enumerate() { - if field_layout == b'p' { - let field = class_field(pointer, i); - if self.in_heap(field) { - locations.insert(class_field_address(pointer, i) as usize, field); - self.dfs_locations(field, locations); - } - } - } - }, RECORD_TYPE => { for (i, &field_layout) in record_layout(pointer).iter().enumerate() { if field_layout == b'p' { @@ -437,19 +404,6 @@ fn fetch_pointer_map() -> HashMap> { pointer_map } -fn class_field(ptr: usize, index: usize) -> usize { - unsafe { - ptr::read_unaligned(class_field_address(ptr, index)) - } -} - -fn class_field_address(ptr: usize, index: usize) -> *const usize { - let ptr = ptr as *const usize; - unsafe { - ptr.add(index + CLASS_DATA_LAYOUT_SIZE) - } -} - fn field(ptr: usize, index: usize) -> usize { unsafe { ptr::read_unaligned(field_address(ptr, index)) @@ -484,9 +438,6 @@ fn size_of(ptr: usize) -> usize { let ptr = ptr.offset(1); ptr::read_unaligned(ptr) + ARRAY_DATA_LAYOUT_SIZE * WORD_SIZE }, - CLASS_TYPE => { - (field_count(ptr as usize) + CLASS_DATA_LAYOUT_SIZE) * WORD_SIZE - }, RECORD_TYPE => { (field_count(ptr as usize) + RECORD_DATA_LAYOUT_SIZE) * WORD_SIZE }, diff --git a/tiger/src/data_layout.rs b/tiger/src/data_layout.rs index 2f76467..cb2a1ec 100644 --- a/tiger/src/data_layout.rs +++ b/tiger/src/data_layout.rs @@ -22,9 +22,6 @@ // Type, Size, Is pointer. pub const ARRAY_DATA_LAYOUT_SIZE: usize = 3; -// Type, String of is pointer, Vtable pointer. -pub const CLASS_DATA_LAYOUT_SIZE: usize = 3; - // Type, String of is pointer. pub const RECORD_DATA_LAYOUT_SIZE: usize = 2; diff --git a/tiger/src/env.rs b/tiger/src/env.rs index 44ebec4..92ee3a5 100644 --- a/tiger/src/env.rs +++ b/tiger/src/env.rs @@ -19,31 +19,53 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +use std::cmp::Ordering; use std::collections::BTreeMap; use std::rc::Rc; use escape::{DepthEscape, EscapeEnv}; use frame::Frame; -use gen; -use gen::{Access, Level}; +use gen::Access; use position::WithPos; -use symbol::{Strings, Symbol, Symbols}; +use symbol::{ + Strings, + Symbol, + Symbols, + SymbolWithPos, +}; use temp::Label; -use types::{Type, Unique}; +use types::Type; + +#[derive(Clone, Debug, PartialEq)] +pub struct ClosureField { + pub ident: Symbol, + pub typ: Type, +} + +impl Eq for ClosureField { +} + +impl PartialOrd for ClosureField { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ClosureField { + fn cmp(&self, other: &Self) -> Ordering { + self.ident.cmp(&other.ident) + } +} #[derive(Clone, Debug)] pub enum Entry { - ClassField { - class: Type, - }, Fun { - access_outside_vars: bool, external: bool, label: Label, - level: Level, parameters: Vec, - pure: bool, + param_type_symbols: Vec, result: Type, + result_symbol: Option, }, RecordField { record: Type, @@ -68,21 +90,10 @@ impl Env { let string_symbol = type_env.symbol("string"); type_env.enter(string_symbol, Type::String); - let object_symbol = type_env.symbol("Object"); let answer_symbol = type_env.symbol("answer"); let cont_symbol = type_env.symbol("cont"); let string_consumer_symbol = type_env.symbol("stringConsumer"); - let object_class = Type::Class { - data_layout: String::new(), - fields: vec![], - methods: vec![], - name: object_symbol, - parent_class: None, - unique: Unique::new(), - vtable_name: Label::with_name("__vtable_Object"), - }; - let var_env = Symbols::new(Rc::clone(strings)); let mut env = Self { escape_env, @@ -90,12 +101,10 @@ impl Env { var_env, }; - for (name, (param_types, return_type, pure)) in env.external_functions() { - env.add_function(name, param_types, return_type, pure); + for (name, (param_types, return_type)) in env.external_functions() { + env.add_function(name, param_types, return_type); } - env.enter_type(object_symbol, object_class); - env.enter_type(answer_symbol, Type::Answer); env.enter_type(cont_symbol, Type::Function { parameters: vec![], @@ -109,16 +118,15 @@ impl Env { env } - fn add_function(&mut self, name: &str, parameters: Vec, result: Type, pure: bool) { + fn add_function(&mut self, name: &str, parameters: Vec, result: Type) { let symbol = self.var_env.symbol(name); let entry = Entry::Fun { - access_outside_vars: false, external: true, label: Label::with_name(name), - level: gen::outermost(), // FIXME: Might want to create a new level. parameters, - pure, + param_type_symbols: vec![], result, + result_symbol: None, }; self.var_env.enter(symbol, entry); } @@ -178,29 +186,27 @@ impl Env { self.var_env.name(symbol) } - pub fn external_functions(&mut self) -> BTreeMap<&'static str, (Vec, Type, bool)> { + pub fn external_functions(&mut self) -> BTreeMap<&'static str, (Vec, Type)> { let mut functions = BTreeMap::new(); - functions.insert("print", (vec![Type::String], Type::Unit, false)); - functions.insert("printi", (vec![Type::Int], Type::Unit, false)); - functions.insert("flush", (vec![], Type::Unit, false)); - functions.insert("getchar", (vec![], Type::String, false)); - functions.insert("ord", (vec![Type::String], Type::Int, true)); - functions.insert("chr", (vec![Type::Int], Type::String, true)); - functions.insert("size", (vec![Type::String], Type::Int, true)); - functions.insert("substring", (vec![Type::String, Type::Int, Type::Int], Type::String, true)); - functions.insert("concat", (vec![Type::String, Type::String], Type::String, true)); - functions.insert("not", (vec![Type::Int], Type::Int, true)); - functions.insert("stringEqual", (vec![Type::String, Type::String], Type::Int, true)); + functions.insert("ord", (vec![Type::String], Type::Int)); + functions.insert("chr", (vec![Type::Int], Type::String)); + functions.insert("size", (vec![Type::String], Type::Int)); + functions.insert("substring", (vec![Type::String, Type::Int, Type::Int], Type::String)); + functions.insert("concat", (vec![Type::String, Type::String], Type::String)); + functions.insert("not", (vec![Type::Int], Type::Int)); + functions.insert("stringEqual", (vec![Type::String, Type::String], Type::Int)); let cont = Type::Name(WithPos::dummy(self.type_env.symbol("cont")), None); - functions.insert("printP", (vec![Type::String, cont.clone()], Type::Answer, true)); - functions.insert("flushP", (vec![cont], Type::Answer, true)); - functions.insert("getcharP", (vec![Type::Name(WithPos::dummy(self.type_env.symbol("stringConsumer")), None)], Type::Answer, true)); - functions.insert("exit", (vec![], Type::Answer, true)); - - functions.insert("allocClass", (vec![Type::Int], Type::Int, true)); - functions.insert("allocRecord", (vec![Type::Int], Type::Int, true)); - functions.insert("initArray", (vec![Type::Int, Type::Int], Type::Int, true)); + functions.insert("debug", (vec![Type::String], Type::Answer)); + functions.insert("debugInt", (vec![Type::Int], Type::Answer)); + functions.insert("printi", (vec![Type::Int, cont.clone()], Type::Answer)); + functions.insert("print", (vec![Type::String, cont.clone()], Type::Answer)); + functions.insert("flush", (vec![cont], Type::Answer)); + functions.insert("getchar", (vec![Type::Name(WithPos::dummy(self.type_env.symbol("stringConsumer")), None)], Type::Answer)); + functions.insert("tigerExit", (vec![], Type::Answer)); + + functions.insert("allocRecord", (vec![Type::Int], Type::Int)); + functions.insert("initArray", (vec![Type::Int, Type::Int], Type::Int)); functions } } diff --git a/tiger/src/error.rs b/tiger/src/error.rs index 56d3c51..630ef88 100644 --- a/tiger/src/error.rs +++ b/tiger/src/error.rs @@ -29,27 +29,12 @@ use self::Error::*; use symbol::Symbols; use terminal::Terminal; use token::Tok; -use types::{FunctionType, Type}; +use types::Type; pub type Result = result::Result; #[derive(Clone, Debug)] pub enum Error { - Assign { - pos: Pos, - }, - BreakOutsideLoop { - pos: Pos, - }, - CannotAccessOutsideVars { - pos: Pos, - }, - CannotAssignInPureFun { - pos: Pos, - }, - CannotCallImpureFun { - pos: Pos, - }, CannotIndex { pos: Pos, typ: Type, @@ -67,11 +52,6 @@ pub enum Error { pos: Pos, struct_name: String, }, - FunctionType { - expected: FunctionType, - pos: Pos, - unexpected: FunctionType, - }, InvalidEscape { escape: String, pos: Pos, @@ -88,14 +68,7 @@ pub enum Error { }, Msg(String), Multi(Vec), - NoLoopInPureFun { - pos: Pos, - }, - NotAClass { - pos: Pos, - typ: Type, - }, - NotARecordOrClass { + NotARecord { pos: Pos, typ: Type, }, @@ -150,30 +123,6 @@ impl Error { } eprint!("{}{}error: {}", terminal.bold(), terminal.red(), terminal.reset_color()); match *self { - Assign { pos } => { - eprintln!("Can only assign to variable, field or array element{}", terminal.end_bold()); - pos.show(symbols, terminal); - highlight_line(pos, symbols, terminal)?; - }, - BreakOutsideLoop { pos } => { - eprintln!("Break statement used outside of loop{}", terminal.end_bold()); - pos.show(symbols, terminal); - }, - CannotCallImpureFun { pos } => { - eprintln!("Cannot call impure functions in pure functions{}", terminal.end_bold()); - pos.show(symbols, terminal); - highlight_line(pos, symbols, terminal)?; - }, - CannotAccessOutsideVars { pos } => { - eprintln!("Cannot convert into a closure a function that accesses variables declared outside of it{}", terminal.end_bold()); - pos.show(symbols, terminal); - highlight_line(pos, symbols, terminal)?; - }, - CannotAssignInPureFun { pos } => { - eprintln!("Cannot assign in pure functions{}", terminal.end_bold()); - pos.show(symbols, terminal); - highlight_line(pos, symbols, terminal)?; - }, CannotIndex { pos, ref typ } => { eprintln!("Cannot index value of type `{}`{}", typ.show(symbols), terminal.end_bold()); pos.show(symbols, terminal) @@ -192,11 +141,6 @@ impl Error { eprintln!("Extra field `{}` in struct of type `{}`{}", ident, struct_name, terminal.end_bold()); pos.show(symbols, terminal); }, - Error::FunctionType { ref expected, pos, ref unexpected } => { - eprintln!("Overridden method should have the same type as the inherited method:\nunexpected {}\n expecting {}{}", unexpected.show(symbols), expected.show(symbols), terminal.end_bold()); - pos.show(symbols, terminal); - highlight_line(pos, symbols, terminal)?; - }, InvalidEscape { ref escape, pos } => { eprintln!("Invalid escape \\{}{}", escape, terminal.end_bold()); pos.show(symbols, terminal); @@ -213,18 +157,8 @@ impl Error { }, Msg(ref string) => eprintln!("{}", string), Multi(_) => unreachable!(), - NoLoopInPureFun { pos } => { - eprintln!("Cannot use loops in pure functions{}", terminal.end_bold()); - pos.show(symbols, terminal); - highlight_line(pos, symbols, terminal)?; - }, - NotAClass { pos, ref typ } => { - eprintln!("Type `{}` is not a class type{}", typ.show(symbols), terminal.end_bold()); - pos.show(symbols, terminal); - highlight_line(pos, symbols, terminal)?; - }, - NotARecordOrClass { pos, ref typ } => { - eprintln!("Type `{}` is not a struct or a class type{}", typ.show(symbols), terminal.end_bold()); + NotARecord { pos, ref typ } => { + eprintln!("Type `{}` is not a struct{}", typ.show(symbols), terminal.end_bold()); pos.show(symbols, terminal); highlight_line(pos, symbols, terminal)?; }, @@ -255,6 +189,7 @@ impl Error { UnexpectedField { ref ident, pos, ref struct_name } => { eprintln!("Unexpected field `{}` in struct of type `{}`{}", ident, struct_name, terminal.end_bold()); pos.show(symbols, terminal); + highlight_line(pos, symbols, terminal)?; }, UnexpectedToken { ref expected, pos, ref unexpected } => { eprintln!("Unexpected token {}, expecting {}{}", unexpected, expected, terminal.end_bold()); diff --git a/tiger/src/escape.rs b/tiger/src/escape.rs index e5839f4..3e4a8a2 100644 --- a/tiger/src/escape.rs +++ b/tiger/src/escape.rs @@ -57,16 +57,12 @@ impl EscapeFinder { fn visit_dec(&mut self, declaration: &DeclarationWithPos, depth: u32) { match declaration.node { - Declaration::ClassDeclaration { ref declarations, .. } => { - for declaration in declarations { - self.visit_dec(declaration, depth + 1); - } - }, Declaration::Function(ref declarations) => { for &WithPos { node: FuncDeclaration { ref params, ref body, .. }, .. } in declarations { for param in params { + // TODO: param dig are considered escaping while they should not. self.env.enter(param.node.name, DepthEscape { - depth, + depth: depth + 1, escape: false, }); } @@ -75,7 +71,7 @@ impl EscapeFinder { }, Declaration::Type(_) => (), Declaration::VariableDeclaration { ref init, name, .. } => { - self.visit_exp(init, depth + 1); // TODO: do we really need to increment depth here? + self.visit_exp(init, depth); self.env.enter(name, DepthEscape { depth, escape: false, @@ -90,22 +86,17 @@ impl EscapeFinder { self.visit_exp(size, depth); self.visit_exp(init, depth); }, - Expr::Assign { ref expr, ref var } => { - self.visit_exp(var, depth); - self.visit_exp(expr, depth); - }, - Expr::Break => { - }, Expr::Closure { ref body, ref params, .. } => { for param in params { self.env.enter(param.node.name, DepthEscape { - depth, + depth: depth + 1, escape: false, }); } self.visit_exp(body, depth + 1); }, - Expr::Call { ref args, .. } => { + Expr::Call { ref args, ref function, .. } => { + self.visit_exp(function, depth); for arg in args { self.visit_exp(arg, depth); } @@ -118,7 +109,7 @@ impl EscapeFinder { } } }, - Expr::ClosurePointer { .. } | Expr::FunctionPointer { .. } => (), + Expr::ClosurePointer { .. } => (), Expr::FunctionPointerCall { ref args, .. } => { for arg in args { self.visit_exp(arg, depth); @@ -138,12 +129,6 @@ impl EscapeFinder { } self.visit_exp(body, depth); }, - Expr::MethodCall { ref args, .. } => { - for arg in args { - self.visit_exp(arg, depth); - } - }, - Expr::New { .. } => (), Expr::Nil => (), Expr::Oper { ref left, oper: WithPos { node: Operator::Plus, .. }, ref right } | Expr::Oper { ref left, oper: WithPos { node: Operator::Minus, .. }, ref right } @@ -179,10 +164,6 @@ impl EscapeFinder { self.visit_exp(this, depth); self.visit_exp(expr, depth); }, - Expr::While { ref body, ref test } => { - self.visit_exp(test, depth); - self.visit_exp(body, depth); - }, } } } diff --git a/tiger/src/frame/mod.rs b/tiger/src/frame/mod.rs index e9671c1..5389589 100644 --- a/tiger/src/frame/mod.rs +++ b/tiger/src/frame/mod.rs @@ -40,10 +40,6 @@ pub enum Fragment { temp_map: TempMap, }, Str(Label, String), - VTable { - class: Label, - methods: Vec