| author | |
| committer | |
| log | df589eecd61a4a2c93922302f8f486f18d0ff06b |
| tree | dffedae386db77c3a7beea33efbd91976679c324 |
| parent | 8d2acff197a46a9de33ce78713291428aa45ee7c |
3 files changed, 46 insertions(+), 32 deletions(-)
src/translate_c.zig+19-9| ... | ... | @@ -395,7 +395,15 @@ pub fn translate( |
| 395 | 395 | context.pattern_list.deinit(gpa); |
| 396 | 396 | } |
| 397 | 397 | |
| 398 | try context.global_scope.nodes.append(Tag.usingnamespace_builtins.init()); | |
| 398 | inline for (meta.declarations(std.zig.c_builtins)) |decl| { | |
| 399 | if (decl.is_pub) { | |
| 400 | const builtin = try Tag.pub_var_simple.create(context.arena, .{ | |
| 401 | .name = decl.name, | |
| 402 | .init = try Tag.import_builtin.create(context.arena, decl.name), | |
| 403 | }); | |
| 404 | try context.global_scope.nodes.append(builtin); | |
| 405 | } | |
| 406 | } | |
| 399 | 407 | |
| 400 | 408 | try prepopulateGlobalNameTable(ast_unit, &context); |
| 401 | 409 | |
| ... | ... | @@ -5249,16 +5257,19 @@ const MacroCtx = struct { |
| 5249 | 5257 | return MacroSlicer{ .source = self.source, .tokens = self.list }; |
| 5250 | 5258 | } |
| 5251 | 5259 | |
| 5252 | fn containsUndefinedIdentifier(self: *MacroCtx, scope: *Scope) ?[]const u8 { | |
| 5260 | fn containsUndefinedIdentifier(self: *MacroCtx, scope: *Scope, params: []const ast.Payload.Param) ?[]const u8 { | |
| 5253 | 5261 | const slicer = self.makeSlicer(); |
| 5254 | 5262 | var i: usize = 1; // index 0 is the macro name |
| 5255 | 5263 | while (i < self.list.len) : (i += 1) { |
| 5256 | 5264 | const token = self.list[i]; |
| 5257 | 5265 | switch (token.id) { |
| 5258 | .Period => i += 1, // skip next token since field identifiers can be unknown | |
| 5266 | .Period, .Arrow => i += 1, // skip next token since field identifiers can be unknown | |
| 5259 | 5267 | .Identifier => { |
| 5260 | 5268 | const identifier = slicer.slice(token); |
| 5261 | if (!scope.contains(identifier)) return identifier; | |
| 5269 | const is_param = for (params) |param| { | |
| 5270 | if (param.name != null and mem.eql(u8, identifier, param.name.?)) break true; | |
| 5271 | } else false; | |
| 5272 | if (!scope.contains(identifier) and !isBuiltinDefined(identifier) and !is_param) return identifier; | |
| 5262 | 5273 | }, |
| 5263 | 5274 | else => {}, |
| 5264 | 5275 | } |
| ... | ... | @@ -5361,7 +5372,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void { |
| 5361 | 5372 | fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5362 | 5373 | const scope = &c.global_scope.base; |
| 5363 | 5374 | |
| 5364 | if (m.containsUndefinedIdentifier(scope)) |ident| | |
| 5375 | if (m.containsUndefinedIdentifier(scope, &.{})) |ident| | |
| 5365 | 5376 | return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}); |
| 5366 | 5377 | |
| 5367 | 5378 | const init_node = try parseCExpr(c, m, scope); |
| ... | ... | @@ -5414,6 +5425,9 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 5414 | 5425 | return m.fail(c, "unable to translate C expr: expected ')'", .{}); |
| 5415 | 5426 | } |
| 5416 | 5427 | |
| 5428 | if (m.containsUndefinedIdentifier(scope, fn_params.items)) |ident| | |
| 5429 | return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident}); | |
| 5430 | ||
| 5417 | 5431 | const expr = try parseCExpr(c, m, scope); |
| 5418 | 5432 | const last = m.next().?; |
| 5419 | 5433 | if (last != .Eof and last != .Nl) |
| ... | ... | @@ -5755,10 +5769,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 5755 | 5769 | }, |
| 5756 | 5770 | .Identifier => { |
| 5757 | 5771 | const mangled_name = scope.getAlias(slice); |
| 5758 | if (mem.startsWith(u8, mangled_name, "__builtin_") and !isBuiltinDefined(mangled_name)) { | |
| 5759 | try m.fail(c, "TODO implement function '{s}' in std.zig.c_builtins", .{mangled_name}); | |
| 5760 | return error.ParseError; | |
| 5761 | } | |
| 5762 | 5772 | if (builtin_typedef_map.get(mangled_name)) |ty| return Tag.type.create(c.arena, ty); |
| 5763 | 5773 | const identifier = try Tag.identifier.create(c.arena, mangled_name); |
| 5764 | 5774 | scope.skipVariableDiscard(identifier.castTag(.identifier).?.data); |
src/translate_c/ast.zig+14-21| ... | ... | @@ -31,8 +31,6 @@ pub const Node = extern union { |
| 31 | 31 | @"anytype", |
| 32 | 32 | @"continue", |
| 33 | 33 | @"break", |
| 34 | /// pub usingnamespace @import("std").zig.c_builtins | |
| 35 | usingnamespace_builtins, | |
| 36 | 34 | // After this, the tag requires a payload. |
| 37 | 35 | |
| 38 | 36 | integer_literal, |
| ... | ... | @@ -119,6 +117,8 @@ pub const Node = extern union { |
| 119 | 117 | ellipsis3, |
| 120 | 118 | assign, |
| 121 | 119 | |
| 120 | /// @import("std").zig.c_builtins.<name> | |
| 121 | import_builtin, | |
| 122 | 122 | log2_int_type, |
| 123 | 123 | /// @import("std").math.Log2Int(operand) |
| 124 | 124 | std_math_Log2Int, |
| ... | ... | @@ -224,7 +224,7 @@ pub const Node = extern union { |
| 224 | 224 | /// [1]type{val} ** count |
| 225 | 225 | array_filler, |
| 226 | 226 | |
| 227 | pub const last_no_payload_tag = Tag.usingnamespace_builtins; | |
| 227 | pub const last_no_payload_tag = Tag.@"break"; | |
| 228 | 228 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| 229 | 229 | |
| 230 | 230 | pub fn Type(comptime t: Tag) type { |
| ... | ... | @@ -236,7 +236,6 @@ pub const Node = extern union { |
| 236 | 236 | .true_literal, |
| 237 | 237 | .false_literal, |
| 238 | 238 | .empty_block, |
| 239 | .usingnamespace_builtins, | |
| 240 | 239 | .return_void, |
| 241 | 240 | .zero_literal, |
| 242 | 241 | .one_literal, |
| ... | ... | @@ -344,6 +343,7 @@ pub const Node = extern union { |
| 344 | 343 | .warning, |
| 345 | 344 | .type, |
| 346 | 345 | .helpers_macro, |
| 346 | .import_builtin, | |
| 347 | 347 | => Payload.Value, |
| 348 | 348 | .discard => Payload.Discard, |
| 349 | 349 | .@"if" => Payload.If, |
| ... | ... | @@ -871,22 +871,6 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 871 | 871 | try c.buf.append('\n'); |
| 872 | 872 | return @as(NodeIndex, 0); // error: integer value 0 cannot be coerced to type 'std.mem.Allocator.Error!u32' |
| 873 | 873 | }, |
| 874 | .usingnamespace_builtins => { | |
| 875 | // pub usingnamespace @import("std").c.builtins; | |
| 876 | _ = try c.addToken(.keyword_pub, "pub"); | |
| 877 | const usingnamespace_token = try c.addToken(.keyword_usingnamespace, "usingnamespace"); | |
| 878 | const import_node = try renderStdImport(c, &.{ "zig", "c_builtins" }); | |
| 879 | _ = try c.addToken(.semicolon, ";"); | |
| 880 | ||
| 881 | return c.addNode(.{ | |
| 882 | .tag = .@"usingnamespace", | |
| 883 | .main_token = usingnamespace_token, | |
| 884 | .data = .{ | |
| 885 | .lhs = import_node, | |
| 886 | .rhs = undefined, | |
| 887 | }, | |
| 888 | }); | |
| 889 | }, | |
| 890 | 874 | .std_math_Log2Int => { |
| 891 | 875 | const payload = node.castTag(.std_math_Log2Int).?.data; |
| 892 | 876 | const import_node = try renderStdImport(c, &.{ "math", "Log2Int" }); |
| ... | ... | @@ -1143,6 +1127,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1143 | 1127 | }; |
| 1144 | 1128 | return renderStdImport(c, &chain); |
| 1145 | 1129 | }, |
| 1130 | .import_builtin => { | |
| 1131 | const payload = node.castTag(.import_builtin).?.data; | |
| 1132 | const chain = [_][]const u8{ | |
| 1133 | "zig", | |
| 1134 | "c_builtins", | |
| 1135 | payload, | |
| 1136 | }; | |
| 1137 | return renderStdImport(c, &chain); | |
| 1138 | }, | |
| 1146 | 1139 | .string_slice => { |
| 1147 | 1140 | const payload = node.castTag(.string_slice).?.data; |
| 1148 | 1141 | |
| ... | ... | @@ -2352,7 +2345,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2352 | 2345 | .@"comptime", |
| 2353 | 2346 | .@"defer", |
| 2354 | 2347 | .asm_simple, |
| 2355 | .usingnamespace_builtins, | |
| 2356 | 2348 | .while_true, |
| 2357 | 2349 | .if_not_break, |
| 2358 | 2350 | .switch_else, |
| ... | ... | @@ -2371,6 +2363,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2371 | 2363 | .bit_xor_assign, |
| 2372 | 2364 | .assign, |
| 2373 | 2365 | .helpers_macro, |
| 2366 | .import_builtin, | |
| 2374 | 2367 | => { |
| 2375 | 2368 | // these should never appear in places where grouping might be needed. |
| 2376 | 2369 | unreachable; |
test/translate_c.zig+13-2| ... | ... | @@ -195,6 +195,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 195 | 195 | |
| 196 | 196 | cases.add("use cast param as macro fn return type", |
| 197 | 197 | \\#include <stdint.h> |
| 198 | \\#define SYS_BASE_CACHED 0 | |
| 198 | 199 | \\#define MEM_PHYSICAL_TO_K0(x) (void*)((uint32_t)(x) + SYS_BASE_CACHED) |
| 199 | 200 | , &[_][]const u8{ |
| 200 | 201 | \\pub inline fn MEM_PHYSICAL_TO_K0(x: anytype) ?*c_void { |
| ... | ... | @@ -364,6 +365,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 364 | 365 | }); |
| 365 | 366 | |
| 366 | 367 | cases.add("correct semicolon after infixop", |
| 368 | \\#define _IO_ERR_SEEN 0 | |
| 367 | 369 | \\#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0) |
| 368 | 370 | , &[_][]const u8{ |
| 369 | 371 | \\pub inline fn __ferror_unlocked_body(_fp: anytype) @TypeOf((_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0)) { |
| ... | ... | @@ -430,6 +432,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 430 | 432 | |
| 431 | 433 | cases.add("macro comma operator", |
| 432 | 434 | \\#define foo (foo, bar) |
| 435 | \\int baz(int x, int y) { return 0; } | |
| 433 | 436 | \\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2)) |
| 434 | 437 | , &[_][]const u8{ |
| 435 | 438 | \\pub const foo = blk: { |
| ... | ... | @@ -2573,6 +2576,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2573 | 2576 | |
| 2574 | 2577 | cases.add("macro call", |
| 2575 | 2578 | \\#define CALL(arg) bar(arg) |
| 2579 | \\int bar(int x) { return x; } | |
| 2576 | 2580 | , &[_][]const u8{ |
| 2577 | 2581 | \\pub inline fn CALL(arg: anytype) @TypeOf(bar(arg)) { |
| 2578 | 2582 | \\ return bar(arg); |
| ... | ... | @@ -2581,6 +2585,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2581 | 2585 | |
| 2582 | 2586 | cases.add("macro call with no args", |
| 2583 | 2587 | \\#define CALL(arg) bar() |
| 2588 | \\int bar(void) { return 0; } | |
| 2584 | 2589 | , &[_][]const u8{ |
| 2585 | 2590 | \\pub inline fn CALL(arg: anytype) @TypeOf(bar()) { |
| 2586 | 2591 | \\ _ = arg; |
| ... | ... | @@ -3139,6 +3144,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3139 | 3144 | |
| 3140 | 3145 | cases.add("macro cast", |
| 3141 | 3146 | \\#include <stdint.h> |
| 3147 | \\int baz(void *arg) { return 0; } | |
| 3142 | 3148 | \\#define FOO(bar) baz((void *)(baz)) |
| 3143 | 3149 | \\#define BAR (void*) a |
| 3144 | 3150 | \\#define BAZ (uint32_t)(2) |
| ... | ... | @@ -3475,11 +3481,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3475 | 3481 | \\pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal); |
| 3476 | 3482 | }); |
| 3477 | 3483 | |
| 3478 | // See __builtin_alloca_with_align comment in std.zig.c_builtins | |
| 3479 | 3484 | cases.add("demote un-implemented builtins", |
| 3480 | 3485 | \\#define FOO(X) __builtin_alloca_with_align((X), 8) |
| 3481 | 3486 | , &[_][]const u8{ |
| 3482 | \\pub const FOO = @compileError("TODO implement function '__builtin_alloca_with_align' in std.zig.c_builtins"); | |
| 3487 | \\pub const FOO = @compileError("unable to translate macro: undefined identifier `__builtin_alloca_with_align`"); | |
| 3483 | 3488 | }); |
| 3484 | 3489 | |
| 3485 | 3490 | cases.add("null sentinel arrays when initialized from string literal. Issue #8256", |
| ... | ... | @@ -3661,4 +3666,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3661 | 3666 | , &[_][]const u8{ |
| 3662 | 3667 | \\pub const FOO = @compileError("unable to translate macro: undefined identifier `BAR`"); |
| 3663 | 3668 | }); |
| 3669 | ||
| 3670 | cases.add("Macro redefines builtin", | |
| 3671 | \\#define FOO __builtin_popcount | |
| 3672 | , &[_][]const u8{ | |
| 3673 | \\pub const FOO = __builtin_popcount; | |
| 3674 | }); | |
| 3664 | 3675 | } |