authorgravatar for jonathan.haehne@hotmail.comTau <jonathan.haehne@hotmail.com> 2022-10-10 22:30:33+02:00
committergravatar for jonathan.haehne@hotmail.comTau <jonathan.haehne@hotmail.com> 2022-10-10 22:30:33+02:00
log6be16eeae92120fab81c51dbeaf9960375dc0ab1
treef57aac88112f3e0a74239cf5e4e7c77f26273e7d
parent2ca503ec059c96d864034d2e1b09305eea7722cd

translate-c: fix the remaining function pointer issues


2 files changed, 73 insertions(+), 21 deletions(-)

src/translate_c.zig+5-13
......@@ -436,7 +436,7 @@ pub fn translate(
436436 }
437437 }
438438
439 return ast.render(gpa, context.global_scope.nodes.items);
439 return ast.render(gpa, zig_is_stage1, context.global_scope.nodes.items);
440440}
441441
442442/// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens)
......@@ -2072,10 +2072,7 @@ fn transImplicitCastExpr(
20722072 },
20732073 .PointerToBoolean => {
20742074 // @ptrToInt(val) != 0
2075 var ptr_node = try transExpr(c, scope, sub_expr, .used);
2076 if (ptr_node.tag() == .fn_identifier) {
2077 ptr_node = try Tag.address_of.create(c.arena, ptr_node);
2078 }
2075 const ptr_node = try transExpr(c, scope, sub_expr, .used);
20792076 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, ptr_node);
20802077
20812078 const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() });
......@@ -2524,10 +2521,7 @@ fn transCCast(
25242521 }
25252522 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {
25262523 // @intCast(dest_type, @ptrToInt(val))
2527 const ptr_to_int = if (expr.tag() == .fn_identifier)
2528 try Tag.ptr_to_int.create(c.arena, try Tag.address_of.create(c.arena, expr))
2529 else
2530 try Tag.ptr_to_int.create(c.arena, expr);
2524 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
25312525 return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });
25322526 }
25332527 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {
......@@ -3566,7 +3560,8 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
35663560
35673561 // Special case: actual pointer (not decayed array) and signed integer subscript
35683562 // See discussion at https://github.com/ziglang/zig/pull/8589
3569 if (is_signed and (base_stmt == unwrapped_base) and !is_vector and !is_nonnegative_int_literal) return transSignedArrayAccess(c, scope, base_stmt, subscr_expr, result_used);
3563 if (is_signed and (base_stmt == unwrapped_base) and !is_vector and !is_nonnegative_int_literal)
3564 return transSignedArrayAccess(c, scope, base_stmt, subscr_expr, result_used);
35703565
35713566 const container_node = try transExpr(c, scope, unwrapped_base, .used);
35723567 const rhs = if (is_longlong or is_signed) blk: {
......@@ -3761,9 +3756,6 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
37613756 else
37623757 return transCreatePreCrement(c, scope, stmt, .sub_assign, used),
37633758 .AddrOf => {
3764 if (c.zig_is_stage1 and cIsFunctionDeclRef(op_expr)) {
3765 return transExpr(c, scope, op_expr, used);
3766 }
37673759 return Tag.address_of.create(c.arena, try transExpr(c, scope, op_expr, used));
37683760 },
37693761 .Deref => {
src/translate_c/ast.zig+68-8
......@@ -717,10 +717,11 @@ pub const Payload = struct {
717717
718718/// Converts the nodes into a Zig Ast.
719719/// Caller must free the source slice.
720pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
720pub fn render(gpa: Allocator, zig_is_stage1: bool, nodes: []const Node) !std.zig.Ast {
721721 var ctx = Context{
722722 .gpa = gpa,
723723 .buf = std.ArrayList(u8).init(gpa),
724 .zig_is_stage1 = zig_is_stage1,
724725 };
725726 defer ctx.buf.deinit();
726727 defer ctx.nodes.deinit(gpa);
......@@ -789,6 +790,11 @@ const Context = struct {
789790 extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{},
790791 tokens: std.zig.Ast.TokenList = .{},
791792
793 /// This is used to emit different code depending on whether
794 /// the output zig source code is intended to be compiled with stage1 or stage2.
795 /// Refer to the Context in translate_c.zig.
796 zig_is_stage1: bool,
797
792798 fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
793799 const start_index = c.buf.items.len;
794800 try c.buf.writer().print(format ++ " ", args);
......@@ -910,7 +916,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
910916 },
911917 .call => {
912918 const payload = node.castTag(.call).?.data;
913 const lhs = try renderNodeGrouped(c, payload.lhs);
919 // Cosmetic: avoids an unnecesary address_of on most function calls.
920 const lhs = if (!c.zig_is_stage1 and payload.lhs.tag() == .fn_identifier)
921 try c.addNode(.{
922 .tag = .identifier,
923 .main_token = try c.addIdentifier(payload.lhs.castTag(.fn_identifier).?.data),
924 .data = undefined,
925 })
926 else
927 try renderNodeGrouped(c, payload.lhs);
914928 return renderCall(c, lhs, payload.args);
915929 },
916930 .null_literal => return c.addNode(.{
......@@ -1064,12 +1078,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
10641078 });
10651079 },
10661080 .fn_identifier => {
1081 // C semantics are that a function identifier has address
1082 // value (implicit in stage1, explicit in stage2), except in
1083 // the context of an address_of, which is handled there.
10671084 const payload = node.castTag(.fn_identifier).?.data;
1068 return c.addNode(.{
1069 .tag = .identifier,
1070 .main_token = try c.addIdentifier(payload),
1071 .data = undefined,
1072 });
1085 if (c.zig_is_stage1) {
1086 return try c.addNode(.{
1087 .tag = .identifier,
1088 .main_token = try c.addIdentifier(payload),
1089 .data = undefined,
1090 });
1091 } else {
1092 const tok = try c.addToken(.ampersand, "&");
1093 const arg = try c.addNode(.{
1094 .tag = .identifier,
1095 .main_token = try c.addIdentifier(payload),
1096 .data = undefined,
1097 });
1098 return c.addNode(.{
1099 .tag = .address_of,
1100 .main_token = tok,
1101 .data = .{
1102 .lhs = arg,
1103 .rhs = undefined,
1104 },
1105 });
1106 }
10731107 },
10741108 .float_literal => {
10751109 const payload = node.castTag(.float_literal).?.data;
......@@ -1391,7 +1425,33 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13911425 .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"),
13921426 .not => return renderPrefixOp(c, node, .bool_not, .bang, "!"),
13931427 .optional_type => return renderPrefixOp(c, node, .optional_type, .question_mark, "?"),
1394 .address_of => return renderPrefixOp(c, node, .address_of, .ampersand, "&"),
1428 .address_of => {
1429 const payload = node.castTag(.address_of).?.data;
1430 if (c.zig_is_stage1 and payload.tag() == .fn_identifier)
1431 return try c.addNode(.{
1432 .tag = .identifier,
1433 .main_token = try c.addIdentifier(payload.castTag(.fn_identifier).?.data),
1434 .data = undefined,
1435 });
1436
1437 const ampersand = try c.addToken(.ampersand, "&");
1438 const base = if (payload.tag() == .fn_identifier)
1439 try c.addNode(.{
1440 .tag = .identifier,
1441 .main_token = try c.addIdentifier(payload.castTag(.fn_identifier).?.data),
1442 .data = undefined,
1443 })
1444 else
1445 try renderNodeGrouped(c, payload);
1446 return c.addNode(.{
1447 .tag = .address_of,
1448 .main_token = ampersand,
1449 .data = .{
1450 .lhs = base,
1451 .rhs = undefined,
1452 },
1453 });
1454 },
13951455 .deref => {
13961456 const payload = node.castTag(.deref).?.data;
13971457 const operand = try renderNodeGrouped(c, payload);