authorgravatar for garrettlennoxbeck@gmail.comGarrett Beck <garrettlennoxbeck@gmail.com> 2023-11-21 07:54:46-06:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-11-21 13:54:46+00:00
log40b8c993f54fce9075044252d2802452dcf1df5e
tree875a8c0f39855233137fdc853d25082ef38fd54c
parent478c89b46f07ee6870ff1492d6a1ebeed350e6eb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

translate-c: skip blank macros when translating defines


5 files changed, 79 insertions(+), 5 deletions(-)

src/aro_translate_c.zig+1-1
...@@ -141,7 +141,7 @@ pub fn translate(...@@ -141,7 +141,7 @@ pub fn translate(
141 defer mapper.deinit(tree.comp.gpa);141 defer mapper.deinit(tree.comp.gpa);
142142
143 var arena_allocator = std.heap.ArenaAllocator.init(gpa);143 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
144 errdefer arena_allocator.deinit();144 defer arena_allocator.deinit();
145 const arena = arena_allocator.allocator();145 const arena = arena_allocator.allocator();
146146
147 var context = Context{147 var context = Context{
src/translate_c.zig+60-4
...@@ -139,7 +139,7 @@ pub fn translate(...@@ -139,7 +139,7 @@ pub fn translate(
139 // For memory that has the same lifetime as the Ast that we return139 // For memory that has the same lifetime as the Ast that we return
140 // from this function.140 // from this function.
141 var arena_allocator = std.heap.ArenaAllocator.init(gpa);141 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
142 errdefer arena_allocator.deinit();142 defer arena_allocator.deinit();
143 const arena = arena_allocator.allocator();143 const arena = arena_allocator.allocator();
144144
145 var context = Context{145 var context = Context{
...@@ -5497,6 +5497,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {...@@ -5497,6 +5497,7 @@ fn transPreprocessorEntities(c: *Context, unit: *clang.ASTUnit) Error!void {
5497 const str_node = try Tag.string_literal.create(c.arena, "\"\"");5497 const str_node = try Tag.string_literal.create(c.arena, "\"\"");
5498 const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = name, .init = str_node });5498 const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = name, .init = str_node });
5499 try c.global_scope.macro_table.put(name, var_decl);5499 try c.global_scope.macro_table.put(name, var_decl);
5500 try c.global_scope.blank_macros.put(name, {});
5500 continue;5501 continue;
5501 },5502 },
5502 .LParen => {5503 .LParen => {
...@@ -5527,6 +5528,29 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -5527,6 +5528,29 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
5527 .invalid_arg_usage => unreachable, // no args5528 .invalid_arg_usage => unreachable, // no args
5528 };5529 };
55295530
5531 // Check if the macro only uses other blank macros.
5532 while (true) {
5533 switch (m.peek().?) {
5534 .Identifier => {
5535 const tok = m.list[m.i + 1];
5536 const slice = m.source[tok.start..tok.end];
5537 if (c.global_scope.blank_macros.contains(slice)) {
5538 m.i += 1;
5539 continue;
5540 }
5541 },
5542 .Eof, .Nl => {
5543 try c.global_scope.blank_macros.put(m.name, {});
5544 const init_node = try Tag.string_literal.create(c.arena, "\"\"");
5545 const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
5546 try c.global_scope.macro_table.put(m.name, var_decl);
5547 return;
5548 },
5549 else => {},
5550 }
5551 break;
5552 }
5553
5530 const init_node = try parseCExpr(c, m, scope);5554 const init_node = try parseCExpr(c, m, scope);
5531 const last = m.next().?;5555 const last = m.next().?;
5532 if (last != .Eof and last != .Nl)5556 if (last != .Eof and last != .Nl)
...@@ -5960,6 +5984,9 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N...@@ -5960,6 +5984,9 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
5960 return parseCNumLit(c, m);5984 return parseCNumLit(c, m);
5961 },5985 },
5962 .Identifier => {5986 .Identifier => {
5987 if (c.global_scope.blank_macros.contains(slice)) {
5988 return parseCPrimaryExprInner(c, m, scope);
5989 }
5963 const mangled_name = scope.getAlias(slice);5990 const mangled_name = scope.getAlias(slice);
5964 if (builtin_typedef_map.get(mangled_name)) |ty| return Tag.type.create(c.arena, ty);5991 if (builtin_typedef_map.get(mangled_name)) |ty| return Tag.type.create(c.arena, ty);
5965 const identifier = try Tag.identifier.create(c.arena, mangled_name);5992 const identifier = try Tag.identifier.create(c.arena, mangled_name);
...@@ -5992,10 +6019,19 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -5992,10 +6019,19 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
5992 // after a primary expression.6019 // after a primary expression.
5993 while (true) {6020 while (true) {
5994 switch (m.peek().?) {6021 switch (m.peek().?) {
5995 .StringLiteral, .Identifier => {},6022 .StringLiteral => {},
6023 .Identifier => {
6024 const tok = m.list[m.i + 1];
6025 const slice = m.source[tok.start..tok.end];
6026 if (c.global_scope.blank_macros.contains(slice)) {
6027 m.i += 1;
6028 continue;
6029 }
6030 },
5996 else => break,6031 else => break,
5997 }6032 }
5998 node = try Tag.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });6033 const rhs = try parseCPrimaryExprInner(c, m, scope);
6034 node = try Tag.array_cat.create(c.arena, .{ .lhs = node, .rhs = rhs });
5999 }6035 }
6000 return node;6036 return node;
6001}6037}
...@@ -6211,7 +6247,24 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -6211,7 +6247,24 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
6211 switch (m.next().?) {6247 switch (m.next().?) {
6212 .LParen => {6248 .LParen => {
6213 if (try parseCTypeName(c, m, scope, true)) |type_name| {6249 if (try parseCTypeName(c, m, scope, true)) |type_name| {
6214 try m.skip(c, .RParen);6250 while (true) {
6251 const next_token = m.next().?;
6252 switch (next_token) {
6253 .RParen => break,
6254 else => |next_tag| {
6255 // Skip trailing blank defined before the RParen.
6256 if (next_tag == .Identifier and c.global_scope.blank_macros.contains(m.slice())) {
6257 continue;
6258 }
6259 try m.fail(
6260 c,
6261 "unable to translate C expr: expected ')' instead got '{s}'",
6262 .{next_token.symbol()},
6263 );
6264 return error.ParseError;
6265 },
6266 }
6267 }
6215 if (m.peek().? == .LBrace) {6268 if (m.peek().? == .LBrace) {
6216 // initializer list6269 // initializer list
6217 return parseCPostfixExpr(c, m, scope, type_name);6270 return parseCPostfixExpr(c, m, scope, type_name);
...@@ -6239,6 +6292,9 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_...@@ -6239,6 +6292,9 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_
6239 const tok = m.next().?;6292 const tok = m.next().?;
6240 switch (tok) {6293 switch (tok) {
6241 .Identifier => {6294 .Identifier => {
6295 if (c.global_scope.blank_macros.contains(m.slice())) {
6296 return try parseCSpecifierQualifierList(c, m, scope, allow_fail);
6297 }
6242 const mangled_name = scope.getAlias(m.slice());6298 const mangled_name = scope.getAlias(m.slice());
6243 if (!allow_fail or c.typedefs.contains(mangled_name)) {6299 if (!allow_fail or c.typedefs.contains(mangled_name)) {
6244 if (builtin_typedef_map.get(mangled_name)) |ty| return try Tag.type.create(c.arena, ty);6300 if (builtin_typedef_map.get(mangled_name)) |ty| return try Tag.type.create(c.arena, ty);
src/translate_c/common.zig+3
...@@ -184,6 +184,7 @@ pub fn ScopeExtra(comptime Context: type, comptime Type: type) type {...@@ -184,6 +184,7 @@ pub fn ScopeExtra(comptime Context: type, comptime Type: type) type {
184 base: Scope,184 base: Scope,
185 sym_table: SymbolTable,185 sym_table: SymbolTable,
186 macro_table: SymbolTable,186 macro_table: SymbolTable,
187 blank_macros: std.StringArrayHashMap(void),
187 context: *Context,188 context: *Context,
188 nodes: std.ArrayList(Node),189 nodes: std.ArrayList(Node),
189190
...@@ -195,6 +196,7 @@ pub fn ScopeExtra(comptime Context: type, comptime Type: type) type {...@@ -195,6 +196,7 @@ pub fn ScopeExtra(comptime Context: type, comptime Type: type) type {
195 },196 },
196 .sym_table = SymbolTable.init(c.gpa),197 .sym_table = SymbolTable.init(c.gpa),
197 .macro_table = SymbolTable.init(c.gpa),198 .macro_table = SymbolTable.init(c.gpa),
199 .blank_macros = std.StringArrayHashMap(void).init(c.gpa),
198 .context = c,200 .context = c,
199 .nodes = std.ArrayList(Node).init(c.gpa),201 .nodes = std.ArrayList(Node).init(c.gpa),
200 };202 };
...@@ -203,6 +205,7 @@ pub fn ScopeExtra(comptime Context: type, comptime Type: type) type {...@@ -203,6 +205,7 @@ pub fn ScopeExtra(comptime Context: type, comptime Type: type) type {
203 pub fn deinit(scope: *Root) void {205 pub fn deinit(scope: *Root) void {
204 scope.sym_table.deinit();206 scope.sym_table.deinit();
205 scope.macro_table.deinit();207 scope.macro_table.deinit();
208 scope.blank_macros.deinit();
206 scope.nodes.deinit();209 scope.nodes.deinit();
207 }210 }
208211
test/behavior/translate_c_macros.h+6
...@@ -62,3 +62,9 @@ typedef _Bool uintptr_t;...@@ -62,3 +62,9 @@ typedef _Bool uintptr_t;
6262
63#define LONG(x) x##L63#define LONG(x) x##L
64#define X LONG(10)64#define X LONG(10)
65
66#define BLANK_MACRO
67#define BLANK_CHILD_MACRO BLANK_MACRO BLANK_MACRO BLANK_MACRO
68#define MACRO_VALUE 0
69typedef long def_type;
70#define BLANK_MACRO_CAST (BLANK_CHILD_MACRO def_type BLANK_CHILD_MACRO)MACRO_VALUE
test/behavior/translate_c_macros.zig+9
...@@ -231,3 +231,12 @@ test "Macro that uses Long type concatenation casting" {...@@ -231,3 +231,12 @@ test "Macro that uses Long type concatenation casting" {
231 try expect((@TypeOf(h.X)) == c_long);231 try expect((@TypeOf(h.X)) == c_long);
232 try expectEqual(h.X, @as(c_long, 10));232 try expectEqual(h.X, @as(c_long, 10));
233}233}
234
235test "Blank macros" {
236 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
237
238 try expectEqual(h.BLANK_MACRO, "");
239 try expectEqual(h.BLANK_CHILD_MACRO, "");
240 try expect(@TypeOf(h.BLANK_MACRO_CAST) == h.def_type);
241 try expectEqual(h.BLANK_MACRO_CAST, @as(c_long, 0));
242}