diff --git a/codegen-luau/runtime/runtime.lua b/codegen-luau/runtime/runtime.lua index b09b928..d28d8e7 100644 --- a/codegen-luau/runtime/runtime.lua +++ b/codegen-luau/runtime/runtime.lua @@ -20,6 +20,17 @@ local function no_op(num) return num end +do + local num = {} + + num.K_ZERO = I64.K_ZERO + num.K_ONE = I64.K_ONE + + num.from_32 = num_from_u32 + + module.num = num +end + do local add = {} local sub = {} diff --git a/codegen-luau/src/analyzer/localize.rs b/codegen-luau/src/analyzer/localize.rs index ce13f44..3136f40 100644 --- a/codegen-luau/src/analyzer/localize.rs +++ b/codegen-luau/src/analyzer/localize.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use wasm_ast::{ - node::{BinOp, CmpOp, Intermediate, LoadAt, StoreAt, UnOp}, + node::{BinOp, CmpOp, Intermediate, LoadAt, StoreAt, UnOp, Value}, visit::{Driver, Visitor}, }; @@ -24,6 +24,17 @@ impl Visitor for Visit { self.result.insert(("store", name)); } + fn visit_value(&mut self, v: &Value) { + let name = match v { + Value::I64(0) => "K_ZERO", + Value::I64(1) => "K_ONE", + Value::I64(_) => "from_u32", + _ => return, + }; + + self.result.insert(("num", name)); + } + fn visit_un_op(&mut self, v: &UnOp) { let name = v.op.as_name(); diff --git a/codegen-luau/src/backend/expression.rs b/codegen-luau/src/backend/expression.rs index ee033d4..219ce39 100644 --- a/codegen-luau/src/backend/expression.rs +++ b/codegen-luau/src/backend/expression.rs @@ -66,6 +66,20 @@ impl Driver for MemoryGrow { } } +fn write_i64(number: i64, w: &mut dyn Write) -> Result<()> { + match number { + 0 => write!(w, "num_K_ZERO "), + 1 => write!(w, "num_K_ONE "), + _ => { + let list = number.to_ne_bytes(); + let a = u32::from_ne_bytes(list[0..4].try_into().unwrap()); + let b = u32::from_ne_bytes(list[4..8].try_into().unwrap()); + + write!(w, "num_from_u32({a}, {b}) ") + } + } +} + fn write_f32(number: f32, w: &mut dyn Write) -> Result<()> { let sign = if number.is_sign_negative() { "-" } else { "" }; @@ -94,7 +108,7 @@ impl Driver for Value { fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { match self { Self::I32(i) => write!(w, "{i} "), - Self::I64(i) => write!(w, "{i} "), + Self::I64(i) => write_i64(*i, w), Self::F32(f) => write_f32(*f, w), Self::F64(f) => write_f64(*f, w), } diff --git a/codegen-luau/src/backend/statement.rs b/codegen-luau/src/backend/statement.rs index 87e54d3..45f914e 100644 --- a/codegen-luau/src/backend/statement.rs +++ b/codegen-luau/src/backend/statement.rs @@ -3,6 +3,7 @@ use std::{ ops::Range, }; +use parity_wasm::elements::ValueType; use wasm_ast::node::{ Backward, Br, BrIf, BrTable, Call, CallIndirect, Else, Forward, If, Intermediate, Memorize, Return, SetGlobal, SetLocal, Statement, StoreAt, @@ -262,13 +263,18 @@ fn write_variable_list(ir: &Intermediate, w: &mut dyn Write) -> Result<()> { for data in &ir.local_data { let range = total..total + usize::try_from(data.count()).unwrap(); + let zero = if data.value_type() == ValueType::I64 { + "num_K_ZERO " + } else { + "0 " + }; total = range.end; write!(w, "local ")?; write_ascending("loc", range.clone(), w)?; write!(w, " = ")?; - write_separated(range, |_, w| w.write_all(b"0"), w)?; + write_separated(range, |_, w| w.write_all(zero.as_bytes()), w)?; write!(w, " ")?; }