From 7bddeaafcf64bfd51c7ee584f80fe72227338eba Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Sat, 22 Jun 2024 11:12:21 -0700 Subject: [PATCH] [ir] Attach expected pointer type to IsPointer instruction --- crates/samlang-ast/src/lir.rs | 10 +++---- crates/samlang-ast/src/lir_tests.rs | 8 ++++-- crates/samlang-ast/src/mir.rs | 10 ++++--- crates/samlang-ast/src/mir_tests.rs | 10 ++++--- crates/samlang-compiler/src/lir_lowering.rs | 6 ++--- .../src/lir_unused_name_elimination.rs | 6 ++++- .../src/mir_constant_param_elimination.rs | 3 ++- .../src/mir_generics_specialization.rs | 11 ++++---- .../src/mir_type_deduplication.rs | 10 +++---- crates/samlang-compiler/src/wasm_lowering.rs | 11 +++++--- .../src/common_subexpression_elimination.rs | 26 ++++++++++++------- .../src/conditional_constant_propagation.rs | 9 ++++--- .../conditional_constant_propagation_tests.rs | 5 ++-- .../src/dead_code_elimination.rs | 5 ++-- .../src/dead_code_elimination_tests.rs | 11 +++++--- crates/samlang-optimization/src/inlining.rs | 3 ++- .../src/inlining_tests.rs | 7 ++--- .../src/local_value_numbering.rs | 4 +-- .../src/local_value_numbering_tests.rs | 5 ++-- .../loop_induction_variable_elimination.rs | 13 ++++++---- .../src/loop_invariant_code_motion.rs | 13 +++++++--- .../src/optimization_common.rs | 4 +-- .../src/unused_name_elimination.rs | 20 ++++++++++---- 23 files changed, 134 insertions(+), 76 deletions(-) diff --git a/crates/samlang-ast/src/lir.rs b/crates/samlang-ast/src/lir.rs index 7ee2f1d8..7818abe1 100644 --- a/crates/samlang-ast/src/lir.rs +++ b/crates/samlang-ast/src/lir.rs @@ -1,13 +1,10 @@ -use std::collections::HashMap; - -use crate::hir; - use super::{ hir::{BinaryOperator, GlobalString}, mir::{FunctionName, SymbolTable, TypeNameId}, }; use enum_as_inner::EnumAsInner; use samlang_heap::{Heap, PStr}; +use std::collections::HashMap; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PrimitiveType { @@ -153,6 +150,7 @@ pub struct GenenalLoopVariable { pub enum Statement { IsPointer { name: PStr, + pointer_type: TypeNameId, operand: Expression, }, Not { @@ -262,7 +260,7 @@ impl Statement { collector: &mut String, ) { match self { - Statement::IsPointer { name, operand } => { + Statement::IsPointer { name, pointer_type: _, operand } => { Self::append_spaces(collector, level); collector.push_str("let "); collector.push_str(name.as_str(heap)); @@ -621,7 +619,7 @@ impl Sources { let mut collector = ts_prolog(); let mut str_lookup_table = HashMap::new(); - for (i, hir::GlobalString(s)) in self.global_variables.iter().enumerate() { + for (i, GlobalString(s)) in self.global_variables.iter().enumerate() { collector.push_str("const GLOBAL_STRING_"); collector.push_str(&i.to_string()); collector.push_str(": _Str = [0, `"); diff --git a/crates/samlang-ast/src/lir_tests.rs b/crates/samlang-ast/src/lir_tests.rs index e2942894..dfc55474 100644 --- a/crates/samlang-ast/src/lir_tests.rs +++ b/crates/samlang-ast/src/lir_tests.rs @@ -3,7 +3,7 @@ mod tests { use super::super::lir::*; use crate::{ hir::{BinaryOperator, GlobalString}, - mir::{FunctionName, SymbolTable}, + mir::{FunctionName, SymbolTable, TypeNameId}, }; use pretty_assertions::assert_eq; use samlang_heap::{Heap, PStr}; @@ -152,7 +152,11 @@ mod tests { ], s2: vec![ Statement::Not { name: heap.alloc_str_for_test("dd"), operand: ZERO }, - Statement::IsPointer { name: heap.alloc_str_for_test("dd"), operand: ZERO }, + Statement::IsPointer { + name: heap.alloc_str_for_test("dd"), + pointer_type: TypeNameId::STR, + operand: ZERO, + }, Statement::binary(heap.alloc_str_for_test("dd"), BinaryOperator::PLUS, ZERO, ZERO), Statement::binary(heap.alloc_str_for_test("dd"), BinaryOperator::MINUS, ZERO, ZERO), Statement::binary( diff --git a/crates/samlang-ast/src/mir.rs b/crates/samlang-ast/src/mir.rs index 4219db92..5ce71184 100644 --- a/crates/samlang-ast/src/mir.rs +++ b/crates/samlang-ast/src/mir.rs @@ -235,7 +235,7 @@ impl ClosureTypeDefinition { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum EnumTypeDefinition { Boxed(Vec), - Unboxed(Type), + Unboxed(TypeNameId), Int, } @@ -245,7 +245,7 @@ impl EnumTypeDefinition { EnumTypeDefinition::Boxed(types) => { format!("Boxed({})", types.iter().map(|it| it.pretty_print(heap, table)).join(", ")) } - EnumTypeDefinition::Unboxed(t) => format!("Unboxed({})", t.pretty_print(heap, table)), + EnumTypeDefinition::Unboxed(t) => format!("Unboxed({})", t.encoded_for_test(heap, table)), EnumTypeDefinition::Int => "int".to_string(), } } @@ -482,6 +482,7 @@ impl GenenalLoopVariable { pub enum Statement { IsPointer { name: PStr, + pointer_type: TypeNameId, operand: Expression, }, Not { @@ -644,12 +645,13 @@ impl Statement { collector: &mut Vec, ) { match self { - Statement::IsPointer { name, operand } => { + Statement::IsPointer { name, pointer_type, operand } => { collector.push(format!( - "{}let {} = is_pointer({});\n", + "{}let {} = {} is {};\n", " ".repeat(level), name.as_str(heap), operand.debug_print(heap, table), + pointer_type.encoded_for_test(heap, table) )); } Statement::Not { name, operand } => { diff --git a/crates/samlang-ast/src/mir_tests.rs b/crates/samlang-ast/src/mir_tests.rs index 8a33dde2..e24e6bba 100644 --- a/crates/samlang-ast/src/mir_tests.rs +++ b/crates/samlang-ast/src/mir_tests.rs @@ -145,7 +145,7 @@ mod tests { name: table.create_type_name_for_test(PStr::UPPER_A), mappings: TypeDefinitionMappings::Struct(vec![INT_32_TYPE, INT_32_TYPE]), }; - let ed1 = EnumTypeDefinition::Unboxed(Type::Id(table.create_type_name_for_test(PStr::UPPER_D))); + let ed1 = EnumTypeDefinition::Unboxed(table.create_type_name_for_test(PStr::UPPER_D)); let ed2 = EnumTypeDefinition::Boxed(vec![INT_32_TYPE, INT_32_TYPE]); let ed3 = EnumTypeDefinition::Int; assert!(ed1.eq(&ed1)); @@ -235,7 +235,11 @@ mod tests { ], s2: vec![ Statement::Not { name: heap.alloc_str_for_test("dd"), operand: ZERO }, - Statement::IsPointer { name: heap.alloc_str_for_test("dd"), operand: ZERO }, + Statement::IsPointer { + name: heap.alloc_str_for_test("dd"), + pointer_type: TypeNameId::STR, + operand: ZERO, + }, Statement::binary(heap.alloc_str_for_test("dd"), BinaryOperator::PLUS, ZERO, ZERO), Statement::binary(heap.alloc_str_for_test("dd"), BinaryOperator::MINUS, ZERO, ZERO), Statement::binary( @@ -327,7 +331,7 @@ if 0 { bar = (b1: int); } else { let dd = !0; - let dd = is_pointer(0); + let dd = 0 is _Str; let dd = 0 + 0; let dd = 0 + 0; let dd = 0 - -2147483648; diff --git a/crates/samlang-compiler/src/lir_lowering.rs b/crates/samlang-compiler/src/lir_lowering.rs index b7d883e5..9870beb2 100644 --- a/crates/samlang-compiler/src/lir_lowering.rs +++ b/crates/samlang-compiler/src/lir_lowering.rs @@ -128,8 +128,8 @@ impl<'a> LoweringManager<'a> { fn lower_stmt(&mut self, stmt: mir::Statement) -> Vec { match stmt { - mir::Statement::IsPointer { name, operand } => { - vec![lir::Statement::IsPointer { name, operand: lower_expression(operand) }] + mir::Statement::IsPointer { name, pointer_type, operand } => { + vec![lir::Statement::IsPointer { name, pointer_type, operand: lower_expression(operand) }] } mir::Statement::Not { name, operand } => { vec![lir::Statement::Not { name, operand: lower_expression(operand) }] @@ -809,7 +809,7 @@ mod tests { name: table.create_type_name_for_test(heap.alloc_str_for_test("Variant")), mappings: TypeDefinitionMappings::Enum(vec![ EnumTypeDefinition::Int, - EnumTypeDefinition::Unboxed(INT_32_TYPE), + EnumTypeDefinition::Unboxed(TypeNameId::STR), EnumTypeDefinition::Boxed(vec![INT_32_TYPE, INT_31_TYPE]), ]), }, diff --git a/crates/samlang-compiler/src/lir_unused_name_elimination.rs b/crates/samlang-compiler/src/lir_unused_name_elimination.rs index ebe1c016..99478711 100644 --- a/crates/samlang-compiler/src/lir_unused_name_elimination.rs +++ b/crates/samlang-compiler/src/lir_unused_name_elimination.rs @@ -39,7 +39,11 @@ fn collect_used_names_from_statement( statement: &Statement, ) { match statement { - Statement::IsPointer { name: _, operand } | Statement::Not { name: _, operand } => { + Statement::IsPointer { name: _, pointer_type, operand } => { + type_set.insert(*pointer_type); + collect_used_names_from_expression(str_name_set, fn_name_set, type_set, operand); + } + Statement::Not { name: _, operand } => { collect_used_names_from_expression(str_name_set, fn_name_set, type_set, operand); } Statement::Binary { name: _, operator: _, e1, e2 } => { diff --git a/crates/samlang-compiler/src/mir_constant_param_elimination.rs b/crates/samlang-compiler/src/mir_constant_param_elimination.rs index 77b9d51e..cb71bd39 100644 --- a/crates/samlang-compiler/src/mir_constant_param_elimination.rs +++ b/crates/samlang-compiler/src/mir_constant_param_elimination.rs @@ -263,7 +263,8 @@ fn rewrite_expr(state: &RewriteState, expr: &mut Expression) { fn rewrite_stmt(state: &RewriteState, stmt: &mut Statement) { match stmt { - Statement::IsPointer { name: _, operand } | Statement::Not { name: _, operand } => { + Statement::IsPointer { name: _, pointer_type: _, operand } + | Statement::Not { name: _, operand } => { rewrite_expr(state, operand); } Statement::Binary(Binary { name: _, operator: _, e1, e2 }) => { diff --git a/crates/samlang-compiler/src/mir_generics_specialization.rs b/crates/samlang-compiler/src/mir_generics_specialization.rs index 2bec7e48..96a6c139 100644 --- a/crates/samlang-compiler/src/mir_generics_specialization.rs +++ b/crates/samlang-compiler/src/mir_generics_specialization.rs @@ -172,6 +172,7 @@ impl Rewriter { // Here we test whether this is a pointer collector.push(mir::Statement::IsPointer { name: comparison_temp, + pointer_type: *unboxed_t, operand: mir::Expression::var_name(casted_int_collector, mir::INT_32_TYPE), }); let mut nested_stmts = vec![]; @@ -179,7 +180,7 @@ impl Rewriter { // unboxed pointer type. nested_stmts.push(mir::Statement::Cast { name: binded_name, - type_: *unboxed_t, + type_: mir::Type::Id(*unboxed_t), assigned_expression: test_expr, }); nested_stmts.append(&mut self.rewrite_stmts(heap, s1, generics_replacement_map)); @@ -543,13 +544,13 @@ impl Rewriter { mapping_types.push(self.rewrite_type(heap, t, &solved_targs_replacement_map)); } if permit_unboxed_optimization + && already_unused_boxed_optimization.is_none() && mapping_types.len() == 2 && self.type_permit_enum_boxed_optimization(&mapping_types[1]) - && already_unused_boxed_optimization.is_none() { - let t = mapping_types[1]; + let t = mapping_types[1].into_id().unwrap(); mir_variants.push(mir::EnumTypeDefinition::Unboxed(t)); - already_unused_boxed_optimization = Some((tag, t)); + already_unused_boxed_optimization = Some((tag, mir::Type::Id(t))); } else { mir_variants.push(mir::EnumTypeDefinition::Boxed(mapping_types)); } @@ -1322,7 +1323,7 @@ function _DUMMY_I$main(): int { } let b = 0 as DUMMY_Enum; let _t1 = (b: DUMMY_Enum) as int; - let _t2 = is_pointer((_t1: int)); + let _t2 = (_t1: int) is DUMMY_J; if (_t2: int) { let a = (b: DUMMY_Enum) as DUMMY_J; } else { diff --git a/crates/samlang-compiler/src/mir_type_deduplication.rs b/crates/samlang-compiler/src/mir_type_deduplication.rs index 5fe2eca1..e615e056 100644 --- a/crates/samlang-compiler/src/mir_type_deduplication.rs +++ b/crates/samlang-compiler/src/mir_type_deduplication.rs @@ -58,8 +58,8 @@ fn rewrite_expressions(state: &State, expressions: Vec) -> Vec Statement { match stmt { - Statement::IsPointer { name, operand } => { - Statement::IsPointer { name, operand: rewrite_expr(state, operand) } + Statement::IsPointer { name, pointer_type, operand } => { + Statement::IsPointer { name, pointer_type, operand: rewrite_expr(state, operand) } } Statement::Not { name, operand } => { Statement::Not { name, operand: rewrite_expr(state, operand) } @@ -226,7 +226,7 @@ pub(super) fn deduplicate( types.into_iter().map(|t| rewrite_type(&state, t)).collect(), ), EnumTypeDefinition::Unboxed(t) => { - EnumTypeDefinition::Unboxed(rewrite_type(&state, t)) + EnumTypeDefinition::Unboxed(rewrite_id_type_name(&state, t)) } EnumTypeDefinition::Int => EnumTypeDefinition::Int, }) @@ -332,7 +332,7 @@ mod tests { name: table.create_type_name_for_test(PStr::UPPER_E), mappings: TypeDefinitionMappings::Enum(vec![ EnumTypeDefinition::Boxed(vec![INT_32_TYPE]), - EnumTypeDefinition::Unboxed(INT_32_TYPE), + EnumTypeDefinition::Unboxed(TypeNameId::STR), EnumTypeDefinition::Int, ]), }, @@ -406,7 +406,7 @@ mod tests { r#"closure type _A = () -> int closure type _C = () -> _C object type _C = [int, _Str] -variant type _E = [Boxed(int), Unboxed(int), int] +variant type _E = [Boxed(int), Unboxed(_Str), int] function __$main(): int { let _: int; if 1 { diff --git a/crates/samlang-compiler/src/wasm_lowering.rs b/crates/samlang-compiler/src/wasm_lowering.rs index 327aec71..26276973 100644 --- a/crates/samlang-compiler/src/wasm_lowering.rs +++ b/crates/samlang-compiler/src/wasm_lowering.rs @@ -46,7 +46,7 @@ impl<'a> LoweringManager<'a> { fn lower_stmt(&mut self, s: &lir::Statement) -> Vec { match s { - lir::Statement::IsPointer { name, operand } => { + lir::Statement::IsPointer { name, pointer_type: _, operand } => { let operand1 = Box::new(self.lower_expr(operand)); let operand2 = Box::new(self.lower_expr(operand)); vec![wasm::Instruction::Inline(self.set( @@ -323,7 +323,8 @@ mod tests { use samlang_ast::{ hir::{BinaryOperator, GlobalString}, lir::{Expression, Function, GenenalLoopVariable, Sources, Statement, Type, INT_32_TYPE, ZERO}, - mir, wasm, + mir::{self, TypeNameId}, + wasm, }; use samlang_heap::{Heap, PStr}; @@ -414,7 +415,11 @@ mod tests { )], }, Statement::Not { name: heap.alloc_str_for_test("un1"), operand: ZERO }, - Statement::IsPointer { name: heap.alloc_str_for_test("un2"), operand: ZERO }, + Statement::IsPointer { + name: heap.alloc_str_for_test("un2"), + pointer_type: TypeNameId::STR, + operand: ZERO, + }, Statement::binary( heap.alloc_str_for_test("bin"), BinaryOperator::PLUS, diff --git a/crates/samlang-optimization/src/common_subexpression_elimination.rs b/crates/samlang-optimization/src/common_subexpression_elimination.rs index ffe52655..ae321e0c 100644 --- a/crates/samlang-optimization/src/common_subexpression_elimination.rs +++ b/crates/samlang-optimization/src/common_subexpression_elimination.rs @@ -31,9 +31,9 @@ fn optimize_stmts( | Statement::StructInit { .. } | Statement::ClosureInit { .. } => collector.push(stmt), - Statement::IsPointer { name, operand } => { - set.insert(BindedValue::IsPointer(operand)); - collector.push(Statement::IsPointer { name, operand }); + Statement::IsPointer { name, pointer_type, operand } => { + set.insert(BindedValue::IsPointer(pointer_type, operand)); + collector.push(Statement::IsPointer { name, pointer_type, operand }); } Statement::Not { name, operand } => { set.insert(BindedValue::Not(operand)); @@ -73,8 +73,8 @@ fn optimize_stmts( BindedValue::Binary(BinaryBindedValue { operator, e1, e2 }) => Statement::Binary( Statement::binary_unwrapped(heap.alloc_temp_str(), operator, e1, e2), ), - BindedValue::IsPointer(operand) => { - Statement::IsPointer { name: heap.alloc_temp_str(), operand } + BindedValue::IsPointer(pointer_type, operand) => { + Statement::IsPointer { name: heap.alloc_temp_str(), pointer_type, operand } } BindedValue::Not(operand) => Statement::Not { name: heap.alloc_temp_str(), operand }, }) @@ -98,7 +98,7 @@ mod tests { hir::BinaryOperator, mir::{ Callee, Expression, Function, FunctionName, FunctionNameExpression, Statement, SymbolTable, - Type, VariableName, INT_32_TYPE, ONE, ZERO, + Type, TypeNameId, VariableName, INT_32_TYPE, ONE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -130,7 +130,11 @@ mod tests { s1: vec![ Statement::binary(heap.alloc_str_for_test("ddddd"), BinaryOperator::PLUS, ONE, ONE), Statement::Not { name: heap.alloc_str_for_test("ud1"), operand: ZERO }, - Statement::IsPointer { name: heap.alloc_str_for_test("ud3"), operand: ZERO }, + Statement::IsPointer { + name: heap.alloc_str_for_test("ud3"), + pointer_type: TypeNameId::STR, + operand: ZERO, + }, Statement::binary(PStr::LOWER_A, BinaryOperator::PLUS, ONE, ZERO), Statement::IndexedAccess { name: heap.alloc_str_for_test("ddd"), @@ -153,7 +157,11 @@ mod tests { ], s2: vec![ Statement::Not { name: heap.alloc_str_for_test("ud2"), operand: ZERO }, - Statement::IsPointer { name: heap.alloc_str_for_test("ud4"), operand: ZERO }, + Statement::IsPointer { + name: heap.alloc_str_for_test("ud4"), + pointer_type: TypeNameId::STR, + operand: ZERO, + }, Statement::binary(heap.alloc_str_for_test("fd"), BinaryOperator::PLUS, ONE, ZERO), Statement::IndexedAccess { name: heap.alloc_str_for_test("eee"), @@ -179,7 +187,7 @@ mod tests { heap, r#"let _t3: int = 0[3]; let _t2 = 1 + 0; -let _t1 = is_pointer(0); +let _t1 = 0 is _Str; let _t0 = !0; if (b: int) { let ddddd = 1 + 1; diff --git a/crates/samlang-optimization/src/conditional_constant_propagation.rs b/crates/samlang-optimization/src/conditional_constant_propagation.rs index 930bfa1d..f58c50b3 100644 --- a/crates/samlang-optimization/src/conditional_constant_propagation.rs +++ b/crates/samlang-optimization/src/conditional_constant_propagation.rs @@ -168,9 +168,12 @@ fn optimize_stmt( } false } - Statement::IsPointer { name, operand } => { - collector - .push(Statement::IsPointer { name: *name, operand: optimize_expr(value_cx, operand) }); + Statement::IsPointer { name, pointer_type, operand } => { + collector.push(Statement::IsPointer { + name: *name, + pointer_type: *pointer_type, + operand: optimize_expr(value_cx, operand), + }); false } Statement::Binary(Binary { name, operator, e1, e2 }) => { diff --git a/crates/samlang-optimization/src/conditional_constant_propagation_tests.rs b/crates/samlang-optimization/src/conditional_constant_propagation_tests.rs index d28720a8..4ea3c185 100644 --- a/crates/samlang-optimization/src/conditional_constant_propagation_tests.rs +++ b/crates/samlang-optimization/src/conditional_constant_propagation_tests.rs @@ -6,7 +6,7 @@ mod tests { hir::BinaryOperator, mir::{ Callee, Expression, Function, FunctionName, FunctionNameExpression, GenenalLoopVariable, - Statement, SymbolTable, Type, VariableName, INT_32_TYPE, ONE, ZERO, + Statement, SymbolTable, Type, TypeNameId, VariableName, INT_32_TYPE, ONE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -185,6 +185,7 @@ mod tests { }, Statement::IsPointer { name: heap.alloc_str_for_test("a8"), + pointer_type: TypeNameId::STR, operand: Expression::var_name(heap.alloc_str_for_test("a6"), INT_32_TYPE), }, Statement::StructInit { @@ -315,7 +316,7 @@ let i0: int = 6[2]; let b8 = (i0: int) * (i0: int); let a6 = (i1: int) / 30; let a7 = !(a6: int); -let a8 = is_pointer((a6: int)); +let a8 = (a6: int) is _Str; let s: _Id = [0, (a6: int), 30, (a7: int), (a8: int)]; let s: _Id = Closure { fun: (__$closure: () -> int), context: 0 }; __$fff(1, 0, 0, 0, 0, 0, 1); diff --git a/crates/samlang-optimization/src/dead_code_elimination.rs b/crates/samlang-optimization/src/dead_code_elimination.rs index 0c0fda92..c8e38934 100644 --- a/crates/samlang-optimization/src/dead_code_elimination.rs +++ b/crates/samlang-optimization/src/dead_code_elimination.rs @@ -25,7 +25,8 @@ fn collect_use_from_while_parts( fn collect_use_from_stmt(stmt: &Statement, set: &mut HashSet) { match stmt { - Statement::IsPointer { name: _, operand } | Statement::Not { name: _, operand } => { + Statement::IsPointer { name: _, pointer_type: _, operand } + | Statement::Not { name: _, operand } => { collect_use_from_expression(operand, set); } Statement::Binary(Binary { name: _, operator: _, e1, e2 }) => { @@ -89,7 +90,7 @@ pub(super) fn collect_use_from_stmts(stmts: &[Statement], set: &mut HashSet) -> bool { match stmt { - Statement::IsPointer { name, operand } | Statement::Not { name, operand } => { + Statement::IsPointer { name, pointer_type: _, operand } | Statement::Not { name, operand } => { if !set.contains(name) { false } else { diff --git a/crates/samlang-optimization/src/dead_code_elimination_tests.rs b/crates/samlang-optimization/src/dead_code_elimination_tests.rs index ad1be634..e3549967 100644 --- a/crates/samlang-optimization/src/dead_code_elimination_tests.rs +++ b/crates/samlang-optimization/src/dead_code_elimination_tests.rs @@ -7,7 +7,7 @@ mod tests { hir::BinaryOperator, mir::{ Callee, Expression, Function, FunctionName, FunctionNameExpression, GenenalLoopVariable, - Statement, SymbolTable, Type, VariableName, INT_32_TYPE, ONE, ZERO, + Statement, SymbolTable, Type, TypeNameId, VariableName, INT_32_TYPE, ONE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -31,6 +31,7 @@ mod tests { dead_code_elimination::collect_use_from_stmts( &[Statement::IsPointer { name: heap.alloc_str_for_test("uu"), + pointer_type: TypeNameId::STR, operand: Expression::var_name(heap.alloc_str_for_test("tmp_i"), INT_32_TYPE), }], &mut HashSet::new(), @@ -135,7 +136,11 @@ return (ii: int);"#, assert_correctly_optimized( vec![ Statement::Not { name: heap.alloc_str_for_test("u0_unused"), operand: ONE }, - Statement::IsPointer { name: heap.alloc_str_for_test("u0"), operand: ONE }, + Statement::IsPointer { + name: heap.alloc_str_for_test("u0"), + pointer_type: TypeNameId::STR, + operand: ONE, + }, Statement::binary( heap.alloc_str_for_test("u1"), BinaryOperator::DIV, @@ -213,7 +218,7 @@ return (ii: int);"#, ZERO, heap, table, - r#"let u0 = is_pointer(1); + r#"let u0 = 1 is _Str; let u1 = (u0: int) / 1; let u2 = 0 % 1; let p = 0 + 1; diff --git a/crates/samlang-optimization/src/inlining.rs b/crates/samlang-optimization/src/inlining.rs index 33af4df7..60d15a8d 100644 --- a/crates/samlang-optimization/src/inlining.rs +++ b/crates/samlang-optimization/src/inlining.rs @@ -221,8 +221,9 @@ fn inline_rewrite_stmt( stmt: &Statement, ) -> Statement { match stmt { - Statement::IsPointer { name, operand } => Statement::IsPointer { + Statement::IsPointer { name, pointer_type, operand } => Statement::IsPointer { name: bind_with_mangled_name(cx, heap, prefix, name, &INT_32_TYPE), + pointer_type: *pointer_type, operand: inline_rewrite_expr(operand, cx), }, Statement::Not { name, operand } => Statement::Not { diff --git a/crates/samlang-optimization/src/inlining_tests.rs b/crates/samlang-optimization/src/inlining_tests.rs index 32fa6b06..462c4dd9 100644 --- a/crates/samlang-optimization/src/inlining_tests.rs +++ b/crates/samlang-optimization/src/inlining_tests.rs @@ -6,7 +6,7 @@ mod tests { hir::BinaryOperator, mir::{ Callee, Expression, Function, FunctionName, FunctionNameExpression, GenenalLoopVariable, - Statement, SymbolTable, Type, VariableName, INT_32_TYPE, ONE, ZERO, + Statement, SymbolTable, Type, TypeNameId, VariableName, INT_32_TYPE, ONE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -302,6 +302,7 @@ mod tests { }, Statement::IsPointer { name: heap.alloc_str_for_test("u1"), + pointer_type: TypeNameId::STR, operand: Expression::var_name(PStr::LOWER_A, INT_32_TYPE), }, Statement::Cast { @@ -388,7 +389,7 @@ function __$loop(): int { function __$moveMove(a: int): int { let u0 = !(a: int); - let u1 = is_pointer((a: int)); + let u1 = (a: int) is _Str; let _ = 0 as int; let b: int; b = 0; @@ -400,7 +401,7 @@ function __$insanelyBigFunction(a: int): int { let _t2c: int = (a: int)[0]; (a: int)(); let _t4u0 = !(a: int); - let _t4u1 = is_pointer((a: int)); + let _t4u1 = (a: int) is _Str; let _t4_ = 0 as int; let _t4b: int; _t4b = 0; diff --git a/crates/samlang-optimization/src/local_value_numbering.rs b/crates/samlang-optimization/src/local_value_numbering.rs index 3cd7b653..c39fe2a3 100644 --- a/crates/samlang-optimization/src/local_value_numbering.rs +++ b/crates/samlang-optimization/src/local_value_numbering.rs @@ -36,9 +36,9 @@ fn optimize_stmt( binded_value_cx: &mut LocalBindedValueContext, ) -> bool { match stmt { - Statement::IsPointer { name, operand } => { + Statement::IsPointer { name, pointer_type, operand } => { optimize_expr(operand, variable_cx); - let value = BindedValue::IsPointer(*operand); + let value = BindedValue::IsPointer(*pointer_type, *operand); if let Some(binded) = binded_value_cx.get(&value) { lvn_bind_var(variable_cx, *name, *binded); false diff --git a/crates/samlang-optimization/src/local_value_numbering_tests.rs b/crates/samlang-optimization/src/local_value_numbering_tests.rs index 2376b732..d68b69ac 100644 --- a/crates/samlang-optimization/src/local_value_numbering_tests.rs +++ b/crates/samlang-optimization/src/local_value_numbering_tests.rs @@ -7,7 +7,7 @@ mod tests { hir::BinaryOperator, mir::{ Callee, Expression, Function, FunctionName, FunctionNameExpression, GenenalLoopVariable, - Statement, SymbolTable, Type, VariableName, INT_32_TYPE, ONE, ZERO, + Statement, SymbolTable, Type, TypeNameId, VariableName, INT_32_TYPE, ONE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -62,6 +62,7 @@ mod tests { ), Statement::IsPointer { name: heap.alloc_str_for_test("u0"), + pointer_type: TypeNameId::STR, operand: Expression::var_name(heap.alloc_str_for_test("i0"), INT_32_TYPE), }, Statement::binary( @@ -129,7 +130,7 @@ mod tests { table, r#"let i0: int = (a: int)[2]; let b0 = (i0: int) + 3; -let u0 = is_pointer((i0: int)); +let u0 = (i0: int) is _Str; let b3 = (i0: int) + (b0: int); let c1 = 0 as int; let c2: int; diff --git a/crates/samlang-optimization/src/loop_induction_variable_elimination.rs b/crates/samlang-optimization/src/loop_induction_variable_elimination.rs index 3b92a3b5..2d96cf10 100644 --- a/crates/samlang-optimization/src/loop_induction_variable_elimination.rs +++ b/crates/samlang-optimization/src/loop_induction_variable_elimination.rs @@ -25,9 +25,8 @@ fn stmt_uses_basic_induction_var( v: &BasicInductionVariableWithLoopGuard, ) -> bool { match stmt { - Statement::IsPointer { name: _, operand } | Statement::Not { name: _, operand } => { - expr_uses_basic_induction_var(operand, v) - } + Statement::IsPointer { name: _, pointer_type: _, operand } + | Statement::Not { name: _, operand } => expr_uses_basic_induction_var(operand, v), Statement::Binary(b) => { expr_uses_basic_induction_var(&b.e1, v) || expr_uses_basic_induction_var(&b.e2, v) } @@ -204,7 +203,7 @@ mod tests { hir::BinaryOperator, mir::{ Callee, Expression, FunctionName, FunctionNameExpression, GenenalLoopVariable, Statement, - SymbolTable, Type, VariableName, INT_32_TYPE, ONE, ZERO, + SymbolTable, Type, TypeNameId, VariableName, INT_32_TYPE, ONE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -281,7 +280,11 @@ mod tests { index: 3 }, Statement::Not { name: PStr::LOWER_A, operand: ZERO }, - Statement::IsPointer { name: PStr::LOWER_A, operand: ZERO }, + Statement::IsPointer { + name: PStr::LOWER_A, + pointer_type: TypeNameId::STR, + operand: ZERO + }, Statement::binary(PStr::LOWER_A, BinaryOperator::NE, ZERO, ZERO), Statement::IfElse { condition: ZERO, diff --git a/crates/samlang-optimization/src/loop_invariant_code_motion.rs b/crates/samlang-optimization/src/loop_invariant_code_motion.rs index 2f795cda..d38e170b 100644 --- a/crates/samlang-optimization/src/loop_invariant_code_motion.rs +++ b/crates/samlang-optimization/src/loop_invariant_code_motion.rs @@ -30,7 +30,8 @@ pub(super) fn optimize( let mut inner_stmts = vec![]; for stmt in stmts { match &stmt { - Statement::IsPointer { name, operand } | Statement::Not { name, operand } => { + Statement::IsPointer { name, pointer_type: _, operand } + | Statement::Not { name, operand } => { if expression_is_loop_invariant(operand, &non_loop_invariant_variables) { hoisted_stmts.push(stmt); } else { @@ -132,7 +133,7 @@ mod tests { hir::BinaryOperator, mir::{ Callee, Expression, FunctionName, FunctionNameExpression, GenenalLoopVariable, Statement, - SymbolTable, Type, VariableName, INT_32_TYPE, ONE, ZERO, + SymbolTable, Type, TypeNameId, VariableName, INT_32_TYPE, ONE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -192,7 +193,11 @@ mod tests { statements: vec![Statement::Break(ZERO)], }, Statement::Not { name: PStr::UNDERSCORE, operand: ZERO }, - Statement::IsPointer { name: PStr::UNDERSCORE, operand: ZERO }, + Statement::IsPointer { + name: PStr::UNDERSCORE, + pointer_type: TypeNameId::STR, + operand: ZERO, + }, Statement::binary( heap.alloc_str_for_test("tmp_i"), BinaryOperator::PLUS, @@ -335,7 +340,7 @@ mod tests { .join("\n"); assert_eq!( r#"let _ = !0; -let _ = is_pointer(0); +let _ = 0 is _Str; let c = (a: int) - (b: int); let d: int = (c: int)[0]; let h: _I = Closure { fun: (__$f: () -> int), context: (d: int) }; diff --git a/crates/samlang-optimization/src/optimization_common.rs b/crates/samlang-optimization/src/optimization_common.rs index 87769ac8..995491ef 100644 --- a/crates/samlang-optimization/src/optimization_common.rs +++ b/crates/samlang-optimization/src/optimization_common.rs @@ -31,7 +31,7 @@ pub(super) struct BinaryBindedValue { pub(super) enum BindedValue { IndexedAccess(IndexAccessBindedValue), Binary(BinaryBindedValue), - IsPointer(Expression), + IsPointer(TypeNameId, Expression), Not(Expression), } @@ -134,7 +134,7 @@ mod tests { let bv2 = BindedValue::Binary(BinaryBindedValue { operator: BinaryOperator::PLUS, e1: ZERO, e2: ZERO }); let bv3 = BindedValue::Not(ZERO); - let bv4 = BindedValue::IsPointer(ZERO); + let bv4 = BindedValue::IsPointer(TypeNameId::STR, ZERO); assert_eq!(Some(std::cmp::Ordering::Equal), bv1.partial_cmp(&bv1)); assert_eq!(Some(std::cmp::Ordering::Equal), bv2.partial_cmp(&bv2)); assert_eq!(Some(std::cmp::Ordering::Equal), bv3.partial_cmp(&bv3)); diff --git a/crates/samlang-optimization/src/unused_name_elimination.rs b/crates/samlang-optimization/src/unused_name_elimination.rs index 12ee53d1..079dbac0 100644 --- a/crates/samlang-optimization/src/unused_name_elimination.rs +++ b/crates/samlang-optimization/src/unused_name_elimination.rs @@ -42,7 +42,11 @@ fn collect_used_names_from_statement( statement: &Statement, ) { match statement { - Statement::IsPointer { name: _, operand } | Statement::Not { name: _, operand } => { + Statement::IsPointer { name: _, pointer_type, operand } => { + type_set.insert(*pointer_type); + collect_used_names_from_expression(str_name_set, type_set, operand); + } + Statement::Not { name: _, operand } => { collect_used_names_from_expression(str_name_set, type_set, operand); } Statement::Binary(Binary { name: _, operator: _, e1, e2 }) => { @@ -179,7 +183,9 @@ fn analyze_all_used_names( EnumTypeDefinition::Boxed(ts) => { collect_types_for_type_set(ts, &mut type_set); } - EnumTypeDefinition::Unboxed(t) => collect_for_type_set(t, &mut type_set), + EnumTypeDefinition::Unboxed(t) => { + type_set.insert(*t); + } EnumTypeDefinition::Int => {} } } @@ -251,7 +257,7 @@ mod tests { mir::{ Callee, ClosureTypeDefinition, EnumTypeDefinition, Expression, Function, FunctionName, FunctionNameExpression, GenenalLoopVariable, Sources, Statement, SymbolTable, Type, - TypeDefinition, TypeDefinitionMappings, VariableName, INT_32_TYPE, ZERO, + TypeDefinition, TypeDefinitionMappings, TypeNameId, VariableName, INT_32_TYPE, ZERO, }, }; use samlang_heap::{Heap, PStr}; @@ -303,7 +309,7 @@ mod tests { name: table.create_type_name_for_test(heap.alloc_str_for_test("Baz")), mappings: TypeDefinitionMappings::Enum(vec![ EnumTypeDefinition::Int, - EnumTypeDefinition::Unboxed(INT_32_TYPE), + EnumTypeDefinition::Unboxed(TypeNameId::STR), EnumTypeDefinition::Boxed(vec![INT_32_TYPE]), ]), }, @@ -398,7 +404,11 @@ mod tests { return_collector: None, }, Statement::Not { name: PStr::LOWER_A, operand: ZERO }, - Statement::IsPointer { name: PStr::LOWER_A, operand: ZERO }, + Statement::IsPointer { + name: PStr::LOWER_A, + pointer_type: TypeNameId::STR, + operand: ZERO, + }, Statement::IfElse { condition: ZERO, s1: vec![Statement::binary(