From 0e92163cb303700d4959ec315fe29f69b85d0e30 Mon Sep 17 00:00:00 2001 From: Rerumu Date: Thu, 19 May 2022 17:09:44 -0400 Subject: [PATCH] Fix constant generation --- codegen-luajit/src/backend/expression.rs | 27 ++++++++++- codegen-luajit/src/backend/manager.rs | 24 ---------- codegen-luajit/src/translator.rs | 57 +++++++++++------------- codegen-luau/src/backend/expression.rs | 26 ++++++++++- codegen-luau/src/backend/manager.rs | 24 ---------- codegen-luau/src/translator.rs | 52 +++++++++------------ wasm-ast/src/builder.rs | 17 ++++++- 7 files changed, 115 insertions(+), 112 deletions(-) diff --git a/codegen-luajit/src/backend/expression.rs b/codegen-luajit/src/backend/expression.rs index 9761906..4abad2b 100644 --- a/codegen-luajit/src/backend/expression.rs +++ b/codegen-luajit/src/backend/expression.rs @@ -8,8 +8,7 @@ use wasm_ast::node::{ use crate::analyzer::operator::bin_symbol_of; use super::manager::{ - write_cmp_op, write_condition, write_f32, write_f64, write_separated, write_variable, Driver, - Manager, + write_cmp_op, write_condition, write_separated, write_variable, Driver, Manager, }; impl Driver for Recall { @@ -69,6 +68,30 @@ impl Driver for MemoryGrow { } } +pub fn write_f32(number: f32, w: &mut dyn Write) -> Result<()> { + let sign = if number.is_sign_negative() { "-" } else { "" }; + + if number.is_infinite() { + write!(w, "{sign}math.huge ") + } else if number.is_nan() { + write!(w, "{sign}0/0 ") + } else { + write!(w, "{number:e} ") + } +} + +pub fn write_f64(number: f64, w: &mut dyn Write) -> Result<()> { + let sign = if number.is_sign_negative() { "-" } else { "" }; + + if number.is_infinite() { + write!(w, "{sign}math.huge ") + } else if number.is_nan() { + write!(w, "{sign}0/0 ") + } else { + write!(w, "{number:e} ") + } +} + impl Driver for Value { fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { match self { diff --git a/codegen-luajit/src/backend/manager.rs b/codegen-luajit/src/backend/manager.rs index 562183f..8b54817 100644 --- a/codegen-luajit/src/backend/manager.rs +++ b/codegen-luajit/src/backend/manager.rs @@ -55,30 +55,6 @@ pub fn write_ascending(prefix: &str, range: Range, w: &mut dyn Write) -> write_separated(range, |i, w| write!(w, "{prefix}_{i}"), w) } -pub fn write_f32(number: f32, w: &mut dyn Write) -> Result<()> { - let sign = if number.is_sign_negative() { "-" } else { "" }; - - if number.is_infinite() { - write!(w, "{sign}math.huge ") - } else if number.is_nan() { - write!(w, "{sign}0/0 ") - } else { - write!(w, "{number:e} ") - } -} - -pub fn write_f64(number: f64, w: &mut dyn Write) -> Result<()> { - let sign = if number.is_sign_negative() { "-" } else { "" }; - - if number.is_infinite() { - write!(w, "{sign}math.huge ") - } else if number.is_nan() { - write!(w, "{sign}0/0 ") - } else { - write!(w, "{number:e} ") - } -} - pub fn write_variable(var: usize, mng: &Manager, w: &mut dyn Write) -> Result<()> { if let Some(rem) = var.checked_sub(mng.num_param) { write!(w, "loc_{rem} ") diff --git a/codegen-luajit/src/translator.rs b/codegen-luajit/src/translator.rs index 8411fca..5e4942b 100644 --- a/codegen-luajit/src/translator.rs +++ b/codegen-luajit/src/translator.rs @@ -14,7 +14,7 @@ use wasm_ast::{ use crate::{ analyzer::{localize, memory}, - backend::manager::{write_f32, write_f64, Driver, Manager}, + backend::manager::{Driver, Manager}, }; fn aux_internal_index(internal: Internal) -> u32 { @@ -48,24 +48,12 @@ fn write_named_array(name: &str, len: usize, w: &mut dyn Write) -> Result<()> { write!(w, "local {name} = table_new({len}, {hash})") } -fn write_constant(code: &[Instruction], w: &mut dyn Write) -> Result<()> { - // FIXME: Badly generated WASM will produce the wrong constant. - for inst in code { - let result = match *inst { - Instruction::I32Const(v) => write!(w, "{v} "), - Instruction::I64Const(v) => write!(w, "{v}LL "), - Instruction::F32Const(v) => write_f32(f32::from_bits(v), w), - Instruction::F64Const(v) => write_f64(f64::from_bits(v), w), - Instruction::GetGlobal(i) => write!(w, "GLOBAL_LIST[{i}].value "), - _ => { - continue; - } - }; +fn write_constant(code: &[Instruction], type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { + let func = Builder::new(type_info).with_anon(code); - return result; - } - - write!(w, "error(\"mundane expression\")") + write!(w, "(")?; + func.write(&mut Manager::default(), w)?; + write!(w, ")()") } fn write_import_of(wasm: &Module, lower: &str, cond: T, w: &mut dyn Write) -> Result<()> @@ -154,7 +142,7 @@ fn write_memory_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { Ok(()) } -fn write_global_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { +fn write_global_list(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { let global = match wasm.global_section() { Some(v) => v, None => return Ok(()), @@ -163,25 +151,27 @@ fn write_global_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { for (i, v) in global.entries().iter().enumerate() { write!(w, "GLOBAL_LIST[{}] = {{ value =", i + offset)?; - write_constant(v.init_expr().code(), w)?; + write_constant(v.init_expr().code(), type_info, w)?; write!(w, "}}")?; } Ok(()) } -fn write_element_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { +fn write_element_list(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { let element = match wasm.elements_section() { Some(v) => v.entries(), None => return Ok(()), }; for v in element { + let code = v.offset().as_ref().unwrap().code(); + write!(w, "do ")?; write!(w, "local target = TABLE_LIST[{}].data ", v.index())?; write!(w, "local offset =")?; - write_constant(v.offset().as_ref().unwrap().code(), w)?; + write_constant(code, type_info, w)?; write!(w, "local data = {{")?; @@ -199,18 +189,20 @@ fn write_element_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { Ok(()) } -fn write_data_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { +fn write_data_list(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { let data = match wasm.data_section() { Some(v) => v.entries(), None => return Ok(()), }; for v in data { + let code = v.offset().as_ref().unwrap().code(); + write!(w, "do ")?; write!(w, "local target = MEMORY_LIST[{}]", v.index())?; write!(w, "local offset =")?; - write_constant(v.offset().as_ref().unwrap().code(), w)?; + write_constant(code, type_info, w)?; write!(w, "local data = \"")?; @@ -234,7 +226,7 @@ fn build_func_list(wasm: &Module, type_info: &TypeInfo) -> Vec { let iter = list.iter().enumerate(); - iter.map(|f| Builder::new(type_info).consume(f.0, f.1)) + iter.map(|f| Builder::new(type_info).with_index(f.0, f.1)) .collect() } @@ -287,13 +279,18 @@ fn write_func_list( }) } -fn write_module_start(wasm: &Module, mem_list: &[usize], w: &mut dyn Write) -> Result<()> { +fn write_module_start( + wasm: &Module, + type_info: &TypeInfo, + mem_list: &[usize], + w: &mut dyn Write, +) -> Result<()> { write!(w, "local function run_init_code()")?; write_table_list(wasm, w)?; write_memory_list(wasm, w)?; - write_global_list(wasm, w)?; - write_element_list(wasm, w)?; - write_data_list(wasm, w)?; + write_global_list(wasm, type_info, w)?; + write_element_list(wasm, type_info, w)?; + write_data_list(wasm, type_info, w)?; write!(w, "end ")?; write!(w, "return function(wasm)")?; @@ -329,5 +326,5 @@ pub fn translate(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Resu write_named_array("GLOBAL_LIST", wasm.globals_space(), w)?; write_func_list(wasm, type_info, &func_list, w)?; - write_module_start(wasm, &mem_list, w) + write_module_start(wasm, type_info, &mem_list, w) } diff --git a/codegen-luau/src/backend/expression.rs b/codegen-luau/src/backend/expression.rs index 24e721a..3f01653 100644 --- a/codegen-luau/src/backend/expression.rs +++ b/codegen-luau/src/backend/expression.rs @@ -7,7 +7,7 @@ use wasm_ast::node::{ use crate::analyzer::operator::bin_symbol_of; -use super::manager::{write_f32, write_f64, write_separated, write_variable, Driver, Manager}; +use super::manager::{write_separated, write_variable, Driver, Manager}; impl Driver for Recall { fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { @@ -66,6 +66,30 @@ impl Driver for MemoryGrow { } } +pub fn write_f32(number: f32, w: &mut dyn Write) -> Result<()> { + let sign = if number.is_sign_negative() { "-" } else { "" }; + + if number.is_infinite() { + write!(w, "{sign}math.huge ") + } else if number.is_nan() { + write!(w, "{sign}0/0 ") + } else { + write!(w, "{number:e} ") + } +} + +pub fn write_f64(number: f64, w: &mut dyn Write) -> Result<()> { + let sign = if number.is_sign_negative() { "-" } else { "" }; + + if number.is_infinite() { + write!(w, "{sign}math.huge ") + } else if number.is_nan() { + write!(w, "{sign}0/0 ") + } else { + write!(w, "{number:e} ") + } +} + impl Driver for Value { fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { match self { diff --git a/codegen-luau/src/backend/manager.rs b/codegen-luau/src/backend/manager.rs index d917b54..5cf3990 100644 --- a/codegen-luau/src/backend/manager.rs +++ b/codegen-luau/src/backend/manager.rs @@ -56,30 +56,6 @@ pub fn write_ascending(prefix: &str, range: Range, w: &mut dyn Write) -> write_separated(range, |i, w| write!(w, "{prefix}_{i}"), w) } -pub fn write_f32(number: f32, w: &mut dyn Write) -> Result<()> { - let sign = if number.is_sign_negative() { "-" } else { "" }; - - if number.is_infinite() { - write!(w, "{sign}math.huge ") - } else if number.is_nan() { - write!(w, "{sign}0/0 ") - } else { - write!(w, "{number:e} ") - } -} - -pub fn write_f64(number: f64, w: &mut dyn Write) -> Result<()> { - let sign = if number.is_sign_negative() { "-" } else { "" }; - - if number.is_infinite() { - write!(w, "{sign}math.huge ") - } else if number.is_nan() { - write!(w, "{sign}0/0 ") - } else { - write!(w, "{number:e} ") - } -} - pub fn write_variable(var: usize, mng: &Manager, w: &mut dyn Write) -> Result<()> { if let Some(rem) = var.checked_sub(mng.num_param) { write!(w, "loc_{rem} ") diff --git a/codegen-luau/src/translator.rs b/codegen-luau/src/translator.rs index bedf0cd..8a4a524 100644 --- a/codegen-luau/src/translator.rs +++ b/codegen-luau/src/translator.rs @@ -14,7 +14,7 @@ use wasm_ast::{ use crate::{ analyzer::localize, - backend::manager::{write_f32, write_f64, Driver, Manager}, + backend::manager::{Driver, Manager}, }; fn aux_internal_index(internal: Internal) -> u32 { @@ -47,24 +47,12 @@ fn write_named_array(name: &str, len: usize, w: &mut dyn Write) -> Result<()> { write!(w, "local {name} = table.create({len})") } -fn write_constant(code: &[Instruction], w: &mut dyn Write) -> Result<()> { - // FIXME: Badly generated WASM will produce the wrong constant. - for inst in code { - let result = match *inst { - Instruction::I32Const(v) => write!(w, "{v} "), - Instruction::I64Const(v) => write!(w, "{v} "), - Instruction::F32Const(v) => write_f32(f32::from_bits(v), w), - Instruction::F64Const(v) => write_f64(f64::from_bits(v), w), - Instruction::GetGlobal(i) => write!(w, "GLOBAL_LIST[{i}].value "), - _ => { - continue; - } - }; +fn write_constant(code: &[Instruction], type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { + let func = Builder::new(type_info).with_anon(code); - return result; - } - - write!(w, "error(\"mundane expression\")") + write!(w, "(")?; + func.write(&mut Manager::default(), w)?; + write!(w, ")()") } fn write_import_of(wasm: &Module, lower: &str, cond: T, w: &mut dyn Write) -> Result<()> @@ -153,7 +141,7 @@ fn write_memory_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { Ok(()) } -fn write_global_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { +fn write_global_list(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { let global = match wasm.global_section() { Some(v) => v, None => return Ok(()), @@ -162,25 +150,27 @@ fn write_global_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { for (i, v) in global.entries().iter().enumerate() { write!(w, "GLOBAL_LIST[{}] = {{ value =", i + offset)?; - write_constant(v.init_expr().code(), w)?; + write_constant(v.init_expr().code(), type_info, w)?; write!(w, "}}")?; } Ok(()) } -fn write_element_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { +fn write_element_list(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { let element = match wasm.elements_section() { Some(v) => v.entries(), None => return Ok(()), }; for v in element { + let code = v.offset().as_ref().unwrap().code(); + write!(w, "do ")?; write!(w, "local target = TABLE_LIST[{}].data ", v.index())?; write!(w, "local offset =")?; - write_constant(v.offset().as_ref().unwrap().code(), w)?; + write_constant(code, type_info, w)?; write!(w, "local data = {{")?; @@ -198,18 +188,20 @@ fn write_element_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { Ok(()) } -fn write_data_list(wasm: &Module, w: &mut dyn Write) -> Result<()> { +fn write_data_list(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { let data = match wasm.data_section() { Some(v) => v.entries(), None => return Ok(()), }; for v in data { + let code = v.offset().as_ref().unwrap().code(); + write!(w, "do ")?; write!(w, "local target = MEMORY_LIST[{}]", v.index())?; write!(w, "local offset =")?; - write_constant(v.offset().as_ref().unwrap().code(), w)?; + write_constant(code, type_info, w)?; write!(w, "local data = \"")?; @@ -233,7 +225,7 @@ fn build_func_list(wasm: &Module, type_info: &TypeInfo) -> Vec { let iter = list.iter().enumerate(); - iter.map(|f| Builder::new(type_info).consume(f.0, f.1)) + iter.map(|f| Builder::new(type_info).with_index(f.0, f.1)) .collect() } @@ -279,13 +271,13 @@ fn write_func_list( }) } -fn write_module_start(wasm: &Module, w: &mut dyn Write) -> Result<()> { +fn write_module_start(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Result<()> { write!(w, "local function run_init_code()")?; write_table_list(wasm, w)?; write_memory_list(wasm, w)?; - write_global_list(wasm, w)?; - write_element_list(wasm, w)?; - write_data_list(wasm, w)?; + write_global_list(wasm, type_info, w)?; + write_element_list(wasm, type_info, w)?; + write_data_list(wasm, type_info, w)?; write!(w, "end ")?; write!(w, "return function(wasm)")?; @@ -314,5 +306,5 @@ pub fn translate(wasm: &Module, type_info: &TypeInfo, w: &mut dyn Write) -> Resu write_named_array("GLOBAL_LIST", wasm.globals_space(), w)?; write_func_list(wasm, type_info, &func_list, w)?; - write_module_start(wasm, w) + write_module_start(wasm, type_info, w) } diff --git a/wasm-ast/src/builder.rs b/wasm-ast/src/builder.rs index c4a4922..8bb531b 100644 --- a/wasm-ast/src/builder.rs +++ b/wasm-ast/src/builder.rs @@ -289,7 +289,22 @@ impl<'a> Builder<'a> { } #[must_use] - pub fn consume(mut self, index: usize, func: &'a FuncBody) -> Intermediate { + pub fn with_anon(mut self, mut inst: &[Instruction]) -> Intermediate { + self.num_result = 1; + + let code = self.new_forward(&mut inst); + let num_stack = self.data.last_stack; + + Intermediate { + local_data: Vec::new(), + num_param: 0, + num_stack, + code, + } + } + + #[must_use] + pub fn with_index(mut self, index: usize, func: &'a FuncBody) -> Intermediate { let arity = &self.type_info.arity_of(self.type_info.len_ex() + index); self.num_result = arity.num_result;