| author | |
| committer | |
| log | 29ea425ca20305a427919b9a1df85a5c5a8657c3 |
| tree | 244557b0172b781f1dcaa6b2538cf9e515943576 |
| parent | b3aef49eeaa42127ac57ded3b15228db39f806b3 |
| parent | d7902707bcc1faede9ef5490d02bcea935e3b8fc |
| signature |
closes #46882 files changed, 96 insertions(+), 24 deletions(-)
src-self-hosted/translate_c.zig+61-20| ... | ... | @@ -5479,18 +5479,20 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5479 | 5479 | .LParen => { |
| 5480 | 5480 | const inner_node = try parseCExpr(c, it, source, source_loc, scope); |
| 5481 | 5481 | |
| 5482 | if (it.next().?.id != .RParen) { | |
| 5482 | const next_id = it.next().?.id; | |
| 5483 | if (next_id != .RParen) { | |
| 5483 | 5484 | const first_tok = it.list.at(0); |
| 5484 | 5485 | try failDecl( |
| 5485 | 5486 | c, |
| 5486 | 5487 | source_loc, |
| 5487 | 5488 | source[first_tok.start..first_tok.end], |
| 5488 | "unable to translate C expr: expected ')'' here", | |
| 5489 | .{}, | |
| 5489 | "unable to translate C expr: expected ')'' instead got: {}", | |
| 5490 | .{@tagName(next_id)}, | |
| 5490 | 5491 | ); |
| 5491 | 5492 | return error.ParseError; |
| 5492 | 5493 | } |
| 5493 | 5494 | var saw_l_paren = false; |
| 5495 | var saw_integer_literal = false; | |
| 5494 | 5496 | switch (it.peek().?.id) { |
| 5495 | 5497 | // (type)(to_cast) |
| 5496 | 5498 | .LParen => { |
| ... | ... | @@ -5499,6 +5501,10 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5499 | 5501 | }, |
| 5500 | 5502 | // (type)identifier |
| 5501 | 5503 | .Identifier => {}, |
| 5504 | // (type)integer | |
| 5505 | .IntegerLiteral => { | |
| 5506 | saw_integer_literal = true; | |
| 5507 | }, | |
| 5502 | 5508 | else => return inner_node, |
| 5503 | 5509 | } |
| 5504 | 5510 | |
| ... | ... | @@ -5519,12 +5525,21 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5519 | 5525 | return error.ParseError; |
| 5520 | 5526 | } |
| 5521 | 5527 | |
| 5522 | //if (@typeInfo(@TypeOf(x)) == .Pointer) | |
| 5523 | // @ptrCast(dest, x) | |
| 5524 | //else if (@typeInfo(@TypeOf(x)) == .Int and @typeInfo(dest) == .Pointer) | |
| 5528 | if (saw_integer_literal) { | |
| 5529 | // @intToPtr(dest, x) | |
| 5530 | const int_to_ptr = try transCreateNodeBuiltinFnCall(c, "@intToPtr"); | |
| 5531 | try int_to_ptr.params.push(inner_node); | |
| 5532 | try int_to_ptr.params.push(node_to_cast); | |
| 5533 | int_to_ptr.rparen_token = try appendToken(c, .RParen, ")"); | |
| 5534 | return &int_to_ptr.base; | |
| 5535 | } | |
| 5536 | ||
| 5537 | //( if (@typeInfo(@TypeOf(x)) == .Pointer) | |
| 5538 | // @ptrCast(dest, @alignCast(@alignOf(dest.Child), x)) | |
| 5539 | //else if (@typeInfo(@TypeOf(x)) == .Integer and @typeInfo(dest) == .Pointer)) | |
| 5525 | 5540 | // @intToPtr(dest, x) |
| 5526 | 5541 | //else |
| 5527 | // @as(dest, x) | |
| 5542 | // @as(dest, x) ) | |
| 5528 | 5543 | |
| 5529 | 5544 | const lparen = try appendToken(c, .LParen, "("); |
| 5530 | 5545 | |
| ... | ... | @@ -5546,9 +5561,30 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5546 | 5561 | if_1.condition = &cmp_1.base; |
| 5547 | 5562 | _ = try appendToken(c, .RParen, ")"); |
| 5548 | 5563 | |
| 5564 | const period_tok = try appendToken(c, .Period, "."); | |
| 5565 | const child_ident = try transCreateNodeIdentifier(c, "Child"); | |
| 5566 | const inner_node_child = try c.a().create(ast.Node.InfixOp); | |
| 5567 | inner_node_child.* = .{ | |
| 5568 | .op_token = period_tok, | |
| 5569 | .lhs = inner_node, | |
| 5570 | .op = .Period, | |
| 5571 | .rhs = child_ident, | |
| 5572 | }; | |
| 5573 | ||
| 5574 | const align_of = try transCreateNodeBuiltinFnCall(c, "@alignOf"); | |
| 5575 | try align_of.params.push(&inner_node_child.base); | |
| 5576 | align_of.rparen_token = try appendToken(c, .RParen, ")"); | |
| 5577 | // hack to get zig fmt to render a comma in builtin calls | |
| 5578 | _ = try appendToken(c, .Comma, ","); | |
| 5579 | ||
| 5580 | const align_cast = try transCreateNodeBuiltinFnCall(c, "@alignCast"); | |
| 5581 | try align_cast.params.push(&align_of.base); | |
| 5582 | try align_cast.params.push(node_to_cast); | |
| 5583 | align_cast.rparen_token = try appendToken(c, .RParen, ")"); | |
| 5584 | ||
| 5549 | 5585 | const ptr_cast = try transCreateNodeBuiltinFnCall(c, "@ptrCast"); |
| 5550 | 5586 | try ptr_cast.params.push(inner_node); |
| 5551 | try ptr_cast.params.push(node_to_cast); | |
| 5587 | try ptr_cast.params.push(&align_cast.base); | |
| 5552 | 5588 | ptr_cast.rparen_token = try appendToken(c, .RParen, ")"); |
| 5553 | 5589 | if_1.body = &ptr_cast.base; |
| 5554 | 5590 | |
| ... | ... | @@ -5729,19 +5765,24 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5729 | 5765 | // hack to get zig fmt to render a comma in builtin calls |
| 5730 | 5766 | _ = try appendToken(c, .Comma, ","); |
| 5731 | 5767 | |
| 5732 | const ptr_kind = blk: { | |
| 5733 | // * token | |
| 5734 | _ = it.prev(); | |
| 5735 | // last token of `node` | |
| 5736 | const prev_id = it.prev().?.id; | |
| 5737 | _ = it.next(); | |
| 5738 | _ = it.next(); | |
| 5739 | break :blk if (prev_id == .Keyword_void) .Asterisk else Token.Id.Identifier; | |
| 5740 | }; | |
| 5768 | // * token | |
| 5769 | _ = it.prev(); | |
| 5770 | // last token of `node` | |
| 5771 | const prev_id = it.prev().?.id; | |
| 5772 | _ = it.next(); | |
| 5773 | _ = it.next(); | |
| 5741 | 5774 | |
| 5742 | const ptr = try transCreateNodePtrType(c, false, false, ptr_kind); | |
| 5743 | ptr.rhs = node; | |
| 5744 | return &ptr.base; | |
| 5775 | if (prev_id == .Keyword_void) { | |
| 5776 | const ptr = try transCreateNodePtrType(c, false, false, .Asterisk); | |
| 5777 | ptr.rhs = node; | |
| 5778 | const optional_node = try transCreateNodePrefixOp(c, .OptionalType, .QuestionMark, "?"); | |
| 5779 | optional_node.rhs = &ptr.base; | |
| 5780 | return &optional_node.base; | |
| 5781 | } else { | |
| 5782 | const ptr = try transCreateNodePtrType(c, false, false, Token.Id.Identifier); | |
| 5783 | ptr.rhs = node; | |
| 5784 | return &ptr.base; | |
| 5785 | } | |
| 5745 | 5786 | } else { |
| 5746 | 5787 | // expr * expr |
| 5747 | 5788 | op_token = try appendToken(c, .Asterisk, "*"); |
test/translate_c.zig+35-4| ... | ... | @@ -1458,7 +1458,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1458 | 1458 | cases.add("macro pointer cast", |
| 1459 | 1459 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) |
| 1460 | 1460 | , &[_][]const u8{ |
| 1461 | \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int and @typeInfo([*c]NRF_GPIO_Type) == .Pointer) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE)); | |
| 1461 | \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, @alignCast(@alignOf([*c]NRF_GPIO_Type.Child), NRF_GPIO_BASE)) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int and @typeInfo([*c]NRF_GPIO_Type) == .Pointer) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE)); | |
| 1462 | 1462 | }); |
| 1463 | 1463 | |
| 1464 | 1464 | cases.add("basic macro function", |
| ... | ... | @@ -2668,11 +2668,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2668 | 2668 | \\#define FOO(bar) baz((void *)(baz)) |
| 2669 | 2669 | \\#define BAR (void*) a |
| 2670 | 2670 | , &[_][]const u8{ |
| 2671 | \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(*c_void) == .Pointer) @intToPtr(*c_void, baz) else @as(*c_void, baz)))) { | |
| 2672 | \\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(*c_void) == .Pointer) @intToPtr(*c_void, baz) else @as(*c_void, baz))); | |
| 2671 | \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(?*c_void, @alignCast(@alignOf(?*c_void.Child), baz)) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(?*c_void) == .Pointer) @intToPtr(?*c_void, baz) else @as(?*c_void, baz)))) { | |
| 2672 | \\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(?*c_void, @alignCast(@alignOf(?*c_void.Child), baz)) else if (@typeInfo(@TypeOf(baz)) == .Int and @typeInfo(?*c_void) == .Pointer) @intToPtr(?*c_void, baz) else @as(?*c_void, baz))); | |
| 2673 | 2673 | \\} |
| 2674 | 2674 | , |
| 2675 | \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int and @typeInfo(*c_void) == .Pointer) @intToPtr(*c_void, a) else @as(*c_void, a)); | |
| 2675 | \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(?*c_void, @alignCast(@alignOf(?*c_void.Child), a)) else if (@typeInfo(@TypeOf(a)) == .Int and @typeInfo(?*c_void) == .Pointer) @intToPtr(?*c_void, a) else @as(?*c_void, a)); | |
| 2676 | 2676 | }); |
| 2677 | 2677 | |
| 2678 | 2678 | cases.add("macro conditional operator", |
| ... | ... | @@ -2879,4 +2879,35 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2879 | 2879 | , &[_][]const u8{ |
| 2880 | 2880 | \\pub const FOO = 0x61626364; |
| 2881 | 2881 | }); |
| 2882 | ||
| 2883 | cases.add("Make sure casts are grouped", | |
| 2884 | \\typedef struct | |
| 2885 | \\{ | |
| 2886 | \\ int i; | |
| 2887 | \\} | |
| 2888 | \\*_XPrivDisplay; | |
| 2889 | \\typedef struct _XDisplay Display; | |
| 2890 | \\#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen) | |
| 2891 | \\ | |
| 2892 | , &[_][]const u8{ | |
| 2893 | \\pub inline fn DefaultScreen(dpy: var) @TypeOf((if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int and @typeInfo(_XPrivDisplay) == .Pointer) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen) { | |
| 2894 | \\ return (if (@typeInfo(@TypeOf(dpy)) == .Pointer) @ptrCast(_XPrivDisplay, @alignCast(@alignOf(_XPrivDisplay.Child), dpy)) else if (@typeInfo(@TypeOf(dpy)) == .Int and @typeInfo(_XPrivDisplay) == .Pointer) @intToPtr(_XPrivDisplay, dpy) else @as(_XPrivDisplay, dpy)).*.default_screen; | |
| 2895 | \\} | |
| 2896 | }); | |
| 2897 | ||
| 2898 | cases.add("Cast from integer literals to poiter", | |
| 2899 | \\#define NULL ((void*)0) | |
| 2900 | \\#define GPIO_0_MEM_MAP ((unsigned*)0x8000) | |
| 2901 | \\#define GPIO_1_MEM_MAP ((unsigned*)0x8004) | |
| 2902 | \\#define GPIO_2_MEM_MAP ((unsigned*)0x8008) | |
| 2903 | \\ | |
| 2904 | , &[_][]const u8{ | |
| 2905 | \\pub const NULL = @intToPtr(?*c_void, 0); | |
| 2906 | , | |
| 2907 | \\pub const GPIO_0_MEM_MAP = @intToPtr([*c]c_uint, 0x8000); | |
| 2908 | , | |
| 2909 | \\pub const GPIO_1_MEM_MAP = @intToPtr([*c]c_uint, 0x8004); | |
| 2910 | , | |
| 2911 | \\pub const GPIO_2_MEM_MAP = @intToPtr([*c]c_uint, 0x8008); | |
| 2912 | }); | |
| 2882 | 2913 | } |