Commit d7902707bc

Lachlan Easton <lachlan@lakebythewoods.xyz>
2020-03-09 10:46:18
Translate C: Allow casting literal ints to pointers
1 parent 7b5fb79
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -5479,18 +5479,20 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
         .LParen => {
             const inner_node = try parseCExpr(c, it, source, source_loc, scope);
 
-            if (it.next().?.id != .RParen) {
+            const next_id = it.next().?.id;
+            if (next_id != .RParen) {
                 const first_tok = it.list.at(0);
                 try failDecl(
                     c,
                     source_loc,
                     source[first_tok.start..first_tok.end],
-                    "unable to translate C expr: expected ')'' here",
-                    .{},
+                    "unable to translate C expr: expected ')'' instead got: {}",
+                    .{@tagName(next_id)},
                 );
                 return error.ParseError;
             }
             var saw_l_paren = false;
+            var saw_integer_literal = false;
             switch (it.peek().?.id) {
                 // (type)(to_cast)
                 .LParen => {
@@ -5499,6 +5501,10 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                 },
                 // (type)identifier
                 .Identifier => {},
+                // (type)integer
+                .IntegerLiteral => {
+                    saw_integer_literal = true;
+                },
                 else => return inner_node,
             }
 
@@ -5519,6 +5525,15 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                 return error.ParseError;
             }
 
+            if (saw_integer_literal) {
+                // @intToPtr(dest, x)
+                const int_to_ptr = try transCreateNodeBuiltinFnCall(c, "@intToPtr");
+                try int_to_ptr.params.push(inner_node);
+                try int_to_ptr.params.push(node_to_cast);
+                int_to_ptr.rparen_token = try appendToken(c, .RParen, ")");
+                return &int_to_ptr.base;
+            }
+
             //(  if (@typeInfo(@TypeOf(x)) == .Pointer)
             //    @ptrCast(dest, @alignCast(@alignOf(dest.Child), x))
             //else if (@typeInfo(@TypeOf(x)) == .Integer and @typeInfo(dest) == .Pointer))
@@ -5750,19 +5765,24 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                     // hack to get zig fmt to render a comma in builtin calls
                     _ = try appendToken(c, .Comma, ",");
 
-                    const ptr_kind = blk: {
-                        // * token
-                        _ = it.prev();
-                        // last token of `node`
-                        const prev_id = it.prev().?.id;
-                        _ = it.next();
-                        _ = it.next();
-                        break :blk if (prev_id == .Keyword_void) .Asterisk else Token.Id.Identifier;
-                    };
+                    // * token
+                    _ = it.prev();
+                    // last token of `node`
+                    const prev_id = it.prev().?.id;
+                    _ = it.next();
+                    _ = it.next();
 
-                    const ptr = try transCreateNodePtrType(c, false, false, ptr_kind);
-                    ptr.rhs = node;
-                    return &ptr.base;
+                    if (prev_id == .Keyword_void) {
+                        const ptr = try transCreateNodePtrType(c, false, false, .Asterisk);
+                        ptr.rhs = node;
+                        const optional_node = try transCreateNodePrefixOp(c, .OptionalType, .QuestionMark, "?");
+                        optional_node.rhs = &ptr.base;
+                        return &optional_node.base;
+                    } else {
+                        const ptr = try transCreateNodePtrType(c, false, false, Token.Id.Identifier);
+                        ptr.rhs = node;
+                        return &ptr.base;
+                    }
                 } else {
                     // expr * expr
                     op_token = try appendToken(c, .Asterisk, "*");
test/translate_c.zig
@@ -2668,11 +2668,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\#define FOO(bar) baz((void *)(baz))
         \\#define BAR (void*) a
     , &[_][]const u8{
-        \\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)))) {
-        \\    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)));
+        \\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)))) {
+        \\    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)));
         \\}
     ,
-        \\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));
+        \\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));
     });
 
     cases.add("macro conditional operator",
@@ -2894,4 +2894,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    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;
         \\}
     });
+
+    cases.add("Cast from integer literals to poiter",
+        \\#define NULL ((void*)0)
+        \\#define GPIO_0_MEM_MAP ((unsigned*)0x8000)
+        \\#define GPIO_1_MEM_MAP ((unsigned*)0x8004)
+        \\#define GPIO_2_MEM_MAP ((unsigned*)0x8008)
+        \\
+    , &[_][]const u8{
+        \\pub const NULL = @intToPtr(?*c_void, 0);
+    ,
+        \\pub const GPIO_0_MEM_MAP = @intToPtr([*c]c_uint, 0x8000);
+    ,
+        \\pub const GPIO_1_MEM_MAP = @intToPtr([*c]c_uint, 0x8004);
+    ,
+        \\pub const GPIO_2_MEM_MAP = @intToPtr([*c]c_uint, 0x8008);
+    });
 }