aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/c.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-12-03 00:20:57 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-12-04 15:57:40 -0700
commit8bfbfa589c424fc58d9c9a097b1df050738a337c (patch)
treec68e4b56f504f260dd1f28a56370d51e86c0fed2 /src/codegen/c.zig
parent73a76b45c5a2c8fc6ff884c4d3c84c29d37c3034 (diff)
downloadzig-8bfbfa589c424fc58d9c9a097b1df050738a337c.tar.gz
zig-8bfbfa589c424fc58d9c9a097b1df050738a337c.zip
CBE: fix clone of freed locals not being deep clone
Diffstat (limited to 'src/codegen/c.zig')
-rw-r--r--src/codegen/c.zig47
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);
+}