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(...@@ -436,7 +436,7 @@ pub fn translate(
436 }436 }
437 }437 }
438438
439 return ast.render(gpa, context.global_scope.nodes.items);439 return ast.render(gpa, zig_is_stage1, context.global_scope.nodes.items);
440}440}
441441
442/// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens)442/// Determines whether macro is of the form: `#define FOO FOO` (Possibly with trailing tokens)
...@@ -2072,10 +2072,7 @@ fn transImplicitCastExpr(...@@ -2072,10 +2072,7 @@ fn transImplicitCastExpr(
2072 },2072 },
2073 .PointerToBoolean => {2073 .PointerToBoolean => {
2074 // @ptrToInt(val) != 02074 // @ptrToInt(val) != 0
2075 var ptr_node = try transExpr(c, scope, sub_expr, .used);2075 const 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 }
2079 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, ptr_node);2076 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, ptr_node);
20802077
2081 const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() });2078 const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() });
...@@ -2524,10 +2521,7 @@ fn transCCast(...@@ -2524,10 +2521,7 @@ fn transCCast(
2524 }2521 }
2525 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {2522 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {
2526 // @intCast(dest_type, @ptrToInt(val))2523 // @intCast(dest_type, @ptrToInt(val))
2527 const ptr_to_int = if (expr.tag() == .fn_identifier)2524 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
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);
2531 return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });2525 return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });
2532 }2526 }
2533 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {2527 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {
...@@ -3566,7 +3560,8 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip...@@ -3566,7 +3560,8 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
35663560
3567 // Special case: actual pointer (not decayed array) and signed integer subscript3561 // Special case: actual pointer (not decayed array) and signed integer subscript
3568 // See discussion at https://github.com/ziglang/zig/pull/85893562 // 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
3571 const container_node = try transExpr(c, scope, unwrapped_base, .used);3566 const container_node = try transExpr(c, scope, unwrapped_base, .used);
3572 const rhs = if (is_longlong or is_signed) blk: {3567 const rhs = if (is_longlong or is_signed) blk: {
...@@ -3761,9 +3756,6 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat...@@ -3761,9 +3756,6 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
3761 else3756 else
3762 return transCreatePreCrement(c, scope, stmt, .sub_assign, used),3757 return transCreatePreCrement(c, scope, stmt, .sub_assign, used),
3763 .AddrOf => {3758 .AddrOf => {
3764 if (c.zig_is_stage1 and cIsFunctionDeclRef(op_expr)) {
3765 return transExpr(c, scope, op_expr, used);
3766 }
3767 return Tag.address_of.create(c.arena, try transExpr(c, scope, op_expr, used));3759 return Tag.address_of.create(c.arena, try transExpr(c, scope, op_expr, used));
3768 },3760 },
3769 .Deref => {3761 .Deref => {
src/translate_c/ast.zig+68-8
...@@ -717,10 +717,11 @@ pub const Payload = struct {...@@ -717,10 +717,11 @@ pub const Payload = struct {
717717
718/// Converts the nodes into a Zig Ast.718/// Converts the nodes into a Zig Ast.
719/// Caller must free the source slice.719/// 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 {
721 var ctx = Context{721 var ctx = Context{
722 .gpa = gpa,722 .gpa = gpa,
723 .buf = std.ArrayList(u8).init(gpa),723 .buf = std.ArrayList(u8).init(gpa),
724 .zig_is_stage1 = zig_is_stage1,
724 };725 };
725 defer ctx.buf.deinit();726 defer ctx.buf.deinit();
726 defer ctx.nodes.deinit(gpa);727 defer ctx.nodes.deinit(gpa);
...@@ -789,6 +790,11 @@ const Context = struct {...@@ -789,6 +790,11 @@ const Context = struct {
789 extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{},790 extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{},
790 tokens: std.zig.Ast.TokenList = .{},791 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
792 fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {798 fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
793 const start_index = c.buf.items.len;799 const start_index = c.buf.items.len;
794 try c.buf.writer().print(format ++ " ", args);800 try c.buf.writer().print(format ++ " ", args);
...@@ -910,7 +916,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -910,7 +916,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
910 },916 },
911 .call => {917 .call => {
912 const payload = node.castTag(.call).?.data;918 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);
914 return renderCall(c, lhs, payload.args);928 return renderCall(c, lhs, payload.args);
915 },929 },
916 .null_literal => return c.addNode(.{930 .null_literal => return c.addNode(.{
...@@ -1064,12 +1078,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1064,12 +1078,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1064 });1078 });
1065 },1079 },
1066 .fn_identifier => {1080 .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.
1067 const payload = node.castTag(.fn_identifier).?.data;1084 const payload = node.castTag(.fn_identifier).?.data;
1068 return c.addNode(.{1085 if (c.zig_is_stage1) {
1069 .tag = .identifier,1086 return try c.addNode(.{
1070 .main_token = try c.addIdentifier(payload),1087 .tag = .identifier,
1071 .data = undefined,1088 .main_token = try c.addIdentifier(payload),
1072 });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 }
1073 },1107 },
1074 .float_literal => {1108 .float_literal => {
1075 const payload = node.castTag(.float_literal).?.data;1109 const payload = node.castTag(.float_literal).?.data;
...@@ -1391,7 +1425,33 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1391,7 +1425,33 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1391 .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"),1425 .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"),
1392 .not => return renderPrefixOp(c, node, .bool_not, .bang, "!"),1426 .not => return renderPrefixOp(c, node, .bool_not, .bang, "!"),
1393 .optional_type => return renderPrefixOp(c, node, .optional_type, .question_mark, "?"),1427 .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 },
1395 .deref => {1455 .deref => {
1396 const payload = node.castTag(.deref).?.data;1456 const payload = node.castTag(.deref).?.data;
1397 const operand = try renderNodeGrouped(c, payload);1457 const operand = try renderNodeGrouped(c, payload);