| ... | @@ -212,7 +212,8 @@ fn buildOpcode(args: OpcodeBuildArguments) wasm.Opcode { | ... | @@ -212,7 +212,8 @@ fn buildOpcode(args: OpcodeBuildArguments) wasm.Opcode { |
| 212 | 16 => switch (args.valtype1.?) { | 212 | 16 => switch (args.valtype1.?) { |
| 213 | .i32 => if (args.signedness.? == .signed) return .i32_load16_s else return .i32_load16_u, | 213 | .i32 => if (args.signedness.? == .signed) return .i32_load16_s else return .i32_load16_u, |
| 214 | .i64 => if (args.signedness.? == .signed) return .i64_load16_s else return .i64_load16_u, | 214 | .i64 => if (args.signedness.? == .signed) return .i64_load16_s else return .i64_load16_u, |
| 215 | .f32, .f64 => unreachable, | 215 | .f32 => return .f32_load, |
| | 216 | .f64 => unreachable, |
| 216 | }, | 217 | }, |
| 217 | 32 => switch (args.valtype1.?) { | 218 | 32 => switch (args.valtype1.?) { |
| 218 | .i64 => if (args.signedness.? == .signed) return .i64_load32_s else return .i64_load32_u, | 219 | .i64 => if (args.signedness.? == .signed) return .i64_load32_s else return .i64_load32_u, |
| ... | @@ -242,7 +243,8 @@ fn buildOpcode(args: OpcodeBuildArguments) wasm.Opcode { | ... | @@ -242,7 +243,8 @@ fn buildOpcode(args: OpcodeBuildArguments) wasm.Opcode { |
| 242 | 16 => switch (args.valtype1.?) { | 243 | 16 => switch (args.valtype1.?) { |
| 243 | .i32 => return .i32_store16, | 244 | .i32 => return .i32_store16, |
| 244 | .i64 => return .i64_store16, | 245 | .i64 => return .i64_store16, |
| 245 | .f32, .f64 => unreachable, | 246 | .f32 => return .f32_store, |
| | 247 | .f64 => unreachable, |
| 246 | }, | 248 | }, |
| 247 | 32 => switch (args.valtype1.?) { | 249 | 32 => switch (args.valtype1.?) { |
| 248 | .i64 => return .i64_store32, | 250 | .i64 => return .i64_store32, |
| ... | @@ -1064,7 +1066,7 @@ fn allocStackPtr(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1064,7 +1066,7 @@ fn allocStackPtr(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1064 | } | 1066 | } |
| 1065 | | 1067 | |
| 1066 | /// From given zig bitsize, returns the wasm bitsize | 1068 | /// From given zig bitsize, returns the wasm bitsize |
| 1067 | fn toWasmIntBits(bits: u16) ?u16 { | 1069 | fn toWasmBits(bits: u16) ?u16 { |
| 1068 | return for ([_]u16{ 32, 64 }) |wasm_bits| { | 1070 | return for ([_]u16{ 32, 64 }) |wasm_bits| { |
| 1069 | if (bits <= wasm_bits) return wasm_bits; | 1071 | if (bits <= wasm_bits) return wasm_bits; |
| 1070 | } else null; | 1072 | } else null; |
| ... | @@ -1120,11 +1122,11 @@ fn isByRef(ty: Type, target: std.Target) bool { | ... | @@ -1120,11 +1122,11 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1120 | .ErrorSet, | 1122 | .ErrorSet, |
| 1121 | .Fn, | 1123 | .Fn, |
| 1122 | .Enum, | 1124 | .Enum, |
| 1123 | .Vector, | | |
| 1124 | .AnyFrame, | 1125 | .AnyFrame, |
| 1125 | => return false, | 1126 | => return false, |
| 1126 | | 1127 | |
| 1127 | .Array, | 1128 | .Array, |
| | 1129 | .Vector, |
| 1128 | .Struct, | 1130 | .Struct, |
| 1129 | .Frame, | 1131 | .Frame, |
| 1130 | .Union, | 1132 | .Union, |
| ... | @@ -1218,6 +1220,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1218,6 +1220,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1218 | .cond_br => self.airCondBr(inst), | 1220 | .cond_br => self.airCondBr(inst), |
| 1219 | .dbg_stmt => WValue.none, | 1221 | .dbg_stmt => WValue.none, |
| 1220 | .intcast => self.airIntcast(inst), | 1222 | .intcast => self.airIntcast(inst), |
| | 1223 | .fpext => self.airFpext(inst), |
| 1221 | .float_to_int => self.airFloatToInt(inst), | 1224 | .float_to_int => self.airFloatToInt(inst), |
| 1222 | .get_union_tag => self.airGetUnionTag(inst), | 1225 | .get_union_tag => self.airGetUnionTag(inst), |
| 1223 | | 1226 | |
| ... | @@ -1298,7 +1301,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1298,7 +1301,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1298 | .is_err_ptr, | 1301 | .is_err_ptr, |
| 1299 | .is_non_err_ptr, | 1302 | .is_non_err_ptr, |
| 1300 | .fptrunc, | 1303 | .fptrunc, |
| 1301 | .fpext, | | |
| 1302 | .unwrap_errunion_payload_ptr, | 1304 | .unwrap_errunion_payload_ptr, |
| 1303 | .unwrap_errunion_err_ptr, | 1305 | .unwrap_errunion_err_ptr, |
| 1304 | | 1306 | |
| ... | @@ -1513,7 +1515,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro | ... | @@ -1513,7 +1515,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1513 | | 1515 | |
| 1514 | return self.memCopy(ty, lhs, rhs); | 1516 | return self.memCopy(ty, lhs, rhs); |
| 1515 | }, | 1517 | }, |
| 1516 | .Struct, .Array, .Union => { | 1518 | .Struct, .Array, .Union, .Vector => { |
| 1517 | return self.memCopy(ty, lhs, rhs); | 1519 | return self.memCopy(ty, lhs, rhs); |
| 1518 | }, | 1520 | }, |
| 1519 | .Pointer => { | 1521 | .Pointer => { |
| ... | @@ -2408,9 +2410,9 @@ fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2408,9 +2410,9 @@ fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2408 | const ref_info = ref_ty.intInfo(self.target); | 2410 | const ref_info = ref_ty.intInfo(self.target); |
| 2409 | const wanted_info = ty.intInfo(self.target); | 2411 | const wanted_info = ty.intInfo(self.target); |
| 2410 | | 2412 | |
| 2411 | const op_bits = toWasmIntBits(ref_info.bits) orelse | 2413 | const op_bits = toWasmBits(ref_info.bits) orelse |
| 2412 | return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{ref_info.bits}); | 2414 | return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{ref_info.bits}); |
| 2413 | const wanted_bits = toWasmIntBits(wanted_info.bits) orelse | 2415 | const wanted_bits = toWasmBits(wanted_info.bits) orelse |
| 2414 | return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{wanted_info.bits}); | 2416 | return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{wanted_info.bits}); |
| 2415 | | 2417 | |
| 2416 | // hot path | 2418 | // hot path |
| ... | @@ -2651,7 +2653,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2651,7 +2653,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2651 | const result = try self.allocLocal(self.air.getRefType(ty_op.ty)); | 2653 | const result = try self.allocLocal(self.air.getRefType(ty_op.ty)); |
| 2652 | const op_bits = op_ty.intInfo(self.target).bits; | 2654 | const op_bits = op_ty.intInfo(self.target).bits; |
| 2653 | | 2655 | |
| 2654 | const wasm_bits = toWasmIntBits(wanted_bits) orelse | 2656 | const wasm_bits = toWasmBits(wanted_bits) orelse |
| 2655 | return self.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{wanted_bits}); | 2657 | return self.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{wanted_bits}); |
| 2656 | | 2658 | |
| 2657 | // Use wasm's instruction to wrap from 64bit to 32bit integer when possible | 2659 | // Use wasm's instruction to wrap from 64bit to 32bit integer when possible |
| ... | @@ -3182,3 +3184,28 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3182,3 +3184,28 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3182 | } else @as(u32, 0); | 3184 | } else @as(u32, 0); |
| 3183 | return self.load(operand, tag_ty, offset); | 3185 | return self.load(operand, tag_ty, offset); |
| 3184 | } | 3186 | } |
| | 3187 | |
| | 3188 | fn airFpext(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| | 3189 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| | 3190 | |
| | 3191 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| | 3192 | const ty = self.air.typeOfIndex(inst); |
| | 3193 | const wanted_bits = ty.floatBits(self.target); |
| | 3194 | const have_bits = self.air.typeOf(ty_op.operand).floatBits(self.target); |
| | 3195 | const operand = try self.resolveInst(ty_op.operand); |
| | 3196 | |
| | 3197 | const have = toWasmBits(have_bits) orelse { |
| | 3198 | return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{have_bits}); |
| | 3199 | }; |
| | 3200 | const wanted = toWasmBits(wanted_bits) orelse { |
| | 3201 | return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{wanted_bits}); |
| | 3202 | }; |
| | 3203 | if (have == wanted) return operand; |
| | 3204 | |
| | 3205 | assert(have < wanted); |
| | 3206 | const result = try self.allocLocal(ty); |
| | 3207 | try self.emitWValue(operand); |
| | 3208 | try self.addTag(.f64_promote_f32); |
| | 3209 | try self.addLabel(.local_set, result.local); |
| | 3210 | return result; |
| | 3211 | } |