authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-07-19 15:56:02+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-20 12:19:16-07:00
log1150fc13dc779c91d54538304466cc068ccbf8ed
tree5b2a846377aee8f1196894d01715f8265aaaab4c
parent95756299af77a83564c2dbae09884be20ffe0c5c

wasm: Resolve regressions, add intcast support


1 files changed, 24 insertions(+), 23 deletions(-)

src/codegen/wasm.zig+24-23
...@@ -24,8 +24,8 @@ const WValue = union(enum) {...@@ -24,8 +24,8 @@ const WValue = union(enum) {
24 none: void,24 none: void,
25 /// Index of the local variable25 /// Index of the local variable
26 local: u32,26 local: u32,
27 /// Instruction holding a constant `Value`27 /// Holds a memoized typed value
28 constant: Air.Inst.Index,28 constant: TypedValue,
29 /// Offset position in the list of bytecode instructions29 /// Offset position in the list of bytecode instructions
30 code_offset: usize,30 code_offset: usize,
31 /// Used for variables that create multiple locals on the stack when allocated31 /// Used for variables that create multiple locals on the stack when allocated
...@@ -484,7 +484,7 @@ pub const Result = union(enum) {...@@ -484,7 +484,7 @@ pub const Result = union(enum) {
484};484};
485485
486/// Hashmap to store generated `WValue` for each `Air.Inst.Ref`486/// Hashmap to store generated `WValue` for each `Air.Inst.Ref`
487pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Ref, WValue);487pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Index, WValue);
488488
489/// Code represents the `Code` section of wasm that489/// Code represents the `Code` section of wasm that
490/// belongs to a function490/// belongs to a function
...@@ -548,14 +548,23 @@ pub const Context = struct {...@@ -548,14 +548,23 @@ pub const Context = struct {
548 /// Resolves the `WValue` for the given instruction `inst`548 /// Resolves the `WValue` for the given instruction `inst`
549 /// When the given instruction has a `Value`, it returns a constant instead549 /// When the given instruction has a `Value`, it returns a constant instead
550 fn resolveInst(self: Context, ref: Air.Inst.Ref) WValue {550 fn resolveInst(self: Context, ref: Air.Inst.Ref) WValue {
551 const ref_type = self.air.getRefType(ref);551 const inst_index = Air.refToIndex(ref) orelse {
552 if (ref_type.hasCodeGenBits()) return .none;552 const tv = Air.Inst.Ref.typed_value_map[@enumToInt(ref)];
553 if (!tv.ty.hasCodeGenBits()) {
554 return WValue.none;
555 }
556 return WValue{ .constant = tv };
557 };
553558
554 if (self.air.instructions.items(.tag)[@enumToInt(ref)] == .constant) {559 const inst_type = self.air.typeOfIndex(inst_index);
555 return WValue{ .constant = @enumToInt(ref) };560 if (!inst_type.hasCodeGenBits()) return .none;
561
562 if (self.air.instructions.items(.tag)[inst_index] == .constant) {
563 const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl;
564 return WValue{ .constant = .{ .ty = inst_type, .val = self.air.values[ty_pl.payload] } };
556 }565 }
557566
558 return self.values.get(ref).?; // Instruction does not dominate all uses!567 return self.values.get(inst_index).?; // Instruction does not dominate all uses!
559 }568 }
560569
561 /// Using a given `Type`, returns the corresponding wasm Valtype570 /// Using a given `Type`, returns the corresponding wasm Valtype
...@@ -611,12 +620,7 @@ pub const Context = struct {...@@ -611,12 +620,7 @@ pub const Context = struct {
611 try writer.writeByte(wasm.opcode(.local_get));620 try writer.writeByte(wasm.opcode(.local_get));
612 try leb.writeULEB128(writer, idx);621 try leb.writeULEB128(writer, idx);
613 },622 },
614 .constant => |index| {623 .constant => |tv| try self.emitConstant(tv.val, tv.ty), // Creates a new constant on the stack
615 const ty_pl = self.air.instructions.items(.data)[index].ty_pl;
616 const value = self.air.values[ty_pl.payload];
617 // create a new constant onto the stack
618 try self.emitConstant(value, self.air.getRefType(ty_pl.ty));
619 },
620 }624 }
621 }625 }
622626
...@@ -838,7 +842,7 @@ pub const Context = struct {...@@ -838,7 +842,7 @@ pub const Context = struct {
838 fn genBody(self: *Context, body: []const Air.Inst.Index) InnerError!void {842 fn genBody(self: *Context, body: []const Air.Inst.Index) InnerError!void {
839 for (body) |inst| {843 for (body) |inst| {
840 const result = try self.genInst(inst);844 const result = try self.genInst(inst);
841 try self.values.putNoClobber(self.gpa, @intToEnum(Air.Inst.Ref, inst), result);845 try self.values.putNoClobber(self.gpa, inst, result);
842 }846 }
843 }847 }
844848
...@@ -856,8 +860,7 @@ pub const Context = struct {...@@ -856,8 +860,7 @@ pub const Context = struct {
856 const args = self.air.extra[extra.end..][0..extra.data.args_len];860 const args = self.air.extra[extra.end..][0..extra.data.args_len];
857861
858 const target: *Decl = blk: {862 const target: *Decl = blk: {
859 const ty_pl = self.air.instructions.items(.data)[@enumToInt(pl_op.operand)].ty_pl;863 const func_val = self.air.value(pl_op.operand).?;
860 const func_val = self.air.values[ty_pl.payload];
861864
862 if (func_val.castTag(.function)) |func| {865 if (func_val.castTag(.function)) |func| {
863 break :blk func.data.owner_decl;866 break :blk func.data.owner_decl;
...@@ -868,7 +871,7 @@ pub const Context = struct {...@@ -868,7 +871,7 @@ pub const Context = struct {
868 };871 };
869872
870 for (args) |arg| {873 for (args) |arg| {
871 const arg_val = self.resolveInst(@intToEnum(Air.Inst.Ref, arg));874 const arg_val = self.resolveInst(Air.indexToRef(arg));
872 try self.emitWValue(arg_val);875 try self.emitWValue(arg_val);
873 }876 }
874877
...@@ -902,7 +905,7 @@ pub const Context = struct {...@@ -902,7 +905,7 @@ pub const Context = struct {
902 // we simply assign the local_index to the rhs one.905 // we simply assign the local_index to the rhs one.
903 // This allows us to update struct fields without having to individually906 // This allows us to update struct fields without having to individually
904 // set each local as each field's index will be calculated off the struct's base index907 // set each local as each field's index will be calculated off the struct's base index
905 .multi_value => self.values.put(self.gpa, bin_op.lhs, rhs) catch unreachable, // Instruction does not dominate all uses!908 .multi_value => self.values.put(self.gpa, Air.refToIndex(bin_op.lhs).?, rhs) catch unreachable, // Instruction does not dominate all uses!
906 .constant, .none => {909 .constant, .none => {
907 // emit all values onto the stack if constant910 // emit all values onto the stack if constant
908 try self.emitWValue(rhs);911 try self.emitWValue(rhs);
...@@ -1294,10 +1297,8 @@ pub const Context = struct {...@@ -1294,10 +1297,8 @@ pub const Context = struct {
1294 try self.startBlock(.block, blocktype, null);1297 try self.startBlock(.block, blocktype, null);
1295 try self.emitWValue(target);1298 try self.emitWValue(target);
12961299
1297 // cases must represent a constant of which its type is in the `typed_value_map`1300 const val = self.air.value(case.data.item).?;
1298 // Therefore we can simply retrieve it.1301 try self.emitConstant(val, target_ty);
1299 const ty_val = Air.Inst.Ref.typed_value_map[@enumToInt(case.data.item)];
1300 try self.emitConstant(ty_val.val, target_ty);
1301 const opcode = buildOpcode(.{1302 const opcode = buildOpcode(.{
1302 .valtype1 = valtype,1303 .valtype1 = valtype,
1303 .op = .ne, // not equal because we jump out the block if it does not match the condition1304 .op = .ne, // not equal because we jump out the block if it does not match the condition