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 {...@@ -2488,9 +2488,7 @@ pub fn genFunc(f: *Function) !void {
2488 const local = f.locals.items[local_index];2488 const local = f.locals.items[local_index];
2489 log.debug("inserting local {d} into free_locals", .{local_index});2489 log.debug("inserting local {d} into free_locals", .{local_index});
2490 const gop = try f.free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());2490 const gop = try f.free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());
2491 if (!gop.found_existing) {2491 if (!gop.found_existing) gop.value_ptr.* = .{};
2492 gop.value_ptr.* = .{};
2493 }
2494 try gop.value_ptr.append(gpa, local_index);2492 try gop.value_ptr.append(gpa, local_index);
2495 }2493 }
24962494
...@@ -3819,14 +3817,16 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3819,14 +3817,16 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
3819 const inst_ty = f.air.typeOfIndex(inst);3817 const inst_ty = f.air.typeOfIndex(inst);
3820 const local = try f.allocLocal(inst, inst_ty);3818 const local = try f.allocLocal(inst, inst_ty);
3821 try f.writeCValue(writer, local, .Other);3819 try f.writeCValue(writer, local, .Other);
3822 try writer.writeAll(" = {(");3820 try writer.writeAll(".ptr = (");
3823 var buf: Type.SlicePtrFieldTypeBuffer = undefined;3821 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3824 try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf));3822 try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf));
3825 try writer.writeByte(')');3823 try writer.writeByte(')');
3826 try f.writeCValue(writer, ptr, .Other);3824 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 = ");
3828 try f.writeCValue(writer, len, .Initializer);3828 try f.writeCValue(writer, len, .Initializer);
3829 try writer.writeAll("};\n");3829 try writer.writeAll(";\n");
38303830
3831 return local;3831 return local;
3832}3832}
...@@ -4292,6 +4292,11 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4292,6 +4292,11 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4292 try die(f, inst, Air.indexToRef(operand));4292 try die(f, inst, Air.indexToRef(operand));
4293 }4293 }
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
4295 try writer.writeAll("if (");4300 try writer.writeAll("if (");
4296 try f.writeCValue(writer, cond, .Other);4301 try f.writeCValue(writer, cond, .Other);
4297 try writer.writeAll(") ");4302 try writer.writeAll(") ");
...@@ -4304,6 +4309,9 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4304,6 +4309,9 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4304 for (liveness_condbr.else_deaths) |operand| {4309 for (liveness_condbr.else_deaths) |operand| {
4305 try die(f, inst, Air.indexToRef(operand));4310 try die(f, inst, Air.indexToRef(operand));
4306 }4311 }
4312
4313 try noticeBranchFrees(f, pre_locals_len);
4314
4307 try genBody(f, else_body);4315 try genBody(f, else_body);
4308 try f.object.indent_writer.insertNewline();4316 try f.object.indent_writer.insertNewline();
43094317
...@@ -4335,10 +4343,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4335,10 +4343,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4335 const gpa = f.object.dg.gpa;4343 const gpa = f.object.dg.gpa;
4336 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.data.cases_len + 1);4344 const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.data.cases_len + 1);
4337 defer gpa.free(liveness.deaths);4345 defer gpa.free(liveness.deaths);
4346
4338 // On the final iteration we do not clone the map. This ensures that4347 // On the final iteration we do not clone the map. This ensures that
4339 // lowering proceeds after the switch_br taking into account the4348 // lowering proceeds after the switch_br taking into account the
4340 // mutations to the liveness information.4349 // mutations to the liveness information.
4341 const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0);4350 const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0);
4351
4342 var extra_index: usize = switch_br.end;4352 var extra_index: usize = switch_br.end;
4343 var case_i: u32 = 0;4353 var case_i: u32 = 0;
4344 while (case_i < switch_br.data.cases_len) : (case_i += 1) {4354 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
...@@ -4358,31 +4368,43 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4358,31 +4368,43 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4358 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other);4368 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other);
4359 try writer.writeAll(": ");4369 try writer.writeAll(": ");
4360 }4370 }
4371
4361 if (case_i != last_case_i) {4372 if (case_i != last_case_i) {
4362 const old_value_map = f.value_map;4373 const old_value_map = f.value_map;
4363 f.value_map = try old_value_map.clone();4374 f.value_map = try old_value_map.clone();
4364 const old_free_locals = f.free_locals;4375 const old_free_locals = f.free_locals;
4365 f.free_locals = try cloneFreeLocalsMap(gpa, &f.free_locals);4376 f.free_locals = try cloneFreeLocalsMap(gpa, &f.free_locals);
43664377
4367 defer {4378 // Remember how many locals there were before entering each branch so that
4368 f.value_map.deinit();4379 // we can notice and use them in subsequent branches. Any new locals must
4369 deinitFreeLocalsMap(gpa, &f.free_locals);4380 // necessarily be free already after the previous branch is complete.
4370 f.value_map = old_value_map;4381 const pre_locals_len = @intCast(LocalIndex, f.locals.items.len);
4371 f.free_locals = old_free_locals;
4372 }
43734382
4374 for (liveness.deaths[case_i]) |operand| {4383 {
4375 try die(f, inst, Air.indexToRef(operand));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);
4376 }4396 }
43774397
4378 try genBody(f, case_body);4398 try noticeBranchFrees(f, pre_locals_len);
4379 } else {4399 } else {
4380 for (liveness.deaths[case_i]) |operand| {4400 for (liveness.deaths[case_i]) |operand| {
4381 try die(f, inst, Air.indexToRef(operand));4401 try die(f, inst, Air.indexToRef(operand));
4382 }4402 }
4383 try genBody(f, case_body);4403 try genBody(f, case_body);
4384 }4404 }
4405
4385 // The case body must be noreturn so we don't need to insert a break.4406 // The case body must be noreturn so we don't need to insert a break.
4407
4386 }4408 }
43874409
4388 const else_body = f.air.extra[extra_index..][0..switch_br.data.else_body_len];4410 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 {...@@ -5278,12 +5300,16 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
5278 try reap(f, inst, &.{ty_op.operand});5300 try reap(f, inst, &.{ty_op.operand});
5279 const writer = f.object.writer();5301 const writer = f.object.writer();
5280 const local = try f.allocLocal(inst, inst_ty);5302 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 }
5281 try f.writeCValue(writer, local, .Other);5309 try f.writeCValue(writer, local, .Other);
5282 try writer.writeAll(" = { .payload = ");5310 try writer.writeAll(".is_null = ");
5283 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
5284 try writer.writeAll(", .is_null = ");
5285 try f.object.dg.renderValue(writer, Type.bool, Value.false, .Initializer);5311 try f.object.dg.renderValue(writer, Type.bool, Value.false, .Initializer);
5286 try writer.writeAll(" };\n");5312 try writer.writeAll(";\n");
5287 if (is_array) {5313 if (is_array) {
5288 try writer.writeAll("memcpy(");5314 try writer.writeAll("memcpy(");
5289 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });5315 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
...@@ -5312,12 +5338,14 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5312,12 +5338,14 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5312 try reap(f, inst, &.{ty_op.operand});5338 try reap(f, inst, &.{ty_op.operand});
53135339
5314 const local = try f.allocLocal(inst, error_union_ty);5340 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 }
5315 try f.writeCValue(writer, local, .Other);5345 try f.writeCValue(writer, local, .Other);
5316 try writer.writeAll(" = { .payload = ");5346 try writer.writeAll(".error = ");
5317 try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer);5347 try f.writeCValue(writer, operand, .Other);
5318 try writer.writeAll(", .error = ");5348 try writer.writeAll(";\n");
5319 try f.writeCValue(writer, operand, .Initializer);
5320 try writer.writeAll(" };\n");
5321 return local;5349 return local;
5322}5350}
53235351
...@@ -5379,7 +5407,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5379,7 +5407,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
5379 }5407 }
53805408
5381 const inst_ty = f.air.typeOfIndex(inst);5409 const inst_ty = f.air.typeOfIndex(inst);
5382 const error_ty = inst_ty.errorUnionSet();
5383 const payload_ty = inst_ty.errorUnionPayload();5410 const payload_ty = inst_ty.errorUnionPayload();
5384 const payload = try f.resolveInst(ty_op.operand);5411 const payload = try f.resolveInst(ty_op.operand);
5385 try reap(f, inst, &.{ty_op.operand});5412 try reap(f, inst, &.{ty_op.operand});
...@@ -5389,12 +5416,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5389,12 +5416,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
53895416
5390 const writer = f.object.writer();5417 const writer = f.object.writer();
5391 const local = try f.allocLocal(inst, inst_ty);5418 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 }
5392 try f.writeCValue(writer, local, .Other);5425 try f.writeCValue(writer, local, .Other);
5393 try writer.writeAll(" = { .payload = ");5426 try writer.writeAll(".error = 0;\n");
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");
5398 if (is_array) {5427 if (is_array) {
5399 try writer.writeAll("memcpy(");5428 try writer.writeAll("memcpy(");
5400 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });5429 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
...@@ -6911,6 +6940,8 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in...@@ -6911,6 +6940,8 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in
6911 // free_locals map while it already exists in the map, which is not6940 // free_locals map while it already exists in the map, which is not
6912 // allowed.6941 // allowed.
6913 assert(mem.indexOfScalar(LocalIndex, gop.value_ptr.items, local_index) == null);6942 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));
6914 }6945 }
6915 try gop.value_ptr.append(gpa, local_index);6946 try gop.value_ptr.append(gpa, local_index);
6916}6947}
...@@ -6960,3 +6991,16 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {...@@ -6960,3 +6991,16 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {
6960 }6991 }
6961 map.deinit(gpa);6992 map.deinit(gpa);
6962}6993}
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}