diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index 41d93df976..ec03a62234 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -92,8 +92,8 @@ pub fn exportAtan(comptime T: type, comptime name: []const u8) void { pub fn exportRound(comptime T: type, comptime name: []const u8) void { comptime var f = struct { - fn func(input: T) callconv(.C) i64 { - return @floatToInt(i64, (@round(input))); + fn func(input: T) callconv(.C) T { + return @round(input); } }.func; @export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong }); diff --git a/compiler/gen_wasm/src/low_level.rs b/compiler/gen_wasm/src/low_level.rs index 64d0769d30..3d6f12a45a 100644 --- a/compiler/gen_wasm/src/low_level.rs +++ b/compiler/gen_wasm/src/low_level.rs @@ -503,18 +503,6 @@ impl<'a> LowLevelCall<'a> { NumCos => todo!("{:?}", self.lowlevel), NumSqrtUnchecked => todo!("{:?}", self.lowlevel), NumLogUnchecked => todo!("{:?}", self.lowlevel), - NumRound => { - self.load_args(backend); - match CodeGenNumType::for_symbol(backend, self.arguments[0]) { - F32 => { - self.load_args_and_call_zig(backend, &bitcode::NUM_ROUND[FloatWidth::F32]) - } - F64 => { - self.load_args_and_call_zig(backend, &bitcode::NUM_ROUND[FloatWidth::F64]) - } - _ => todo!("{:?} for {:?}", self.lowlevel, self.ret_layout), - } - } NumToFloat => { self.load_args(backend); let ret_type = CodeGenNumType::from(self.ret_layout); @@ -534,35 +522,42 @@ impl<'a> LowLevelCall<'a> { } } NumPow => todo!("{:?}", self.lowlevel), - NumCeiling => { + NumCeiling | NumFloor | NumRound => { self.load_args(backend); - match CodeGenNumType::from(self.ret_layout) { - I32 => { + let arg_type = CodeGenNumType::for_symbol(backend, self.arguments[0]); + let ret_type = CodeGenNumType::from(self.ret_layout); + match (arg_type, self.lowlevel) { + (F32, NumCeiling) => { backend.code_builder.f32_ceil(); - backend.code_builder.i32_trunc_s_f32() } - I64 => { + (F64, NumCeiling) => { backend.code_builder.f64_ceil(); - backend.code_builder.i64_trunc_s_f64() } + (F32, NumFloor) => { + backend.code_builder.f32_floor(); + } + (F64, NumFloor) => { + backend.code_builder.f64_floor(); + } + (F32, NumRound) => { + self.load_args_and_call_zig(backend, &bitcode::NUM_ROUND[FloatWidth::F32]) + } + (F64, NumRound) => { + self.load_args_and_call_zig(backend, &bitcode::NUM_ROUND[FloatWidth::F64]) + } + _ => internal_error!("Invalid argument type for ceiling: {:?}", arg_type), + } + match (ret_type, arg_type) { + // TODO: signed truncation + (I32, F32) => backend.code_builder.i32_trunc_s_f32(), + (I32, F64) => backend.code_builder.i32_trunc_s_f64(), + (I64, F32) => backend.code_builder.i64_trunc_s_f32(), + (I64, F64) => backend.code_builder.i64_trunc_s_f64(), + (I128, _) => todo!("{:?} for I128", self.lowlevel), _ => panic_ret_type(), } } NumPowInt => todo!("{:?}", self.lowlevel), - NumFloor => { - self.load_args(backend); - match CodeGenNumType::from(self.ret_layout) { - I32 => { - backend.code_builder.f32_floor(); - backend.code_builder.i32_trunc_s_f32() - } - I64 => { - backend.code_builder.f64_floor(); - backend.code_builder.i64_trunc_s_f64() - } - _ => panic_ret_type(), - } - } NumIsFinite => num_is_finite(backend, self.arguments[0]), NumAtan => match self.ret_layout {