authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-03 02:20:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-04 15:57:40-07:00
log7bd63a602a433044f321534117570b1da338e946
tree760185df484d64ae512b8824d7b6687efed79d2e
parent8bfbfa589c424fc58d9c9a097b1df050738a337c

CBE: fix assignment expr and switch free tracking


1 files changed, 74 insertions(+), 30 deletions(-)

src/codegen/c.zig+74-30
......@@ -2488,9 +2488,7 @@ pub fn genFunc(f: *Function) !void {
24882488 const local = f.locals.items[local_index];
24892489 log.debug("inserting local {d} into free_locals", .{local_index});
24902490 const gop = try f.free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());
2491 if (!gop.found_existing) {
2492 gop.value_ptr.* = .{};
2493 }
2491 if (!gop.found_existing) gop.value_ptr.* = .{};
24942492 try gop.value_ptr.append(gpa, local_index);
24952493 }
24962494
......@@ -3819,14 +3817,16 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
38193817 const inst_ty = f.air.typeOfIndex(inst);
38203818 const local = try f.allocLocal(inst, inst_ty);
38213819 try f.writeCValue(writer, local, .Other);
3822 try writer.writeAll(" = {(");
3820 try writer.writeAll(".ptr = (");
38233821 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
38243822 try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf));
38253823 try writer.writeByte(')');
38263824 try f.writeCValue(writer, ptr, .Other);
3827 try writer.writeAll(", ");
3825 try writer.writeAll("; ");
3826 try f.writeCValue(writer, local, .Other);
3827 try writer.writeAll(".len = ");
38283828 try f.writeCValue(writer, len, .Initializer);
3829 try writer.writeAll("};\n");
3829 try writer.writeAll(";\n");
38303830
38313831 return local;
38323832}
......@@ -4292,6 +4292,11 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
42924292 try die(f, inst, Air.indexToRef(operand));
42934293 }
42944294
4295 // Remember how many locals there were before entering the then branch so
4296 // that we can notice and use them in the else branch. Any new locals must
4297 // necessarily be free already after the then branch is complete.
4298 const pre_locals_len = @intCast(LocalIndex, f.locals.items.len);
4299
42954300 try writer.writeAll("if (");
42964301 try f.writeCValue(writer, cond, .Other);
42974302 try writer.writeAll(") ");
......@@ -4304,6 +4309,9 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
43044309 for (liveness_condbr.else_deaths) |operand| {
43054310 try die(f, inst, Air.indexToRef(operand));
43064311 }
4312
4313 try noticeBranchFrees(f, pre_locals_len);
4314
43074315 try genBody(f, else_body);
43084316 try f.object.indent_writer.insertNewline();
43094317
......@@ -4335,10 +4343,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
43354343 const gpa = f.object.dg.gpa;
43364344 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.data.cases_len + 1);
43374345 defer gpa.free(liveness.deaths);
4346
43384347 // On the final iteration we do not clone the map. This ensures that
43394348 // lowering proceeds after the switch_br taking into account the
43404349 // mutations to the liveness information.
43414350 const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0);
4351
43424352 var extra_index: usize = switch_br.end;
43434353 var case_i: u32 = 0;
43444354 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
......@@ -4358,31 +4368,43 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
43584368 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other);
43594369 try writer.writeAll(": ");
43604370 }
4371
43614372 if (case_i != last_case_i) {
43624373 const old_value_map = f.value_map;
43634374 f.value_map = try old_value_map.clone();
43644375 const old_free_locals = f.free_locals;
43654376 f.free_locals = try cloneFreeLocalsMap(gpa, &f.free_locals);
43664377
4367 defer {
4368 f.value_map.deinit();
4369 deinitFreeLocalsMap(gpa, &f.free_locals);
4370 f.value_map = old_value_map;
4371 f.free_locals = old_free_locals;
4372 }
4378 // Remember how many locals there were before entering each branch so that
4379 // we can notice and use them in subsequent branches. Any new locals must
4380 // necessarily be free already after the previous branch is complete.
4381 const pre_locals_len = @intCast(LocalIndex, f.locals.items.len);
43734382
4374 for (liveness.deaths[case_i]) |operand| {
4375 try die(f, inst, Air.indexToRef(operand));
4383 {
4384 defer {
4385 f.value_map.deinit();
4386 deinitFreeLocalsMap(gpa, &f.free_locals);
4387 f.value_map = old_value_map;
4388 f.free_locals = old_free_locals;
4389 }
4390
4391 for (liveness.deaths[case_i]) |operand| {
4392 try die(f, inst, Air.indexToRef(operand));
4393 }
4394
4395 try genBody(f, case_body);
43764396 }
43774397
4378 try genBody(f, case_body);
4398 try noticeBranchFrees(f, pre_locals_len);
43794399 } else {
43804400 for (liveness.deaths[case_i]) |operand| {
43814401 try die(f, inst, Air.indexToRef(operand));
43824402 }
43834403 try genBody(f, case_body);
43844404 }
4405
43854406 // The case body must be noreturn so we don't need to insert a break.
4407
43864408 }
43874409
43884410 const else_body = f.air.extra[extra_index..][0..switch_br.data.else_body_len];
......@@ -5278,12 +5300,16 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
52785300 try reap(f, inst, &.{ty_op.operand});
52795301 const writer = f.object.writer();
52805302 const local = try f.allocLocal(inst, inst_ty);
5303 if (!is_array) {
5304 try f.writeCValue(writer, local, .Other);
5305 try writer.writeAll(".payload = ");
5306 try f.writeCValue(writer, payload, .Other);
5307 try writer.writeAll("; ");
5308 }
52815309 try f.writeCValue(writer, local, .Other);
5282 try writer.writeAll(" = { .payload = ");
5283 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
5284 try writer.writeAll(", .is_null = ");
5310 try writer.writeAll(".is_null = ");
52855311 try f.object.dg.renderValue(writer, Type.bool, Value.false, .Initializer);
5286 try writer.writeAll(" };\n");
5312 try writer.writeAll(";\n");
52875313 if (is_array) {
52885314 try writer.writeAll("memcpy(");
52895315 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
......@@ -5312,12 +5338,14 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
53125338 try reap(f, inst, &.{ty_op.operand});
53135339
53145340 const local = try f.allocLocal(inst, error_union_ty);
5341 {
5342 // TODO: set the payload to undefined
5343 //try f.writeCValue(writer, local, .Other);
5344 }
53155345 try f.writeCValue(writer, local, .Other);
5316 try writer.writeAll(" = { .payload = ");
5317 try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer);
5318 try writer.writeAll(", .error = ");
5319 try f.writeCValue(writer, operand, .Initializer);
5320 try writer.writeAll(" };\n");
5346 try writer.writeAll(".error = ");
5347 try f.writeCValue(writer, operand, .Other);
5348 try writer.writeAll(";\n");
53215349 return local;
53225350}
53235351
......@@ -5379,7 +5407,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
53795407 }
53805408
53815409 const inst_ty = f.air.typeOfIndex(inst);
5382 const error_ty = inst_ty.errorUnionSet();
53835410 const payload_ty = inst_ty.errorUnionPayload();
53845411 const payload = try f.resolveInst(ty_op.operand);
53855412 try reap(f, inst, &.{ty_op.operand});
......@@ -5389,12 +5416,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
53895416
53905417 const writer = f.object.writer();
53915418 const local = try f.allocLocal(inst, inst_ty);
5419 if (!is_array) {
5420 try f.writeCValue(writer, local, .Other);
5421 try writer.writeAll(".payload = ");
5422 try f.writeCValue(writer, payload, .Other);
5423 try writer.writeAll("; ");
5424 }
53925425 try f.writeCValue(writer, local, .Other);
5393 try writer.writeAll(" = { .payload = ");
5394 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
5395 try writer.writeAll(", .error = ");
5396 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
5397 try writer.writeAll(" };\n");
5426 try writer.writeAll(".error = 0;\n");
53985427 if (is_array) {
53995428 try writer.writeAll("memcpy(");
54005429 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
......@@ -6911,6 +6940,8 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in
69116940 // free_locals map while it already exists in the map, which is not
69126941 // allowed.
69136942 assert(mem.indexOfScalar(LocalIndex, gop.value_ptr.items, local_index) == null);
6943 // If this trips, an unfreeable allocation was attempted to be freed.
6944 assert(!f.allocs.contains(local_index));
69146945 }
69156946 try gop.value_ptr.append(gpa, local_index);
69166947}
......@@ -6960,3 +6991,16 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {
69606991 }
69616992 map.deinit(gpa);
69626993}
6994
6995fn noticeBranchFrees(f: *Function, pre_locals_len: LocalIndex) !void {
6996 const gpa = f.object.dg.gpa;
6997 var i = pre_locals_len;
6998 while (i < f.locals.items.len) : (i += 1) {
6999 const local = f.locals.items[i];
7000 const unfreeable = f.allocs.contains(i);
7001 if (unfreeable) continue;
7002 const gop = try f.free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());
7003 if (!gop.found_existing) gop.value_ptr.* = .{};
7004 try gop.value_ptr.append(gpa, i);
7005 }
7006}