| ... | ... | @@ -24,8 +24,8 @@ const WValue = union(enum) { |
| 24 | 24 | none: void, |
| 25 | 25 | /// Index of the local variable |
| 26 | 26 | local: u32, |
| 27 | | /// Instruction holding a constant `Value` |
| 28 | | constant: Air.Inst.Index, |
| 27 | /// Holds a memoized typed value |
| 28 | constant: TypedValue, |
| 29 | 29 | /// Offset position in the list of bytecode instructions |
| 30 | 30 | code_offset: usize, |
| 31 | 31 | /// Used for variables that create multiple locals on the stack when allocated |
| ... | ... | @@ -484,7 +484,7 @@ pub const Result = union(enum) { |
| 484 | 484 | }; |
| 485 | 485 | |
| 486 | 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 | 489 | /// Code represents the `Code` section of wasm that |
| 490 | 490 | /// belongs to a function |
| ... | ... | @@ -548,14 +548,23 @@ pub const Context = struct { |
| 548 | 548 | /// Resolves the `WValue` for the given instruction `inst` |
| 549 | 549 | /// When the given instruction has a `Value`, it returns a constant instead |
| 550 | 550 | fn resolveInst(self: Context, ref: Air.Inst.Ref) WValue { |
| 551 | | const ref_type = self.air.getRefType(ref); |
| 552 | | if (ref_type.hasCodeGenBits()) return .none; |
| 551 | const inst_index = Air.refToIndex(ref) orelse { |
| 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) { |
| 555 | | return WValue{ .constant = @enumToInt(ref) }; |
| 559 | const inst_type = self.air.typeOfIndex(inst_index); |
| 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 | 570 | /// Using a given `Type`, returns the corresponding wasm Valtype |
| ... | ... | @@ -611,12 +620,7 @@ pub const Context = struct { |
| 611 | 620 | try writer.writeByte(wasm.opcode(.local_get)); |
| 612 | 621 | try leb.writeULEB128(writer, idx); |
| 613 | 622 | }, |
| 614 | | .constant => |index| { |
| 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 | | }, |
| 623 | .constant => |tv| try self.emitConstant(tv.val, tv.ty), // Creates a new constant on the stack |
| 620 | 624 | } |
| 621 | 625 | } |
| 622 | 626 | |
| ... | ... | @@ -838,7 +842,7 @@ pub const Context = struct { |
| 838 | 842 | fn genBody(self: *Context, body: []const Air.Inst.Index) InnerError!void { |
| 839 | 843 | for (body) |inst| { |
| 840 | 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 | 860 | const args = self.air.extra[extra.end..][0..extra.data.args_len]; |
| 857 | 861 | |
| 858 | 862 | const target: *Decl = blk: { |
| 859 | | const ty_pl = self.air.instructions.items(.data)[@enumToInt(pl_op.operand)].ty_pl; |
| 860 | | const func_val = self.air.values[ty_pl.payload]; |
| 863 | const func_val = self.air.value(pl_op.operand).?; |
| 861 | 864 | |
| 862 | 865 | if (func_val.castTag(.function)) |func| { |
| 863 | 866 | break :blk func.data.owner_decl; |
| ... | ... | @@ -868,7 +871,7 @@ pub const Context = struct { |
| 868 | 871 | }; |
| 869 | 872 | |
| 870 | 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 | 875 | try self.emitWValue(arg_val); |
| 873 | 876 | } |
| 874 | 877 | |
| ... | ... | @@ -902,7 +905,7 @@ pub const Context = struct { |
| 902 | 905 | // we simply assign the local_index to the rhs one. |
| 903 | 906 | // This allows us to update struct fields without having to individually |
| 904 | 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 | 909 | .constant, .none => { |
| 907 | 910 | // emit all values onto the stack if constant |
| 908 | 911 | try self.emitWValue(rhs); |
| ... | ... | @@ -1294,10 +1297,8 @@ pub const Context = struct { |
| 1294 | 1297 | try self.startBlock(.block, blocktype, null); |
| 1295 | 1298 | try self.emitWValue(target); |
| 1296 | 1299 | |
| 1297 | | // cases must represent a constant of which its type is in the `typed_value_map` |
| 1298 | | // Therefore we can simply retrieve it. |
| 1299 | | const ty_val = Air.Inst.Ref.typed_value_map[@enumToInt(case.data.item)]; |
| 1300 | | try self.emitConstant(ty_val.val, target_ty); |
| 1300 | const val = self.air.value(case.data.item).?; |
| 1301 | try self.emitConstant(val, target_ty); |
| 1301 | 1302 | const opcode = buildOpcode(.{ |
| 1302 | 1303 | .valtype1 = valtype, |
| 1303 | 1304 | .op = .ne, // not equal because we jump out the block if it does not match the condition |