| ... | @@ -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 variable | 25 | /// 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 instructions | 29 | /// 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 allocated | 31 | /// 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 | }; |
| 485 | | 485 | |
| 486 | /// Hashmap to store generated `WValue` for each `Air.Inst.Ref` | 486 | /// Hashmap to store generated `WValue` for each `Air.Inst.Ref` |
| 487 | pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Ref, WValue); | 487 | pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Index, WValue); |
| 488 | | 488 | |
| 489 | /// Code represents the `Code` section of wasm that | 489 | /// Code represents the `Code` section of wasm that |
| 490 | /// belongs to a function | 490 | /// 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 instead | 549 | /// 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 | }; |
| 553 | | 558 | |
| 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 | } |
| 557 | | 566 | |
| 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 | } |
| 560 | | 569 | |
| 561 | /// Using a given `Type`, returns the corresponding wasm Valtype | 570 | /// 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 | } |
| 622 | | 626 | |
| ... | @@ -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 | } |
| 844 | | 848 | |
| ... | @@ -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]; |
| 857 | | 861 | |
| 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]; | | |
| 861 | | 864 | |
| 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 | }; |
| 869 | | 872 | |
| 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 | } |
| 874 | | 877 | |
| ... | @@ -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 individually | 906 | // 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 index | 907 | // 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 constant | 910 | // 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); |
| 1296 | | 1299 | |
| 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 condition | 1304 | .op = .ne, // not equal because we jump out the block if it does not match the condition |