| ... | @@ -29,6 +29,9 @@ const errUnionErrorOffset = codegen.errUnionErrorOffset; | ... | @@ -29,6 +29,9 @@ const errUnionErrorOffset = codegen.errUnionErrorOffset; |
| 29 | | 29 | |
| 30 | /// Wasm Value, created when generating an instruction | 30 | /// Wasm Value, created when generating an instruction |
| 31 | const WValue = union(enum) { | 31 | const WValue = union(enum) { |
| | 32 | /// `WValue` which has been freed and may no longer hold |
| | 33 | /// any references. |
| | 34 | dead: void, |
| 32 | /// May be referenced but is unused | 35 | /// May be referenced but is unused |
| 33 | none: void, | 36 | none: void, |
| 34 | /// The value lives on top of the stack | 37 | /// The value lives on top of the stack |
| ... | @@ -86,6 +89,7 @@ const WValue = union(enum) { | ... | @@ -86,6 +89,7 @@ const WValue = union(enum) { |
| 86 | fn offset(value: WValue) u32 { | 89 | fn offset(value: WValue) u32 { |
| 87 | switch (value) { | 90 | switch (value) { |
| 88 | .stack_offset => |stack_offset| return stack_offset.value, | 91 | .stack_offset => |stack_offset| return stack_offset.value, |
| | 92 | .dead => unreachable, |
| 89 | else => return 0, | 93 | else => return 0, |
| 90 | } | 94 | } |
| 91 | } | 95 | } |
| ... | @@ -123,7 +127,7 @@ const WValue = union(enum) { | ... | @@ -123,7 +127,7 @@ const WValue = union(enum) { |
| 123 | .f64 => gen.free_locals_f64.append(gen.gpa, local_value) catch return, | 127 | .f64 => gen.free_locals_f64.append(gen.gpa, local_value) catch return, |
| 124 | .v128 => gen.free_locals_v128.append(gen.gpa, local_value) catch return, | 128 | .v128 => gen.free_locals_v128.append(gen.gpa, local_value) catch return, |
| 125 | } | 129 | } |
| 126 | value.* = undefined; | 130 | value.* = .dead; |
| 127 | } | 131 | } |
| 128 | }; | 132 | }; |
| 129 | | 133 | |
| ... | @@ -832,6 +836,7 @@ const Branch = struct { | ... | @@ -832,6 +836,7 @@ const Branch = struct { |
| 832 | | 836 | |
| 833 | fn deinit(branch: *Branch, gpa: Allocator) void { | 837 | fn deinit(branch: *Branch, gpa: Allocator) void { |
| 834 | branch.values.deinit(gpa); | 838 | branch.values.deinit(gpa); |
| | 839 | branch.* = undefined; |
| 835 | } | 840 | } |
| 836 | }; | 841 | }; |
| 837 | | 842 | |
| ... | @@ -884,7 +889,7 @@ fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void { | ... | @@ -884,7 +889,7 @@ fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void { |
| 884 | if (value.local.value < reserved_indexes) { | 889 | if (value.local.value < reserved_indexes) { |
| 885 | return; // function arguments can never be re-used | 890 | return; // function arguments can never be re-used |
| 886 | } | 891 | } |
| 887 | log.debug("Decreasing reference for ref: %{?d}, using local '{d}'\n", .{ Air.refToIndex(ref), value.local.value }); | 892 | log.debug("Decreasing reference for ref: %{?d}, using local '{d}'", .{ Air.refToIndex(ref), value.local.value }); |
| 888 | value.local.references -= 1; // if this panics, a call to `reuseOperand` was forgotten by the developer | 893 | value.local.references -= 1; // if this panics, a call to `reuseOperand` was forgotten by the developer |
| 889 | if (value.local.references == 0) { | 894 | if (value.local.references == 0) { |
| 890 | value.free(func); | 895 | value.free(func); |
| ... | @@ -1030,6 +1035,7 @@ fn genBlockType(ty: Type, target: std.Target) u8 { | ... | @@ -1030,6 +1035,7 @@ fn genBlockType(ty: Type, target: std.Target) u8 { |
| 1030 | /// Writes the bytecode depending on the given `WValue` in `val` | 1035 | /// Writes the bytecode depending on the given `WValue` in `val` |
| 1031 | fn emitWValue(func: *CodeGen, value: WValue) InnerError!void { | 1036 | fn emitWValue(func: *CodeGen, value: WValue) InnerError!void { |
| 1032 | switch (value) { | 1037 | switch (value) { |
| | 1038 | .dead => unreachable, // reference to free'd `WValue` (missing reuseOperand?) |
| 1033 | .none, .stack => {}, // no-op | 1039 | .none, .stack => {}, // no-op |
| 1034 | .local => |idx| try func.addLabel(.local_get, idx.value), | 1040 | .local => |idx| try func.addLabel(.local_get, idx.value), |
| 1035 | .imm32 => |val| try func.addImm32(@bitCast(i32, val)), | 1041 | .imm32 => |val| try func.addImm32(@bitCast(i32, val)), |
| ... | @@ -1226,6 +1232,7 @@ fn genFunc(func: *CodeGen) InnerError!void { | ... | @@ -1226,6 +1232,7 @@ fn genFunc(func: *CodeGen) InnerError!void { |
| 1226 | defer { | 1232 | defer { |
| 1227 | var outer_branch = func.branches.pop(); | 1233 | var outer_branch = func.branches.pop(); |
| 1228 | outer_branch.deinit(func.gpa); | 1234 | outer_branch.deinit(func.gpa); |
| | 1235 | assert(func.branches.items.len == 0); // missing branch merge |
| 1229 | } | 1236 | } |
| 1230 | // Generate MIR for function body | 1237 | // Generate MIR for function body |
| 1231 | try func.genBody(func.air.getMainBody()); | 1238 | try func.genBody(func.air.getMainBody()); |