diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-12-03 00:20:57 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-12-04 15:57:40 -0700 |
| commit | 8bfbfa589c424fc58d9c9a097b1df050738a337c (patch) | |
| tree | c68e4b56f504f260dd1f28a56370d51e86c0fed2 /src/codegen | |
| parent | 73a76b45c5a2c8fc6ff884c4d3c84c29d37c3034 (diff) | |
| download | zig-8bfbfa589c424fc58d9c9a097b1df050738a337c.tar.gz zig-8bfbfa589c424fc58d9c9a097b1df050738a337c.zip | |
CBE: fix clone of freed locals not being deep clone
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 82ceaacd43..80047870d1 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -411,7 +411,7 @@ pub const Function = struct { pub fn deinit(f: *Function, gpa: mem.Allocator) void { f.allocs.deinit(gpa); f.locals.deinit(gpa); - f.free_locals.deinit(gpa); + deinitFreeLocalsMap(gpa, &f.free_locals); f.blocks.deinit(gpa); f.value_map.deinit(); f.object.code.deinit(); @@ -4285,8 +4285,8 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { const gpa = f.object.dg.gpa; var cloned_map = try f.value_map.clone(); defer cloned_map.deinit(); - var cloned_frees = try f.free_locals.clone(gpa); - defer cloned_frees.deinit(gpa); + var cloned_frees = try cloneFreeLocalsMap(gpa, &f.free_locals); + defer deinitFreeLocalsMap(gpa, &cloned_frees); for (liveness_condbr.then_deaths) |operand| { try die(f, inst, Air.indexToRef(operand)); @@ -4299,7 +4299,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" else "); f.value_map.deinit(); f.value_map = cloned_map.move(); - f.free_locals.deinit(gpa); + deinitFreeLocalsMap(gpa, &f.free_locals); f.free_locals = cloned_frees.move(); for (liveness_condbr.else_deaths) |operand| { try die(f, inst, Air.indexToRef(operand)); @@ -4362,18 +4362,19 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { const old_value_map = f.value_map; f.value_map = try old_value_map.clone(); const old_free_locals = f.free_locals; - f.free_locals = try f.free_locals.clone(gpa); - - for (liveness.deaths[case_i]) |operand| { - try die(f, inst, Air.indexToRef(operand)); - } + f.free_locals = try cloneFreeLocalsMap(gpa, &f.free_locals); defer { f.value_map.deinit(); - f.free_locals.deinit(gpa); + deinitFreeLocalsMap(gpa, &f.free_locals); f.value_map = old_value_map; f.free_locals = old_free_locals; } + + for (liveness.deaths[case_i]) |operand| { + try die(f, inst, Air.indexToRef(operand)); + } + try genBody(f, case_body); } else { for (liveness.deaths[case_i]) |operand| { @@ -6933,3 +6934,29 @@ fn iterateBigTomb(f: *Function, inst: Air.Inst.Index) BigTomb { .lbt = f.liveness.iterateBigTomb(inst), }; } + +/// A naive clone of this map would create copies of the ArrayList which is +/// stored in the values. This function additionally clones the values. +fn cloneFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) !LocalsMap { + var cloned = try map.clone(gpa); + const values = cloned.values(); + var i: usize = 0; + errdefer { + cloned.deinit(gpa); + while (i > 0) { + i -= 1; + values[i].deinit(gpa); + } + } + while (i < values.len) : (i += 1) { + values[i] = try values[i].clone(gpa); + } + return cloned; +} + +fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void { + for (map.values()) |*value| { + value.deinit(gpa); + } + map.deinit(gpa); +} |
