authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-23 20:12:02-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-23 20:30:59-05:00
logc0671a92c7f200a3c32d03db7b7e342c3efdd1fe
tree4a431a548e4eb6fa567fc5c8191f23e5a627ed5e
parent3a1cb62317073b8e599e604b74edf9d10f16d4a2

CBE: simplify always_tail call logic

It should be Sema's job to check this anyway.

1 files changed, 7 insertions(+), 24 deletions(-)

src/codegen/c.zig+7-24
...@@ -54,8 +54,6 @@ pub const CValue = union(enum) {...@@ -54,8 +54,6 @@ pub const CValue = union(enum) {
54 /// Render these bytes literally.54 /// Render these bytes literally.
55 /// TODO make this a [*:0]const u8 to save memory55 /// TODO make this a [*:0]const u8 to save memory
56 bytes: []const u8,56 bytes: []const u8,
57 /// A deferred call_always_tail
58 call_always_tail: void,
59};57};
6058
61const BlockData = struct {59const BlockData = struct {
...@@ -1751,7 +1749,6 @@ pub const DeclGen = struct {...@@ -1751,7 +1749,6 @@ pub const DeclGen = struct {
1751 fmtIdent(ident),1749 fmtIdent(ident),
1752 }),1750 }),
1753 .bytes => |bytes| return w.writeAll(bytes),1751 .bytes => |bytes| return w.writeAll(bytes),
1754 .call_always_tail => return dg.fail("CBE: the result of @call(.always_tail, ...) must be returned directly", .{}),
1755 }1752 }
1756 }1753 }
17571754
...@@ -1785,7 +1782,6 @@ pub const DeclGen = struct {...@@ -1785,7 +1782,6 @@ pub const DeclGen = struct {
1785 try w.writeAll(bytes);1782 try w.writeAll(bytes);
1786 return w.writeByte(')');1783 return w.writeByte(')');
1787 },1784 },
1788 .call_always_tail => return dg.writeCValue(w, c_value),
1789 }1785 }
1790 }1786 }
17911787
...@@ -1798,16 +1794,7 @@ pub const DeclGen = struct {...@@ -1798,16 +1794,7 @@ pub const DeclGen = struct {
1798 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {1794 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
1799 switch (c_value) {1795 switch (c_value) {
1800 .none, .constant, .field, .undef => unreachable,1796 .none, .constant, .field, .undef => unreachable,
1801 .new_local,1797 .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier, .bytes => {
1802 .local,
1803 .arg,
1804 .arg_array,
1805 .decl,
1806 .identifier,
1807 .payload_identifier,
1808 .bytes,
1809 .call_always_tail,
1810 => {
1811 try dg.writeCValue(writer, c_value);1798 try dg.writeCValue(writer, c_value);
1812 try writer.writeAll("->");1799 try writer.writeAll("->");
1813 },1800 },
...@@ -2910,7 +2897,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2910,7 +2897,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
2910 => .none,2897 => .none,
29112898
2912 .call => try airCall(f, inst, .auto),2899 .call => try airCall(f, inst, .auto),
2913 .call_always_tail => .call_always_tail,2900 .call_always_tail => .none,
2914 .call_never_tail => try airCall(f, inst, .never_tail),2901 .call_never_tail => try airCall(f, inst, .never_tail),
2915 .call_never_inline => try airCall(f, inst, .never_inline),2902 .call_never_inline => try airCall(f, inst, .never_inline),
29162903
...@@ -3365,20 +3352,15 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -3365,20 +3352,15 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3365 const un_op = f.air.instructions.items(.data)[inst].un_op;3352 const un_op = f.air.instructions.items(.data)[inst].un_op;
3366 const writer = f.object.writer();3353 const writer = f.object.writer();
3367 const target = f.object.dg.module.getTarget();3354 const target = f.object.dg.module.getTarget();
3355 const op_inst = Air.refToIndex(un_op);
3368 const op_ty = f.air.typeOf(un_op);3356 const op_ty = f.air.typeOf(un_op);
3369 const ret_ty = if (is_ptr) op_ty.childType() else op_ty;3357 const ret_ty = if (is_ptr) op_ty.childType() else op_ty;
3370 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;3358 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
3371 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);3359 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
33723360
3373 const is_naked = if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention() == .Naked else false;3361 if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) {
3374 const peek_operand = f.value_map.get(un_op);
3375 if (if (peek_operand) |operand| operand == .call_always_tail else false) {
3376 try reap(f, inst, &.{un_op});3362 try reap(f, inst, &.{un_op});
3377 if (is_naked) {3363 _ = try airCall(f, op_inst.?, .always_tail);
3378 try f.writeCValue(writer, peek_operand.?, .Other);
3379 unreachable;
3380 }
3381 _ = try airCall(f, Air.refToIndex(un_op).?, .always_tail);
3382 } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) {3364 } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) {
3383 const operand = try f.resolveInst(un_op);3365 const operand = try f.resolveInst(un_op);
3384 try reap(f, inst, &.{un_op});3366 try reap(f, inst, &.{un_op});
...@@ -3412,7 +3394,8 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -3412,7 +3394,8 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3412 } else {3394 } else {
3413 try reap(f, inst, &.{un_op});3395 try reap(f, inst, &.{un_op});
3414 // Not even allowed to return void in a naked function.3396 // Not even allowed to return void in a naked function.
3415 if (!is_naked) try writer.writeAll("return;\n");3397 if (if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention() != .Naked else true)
3398 try writer.writeAll("return;\n");
3416 }3399 }
3417 return .none;3400 return .none;
3418}3401}