From b74cee93961431be5508e215d5a9b6c071541d86 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 1 Jan 2025 20:55:33 +0200 Subject: [PATCH 1/5] store `register` storage class in AST --- src/aro/Builtins.zig | 2 +- src/aro/CodeGen.zig | 4 +- src/aro/Parser.zig | 171 ++++++++++++++++++++++---------- src/aro/SymbolStack.zig | 10 +- src/aro/Tree.zig | 151 ++++++++++++++++++++++++---- src/aro/Type.zig | 14 +-- src/assembly_backend/x86_64.zig | 2 +- test/cases/typeof quals.c | 3 +- 8 files changed, 263 insertions(+), 94 deletions(-) diff --git a/src/aro/Builtins.zig b/src/aro/Builtins.zig index a792a5a9..2f638ff5 100644 --- a/src/aro/Builtins.zig +++ b/src/aro/Builtins.zig @@ -254,7 +254,7 @@ fn createBuiltin(comp: *const Compilation, builtin: Builtin, type_arena: std.mem var param_count: usize = 0; var params: [Builtin.max_param_count]Type.Func.Param = undefined; while (it.next()) |desc| : (param_count += 1) { - params[param_count] = .{ .name_tok = 0, .ty = try createType(desc, &it, comp, type_arena), .name = .empty }; + params[param_count] = .{ .name_tok = 0, .ty = try createType(desc, &it, comp, type_arena), .name = .empty, .node = .null }; } const duped_params = try type_arena.dupe(Type.Func.Param, params[0..param_count]); diff --git a/src/aro/CodeGen.zig b/src/aro/CodeGen.zig index 932bbc0f..28f6cfdd 100644 --- a/src/aro/CodeGen.zig +++ b/src/aro/CodeGen.zig @@ -260,7 +260,7 @@ fn genExpr(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref { .null_stmt, => {}, .variable => |variable| { - if (variable.@"extern" or variable.static) { + if (variable.storage_class == .@"extern" or variable.storage_class == .static) { try c.genVar(variable); return .none; } @@ -878,7 +878,7 @@ fn genLval(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref { }, .deref_expr => |un| return c.genExpr(un.operand), .compound_literal_expr => |literal| { - if (literal.static or literal.thread_local) { + if (literal.storage_class == .static or literal.thread_local) { return c.fail("TODO CodeGen.compound_literal_expr static or thread_local\n", .{}); } const size: u32 = @intCast(literal.type.sizeof(c.comp).?); // TODO add error in parser diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 27a2b65d..41fcc855 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -956,7 +956,12 @@ fn decl(p: *Parser) Error!bool { const attr = Attribute{ .tag = .noreturn, .args = .{ .noreturn = .{} }, .syntax = .keyword }; try p.attr_buf.append(p.gpa, .{ .attr = attr, .tok = tok }); } - var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse { + + var decl_node = try p.tree.addNode(.{ .null_stmt = .{ + .semicolon_or_r_brace_tok = first_tok, + .type = Type.invalid, + } }); + var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top, decl_node)) orelse { _ = try p.expectToken(.semicolon); if (decl_spec.ty.is(.@"enum") or (decl_spec.ty.isRecord() and !decl_spec.ty.isAnonymousRecord(p.comp) and @@ -978,6 +983,10 @@ fn decl(p: *Parser) Error!bool { return true; } + if (p.tree.nodes.len == @intFromEnum(decl_node)) { + p.tree.nodes.len -= 1; + } + try p.errTok(.missing_declaration, first_tok); return true; }; @@ -999,11 +1008,8 @@ fn decl(p: *Parser) Error!bool { } if (p.func.ty != null) try p.err(.func_not_in_root); - const reserved_index = try p.tree.nodes.addOne(p.gpa); // reserve space - const node: Node.Index = @enumFromInt(reserved_index); - const interned_declarator_name = try StrInt.intern(p.comp, p.tokSlice(init_d.d.name)); - try p.syms.defineSymbol(p, interned_declarator_name, init_d.d.ty, init_d.d.name, node, .{}, false); + try p.syms.defineSymbol(p, interned_declarator_name, init_d.d.ty, init_d.d.name, decl_node, .{}, false); const func = p.func; p.func = .{ @@ -1074,6 +1080,18 @@ fn decl(p: *Parser) Error!bool { } d.ty = try Attribute.applyParameterAttributes(p, d.ty, attr_buf_top_declarator, .alignas_on_param); + try param_decl_spec.validateParam(p, &d.ty); + const param_node = try p.addNode(.{ + .param = .{ + .name_tok = d.name, + .type = d.ty, + .storage_class = switch (param_decl_spec.storage_class) { + .none => .auto, + .register => .register, + else => .auto, // Error reported in `validateParam` + }, + }, + }); // bypass redefinition check to avoid duplicate errors try p.syms.define(p.gpa, .{ .kind = .def, @@ -1081,6 +1099,7 @@ fn decl(p: *Parser) Error!bool { .tok = d.name, .ty = d.ty, .val = .{}, + .node = .pack(param_node), }); if (p.eatToken(.comma) == null) break; } @@ -1105,6 +1124,7 @@ fn decl(p: *Parser) Error!bool { .tok = param.name_tok, .ty = param.ty, .val = .{}, + .node = param.node, }); } } @@ -1116,15 +1136,15 @@ fn decl(p: *Parser) Error!bool { }; try decl_spec.validateFnDef(p); - try p.tree.addNodeExtra(.{ .fn_def = .{ + try p.tree.setNode(.{ .fn_def = .{ .name_tok = init_d.d.name, .@"inline" = decl_spec.@"inline" != null, .static = decl_spec.storage_class == .static, .type = init_d.d.ty, .body = body, - } }, reserved_index); + } }, @intFromEnum(decl_node)); - try p.decl_buf.append(node); + try p.decl_buf.append(decl_node); // check gotos if (func.ty == null) { @@ -1149,7 +1169,7 @@ fn decl(p: *Parser) Error!bool { if (init_d.d.old_style_func) |tok_i| try p.errTok(.invalid_old_style_params, tok_i); try decl_spec.validate(p, &init_d.d.ty); - const node = if (init_d.d.ty.isFunc()) try p.addNode(.{ + try p.tree.setNode(if (init_d.d.ty.isFunc()) .{ .fn_proto = .{ .name_tok = init_d.d.name, .type = init_d.d.ty, @@ -1157,22 +1177,27 @@ fn decl(p: *Parser) Error!bool { .@"inline" = decl_spec.@"inline" != null, .definition = null, }, - }) else try p.addNode(.{ + } else .{ .variable = .{ .name_tok = init_d.d.name, .type = init_d.d.ty, - .@"extern" = decl_spec.storage_class == .@"extern" and init_d.initializer == null, - .static = decl_spec.storage_class == .static, .thread_local = decl_spec.thread_local != null, .implicit = false, + .storage_class = switch (decl_spec.storage_class) { + .auto => .auto, + .register => .register, + .static => .static, + .@"extern" => if (init_d.initializer == null) .@"extern" else .auto, + else => .auto, // Error reported in `validate` + }, .initializer = if (init_d.initializer) |some| some.node else null, }, - }); - try p.decl_buf.append(node); + }, @intFromEnum(decl_node)); + try p.decl_buf.append(decl_node); const interned_name = try StrInt.intern(p.comp, p.tokSlice(init_d.d.name)); if (decl_spec.storage_class == .typedef) { - try p.syms.defineTypedef(p, interned_name, init_d.d.ty, init_d.d.name, node); + try p.syms.defineTypedef(p, interned_name, init_d.d.ty, init_d.d.name, decl_node); p.typedefDefined(interned_name, init_d.d.ty); } else if (init_d.initializer) |init| { // TODO validate global variable/constexpr initializer comptime known @@ -1181,14 +1206,14 @@ fn decl(p: *Parser) Error!bool { interned_name, init_d.d.ty, init_d.d.name, - node, + decl_node, if (init_d.d.ty.isConst() or decl_spec.constexpr != null) init.val else .{}, decl_spec.constexpr != null, ); } else if (p.func.ty != null and decl_spec.storage_class != .@"extern") { - try p.syms.defineSymbol(p, interned_name, init_d.d.ty, init_d.d.name, node, .{}, false); + try p.syms.defineSymbol(p, interned_name, init_d.d.ty, init_d.d.name, decl_node, .{}, false); } else { - try p.syms.declareSymbol(p, interned_name, init_d.d.ty, init_d.d.name, node); + try p.syms.declareSymbol(p, interned_name, init_d.d.ty, init_d.d.name, decl_node); } if (p.eatToken(.comma) == null) break; @@ -1204,7 +1229,11 @@ fn decl(p: *Parser) Error!bool { } } - init_d = (try p.initDeclarator(&decl_spec, attr_buf_top)) orelse { + decl_node = try p.tree.addNode(.{ .null_stmt = .{ + .semicolon_or_r_brace_tok = first_tok, + .type = Type.invalid, + } }); + init_d = (try p.initDeclarator(&decl_spec, attr_buf_top, decl_node)) orelse { try p.err(.expected_ident_or_l_paren); continue; }; @@ -1326,8 +1355,7 @@ pub const DeclSpec = struct { fn validateParam(d: DeclSpec, p: *Parser, ty: *Type) Error!void { switch (d.storage_class) { - .none => {}, - .register => ty.qual.register = true, + .none, .register => {}, .auto, .@"extern", .static, .typedef => |tok_i| try p.errTok(.invalid_storage_on_param, tok_i), } if (d.thread_local) |tok_i| try p.errTok(.threadlocal_non_var, tok_i); @@ -1370,7 +1398,6 @@ pub const DeclSpec = struct { .register => if (p.func.ty == null) try p.err(.illegal_storage_on_global), else => {}, } - ty.qual.register = d.storage_class == .register; } } @@ -1402,7 +1429,7 @@ fn typeof(p: *Parser) Error!?Type { const typeof_ty = try p.arena.create(Type); typeof_ty.* = .{ .data = ty.data, - .qual = if (unqual) .{} else ty.qual.inheritFromTypeof(), + .qual = if (unqual) .{} else ty.qual, .specifier = ty.specifier, }; @@ -1417,7 +1444,7 @@ fn typeof(p: *Parser) Error!?Type { if (typeof_expr.ty.is(.nullptr_t)) { return Type{ .specifier = .nullptr_t, - .qual = if (unqual) .{} else typeof_expr.ty.qual.inheritFromTypeof(), + .qual = if (unqual) .{} else typeof_expr.ty.qual, }; } else if (typeof_expr.ty.is(.invalid)) { return null; @@ -1428,7 +1455,7 @@ fn typeof(p: *Parser) Error!?Type { .node = typeof_expr.node, .ty = .{ .data = typeof_expr.ty.data, - .qual = if (unqual) .{} else typeof_expr.ty.qual.inheritFromTypeof(), + .qual = if (unqual) .{} else typeof_expr.ty.qual, .specifier = typeof_expr.ty.specifier, .decayed = typeof_expr.ty.decayed, }, @@ -1735,7 +1762,7 @@ fn attributeSpecifierExtra(p: *Parser, declarator_name: ?TokenIndex) Error!void } /// initDeclarator : declarator assembly? attributeSpecifier? ('=' initializer)? -fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize) Error!?InitDeclarator { +fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize, decl_node: Node.Index) Error!?InitDeclarator { const this_attr_buf_top = p.attr_buf.len; defer p.attr_buf.len = this_attr_buf_top; @@ -1792,7 +1819,7 @@ fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize) Error!? defer p.syms.popScope(); const interned_name = try StrInt.intern(p.comp, p.tokSlice(init_d.d.name)); - try p.syms.declareSymbol(p, interned_name, init_d.d.ty, init_d.d.name, null); + try p.syms.declareSymbol(p, interned_name, init_d.d.ty, init_d.d.name, decl_node); if (c23_auto or auto_type) { p.auto_type_decl_name = interned_name; } @@ -2613,7 +2640,7 @@ fn enumSpec(p: *Parser) Error!Type { new_field_node.enum_field.init = res.node; } - try p.tree.addNodeExtra(new_field_node, @intFromEnum(field_node)); + try p.tree.setNode(new_field_node, @intFromEnum(field_node)); } } @@ -3108,11 +3135,12 @@ fn directDeclarator(p: *Parser, base_type: Type, d: *Declarator, kind: Declarato while (true) { const name_tok = try p.expectIdentifier(); const interned_name = try StrInt.intern(p.comp, p.tokSlice(name_tok)); - try p.syms.defineParam(p, interned_name, undefined, name_tok); + try p.syms.defineParam(p, interned_name, undefined, name_tok, null); try p.param_buf.append(.{ .name = interned_name, .name_tok = name_tok, .ty = .{ .specifier = .int }, + .node = .null, }); if (p.eatToken(.comma) == null) break; } @@ -3178,6 +3206,7 @@ fn paramDecls(p: *Parser, d: *Declarator) Error!?[]Type.Func.Param { .name = try StrInt.intern(p.comp, p.tokSlice(identifier)), .name_tok = identifier, .ty = .{ .specifier = .int }, + .node = .null, }); if (p.eatToken(.comma) == null) break; @@ -3191,6 +3220,7 @@ fn paramDecls(p: *Parser, d: *Declarator) Error!?[]Type.Func.Param { }; var name_tok: TokenIndex = 0; + var param_node: Node.OptIndex = .null; const first_tok = p.tok_i; var param_ty = param_decl_spec.ty; if (try p.declarator(param_decl_spec.ty, .param)) |some| { @@ -3198,13 +3228,26 @@ fn paramDecls(p: *Parser, d: *Declarator) Error!?[]Type.Func.Param { try p.attributeSpecifier(); name_tok = some.name; - param_ty = some.ty; + param_ty = try Attribute.applyParameterAttributes(p, some.ty, attr_buf_top, .alignas_on_param); if (some.name != 0) { + const node = try p.addNode(.{ + .param = .{ + .name_tok = name_tok, + .type = param_ty, + .storage_class = switch (param_decl_spec.storage_class) { + .none => .auto, + .register => .register, + else => .auto, // Error reported in `validateParam` + }, + }, + }); + param_node = .pack(node); const interned_name = try StrInt.intern(p.comp, p.tokSlice(name_tok)); - try p.syms.defineParam(p, interned_name, param_ty, name_tok); + try p.syms.defineParam(p, interned_name, param_ty, name_tok, node); } + } else { + param_ty = try Attribute.applyParameterAttributes(p, param_ty, attr_buf_top, .alignas_on_param); } - param_ty = try Attribute.applyParameterAttributes(p, param_ty, attr_buf_top, .alignas_on_param); if (param_ty.isFunc()) { // params declared as functions are converted to function pointers @@ -3236,6 +3279,7 @@ fn paramDecls(p: *Parser, d: *Declarator) Error!?[]Type.Func.Param { .name = if (name_tok == 0) .empty else try StrInt.intern(p.comp, p.tokSlice(name_tok)), .name_tok = if (name_tok == 0) first_tok else name_tok, .ty = param_ty, + .node = param_node, }); if (p.eatToken(.comma) == null) break; @@ -4862,12 +4906,10 @@ const CallExpr = union(enum) { }, fn init(p: *Parser, call_node: Node.Index, func_node: Node.Index) CallExpr { - if (p.getNode(call_node, .decl_ref_expr)) |decl_ref| { - const name = p.tokSlice(decl_ref.name_tok); - // If this is a builtin then primaryExpr() already created it. - if (p.comp.builtins.getOrCreate(p.comp, name, p.arena) catch unreachable) |expanded| { - return .{ .builtin = .{ .builtin_tok = decl_ref.name_tok, .tag = expanded.builtin.tag } }; - } + if (p.getNode(call_node, .builtin_ref)) |builtin_ref| { + const name = p.tokSlice(builtin_ref.name_tok); + const expanded = p.comp.builtins.lookup(name); + return .{ .builtin = .{ .builtin_tok = builtin_ref.name_tok, .tag = expanded.builtin.tag } }; } return .{ .standard = func_node }; } @@ -7111,7 +7153,19 @@ fn unExpr(p: *Parser) Error!?Result { } else if (operand_ty_valid) { addr_val = try p.computeOffset(operand); } - if (operand.ty.qual.register) try p.errTok(.addr_of_register, tok); + if (p.getNode(operand.node, .decl_ref_expr)) |decl_ref| { + switch (decl_ref.decl.get(&p.tree)) { + .variable => |variable| { + if (variable.storage_class == .register) try p.errTok(.addr_of_register, tok); + }, + else => {}, + } + } else if (p.getNode(operand.node, .compound_literal_expr)) |literal| { + switch (literal.storage_class) { + .register => try p.errTok(.addr_of_register, tok), + else => {}, + } + } if (operand_ty_valid) { const elem_ty = try p.arena.create(Type); @@ -7465,6 +7519,7 @@ fn compoundLiteral(p: *Parser) Error!?Result { try p.errStr(.invalid_compound_literal_storage_class, tok, @tagName(d.storage_class)); d.storage_class = .none; }, + .register => if (p.func.ty == null) try p.err(.illegal_storage_on_global), else => {}, } @@ -7476,7 +7531,6 @@ fn compoundLiteral(p: *Parser) Error!?Result { } return null; }; - if (d.storage_class == .register) ty.qual.register = true; try p.expectClosing(l_paren, .r_paren); if (ty.isFunc()) { @@ -7498,7 +7552,11 @@ fn compoundLiteral(p: *Parser) Error!?Result { init_list_expr.node = try p.addNode(.{ .compound_literal_expr = .{ .l_paren_tok = l_paren, - .static = d.storage_class == .static, + .storage_class = switch (d.storage_class) { + .register => .register, + .static => .static, + else => .auto, + }, .thread_local = d.thread_local != null, .initializer = init_list_expr.node, .type = init_list_expr.ty, @@ -7934,6 +7992,7 @@ fn primaryExpr(p: *Parser) Error!?Result { .decl_ref_expr = .{ .name_tok = name_tok, .type = sym.ty, + .decl = sym.node.unpack().?, }, }), }; @@ -7946,17 +8005,21 @@ fn primaryExpr(p: *Parser) Error!?Result { } } - const dr: Node.DeclRef = .{ - .name_tok = name_tok, - .type = sym.ty, - }; + const node = try p.addNode(if (sym.kind == .enumeration) + .{ .enumeration_ref = .{ + .name_tok = name_tok, + .type = sym.ty, + } } + else + .{ .decl_ref_expr = .{ + .name_tok = name_tok, + .type = sym.ty, + .decl = sym.node.unpack().?, + } }); return .{ .val = if (p.const_decl_folding == .no_const_decl_folding and sym.kind != .enumeration) Value{} else sym.val, .ty = sym.ty, - .node = try p.addNode(if (sym.kind == .enumeration) - .{ .enumeration_ref = dr } - else - .{ .decl_ref_expr = dr }), + .node = node, }; } @@ -7981,7 +8044,7 @@ fn primaryExpr(p: *Parser) Error!?Result { return .{ .ty = some.ty, .node = try p.addNode(.{ - .decl_ref_expr = .{ + .builtin_ref = .{ .name_tok = name_tok, .type = some.ty, }, @@ -8019,6 +8082,7 @@ fn primaryExpr(p: *Parser) Error!?Result { .decl_ref_expr = .{ .name_tok = name_tok, .type = ty, + .decl = node, }, }), }; @@ -8093,6 +8157,7 @@ fn primaryExpr(p: *Parser) Error!?Result { .decl_ref_expr = .{ .name_tok = tok, .type = ty, + .decl = p.func.ident.?.node, }, }), }; @@ -8129,6 +8194,7 @@ fn primaryExpr(p: *Parser) Error!?Result { .decl_ref_expr = .{ .name_tok = p.tok_i, .type = ty, + .decl = undefined, // TODO }, }), }; @@ -8213,8 +8279,7 @@ fn makePredefinedIdentifier(p: *Parser, strings_top: usize) !Result { .variable = .{ .name_tok = p.tok_i, .type = ty, - .@"extern" = false, - .static = true, + .storage_class = .static, .thread_local = false, .implicit = true, .initializer = str_lit, @@ -8881,7 +8946,7 @@ fn genericSelection(p: *Parser) Error!?Result { }, }); try p.list_buf.append(res.node); - try p.param_buf.append(.{ .name = undefined, .ty = ty, .name_tok = start }); + try p.param_buf.append(.{ .name = undefined, .ty = ty, .name_tok = start, .node = undefined }); if (ty.eql(controlling_ty, p.comp, false)) { if (chosen_tok == null) { diff --git a/src/aro/SymbolStack.zig b/src/aro/SymbolStack.zig index c8d5a1ed..308fdbdd 100644 --- a/src/aro/SymbolStack.zig +++ b/src/aro/SymbolStack.zig @@ -306,7 +306,14 @@ pub fn declareSymbol( }); } -pub fn defineParam(s: *SymbolStack, p: *Parser, name: StringId, ty: Type, tok: TokenIndex) !void { +pub fn defineParam( + s: *SymbolStack, + p: *Parser, + name: StringId, + ty: Type, + tok: TokenIndex, + node: ?Node.Index, +) !void { if (s.get(name, .vars)) |prev| { switch (prev.kind) { .enumeration, .decl, .def, .constexpr => { @@ -328,6 +335,7 @@ pub fn defineParam(s: *SymbolStack, p: *Parser, name: StringId, ty: Type, tok: T .name = name, .tok = tok, .ty = ty, + .node = .packOpt(node), .val = .{}, }); } diff --git a/src/aro/Tree.zig b/src/aro/Tree.zig index 0b04dee4..c2fa6205 100644 --- a/src/aro/Tree.zig +++ b/src/aro/Tree.zig @@ -112,7 +112,7 @@ pub const TypeHashContext = struct { var hasher = std.hash.Wyhash.init(0); std.hash.autoHash(&hasher, ty.specifier); - std.hash.autoHash(&hasher, @as(u5, @bitCast(ty.qual))); + std.hash.autoHash(&hasher, @as(u4, @bitCast(ty.qual))); std.hash.autoHash(&hasher, ty.decayed); std.hash.autoHash(&hasher, ty.name); @@ -238,6 +238,7 @@ pub const Node = union(enum) { definition: ?Node.Index, }, fn_def: FnDef, + param: Param, variable: Variable, typedef: struct { name_tok: TokenIndex, @@ -413,7 +414,8 @@ pub const Node = union(enum) { member_access_expr: MemberAccess, member_access_ptr_expr: MemberAccess, decl_ref_expr: DeclRef, - enumeration_ref: DeclRef, + enumeration_ref: NoDeclRef, + builtin_ref: NoDeclRef, /// C23 bool literal `true` / `false` bool_literal: Literal, @@ -484,8 +486,12 @@ pub const Node = union(enum) { compound_literal_expr: struct { l_paren_tok: TokenIndex, type: Type, - static: bool, thread_local: bool, + storage_class: enum { + auto, + static, + register, + }, initializer: Node.Index, }, @@ -497,11 +503,24 @@ pub const Node = union(enum) { body: Node.Index, }; + pub const Param = struct { + name_tok: TokenIndex, + type: Type, + storage_class: enum { + auto, + register, + }, + }; + pub const Variable = struct { name_tok: TokenIndex, type: Type, - @"extern": bool, - static: bool, + storage_class: enum { + auto, + static, + @"extern", + register, + }, thread_local: bool, /// From predefined macro __func__, __FUNCTION__ or __PRETTY_FUNCTION__. /// Implies `static == true`. @@ -634,6 +653,12 @@ pub const Node = union(enum) { pub const DeclRef = struct { name_tok: TokenIndex, type: Type, + decl: Node.Index, + }; + + pub const NoDeclRef = struct { + name_tok: TokenIndex, + type: Type, }; pub const Conditional = struct { @@ -700,14 +725,33 @@ pub const Node = union(enum) { }, }; }, + .param => { + const attr: Node.Repr.DeclAttr = @bitCast(node_data[1]); + return .{ + .param = .{ + .name_tok = node_tok, + .type = tree.type_map.keys()[node_data[0]], + .storage_class = if (attr.register) + .register + else + .auto, + }, + }; + }, .variable => { const attr: Node.Repr.DeclAttr = @bitCast(node_data[1]); return .{ .variable = .{ .name_tok = node_tok, .type = tree.type_map.keys()[node_data[0]], - .@"extern" = attr.@"extern", - .static = attr.static, + .storage_class = if (attr.static) + .static + else if (attr.@"extern") + .@"extern" + else if (attr.register) + .register + else + .auto, .thread_local = attr.thread_local, .implicit = attr.implicit, .initializer = unpackOptIndex(node_data[2]), @@ -1355,6 +1399,7 @@ pub const Node = union(enum) { .decl_ref_expr = .{ .name_tok = node_tok, .type = tree.type_map.keys()[node_data[0]], + .decl = @enumFromInt(node_data[1]), }, }, .enumeration_ref => .{ @@ -1363,6 +1408,12 @@ pub const Node = union(enum) { .type = tree.type_map.keys()[node_data[0]], }, }, + .builtin_ref => .{ + .builtin_ref = .{ + .name_tok = node_tok, + .type = tree.type_map.keys()[node_data[0]], + }, + }, .bool_literal => .{ .bool_literal = .{ .literal_tok = node_tok, @@ -1541,7 +1592,12 @@ pub const Node = union(enum) { .compound_literal_expr = .{ .l_paren_tok = node_tok, .type = tree.type_map.keys()[node_data[0]], - .static = attr.static, + .storage_class = if (attr.static) + .static + else if (attr.register) + .register + else + .auto, .thread_local = attr.thread_local, .initializer = @enumFromInt(node_data[2]), }, @@ -1598,13 +1654,15 @@ pub const Node = union(enum) { @"inline": bool = false, thread_local: bool = false, implicit: bool = false, - _: u27 = 0, + register: bool = false, + _: u26 = 0, }; pub const Tag = enum(u8) { static_assert, fn_proto, fn_def, + param, variable, typedef, global_asm, @@ -1694,6 +1752,7 @@ pub const Node = union(enum) { member_access_ptr_expr, decl_ref_expr, enumeration_ref, + builtin_ref, bool_literal, nullptr_literal, int_literal, @@ -1765,11 +1824,11 @@ pub const Node = union(enum) { pub fn addNode(tree: *Tree, node: Node) !Node.Index { const index = try tree.nodes.addOne(tree.comp.gpa); - try tree.addNodeExtra(node, index); + try tree.setNode(node, index); return @enumFromInt(index); } -pub fn addNodeExtra(tree: *Tree, node: Node, index: usize) !void { +pub fn setNode(tree: *Tree, node: Node, index: usize) !void { var repr: Node.Repr = undefined; switch (node) { .static_assert => |assert| { @@ -1799,14 +1858,23 @@ pub fn addNodeExtra(tree: *Tree, node: Node, index: usize) !void { repr.data[2] = @intFromEnum(def.body); repr.tok = def.name_tok; }, + .param => |param| { + repr.tag = .param; + repr.data[0] = try tree.addType(param.type); + repr.data[1] = @bitCast(Node.Repr.DeclAttr{ + .register = param.storage_class == .register, + }); + repr.tok = param.name_tok; + }, .variable => |variable| { repr.tag = .variable; repr.data[0] = try tree.addType(variable.type); repr.data[1] = @bitCast(Node.Repr.DeclAttr{ - .@"extern" = variable.@"extern", - .static = variable.static, + .@"extern" = variable.storage_class == .@"extern", + .static = variable.storage_class == .static, .thread_local = variable.thread_local, .implicit = variable.implicit, + .register = variable.storage_class == .register, }); repr.data[2] = packOptIndex(variable.initializer); repr.tok = variable.name_tok; @@ -2379,12 +2447,18 @@ pub fn addNodeExtra(tree: *Tree, node: Node, index: usize) !void { .decl_ref_expr => |decl_ref| { repr.tag = .decl_ref_expr; repr.data[0] = try tree.addType(decl_ref.type); + repr.data[1] = @intFromEnum(decl_ref.decl); repr.tok = decl_ref.name_tok; }, - .enumeration_ref => |decl_ref| { + .enumeration_ref => |enumeration_ref| { repr.tag = .enumeration_ref; - repr.data[0] = try tree.addType(decl_ref.type); - repr.tok = decl_ref.name_tok; + repr.data[0] = try tree.addType(enumeration_ref.type); + repr.tok = enumeration_ref.name_tok; + }, + .builtin_ref => |builtin_ref| { + repr.tag = .builtin_ref; + repr.data[0] = try tree.addType(builtin_ref.type); + repr.tok = builtin_ref.name_tok; }, .bool_literal => |literal| { repr.tag = .bool_literal; @@ -2536,7 +2610,8 @@ pub fn addNodeExtra(tree: *Tree, node: Node, index: usize) !void { repr.tag = .compound_literal_expr; repr.data[0] = try tree.addType(literal.type); repr.data[1] = @bitCast(Node.Repr.DeclAttr{ - .static = literal.static, + .static = literal.storage_class == .static, + .register = literal.storage_class == .register, .thread_local = literal.thread_local, }); repr.data[2] = @intFromEnum(literal.initializer); @@ -2893,12 +2968,33 @@ fn dumpNode( try w.print("{s}\n", .{tree.tokSlice(typedef.name_tok)}); try config.setColor(w, .reset); }, + .param => |param| { + try w.writeByteNTimes(' ', level + half); + + switch (param.storage_class) { + .auto => {}, + .register => { + try config.setColor(w, ATTRIBUTE); + try w.writeAll("register "); + try config.setColor(w, .reset); + }, + } + + try w.writeAll("name: "); + try config.setColor(w, NAME); + try w.print("{s}\n", .{tree.tokSlice(param.name_tok)}); + try config.setColor(w, .reset); + }, .variable => |variable| { try w.writeByteNTimes(' ', level + half); try config.setColor(w, ATTRIBUTE); - if (variable.static) try w.writeAll("static "); - if (variable.@"extern") try w.writeAll("extern "); + switch (variable.storage_class) { + .auto => {}, + .static => try w.writeAll("static "), + .@"extern" => try w.writeAll("extern "), + .register => try w.writeAll("register "), + } if (variable.thread_local) try w.writeAll("thread_local "); if (variable.implicit) try w.writeAll("implicit "); try config.setColor(w, .reset); @@ -2985,11 +3081,15 @@ fn dumpNode( } }, .compound_literal_expr => |literal| { - if (literal.static or literal.thread_local) { + if (literal.storage_class != .auto or literal.thread_local) { try w.writeByteNTimes(' ', level + half - 1); try config.setColor(w, ATTRIBUTE); - if (literal.static) try w.writeAll(" static"); + switch (literal.storage_class) { + .auto => {}, + .static => try w.writeAll(" static"), + .register => try w.writeAll(" register"), + } if (literal.thread_local) try w.writeAll(" thread_local"); try w.writeByte('\n'); try config.setColor(w, .reset); @@ -3247,7 +3347,14 @@ fn dumpNode( try w.writeAll("operand:\n"); try tree.dumpNode(un.operand, level + delta, mapper, config, w); }, - .decl_ref_expr, .enumeration_ref => |dr| { + .decl_ref_expr => |dr| { + try w.writeByteNTimes(' ', level + 1); + try w.writeAll("name: "); + try config.setColor(w, NAME); + try w.print("{s}\n", .{tree.tokSlice(dr.name_tok)}); + try config.setColor(w, .reset); + }, + .builtin_ref, .enumeration_ref => |dr| { try w.writeByteNTimes(' ', level + 1); try w.writeAll("name: "); try config.setColor(w, NAME); diff --git a/src/aro/Type.zig b/src/aro/Type.zig index 6de8d71f..86d9f88c 100644 --- a/src/aro/Type.zig +++ b/src/aro/Type.zig @@ -17,9 +17,6 @@ pub const Qualifiers = packed struct { @"volatile": bool = false, restrict: bool = false, - // for function parameters only, stored here since it fits in the padding - register: bool = false, - pub fn any(quals: Qualifiers) bool { return quals.@"const" or quals.restrict or quals.@"volatile" or quals.atomic; } @@ -29,7 +26,6 @@ pub const Qualifiers = packed struct { if (quals.atomic) try w.writeAll("_Atomic "); if (quals.@"volatile") try w.writeAll("volatile "); if (quals.restrict) try w.writeAll("restrict "); - if (quals.register) try w.writeAll("register "); } /// Merge the const/volatile qualifiers, used by type resolution @@ -48,7 +44,6 @@ pub const Qualifiers = packed struct { .atomic = a.atomic or b.atomic, .@"volatile" = a.@"volatile" or b.@"volatile", .restrict = a.restrict or b.restrict, - .register = a.register or b.register, }; } @@ -60,14 +55,6 @@ pub const Qualifiers = packed struct { return true; } - /// register is a storage class and not actually a qualifier - /// so it is not preserved by typeof() - pub fn inheritFromTypeof(quals: Qualifiers) Qualifiers { - var res = quals; - res.register = false; - return res; - } - pub const Builder = struct { @"const": ?TokenIndex = null, atomic: ?TokenIndex = null, @@ -101,6 +88,7 @@ pub const Func = struct { ty: Type, name: StringId, name_tok: TokenIndex, + node: Node.OptIndex, }; fn eql(a: *const Func, b: *const Func, a_spec: Specifier, b_spec: Specifier, comp: *const Compilation) bool { diff --git a/src/assembly_backend/x86_64.zig b/src/assembly_backend/x86_64.zig index 6d431693..56942a12 100644 --- a/src/assembly_backend/x86_64.zig +++ b/src/assembly_backend/x86_64.zig @@ -196,7 +196,7 @@ fn genVar(c: *AsmCodeGen, variable: Node.Variable) !void { const nat_align = ty.alignof(comp); const alignment = if (ty.isArray() and size >= 16) @max(16, nat_align) else nat_align; - if (variable.static) { + if (variable.storage_class == .static) { try c.data.print(" .local \"{s}\"\n", .{name}); } else { try c.data.print(" .globl \"{s}\"\n", .{name}); diff --git a/test/cases/typeof quals.c b/test/cases/typeof quals.c index 90fedb8d..67b869ae 100644 --- a/test/cases/typeof quals.c +++ b/test/cases/typeof quals.c @@ -5,6 +5,7 @@ void test_typeof_quals(void) { typeof(c) d; register int e; typeof(e) f; + (void)&f; _Atomic int g; typeof(g) h; int *restrict i = 0; @@ -13,6 +14,6 @@ void test_typeof_quals(void) { #define EXPECTED_TYPES "const int" "typeof(: const int)" \ "volatile int" "typeof(: volatile int)" \ - "register int" "typeof(: int)" \ + "int" "typeof(: int)" "void" \ "_Atomic int" "typeof(: _Atomic int)" \ "restrict *int" "typeof(: restrict *int)" From 9381d4f6cb3fb882cf89e75db8e3251ca3497e80 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 1 Jan 2025 21:50:28 +0200 Subject: [PATCH 2/5] add implicit typedefs to the AST --- src/aro/Parser.zig | 65 ++++++++++++----- src/aro/SymbolStack.zig | 10 +-- src/aro/Tree.zig | 51 ++++++------- test/cases/ast/_Float16.c | 54 +++++++++----- test/cases/ast/__float80.c | 20 +++++- test/cases/ast/attributed record fields.c | 15 ++++ test/cases/ast/c23 auto.c | 26 +++++-- test/cases/ast/c23 true false ast.c | 28 ++++++-- test/cases/ast/cast kinds.c | 87 +++++++++++++---------- test/cases/ast/complex init.c | 29 ++++++-- test/cases/ast/decayed attributed array.c | 29 ++++++-- test/cases/ast/float eval method.c | 44 ++++++++---- test/cases/ast/for decl stmt.c | 17 ++++- test/cases/ast/forever stmt.c | 17 ++++- test/cases/ast/generic ast.c | 17 ++++- test/cases/ast/native half type.c | 25 +++++-- test/cases/ast/promotion edge cases.c | 47 +++++++----- test/cases/ast/stdckdint_ast.c | 33 ++++++--- test/cases/ast/typeof_unqual.c | 18 +++++ test/cases/ast/types.c | 34 ++++++--- test/cases/ast/vectors.c | 23 ++++-- 21 files changed, 508 insertions(+), 181 deletions(-) diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 41fcc855..f19a3039 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -608,7 +608,7 @@ fn nodeIs(p: *Parser, node: Node.Index, comptime tag: std.meta.Tag(Tree.Node)) b } pub fn getDecayedStringLiteral(p: *Parser, node: Node.Index) ?Value { - const cast = p.getNode(node, .implicit_cast) orelse return null; + const cast = p.getNode(node, .cast) orelse return null; if (cast.kind != .array_to_pointer) return null; var cur = cast.operand; @@ -688,7 +688,6 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { .gpa = pp.comp.gpa, .tree = .{ .comp = pp.comp, - .generated = pp.comp.generated_buf.items, .tokens = pp.tokens.slice(), .arena = .init(pp.comp.gpa), }, @@ -735,29 +734,30 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { { if (p.comp.langopts.hasChar8_T()) { - try p.syms.defineTypedef(&p, try StrInt.intern(p.comp, "char8_t"), .{ .specifier = .uchar }, 0, null); + try p.addImplicitTypedef("char8_t", .{ .specifier = .uchar }); } - try p.syms.defineTypedef(&p, try StrInt.intern(p.comp, "__int128_t"), .{ .specifier = .int128 }, 0, null); - try p.syms.defineTypedef(&p, try StrInt.intern(p.comp, "__uint128_t"), .{ .specifier = .uint128 }, 0, null); + try p.addImplicitTypedef("__int128_t", .{ .specifier = .int128 }); + try p.addImplicitTypedef("__uint128_t", .{ .specifier = .uint128 }); const elem_ty = try p.arena.create(Type); elem_ty.* = .{ .specifier = .char }; - try p.syms.defineTypedef(&p, try StrInt.intern(p.comp, "__builtin_ms_va_list"), .{ + try p.addImplicitTypedef("__builtin_ms_va_list", .{ .specifier = .pointer, .data = .{ .sub_type = elem_ty }, - }, 0, null); + }); const ty = &pp.comp.types.va_list; - try p.syms.defineTypedef(&p, try StrInt.intern(p.comp, "__builtin_va_list"), ty.*, 0, null); + try p.addImplicitTypedef("__builtin_va_list", ty.*); if (ty.isArray()) ty.decayArray(); - try p.syms.defineTypedef(&p, try StrInt.intern(p.comp, "__NSConstantString"), pp.comp.types.ns_constant_string.ty, 0, null); + try p.addImplicitTypedef("__NSConstantString", pp.comp.types.ns_constant_string.ty); if (p.comp.float80Type()) |float80_ty| { - try p.syms.defineTypedef(&p, try StrInt.intern(p.comp, "__float80"), float80_ty, 0, null); + try p.addImplicitTypedef("__float80", float80_ty); } } + const implicit_typedef_count = p.decl_buf.items.len; while (p.eatToken(.eof) == null) { if (try p.pragma()) continue; @@ -805,7 +805,7 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { } p.tree.root_decls = p.decl_buf.moveToUnmanaged(); - if (p.tree.root_decls.items.len == 0) { + if (p.tree.root_decls.items.len == implicit_typedef_count) { try p.errTok(.empty_translation_unit, p.tok_i - 1); } pp.comp.pragmaEvent(.after_parse); @@ -813,6 +813,33 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { return p.tree; } +fn addImplicitTypedef(p: *Parser, name: []const u8, ty: Type) !void { + const start = p.comp.generated_buf.items.len; + try p.comp.generated_buf.appendSlice(p.comp.gpa, name); + try p.comp.generated_buf.append(p.comp.gpa, '\n'); + + const name_tok: u32 = @intCast(p.pp.tokens.len); + try p.pp.tokens.append(p.gpa, .{ .id = .identifier, .loc = .{ + .id = .generated, + .byte_offset = @intCast(start), + .line = p.pp.generated_line, + } }); + p.pp.generated_line += 1; + + // Reset in case there was an allocation. + p.tree.tokens = p.pp.tokens.slice(); + + const node = try p.addNode(.{ + .typedef = .{ + .name_tok = name_tok, + .type = ty, + .implicit = true, + }, + }); + try p.syms.defineTypedef(p, try StrInt.intern(p.comp, name), ty, name_tok, node); + try p.decl_buf.append(node); +} + fn skipToPragmaSentinel(p: *Parser) void { while (true) : (p.tok_i += 1) { if (p.tok_ids[p.tok_i] == .nl) return; @@ -2850,9 +2877,6 @@ fn enumerator(p: *Parser, e: *Enumerator) Error!?EnumFieldAndNode { } } - const interned_name = try StrInt.intern(p.comp, p.tokSlice(name_tok)); - try p.syms.defineEnumeration(p, interned_name, attr_ty, name_tok, e.val); - const node = try p.addNode(.{ .enum_field = .{ .name_tok = name_tok, @@ -2861,6 +2885,10 @@ fn enumerator(p: *Parser, e: *Enumerator) Error!?EnumFieldAndNode { }, }); try p.tree.value_map.put(p.gpa, node, e.val); + + const interned_name = try StrInt.intern(p.comp, p.tokSlice(name_tok)); + try p.syms.defineEnumeration(p, interned_name, attr_ty, name_tok, e.val, node); + return .{ .field = .{ .name = interned_name, .ty = attr_ty, @@ -5250,11 +5278,12 @@ pub const Result = struct { fn implicitCast(operand: *Result, p: *Parser, kind: Node.Cast.Kind, tok: TokenIndex) Error!void { operand.node = try p.addNode(.{ - .implicit_cast = .{ + .cast = .{ .l_paren = tok, .kind = kind, .operand = operand.node, .type = operand.ty, + .implicit = true, }, }); } @@ -6061,11 +6090,12 @@ pub const Result = struct { res.ty = to; res.ty.qual = .{}; res.node = try p.addNode(.{ - .explicit_cast = .{ + .cast = .{ .l_paren = l_paren, .type = res.ty, .operand = res.node, .kind = cast_kind, + .implicit = false, }, }); } @@ -7040,7 +7070,7 @@ fn offsetofMemberDesignator(p: *Parser, base_ty: Type, offset_kind: OffsetKind, fn computeOffsetExtra(p: *Parser, node: Node.Index, offset_so_far: *Value) !Value { switch (node.get(&p.tree)) { - .implicit_cast => |cast| { + .cast => |cast| { return switch (cast.kind) { .array_to_pointer => p.computeOffsetExtra(cast.operand, offset_so_far), .lval_to_rval => .{}, @@ -8009,6 +8039,7 @@ fn primaryExpr(p: *Parser) Error!?Result { .{ .enumeration_ref = .{ .name_tok = name_tok, .type = sym.ty, + .decl = sym.node.unpack().?, } } else .{ .decl_ref_expr = .{ diff --git a/src/aro/SymbolStack.zig b/src/aro/SymbolStack.zig index 308fdbdd..1b10cadd 100644 --- a/src/aro/SymbolStack.zig +++ b/src/aro/SymbolStack.zig @@ -174,7 +174,7 @@ pub fn defineTypedef( name: StringId, ty: Type, tok: TokenIndex, - node: ?Node.Index, + node: Node.Index, ) !void { if (s.get(name, .vars)) |prev| { switch (prev.kind) { @@ -203,7 +203,7 @@ pub fn defineTypedef( .qual = ty.qual, .data = ty.data, }, - .node = .packOpt(node), + .node = .pack(node), .val = .{}, }); } @@ -267,7 +267,7 @@ pub fn declareSymbol( name: StringId, ty: Type, tok: TokenIndex, - node: ?Node.Index, + node: Node.Index, ) !void { if (s.get(name, .vars)) |prev| { switch (prev.kind) { @@ -301,7 +301,7 @@ pub fn declareSymbol( .name = name, .tok = tok, .ty = ty, - .node = .packOpt(node), + .node = .pack(node), .val = .{}, }); } @@ -378,6 +378,7 @@ pub fn defineEnumeration( ty: Type, tok: TokenIndex, val: Value, + node: Node.Index, ) !void { if (s.get(name, .vars)) |prev| { switch (prev.kind) { @@ -404,5 +405,6 @@ pub fn defineEnumeration( .tok = tok, .ty = ty, .val = val, + .node = .pack(node), }); } diff --git a/src/aro/Tree.zig b/src/aro/Tree.zig index c2fa6205..2ca03682 100644 --- a/src/aro/Tree.zig +++ b/src/aro/Tree.zig @@ -192,7 +192,6 @@ const Tree = @This(); comp: *Compilation, // Values from Preprocessor. -generated: []const u8, tokens: Token.List.Slice, // Values owned by this Tree @@ -243,6 +242,7 @@ pub const Node = union(enum) { typedef: struct { name_tok: TokenIndex, type: Type, + implicit: bool, }, global_asm: SimpleAsm, @@ -376,8 +376,7 @@ pub const Node = union(enum) { div_expr: BinaryExpr, mod_expr: BinaryExpr, - explicit_cast: Cast, - implicit_cast: Cast, + cast: Cast, addr_of_expr: UnaryExpr, deref_expr: UnaryExpr, @@ -414,7 +413,7 @@ pub const Node = union(enum) { member_access_expr: MemberAccess, member_access_ptr_expr: MemberAccess, decl_ref_expr: DeclRef, - enumeration_ref: NoDeclRef, + enumeration_ref: DeclRef, builtin_ref: NoDeclRef, /// C23 bool literal `true` / `false` @@ -558,6 +557,7 @@ pub const Node = union(enum) { l_paren: TokenIndex, kind: Kind, operand: Node.Index, + implicit: bool, pub const Kind = enum { /// Does nothing except possibly add qualifiers @@ -762,6 +762,7 @@ pub const Node = union(enum) { .typedef = .{ .name_tok = node_tok, .type = tree.type_map.keys()[node_data[0]], + .implicit = node_data[1] != 0, }, }, .global_asm => .{ @@ -1215,19 +1216,21 @@ pub const Node = union(enum) { }, }, .explicit_cast => .{ - .explicit_cast = .{ + .cast = .{ .l_paren = node_tok, .type = tree.type_map.keys()[node_data[0]], .kind = @enumFromInt(node_data[1]), .operand = @enumFromInt(node_data[2]), + .implicit = false, }, }, .implicit_cast => .{ - .implicit_cast = .{ + .cast = .{ .l_paren = node_tok, .type = tree.type_map.keys()[node_data[0]], .kind = @enumFromInt(node_data[1]), .operand = @enumFromInt(node_data[2]), + .implicit = true, }, }, .addr_of_expr => .{ @@ -1406,6 +1409,7 @@ pub const Node = union(enum) { .enumeration_ref = .{ .name_tok = node_tok, .type = tree.type_map.keys()[node_data[0]], + .decl = @enumFromInt(node_data[1]), }, }, .builtin_ref => .{ @@ -1810,13 +1814,14 @@ pub const Node = union(enum) { pub fn isImplicit(node: Node) bool { return switch (node) { - .implicit_cast, .implicit_return, .array_filler_expr, .default_init_expr, .cond_dummy_expr, => true, + .cast => |cast| cast.implicit, .variable => |info| info.implicit, + .typedef => |info| info.implicit, else => false, }; } @@ -1882,6 +1887,7 @@ pub fn setNode(tree: *Tree, node: Node, index: usize) !void { .typedef => |typedef| { repr.tag = .typedef; repr.data[0] = try tree.addType(typedef.type); + repr.data[1] = @intFromBool(typedef.implicit); repr.tok = typedef.name_tok; }, .global_asm => |global_asm| { @@ -2285,15 +2291,8 @@ pub fn setNode(tree: *Tree, node: Node, index: usize) !void { repr.data[2] = @intFromEnum(bin.rhs); repr.tok = bin.op_tok; }, - .explicit_cast => |cast| { - repr.tag = .explicit_cast; - repr.data[0] = try tree.addType(cast.type); - repr.data[1] = @intFromEnum(cast.kind); - repr.data[2] = @intFromEnum(cast.operand); - repr.tok = cast.l_paren; - }, - .implicit_cast => |cast| { - repr.tag = .implicit_cast; + .cast => |cast| { + repr.tag = if (cast.implicit) .implicit_cast else .explicit_cast; repr.data[0] = try tree.addType(cast.type); repr.data[1] = @intFromEnum(cast.kind); repr.data[2] = @intFromEnum(cast.operand); @@ -2453,6 +2452,7 @@ pub fn setNode(tree: *Tree, node: Node, index: usize) !void { .enumeration_ref => |enumeration_ref| { repr.tag = .enumeration_ref; repr.data[0] = try tree.addType(enumeration_ref.type); + repr.data[1] = @intFromEnum(enumeration_ref.decl); repr.tok = enumeration_ref.name_tok; }, .builtin_ref => |builtin_ref| { @@ -2662,7 +2662,7 @@ pub fn isBitfield(tree: *const Tree, node: Node.Index) bool { pub fn bitfieldWidth(tree: *const Tree, node: Node.Index, inspect_lval: bool) ?u32 { switch (node.get(tree)) { .member_access_expr, .member_access_ptr_expr => |access| return access.isBitFieldWidth(tree), - .implicit_cast => |cast| { + .cast => |cast| { if (!inspect_lval) return null; return switch (cast.kind) { @@ -2694,7 +2694,7 @@ pub fn callableResultUsage(tree: *const Tree, node: Node.Index) ?CallableResultU .paren_expr, .addr_of_expr, .deref_expr => |un| cur_node = un.operand, .comma_expr => |bin| cur_node = bin.rhs, - .explicit_cast, .implicit_cast => |cast| cur_node = cast.operand, + .cast => |cast| cur_node = cast.operand, .call_expr => |call| cur_node = call.callee, .member_access_expr, .member_access_ptr_expr => |access| { var ty = access.base.type(tree); @@ -2847,10 +2847,14 @@ fn dumpNode( const ty = node_index.type(tree); try w.writeByteNTimes(' ', level); - try config.setColor(w, if (node.isImplicit()) IMPLICIT else TAG); + if (config == .no_color) { + if (node.isImplicit()) try w.writeAll("implicit "); + } else { + try config.setColor(w, if (node.isImplicit()) IMPLICIT else TAG); + } try w.print("{s}: ", .{@tagName(node)}); switch (node) { - .implicit_cast, .explicit_cast => |cast| { + .cast => |cast| { try config.setColor(w, .white); try w.print("({s}) ", .{@tagName(cast.kind)}); }, @@ -2996,7 +3000,6 @@ fn dumpNode( .register => try w.writeAll("register "), } if (variable.thread_local) try w.writeAll("thread_local "); - if (variable.implicit) try w.writeAll("implicit "); try config.setColor(w, .reset); try w.writeAll("name: "); @@ -3326,7 +3329,7 @@ fn dumpNode( try w.writeAll("rhs:\n"); try tree.dumpNode(bin.rhs, level + delta, mapper, config, w); }, - .explicit_cast, .implicit_cast => |cast| try tree.dumpNode(cast.operand, level + delta, mapper, config, w), + .cast => |cast| try tree.dumpNode(cast.operand, level + delta, mapper, config, w), .addr_of_expr, .deref_expr, .plus_expr, @@ -3347,14 +3350,14 @@ fn dumpNode( try w.writeAll("operand:\n"); try tree.dumpNode(un.operand, level + delta, mapper, config, w); }, - .decl_ref_expr => |dr| { + .decl_ref_expr, .enumeration_ref => |dr| { try w.writeByteNTimes(' ', level + 1); try w.writeAll("name: "); try config.setColor(w, NAME); try w.print("{s}\n", .{tree.tokSlice(dr.name_tok)}); try config.setColor(w, .reset); }, - .builtin_ref, .enumeration_ref => |dr| { + .builtin_ref => |dr| { try w.writeByteNTimes(' ', level + 1); try w.writeAll("name: "); try config.setColor(w, NAME); diff --git a/test/cases/ast/_Float16.c b/test/cases/ast/_Float16.c index 1315ac6d..5e788cb9 100644 --- a/test/cases/ast/_Float16.c +++ b/test/cases/ast/_Float16.c @@ -1,3 +1,21 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + +implicit typedef: 'long double' + name: __float80 + variable: '__builtin_va_list': '[1]struct __va_list_tag' name: va_list @@ -12,11 +30,11 @@ fn_def: 'fn (x: _Float16, y: _Float16) _Float16' expr: add_expr: '_Float16' lhs: - implicit_cast: (lval_to_rval) '_Float16' + implicit cast: (lval_to_rval) '_Float16' decl_ref_expr: '_Float16' lvalue name: x rhs: - implicit_cast: (lval_to_rval) '_Float16' + implicit cast: (lval_to_rval) '_Float16' decl_ref_expr: '_Float16' lvalue name: y @@ -30,7 +48,7 @@ fn_def: 'fn (x: int, ...) void' builtin_call_expr: 'void' name: __builtin_va_start args: - implicit_cast: (array_to_pointer) 'va_list': '*d[1]struct __va_list_tag' (value: &va) + implicit cast: (array_to_pointer) 'va_list': '*d[1]struct __va_list_tag' (value: &va) decl_ref_expr: 'va_list': '[1]struct __va_list_tag' lvalue name: va decl_ref_expr: 'int' lvalue @@ -39,11 +57,11 @@ fn_def: 'fn (x: int, ...) void' builtin_call_expr: 'void' name: __builtin_va_end args: - implicit_cast: (array_to_pointer) 'va_list': '*d[1]struct __va_list_tag' (value: &va) + implicit cast: (array_to_pointer) 'va_list': '*d[1]struct __va_list_tag' (value: &va) decl_ref_expr: 'va_list': '[1]struct __va_list_tag' lvalue name: va - implicit_return: 'void' + implicit implicit_return: 'void' fn_def: 'fn () void' name: quux @@ -56,16 +74,16 @@ fn_def: 'fn () void' call_expr: 'void' callee: - implicit_cast: (function_to_pointer) '*fn (x: int, ...) void' + implicit cast: (function_to_pointer) '*fn (x: int, ...) void' decl_ref_expr: 'fn (x: int, ...) void' lvalue name: bar args: int_literal: 'int' (value: 1) - implicit_cast: (lval_to_rval) '_Float16' + implicit cast: (lval_to_rval) '_Float16' decl_ref_expr: '_Float16' lvalue name: f - implicit_return: 'void' + implicit implicit_return: 'void' fn_def: 'fn () void' name: conversions @@ -84,7 +102,7 @@ fn_def: 'fn () void' variable: '__fp16' name: fp16 init: - implicit_cast: (int_to_float) '__fp16' (value: 0) + implicit cast: (int_to_float) '__fp16' (value: 0) int_literal: 'int' (value: 0) assign_expr: 'double' @@ -94,29 +112,29 @@ fn_def: 'fn () void' rhs: add_expr: 'double' lhs: - implicit_cast: (lval_to_rval) 'double' + implicit cast: (lval_to_rval) 'double' decl_ref_expr: 'double' lvalue name: d rhs: - implicit_cast: (float_cast) 'double' - implicit_cast: (lval_to_rval) '_Float16' + implicit cast: (float_cast) 'double' + implicit cast: (lval_to_rval) '_Float16' decl_ref_expr: '_Float16' lvalue name: f16 - explicit_cast: (to_void) 'void' + cast: (to_void) 'void' paren_expr: 'float' operand: add_expr: 'float' lhs: - implicit_cast: (float_cast) 'float' - implicit_cast: (lval_to_rval) '_Float16' + implicit cast: (float_cast) 'float' + implicit cast: (lval_to_rval) '_Float16' decl_ref_expr: '_Float16' lvalue name: f16 rhs: - implicit_cast: (float_cast) 'float' - implicit_cast: (lval_to_rval) '__fp16' + implicit cast: (float_cast) 'float' + implicit cast: (lval_to_rval) '__fp16' decl_ref_expr: '__fp16' lvalue name: fp16 - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/__float80.c b/test/cases/ast/__float80.c index 1a20d0b5..efb90b04 100644 --- a/test/cases/ast/__float80.c +++ b/test/cases/ast/__float80.c @@ -1,3 +1,21 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + +implicit typedef: 'long double' + name: __float80 + fn_def: 'fn () void' name: foo body: @@ -35,5 +53,5 @@ fn_def: 'fn () void' operand: float_literal: 'long double' - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/attributed record fields.c b/test/cases/ast/attributed record fields.c index c47aec02..7f856a4d 100644 --- a/test/cases/ast/attributed record fields.c +++ b/test/cases/ast/attributed record fields.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + struct_decl: 'struct S1' struct_decl: 'struct S2' diff --git a/test/cases/ast/c23 auto.c b/test/cases/ast/c23 auto.c index f6c649db..4be51389 100644 --- a/test/cases/ast/c23 auto.c +++ b/test/cases/ast/c23 auto.c @@ -1,3 +1,21 @@ +implicit typedef: 'unsigned char' + name: char8_t + +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + fn_def: 'fn () void' name: bad body: @@ -20,7 +38,7 @@ fn_def: 'fn () void' init: int_literal: 'int' (value: 3) - implicit_return: 'void' + implicit implicit_return: 'void' fn_def: 'fn () void' name: good @@ -34,15 +52,15 @@ fn_def: 'fn () void' variable: '*d[4]char' name: b init: - implicit_cast: (array_to_pointer) '*d[4]char' + implicit cast: (array_to_pointer) '*d[4]char' string_literal_expr: '[4]char' lvalue (value: "foo") variable: '*fn () void' name: c init: - implicit_cast: (function_to_pointer) '*fn () void' + implicit cast: (function_to_pointer) '*fn () void' decl_ref_expr: 'fn () void' lvalue name: good - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/c23 true false ast.c b/test/cases/ast/c23 true false ast.c index dc0379ae..ef0f1922 100644 --- a/test/cases/ast/c23 true false ast.c +++ b/test/cases/ast/c23 true false ast.c @@ -1,3 +1,21 @@ +implicit typedef: 'unsigned char' + name: char8_t + +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + variable: 'bool' name: a init: @@ -11,25 +29,25 @@ variable: 'bool' variable: 'bool' name: c init: - implicit_cast: (int_to_bool) 'bool' (value: false) + implicit cast: (int_to_bool) 'bool' (value: false) int_literal: 'int' (value: 0) variable: 'bool' name: d init: - implicit_cast: (int_to_bool) 'bool' (value: true) + implicit cast: (int_to_bool) 'bool' (value: true) int_literal: 'int' (value: 1) variable: 'int' name: e init: - implicit_cast: (bool_to_int) 'int' (value: 1) + implicit cast: (bool_to_int) 'int' (value: 1) bool_literal: 'bool' (value: true) variable: 'int' name: f init: - implicit_cast: (bool_to_int) 'int' (value: 0) + implicit cast: (bool_to_int) 'int' (value: 0) bool_literal: 'bool' (value: false) variable: 'int' @@ -37,7 +55,7 @@ variable: 'int' init: add_expr: 'int' (value: 2) lhs: - implicit_cast: (bool_to_int) 'int' + implicit cast: (bool_to_int) 'int' bool_literal: 'bool' (value: true) rhs: int_literal: 'int' (value: 1) diff --git a/test/cases/ast/cast kinds.c b/test/cases/ast/cast kinds.c index 02c863d4..8d38c359 100644 --- a/test/cases/ast/cast kinds.c +++ b/test/cases/ast/cast kinds.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + union_decl: 'union U' record_field: 'int' name: x @@ -37,7 +52,7 @@ fn_def: 'fn () void' decl_ref_expr: '*int' lvalue name: p rhs: - explicit_cast: (bitcast) '*int' + cast: (bitcast) '*int' addr_of_expr: '*float' operand: decl_ref_expr: 'float' lvalue @@ -48,7 +63,7 @@ fn_def: 'fn () void' decl_ref_expr: '*int' lvalue name: p rhs: - implicit_cast: (array_to_pointer) '*d[2]int' + implicit cast: (array_to_pointer) '*d[2]int' decl_ref_expr: '[2]int' lvalue name: arr @@ -59,15 +74,15 @@ fn_def: 'fn () void' rhs: call_expr: 'int' callee: - implicit_cast: (function_to_pointer) '*fn () int' + implicit cast: (function_to_pointer) '*fn () int' decl_ref_expr: 'fn () int' lvalue name: bar variable: '_Bool' name: b init: - implicit_cast: (pointer_to_bool) '_Bool' - implicit_cast: (lval_to_rval) '*int' + implicit cast: (pointer_to_bool) '_Bool' + implicit cast: (lval_to_rval) '*int' decl_ref_expr: '*int' lvalue name: p @@ -76,8 +91,8 @@ fn_def: 'fn () void' decl_ref_expr: 'int' lvalue name: x rhs: - implicit_cast: (pointer_to_int) 'int' - implicit_cast: (lval_to_rval) '*int' + implicit cast: (pointer_to_int) 'int' + implicit cast: (lval_to_rval) '*int' decl_ref_expr: '*int' lvalue name: p @@ -86,8 +101,8 @@ fn_def: 'fn () void' decl_ref_expr: 'int' lvalue name: x rhs: - implicit_cast: (bool_to_int) 'int' - implicit_cast: (lval_to_rval) '_Bool' + implicit cast: (bool_to_int) 'int' + implicit cast: (lval_to_rval) '_Bool' decl_ref_expr: '_Bool' lvalue name: b @@ -96,8 +111,8 @@ fn_def: 'fn () void' decl_ref_expr: 'float' lvalue name: f rhs: - implicit_cast: (bool_to_float) 'float' - implicit_cast: (lval_to_rval) '_Bool' + implicit cast: (bool_to_float) 'float' + implicit cast: (lval_to_rval) '_Bool' decl_ref_expr: '_Bool' lvalue name: b @@ -106,8 +121,8 @@ fn_def: 'fn () void' decl_ref_expr: '*int' lvalue name: p rhs: - implicit_cast: (bool_to_pointer) '*int' - implicit_cast: (lval_to_rval) '_Bool' + implicit cast: (bool_to_pointer) '*int' + implicit cast: (lval_to_rval) '_Bool' decl_ref_expr: '_Bool' lvalue name: b @@ -116,8 +131,8 @@ fn_def: 'fn () void' decl_ref_expr: '_Bool' lvalue name: b rhs: - implicit_cast: (int_to_bool) '_Bool' - implicit_cast: (lval_to_rval) 'int' + implicit cast: (int_to_bool) '_Bool' + implicit cast: (lval_to_rval) 'int' decl_ref_expr: 'int' lvalue name: x @@ -126,8 +141,8 @@ fn_def: 'fn () void' decl_ref_expr: 'float' lvalue name: f rhs: - implicit_cast: (int_to_float) 'float' - implicit_cast: (lval_to_rval) 'int' + implicit cast: (int_to_float) 'float' + implicit cast: (lval_to_rval) 'int' decl_ref_expr: 'int' lvalue name: x @@ -136,8 +151,8 @@ fn_def: 'fn () void' decl_ref_expr: '*int' lvalue name: p rhs: - implicit_cast: (int_to_pointer) '*int' - implicit_cast: (lval_to_rval) 'int' + implicit cast: (int_to_pointer) '*int' + implicit cast: (lval_to_rval) 'int' decl_ref_expr: 'int' lvalue name: x @@ -146,8 +161,8 @@ fn_def: 'fn () void' decl_ref_expr: '_Bool' lvalue name: b rhs: - implicit_cast: (float_to_bool) '_Bool' - implicit_cast: (lval_to_rval) 'float' + implicit cast: (float_to_bool) '_Bool' + implicit cast: (lval_to_rval) 'float' decl_ref_expr: 'float' lvalue name: f @@ -156,8 +171,8 @@ fn_def: 'fn () void' decl_ref_expr: 'int' lvalue name: x rhs: - implicit_cast: (float_to_int) 'int' - implicit_cast: (lval_to_rval) 'float' + implicit cast: (float_to_int) 'int' + implicit cast: (lval_to_rval) 'float' decl_ref_expr: 'float' lvalue name: f @@ -166,7 +181,7 @@ fn_def: 'fn () void' decl_ref_expr: 'int' lvalue name: x rhs: - implicit_cast: (int_cast) 'int' + implicit cast: (int_cast) 'int' int_literal: 'long' (value: 1) assign_expr: 'float' @@ -174,8 +189,8 @@ fn_def: 'fn () void' decl_ref_expr: 'float' lvalue name: f rhs: - implicit_cast: (float_cast) 'float' - implicit_cast: (lval_to_rval) 'double' + implicit cast: (float_cast) 'float' + implicit cast: (lval_to_rval) 'double' decl_ref_expr: 'double' lvalue name: d @@ -184,8 +199,8 @@ fn_def: 'fn () void' decl_ref_expr: 'double' lvalue name: d rhs: - implicit_cast: (float_cast) 'double' - implicit_cast: (lval_to_rval) 'float' + implicit cast: (float_cast) 'double' + implicit cast: (lval_to_rval) 'float' decl_ref_expr: 'float' lvalue name: f @@ -194,11 +209,11 @@ fn_def: 'fn () void' decl_ref_expr: '*int' lvalue name: p rhs: - implicit_cast: (null_to_pointer) '*int' + implicit cast: (null_to_pointer) '*int' int_literal: 'int' (value: 0) - explicit_cast: (to_void) 'void' - implicit_cast: (lval_to_rval) '*int' + cast: (to_void) 'void' + implicit cast: (lval_to_rval) '*int' decl_ref_expr: '*int' lvalue name: p @@ -210,8 +225,8 @@ fn_def: 'fn () void' decl_ref_expr: 'union U' lvalue name: u rhs: - explicit_cast: (union_cast) 'union U' - implicit_cast: (lval_to_rval) 'int' + cast: (union_cast) 'union U' + implicit cast: (lval_to_rval) 'int' decl_ref_expr: 'int' lvalue name: x @@ -220,10 +235,10 @@ fn_def: 'fn () void' decl_ref_expr: 'union U' lvalue name: u rhs: - explicit_cast: (union_cast) 'union U' - implicit_cast: (lval_to_rval) 'float' + cast: (union_cast) 'union U' + implicit cast: (lval_to_rval) 'float' decl_ref_expr: 'float' lvalue name: f - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/complex init.c b/test/cases/ast/complex init.c index b8f0462b..23f3e859 100644 --- a/test/cases/ast/complex init.c +++ b/test/cases/ast/complex init.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + fn_def: 'fn () void' name: foo body: @@ -45,13 +60,13 @@ fn_def: 'fn () void' decl_ref_expr: '_Complex double' lvalue name: cd rhs: - implicit_cast: (lval_to_rval) '_Complex double' + implicit cast: (lval_to_rval) '_Complex double' compound_literal_expr: '_Complex double' lvalue array_init_expr: '_Complex double' (value: 1 + 2i) - implicit_cast: (float_cast) 'double' (value: 1) + implicit cast: (float_cast) 'double' (value: 1) float_literal: 'float' (value: 1) - implicit_cast: (float_cast) 'double' (value: 2) + implicit cast: (float_cast) 'double' (value: 2) float_literal: 'float' (value: 2) assign_expr: '_Complex float' @@ -59,14 +74,14 @@ fn_def: 'fn () void' decl_ref_expr: '_Complex float' lvalue name: cf rhs: - implicit_cast: (lval_to_rval) '_Complex float' + implicit cast: (lval_to_rval) '_Complex float' compound_literal_expr: '_Complex float' lvalue array_init_expr: '_Complex float' (value: 1 + 2i) - implicit_cast: (float_cast) 'float' (value: 1) + implicit cast: (float_cast) 'float' (value: 1) float_literal: 'double' (value: 1) - implicit_cast: (float_cast) 'float' (value: 2) + implicit cast: (float_cast) 'float' (value: 2) float_literal: 'double' (value: 2) - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/decayed attributed array.c b/test/cases/ast/decayed attributed array.c index f520d92f..29c2f0ad 100644 --- a/test/cases/ast/decayed attributed array.c +++ b/test/cases/ast/decayed attributed array.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + variable: 'attributed([1]int)' attr: aligned alignment: null name: arr @@ -8,7 +23,7 @@ variable: 'attributed([1]int)' variable: '*int' name: ptr init: - implicit_cast: (array_to_pointer) '*d:attributed([1]int)' (value: &arr) + implicit cast: (array_to_pointer) '*d:attributed([1]int)' (value: &arr) attr: aligned alignment: null decl_ref_expr: 'attributed([1]int)' lvalue attr: aligned alignment: null @@ -19,7 +34,7 @@ fn_def: 'fn () void' body: compound_stmt: 'void' variable: 'attributed([64]char)' - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(8), .requested = 8 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } name: x variable: '*char' @@ -29,16 +44,16 @@ fn_def: 'fn () void' operand: array_access_expr: 'char' lvalue base: - implicit_cast: (array_to_pointer) '*d:attributed([64]char)' - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(8), .requested = 8 } + implicit cast: (array_to_pointer) '*d:attributed([64]char)' + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } paren_expr: 'attributed([64]char)' lvalue - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(8), .requested = 8 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } operand: decl_ref_expr: 'attributed([64]char)' lvalue - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(8), .requested = 8 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } name: x index: int_literal: 'int' (value: 0) - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/float eval method.c b/test/cases/ast/float eval method.c index a47f273f..0b5dd870 100644 --- a/test/cases/ast/float eval method.c +++ b/test/cases/ast/float eval method.c @@ -1,3 +1,21 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + +implicit typedef: 'long double' + name: __float80 + fn_def: 'fn () void' name: foo body: @@ -15,23 +33,23 @@ fn_def: 'fn () void' variable: 'float' name: c init: - implicit_cast: (float_cast) 'float' + implicit cast: (float_cast) 'float' add_expr: 'double' lhs: - implicit_cast: (float_cast) 'double' - implicit_cast: (lval_to_rval) 'float' + implicit cast: (float_cast) 'double' + implicit cast: (lval_to_rval) 'float' decl_ref_expr: 'float' lvalue name: a rhs: - implicit_cast: (float_cast) 'double' - implicit_cast: (lval_to_rval) 'float' + implicit cast: (float_cast) 'double' + implicit cast: (lval_to_rval) 'float' decl_ref_expr: 'float' lvalue name: b variable: '_Complex float' name: ca init: - implicit_cast: (real_to_complex_float) '_Complex float' (value: 0 + 0i) + implicit cast: (real_to_complex_float) '_Complex float' (value: 0 + 0i) float_literal: 'float' (value: 0) assign_expr: '_Complex float' @@ -39,19 +57,19 @@ fn_def: 'fn () void' decl_ref_expr: '_Complex float' lvalue name: ca rhs: - implicit_cast: (complex_float_cast) '_Complex float' + implicit cast: (complex_float_cast) '_Complex float' add_expr: '_Complex double' lhs: - implicit_cast: (complex_float_cast) '_Complex double' - implicit_cast: (lval_to_rval) '_Complex float' + implicit cast: (complex_float_cast) '_Complex double' + implicit cast: (lval_to_rval) '_Complex float' decl_ref_expr: '_Complex float' lvalue name: ca rhs: - implicit_cast: (real_to_complex_float) '_Complex double' - implicit_cast: (float_cast) 'double' - implicit_cast: (lval_to_rval) 'float' + implicit cast: (real_to_complex_float) '_Complex double' + implicit cast: (float_cast) 'double' + implicit cast: (lval_to_rval) 'float' decl_ref_expr: 'float' lvalue name: a - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/for decl stmt.c b/test/cases/ast/for decl stmt.c index 6614cb9b..63a64151 100644 --- a/test/cases/ast/for decl stmt.c +++ b/test/cases/ast/for decl stmt.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + fn_def: 'fn () int' name: main body: @@ -22,5 +37,5 @@ fn_def: 'fn () int' body: null_stmt: 'void' - implicit_return: 'int' + implicit implicit_return: 'int' diff --git a/test/cases/ast/forever stmt.c b/test/cases/ast/forever stmt.c index b7c9d99e..29f582dd 100644 --- a/test/cases/ast/forever stmt.c +++ b/test/cases/ast/forever stmt.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + fn_def: 'fn () int' name: main body: @@ -7,5 +22,5 @@ fn_def: 'fn () int' body: null_stmt: 'void' - implicit_return: 'int' + implicit implicit_return: 'int' diff --git a/test/cases/ast/generic ast.c b/test/cases/ast/generic ast.c index 98399759..298d5193 100644 --- a/test/cases/ast/generic ast.c +++ b/test/cases/ast/generic ast.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + variable: 'int' name: x init: @@ -29,7 +44,7 @@ variable: 'int' variable: 'double' name: z init: - implicit_cast: (int_to_float) 'double' (value: 32) + implicit cast: (int_to_float) 'double' (value: 32) generic_expr: 'int' controlling: int_literal: 'int' (value: 5) diff --git a/test/cases/ast/native half type.c b/test/cases/ast/native half type.c index 7da35e33..8725fdf0 100644 --- a/test/cases/ast/native half type.c +++ b/test/cases/ast/native half type.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + fn_def: 'fn () void' name: foo body: @@ -5,13 +20,13 @@ fn_def: 'fn () void' variable: '__fp16' name: x init: - implicit_cast: (float_cast) '__fp16' (value: 1) + implicit cast: (float_cast) '__fp16' (value: 1) float_literal: 'float' (value: 1) variable: '__fp16' name: y init: - implicit_cast: (float_cast) '__fp16' (value: 2) + implicit cast: (float_cast) '__fp16' (value: 2) float_literal: 'float' (value: 2) assign_expr: '__fp16' @@ -21,13 +36,13 @@ fn_def: 'fn () void' rhs: add_expr: '__fp16' lhs: - implicit_cast: (lval_to_rval) '__fp16' + implicit cast: (lval_to_rval) '__fp16' decl_ref_expr: '__fp16' lvalue name: x rhs: - implicit_cast: (lval_to_rval) '__fp16' + implicit cast: (lval_to_rval) '__fp16' decl_ref_expr: '__fp16' lvalue name: y - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/promotion edge cases.c b/test/cases/ast/promotion edge cases.c index dee039e0..430e31b6 100644 --- a/test/cases/ast/promotion edge cases.c +++ b/test/cases/ast/promotion edge cases.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + struct_decl: 'struct S' record_field: 'unsigned int' name: x @@ -16,7 +31,7 @@ fn_def: 'fn () void' variable: 'char' name: c init: - implicit_cast: (int_cast) 'char' (value: 0) + implicit cast: (int_cast) 'char' (value: 0) int_literal: 'int' (value: 0) variable: 'double' @@ -31,13 +46,13 @@ fn_def: 'fn () void' rhs: add_expr: 'double' lhs: - implicit_cast: (lval_to_rval) 'double' + implicit cast: (lval_to_rval) 'double' decl_ref_expr: 'double' lvalue name: d rhs: - implicit_cast: (int_to_float) 'double' - implicit_cast: (int_cast) 'int' - implicit_cast: (lval_to_rval) 'char' + implicit cast: (int_to_float) 'double' + implicit cast: (int_cast) 'int' + implicit cast: (lval_to_rval) 'char' decl_ref_expr: 'char' lvalue name: c @@ -54,8 +69,8 @@ fn_def: 'fn () void' init: add_expr: 'int' lhs: - implicit_cast: (int_cast) 'int' - implicit_cast: (lval_to_rval) 'unsigned int' + implicit cast: (int_cast) 'int' + implicit cast: (lval_to_rval) 'unsigned int' member_access_expr: 'unsigned int' lvalue bitfield lhs: decl_ref_expr: 'struct S' lvalue @@ -69,8 +84,8 @@ fn_def: 'fn () void' init: add_expr: 'int' lhs: - implicit_cast: (int_cast) 'int' - implicit_cast: (lval_to_rval) 'long' + implicit cast: (int_cast) 'int' + implicit cast: (lval_to_rval) 'long' member_access_expr: 'long' lvalue bitfield lhs: decl_ref_expr: 'struct S' lvalue @@ -82,7 +97,7 @@ fn_def: 'fn () void' variable: '__fp16' name: fp16 init: - implicit_cast: (float_cast) '__fp16' (value: 0) + implicit cast: (float_cast) '__fp16' (value: 0) float_literal: 'float' (value: 0) assign_expr: '__fp16' @@ -90,18 +105,18 @@ fn_def: 'fn () void' decl_ref_expr: '__fp16' lvalue name: fp16 rhs: - implicit_cast: (float_cast) '__fp16' + implicit cast: (float_cast) '__fp16' add_expr: 'float' lhs: - implicit_cast: (float_cast) 'float' - implicit_cast: (lval_to_rval) '__fp16' + implicit cast: (float_cast) 'float' + implicit cast: (lval_to_rval) '__fp16' decl_ref_expr: '__fp16' lvalue name: fp16 rhs: - implicit_cast: (float_cast) 'float' - implicit_cast: (lval_to_rval) '__fp16' + implicit cast: (float_cast) 'float' + implicit cast: (lval_to_rval) '__fp16' decl_ref_expr: '__fp16' lvalue name: fp16 - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/stdckdint_ast.c b/test/cases/ast/stdckdint_ast.c index 2df8d4eb..ac54ce63 100644 --- a/test/cases/ast/stdckdint_ast.c +++ b/test/cases/ast/stdckdint_ast.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + fn_def: 'fn () void' name: foo body: @@ -5,13 +20,13 @@ fn_def: 'fn () void' variable: 'char' name: x init: - implicit_cast: (int_cast) 'char' (value: 0) + implicit cast: (int_cast) 'char' (value: 0) int_literal: 'int' (value: 0) variable: 'unsigned int' name: y init: - implicit_cast: (int_cast) 'unsigned int' (value: 2) + implicit cast: (int_cast) 'unsigned int' (value: 2) int_literal: 'int' (value: 2) variable: '_Bool' @@ -28,10 +43,10 @@ fn_def: 'fn () void' builtin_call_expr: '_Bool' name: __builtin_add_overflow args: - implicit_cast: (lval_to_rval) 'char' + implicit cast: (lval_to_rval) 'char' decl_ref_expr: 'char' lvalue name: x - implicit_cast: (lval_to_rval) 'unsigned int' + implicit cast: (lval_to_rval) 'unsigned int' decl_ref_expr: 'unsigned int' lvalue name: y addr_of_expr: '*long' (value: &res) @@ -47,10 +62,10 @@ fn_def: 'fn () void' builtin_call_expr: '_Bool' name: __builtin_sub_overflow args: - implicit_cast: (lval_to_rval) 'char' + implicit cast: (lval_to_rval) 'char' decl_ref_expr: 'char' lvalue name: x - implicit_cast: (lval_to_rval) 'unsigned int' + implicit cast: (lval_to_rval) 'unsigned int' decl_ref_expr: 'unsigned int' lvalue name: y addr_of_expr: '*long' (value: &res) @@ -66,10 +81,10 @@ fn_def: 'fn () void' builtin_call_expr: '_Bool' name: __builtin_mul_overflow args: - implicit_cast: (lval_to_rval) 'char' + implicit cast: (lval_to_rval) 'char' decl_ref_expr: 'char' lvalue name: x - implicit_cast: (lval_to_rval) 'unsigned int' + implicit cast: (lval_to_rval) 'unsigned int' decl_ref_expr: 'unsigned int' lvalue name: y addr_of_expr: '*long' (value: &res) @@ -77,5 +92,5 @@ fn_def: 'fn () void' decl_ref_expr: 'long' lvalue name: res - implicit_return: 'void' + implicit implicit_return: 'void' diff --git a/test/cases/ast/typeof_unqual.c b/test/cases/ast/typeof_unqual.c index 873ee175..476aa217 100644 --- a/test/cases/ast/typeof_unqual.c +++ b/test/cases/ast/typeof_unqual.c @@ -1,3 +1,21 @@ +implicit typedef: 'unsigned char' + name: char8_t + +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + variable: 'const int' name: a diff --git a/test/cases/ast/types.c b/test/cases/ast/types.c index 35818d42..314736bd 100644 --- a/test/cases/ast/types.c +++ b/test/cases/ast/types.c @@ -1,7 +1,25 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + +implicit typedef: 'long double' + name: __float80 + variable: 'attributed(int)' attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex.null, .requested = 4 } attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex.null, .requested = 4 } - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(0), .requested = 16 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(6), .requested = 16 } name: a variable: 'const volatile int' @@ -50,7 +68,7 @@ fn_def: 'fn (a: *d[2]const int, b: *d[2]const int) void' decl_ref_expr: 'I': '*d[2]const int' lvalue name: b rhs: - implicit_cast: (int_to_pointer) 'I': '*d[2]const int' + implicit cast: (int_to_pointer) 'I': '*d[2]const int' int_literal: 'int' (value: 1) add_assign_expr: 'I': '*d[2]const int' @@ -58,23 +76,23 @@ fn_def: 'fn (a: *d[2]const int, b: *d[2]const int) void' decl_ref_expr: 'I': '*d[2]const int' lvalue name: a rhs: - implicit_cast: (int_to_pointer) 'I': '*d[2]const int' + implicit cast: (int_to_pointer) 'I': '*d[2]const int' int_literal: 'int' (value: 1) - implicit_return: 'void' + implicit implicit_return: 'void' enum_decl: 'enum E: unsigned int' enum_field: 'int' (value: 2) name: D init: - implicit_cast: (int_cast) 'int' - explicit_cast: (int_cast) 'char' (value: 2) + implicit cast: (int_cast) 'int' + cast: (int_cast) 'char' (value: 2) int_literal: 'int' (value: 2) enum_field: 'int' (value: 3) name: E init: - implicit_cast: (int_cast) 'int' - explicit_cast: (int_cast) 'long' (value: 3) + implicit cast: (int_cast) 'int' + cast: (int_cast) 'long' (value: 3) int_literal: 'int' (value: 3) diff --git a/test/cases/ast/vectors.c b/test/cases/ast/vectors.c index a9f5fdc6..d217b910 100644 --- a/test/cases/ast/vectors.c +++ b/test/cases/ast/vectors.c @@ -1,3 +1,18 @@ +implicit typedef: '__int128' + name: __int128_t + +implicit typedef: 'unsigned __int128' + name: __uint128_t + +implicit typedef: '*char' + name: __builtin_ms_va_list + +implicit typedef: '[1]struct __va_list_tag' + name: __builtin_va_list + +implicit typedef: 'struct __NSConstantString_tag' + name: __NSConstantString + variable: 'float' name: invalid2 @@ -19,7 +34,7 @@ fn_def: 'fn () void' decl_ref_expr: 'f2v': 'vector(2, float)' lvalue name: a rhs: - implicit_cast: (lval_to_rval) 'f2v': 'vector(2, float)' + implicit cast: (lval_to_rval) 'f2v': 'vector(2, float)' decl_ref_expr: 'f2v': 'vector(2, float)' lvalue name: b @@ -28,9 +43,9 @@ fn_def: 'fn () void' decl_ref_expr: 'f2v': 'vector(2, float)' lvalue name: a rhs: - implicit_cast: (vector_splat) 'float' - implicit_cast: (int_to_float) 'float' (value: 2) + implicit cast: (vector_splat) 'float' + implicit cast: (int_to_float) 'float' (value: 2) int_literal: 'int' (value: 2) - implicit_return: 'void' + implicit implicit_return: 'void' From 5e926fff751cd2105a91247b75f5d92322fcef1a Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 1 Jan 2025 22:06:33 +0200 Subject: [PATCH 3/5] Tree: merge implicit_return and return_stmt --- src/aro/CodeGen.zig | 36 ++++++----- src/aro/Parser.zig | 10 ++-- src/aro/Tree.zig | 73 ++++++++++++++--------- test/cases/ast/_Float16.c | 6 +- test/cases/ast/__float80.c | 2 +- test/cases/ast/attributed record fields.c | 2 +- test/cases/ast/c23 auto.c | 7 ++- test/cases/ast/c23 true false ast.c | 3 + test/cases/ast/cast kinds.c | 5 +- test/cases/ast/complex init.c | 4 +- test/cases/ast/decayed attributed array.c | 13 ++-- test/cases/ast/float eval method.c | 2 +- test/cases/ast/for decl stmt.c | 5 +- test/cases/ast/forever stmt.c | 5 +- test/cases/ast/generic ast.c | 3 + test/cases/ast/native half type.c | 5 +- test/cases/ast/promotion edge cases.c | 5 +- test/cases/ast/stdckdint_ast.c | 5 +- test/cases/ast/typeof_unqual.c | 3 + test/cases/ast/types.c | 2 +- test/cases/ast/vectors.c | 5 +- test/cases/attributed record fields.c | 1 + test/cases/c23 auto.c | 2 +- test/cases/c23 true false ast.c | 2 +- test/cases/cast kinds.c | 2 +- test/cases/complex init.c | 1 + test/cases/decayed attributed array.c | 1 + test/cases/for decl stmt.c | 1 + test/cases/forever stmt.c | 1 + test/cases/generic ast.c | 1 + test/cases/native half type.c | 2 +- test/cases/promotion edge cases.c | 1 + test/cases/stdckdint_ast.c | 1 + test/cases/typeof_unqual.c | 2 +- test/cases/vectors.c | 7 ++- test/runner.zig | 3 +- 36 files changed, 149 insertions(+), 80 deletions(-) diff --git a/src/aro/CodeGen.zig b/src/aro/CodeGen.zig index 28f6cfdd..f78a23e8 100644 --- a/src/aro/CodeGen.zig +++ b/src/aro/CodeGen.zig @@ -464,19 +464,23 @@ fn genExpr(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref { .continue_stmt => try c.builder.addJump(c.continue_label), .break_stmt => try c.builder.addJump(c.break_label), .return_stmt => |@"return"| { - if (@"return".expr) |expr| { - const operand = try c.genExpr(expr); - try c.ret_nodes.append(c.comp.gpa, .{ .value = operand, .label = c.builder.current_label }); + switch (@"return".operand) { + .expr => |expr| { + const operand = try c.genExpr(expr); + try c.ret_nodes.append(c.comp.gpa, .{ .value = operand, .label = c.builder.current_label }); + }, + .none => {}, + .implicit => |zeroes| { + if (zeroes) { + const operand = try c.builder.addConstant(.zero, try c.genType(@"return".return_type)); + try c.ret_nodes.append(c.comp.gpa, .{ .value = operand, .label = c.builder.current_label }); + } + // No need to emit a jump since an implicit return_stmt is always the last statement. + return .none; + }, } try c.builder.addJump(c.return_label); }, - .implicit_return => |implicit_return| { - if (implicit_return.zero) { - const operand = try c.builder.addConstant(.zero, try c.genType(implicit_return.return_type)); - try c.ret_nodes.append(c.comp.gpa, .{ .value = operand, .label = c.builder.current_label }); - } - // No need to emit a jump since implicit_return is always the last instruction. - }, .goto_stmt, .computed_goto_stmt, .nullptr_literal, @@ -560,7 +564,7 @@ fn genExpr(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref { .addr_of_expr => |un| return try c.genLval(un.operand), .deref_expr => |un| { const operand_node = un.operand.get(c.tree); - if (operand_node == .implicit_cast and operand_node.implicit_cast.kind == .function_to_pointer) { + if (operand_node == .cast and operand_node.cast.kind == .function_to_pointer) { return c.genExpr(un.operand); } const operand = try c.genLval(un.operand); @@ -615,7 +619,7 @@ fn genExpr(c: *CodeGen, node_index: Node.Index) Error!Ir.Ref { }, .paren_expr => |un| return c.genExpr(un.operand), .decl_ref_expr => unreachable, // Lval expression. - .explicit_cast, .implicit_cast => |cast| switch (cast.kind) { + .cast => |cast| switch (cast.kind) { .no_op => return c.genExpr(cast.operand), .to_void => { _ = try c.genExpr(cast.operand); @@ -984,7 +988,7 @@ fn genBoolExpr(c: *CodeGen, base: Node.Index, true_label: Ir.Ref, false_label: I if (c.cond_dummy_ty != null) c.cond_dummy_ref = cmp; return c.addBranch(cmp, true_label, false_label); }, - .explicit_cast, .implicit_cast => |cast| switch (cast.kind) { + .cast => |cast| switch (cast.kind) { .bool_to_int => { const operand = try c.genExpr(cast.operand); if (c.cond_dummy_ty != null) c.cond_dummy_ref = operand; @@ -1062,14 +1066,14 @@ fn genCall(c: *CodeGen, call: Node.Call) Error!Ir.Ref { // Detect direct calls. const fn_ref = blk: { const callee = call.callee.get(c.tree); - if (callee != .implicit_cast or callee.implicit_cast.kind != .function_to_pointer) { + if (callee != .cast or callee.cast.kind != .function_to_pointer) { break :blk try c.genExpr(call.callee); } - var cur = callee.implicit_cast.operand; + var cur = callee.cast.operand; while (true) switch (cur.get(c.tree)) { .paren_expr, .addr_of_expr, .deref_expr => |un| cur = un.operand, - .implicit_cast => |cast| { + .cast => |cast| { if (cast.kind != .function_to_pointer) { break :blk try c.genExpr(call.callee); } diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index f19a3039..649fe039 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -4739,10 +4739,10 @@ fn compoundStmt(p: *Parser, is_fn_body: bool, stmt_expr_state: ?*StmtExprState) try p.errStr(.func_does_not_return, p.tok_i - 1, func_name); } } - const implicit_ret = try p.addNode(.{ .implicit_return = .{ - .r_brace_tok = r_brace, + const implicit_ret = try p.addNode(.{ .return_stmt = .{ + .return_tok = r_brace, .return_type = ret_ty, - .zero = return_zero, + .operand = .{ .implicit = return_zero }, } }); try p.decl_buf.append(implicit_ret); } @@ -4910,7 +4910,7 @@ fn returnStmt(p: *Parser) Error!?Node.Index { return try p.addNode(.{ .return_stmt = .{ .return_tok = ret_tok, - .expr = if (ret_expr) |some| some.node else null, + .operand = if (ret_expr) |some| .{ .expr = some.node } else .none, .return_type = ret_ty, } }); } @@ -9080,7 +9080,7 @@ test "Node locations" { defer tree.deinit(); try std.testing.expectEqual(0, comp.diagnostics.list.items.len); - for (tree.root_decls.items, 0..) |node, i| { + for (tree.root_decls.items[tree.root_decls.items.len - 3 ..], 0..) |node, i| { const slice = tree.tokSlice(node.tok(&tree)); const expected = switch (i) { 0 => "foo", diff --git a/src/aro/Tree.zig b/src/aro/Tree.zig index 2ca03682..adc9b59d 100644 --- a/src/aro/Tree.zig +++ b/src/aro/Tree.zig @@ -334,14 +334,12 @@ pub const Node = union(enum) { return_stmt: struct { return_tok: TokenIndex, return_type: Type, - expr: ?Node.Index, - }, - /// Inserted at the end of a function body if no return stmt is found. - implicit_return: struct { - r_brace_tok: TokenIndex, - return_type: Type, - /// True if the function is called "main" and return_type is compatible with int - zero: bool, + operand: union(enum) { + expr: Node.Index, + /// True if the function is called "main" and return_type is compatible with int + implicit: bool, + none, + }, }, gnu_asm_simple: SimpleAsm, @@ -959,14 +957,25 @@ pub const Node = union(enum) { .return_stmt = .{ .return_tok = node_tok, .return_type = tree.type_map.keys()[node_data[0]], - .expr = unpackOptIndex(node_data[1]), + .operand = .{ + .expr = @enumFromInt(node_data[1]), + }, + }, + }, + .return_none_stmt => .{ + .return_stmt = .{ + .return_tok = node_tok, + .return_type = tree.type_map.keys()[node_data[0]], + .operand = .none, }, }, .implicit_return => .{ - .implicit_return = .{ - .r_brace_tok = node_tok, + .return_stmt = .{ + .return_tok = node_tok, .return_type = tree.type_map.keys()[node_data[0]], - .zero = node_data[1] != 0, + .operand = .{ + .implicit = node_data[1] != 0, + }, }, }, .gnu_asm_simple => .{ @@ -1698,6 +1707,7 @@ pub const Node = union(enum) { break_stmt, null_stmt, return_stmt, + return_none_stmt, implicit_return, gnu_asm_simple, comma_expr, @@ -1814,11 +1824,11 @@ pub const Node = union(enum) { pub fn isImplicit(node: Node) bool { return switch (node) { - .implicit_return, .array_filler_expr, .default_init_expr, .cond_dummy_expr, => true, + .return_stmt => |ret| ret.operand == .implicit, .cast => |cast| cast.implicit, .variable => |info| info.implicit, .typedef => |info| info.implicit, @@ -2065,17 +2075,22 @@ pub fn setNode(tree: *Tree, node: Node, index: usize) !void { repr.tok = @"null".semicolon_or_r_brace_tok; }, .return_stmt => |@"return"| { - repr.tag = .return_stmt; repr.data[0] = try tree.addType(@"return".return_type); - repr.data[1] = packOptIndex(@"return".expr); + switch (@"return".operand) { + .expr => |expr| { + repr.tag = .return_stmt; + repr.data[1] = @intFromEnum(expr); + }, + .none => { + repr.tag = .return_none_stmt; + }, + .implicit => |zeroes| { + repr.tag = .implicit_return; + repr.data[1] = @intFromBool(zeroes); + }, + } repr.tok = @"return".return_tok; }, - .implicit_return => |implicit_return| { - repr.tag = .implicit_return; - repr.data[0] = try tree.addType(implicit_return.return_type); - repr.data[1] = @intFromBool(implicit_return.zero); - repr.tok = implicit_return.r_brace_tok; - }, .gnu_asm_simple => |gnu_asm_simple| { repr.tag = .gnu_asm_simple; repr.data[0] = @intFromEnum(gnu_asm_simple.asm_str); @@ -2899,7 +2914,7 @@ fn dumpNode( }; try w.writeByte(')'); } - if (node == .implicit_return and node.implicit_return.zero) { + if (node == .return_stmt and node.return_stmt.operand == .implicit and node.return_stmt.operand.implicit) { try config.setColor(w, IMPLICIT); try w.writeAll(" (value: 0)"); try config.setColor(w, .reset); @@ -3254,12 +3269,16 @@ fn dumpNode( try w.writeAll("expr:\n"); try tree.dumpNode(goto.expr, level + delta, mapper, config, w); }, - .continue_stmt, .break_stmt, .implicit_return, .null_stmt => {}, + .continue_stmt, .break_stmt, .null_stmt => {}, .return_stmt => |ret| { - if (ret.expr) |some| { - try w.writeByteNTimes(' ', level + half); - try w.writeAll("expr:\n"); - try tree.dumpNode(some, level + delta, mapper, config, w); + switch (ret.operand) { + .expr => |expr| { + try w.writeByteNTimes(' ', level + half); + try w.writeAll("expr:\n"); + try tree.dumpNode(expr, level + delta, mapper, config, w); + }, + .implicit => {}, + .none => {}, } }, .call_expr => |call| { diff --git a/test/cases/ast/_Float16.c b/test/cases/ast/_Float16.c index 5e788cb9..5d86aee8 100644 --- a/test/cases/ast/_Float16.c +++ b/test/cases/ast/_Float16.c @@ -61,7 +61,7 @@ fn_def: 'fn (x: int, ...) void' decl_ref_expr: 'va_list': '[1]struct __va_list_tag' lvalue name: va - implicit implicit_return: 'void' + implicit return_stmt: 'void' fn_def: 'fn () void' name: quux @@ -83,7 +83,7 @@ fn_def: 'fn () void' decl_ref_expr: '_Float16' lvalue name: f - implicit implicit_return: 'void' + implicit return_stmt: 'void' fn_def: 'fn () void' name: conversions @@ -136,5 +136,5 @@ fn_def: 'fn () void' decl_ref_expr: '__fp16' lvalue name: fp16 - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/__float80.c b/test/cases/ast/__float80.c index efb90b04..9f64d75d 100644 --- a/test/cases/ast/__float80.c +++ b/test/cases/ast/__float80.c @@ -53,5 +53,5 @@ fn_def: 'fn () void' operand: float_literal: 'long double' - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/attributed record fields.c b/test/cases/ast/attributed record fields.c index 7f856a4d..bdd48871 100644 --- a/test/cases/ast/attributed record fields.c +++ b/test/cases/ast/attributed record fields.c @@ -7,7 +7,7 @@ implicit typedef: 'unsigned __int128' implicit typedef: '*char' name: __builtin_ms_va_list -implicit typedef: '[1]struct __va_list_tag' +implicit typedef: '*char' name: __builtin_va_list implicit typedef: 'struct __NSConstantString_tag' diff --git a/test/cases/ast/c23 auto.c b/test/cases/ast/c23 auto.c index 4be51389..0d977ee4 100644 --- a/test/cases/ast/c23 auto.c +++ b/test/cases/ast/c23 auto.c @@ -16,6 +16,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + fn_def: 'fn () void' name: bad body: @@ -38,7 +41,7 @@ fn_def: 'fn () void' init: int_literal: 'int' (value: 3) - implicit implicit_return: 'void' + implicit return_stmt: 'void' fn_def: 'fn () void' name: good @@ -62,5 +65,5 @@ fn_def: 'fn () void' decl_ref_expr: 'fn () void' lvalue name: good - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/c23 true false ast.c b/test/cases/ast/c23 true false ast.c index ef0f1922..2c4e0f12 100644 --- a/test/cases/ast/c23 true false ast.c +++ b/test/cases/ast/c23 true false ast.c @@ -16,6 +16,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + variable: 'bool' name: a init: diff --git a/test/cases/ast/cast kinds.c b/test/cases/ast/cast kinds.c index 8d38c359..db840d3a 100644 --- a/test/cases/ast/cast kinds.c +++ b/test/cases/ast/cast kinds.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + union_decl: 'union U' record_field: 'int' name: x @@ -240,5 +243,5 @@ fn_def: 'fn () void' decl_ref_expr: 'float' lvalue name: f - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/complex init.c b/test/cases/ast/complex init.c index 23f3e859..74e4a87a 100644 --- a/test/cases/ast/complex init.c +++ b/test/cases/ast/complex init.c @@ -7,7 +7,7 @@ implicit typedef: 'unsigned __int128' implicit typedef: '*char' name: __builtin_ms_va_list -implicit typedef: '[1]struct __va_list_tag' +implicit typedef: '*char' name: __builtin_va_list implicit typedef: 'struct __NSConstantString_tag' @@ -83,5 +83,5 @@ fn_def: 'fn () void' implicit cast: (float_cast) 'float' (value: 2) float_literal: 'double' (value: 2) - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/decayed attributed array.c b/test/cases/ast/decayed attributed array.c index 29c2f0ad..cf908aa2 100644 --- a/test/cases/ast/decayed attributed array.c +++ b/test/cases/ast/decayed attributed array.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + variable: 'attributed([1]int)' attr: aligned alignment: null name: arr @@ -34,7 +37,7 @@ fn_def: 'fn () void' body: compound_stmt: 'void' variable: 'attributed([64]char)' - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(14), .requested = 8 } name: x variable: '*char' @@ -45,15 +48,15 @@ fn_def: 'fn () void' array_access_expr: 'char' lvalue base: implicit cast: (array_to_pointer) '*d:attributed([64]char)' - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(14), .requested = 8 } paren_expr: 'attributed([64]char)' lvalue - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(14), .requested = 8 } operand: decl_ref_expr: 'attributed([64]char)' lvalue - attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(13), .requested = 8 } + attr: aligned alignment: aro.Attribute.Alignment{ .node = aro.Tree.Node.OptIndex(14), .requested = 8 } name: x index: int_literal: 'int' (value: 0) - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/float eval method.c b/test/cases/ast/float eval method.c index 0b5dd870..ee3ef19e 100644 --- a/test/cases/ast/float eval method.c +++ b/test/cases/ast/float eval method.c @@ -71,5 +71,5 @@ fn_def: 'fn () void' decl_ref_expr: 'float' lvalue name: a - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/for decl stmt.c b/test/cases/ast/for decl stmt.c index 63a64151..7e441264 100644 --- a/test/cases/ast/for decl stmt.c +++ b/test/cases/ast/for decl stmt.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + fn_def: 'fn () int' name: main body: @@ -37,5 +40,5 @@ fn_def: 'fn () int' body: null_stmt: 'void' - implicit implicit_return: 'int' + implicit return_stmt: 'int' diff --git a/test/cases/ast/forever stmt.c b/test/cases/ast/forever stmt.c index 29f582dd..2674fa94 100644 --- a/test/cases/ast/forever stmt.c +++ b/test/cases/ast/forever stmt.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + fn_def: 'fn () int' name: main body: @@ -22,5 +25,5 @@ fn_def: 'fn () int' body: null_stmt: 'void' - implicit implicit_return: 'int' + implicit return_stmt: 'int' diff --git a/test/cases/ast/generic ast.c b/test/cases/ast/generic ast.c index 298d5193..e4e1c8d8 100644 --- a/test/cases/ast/generic ast.c +++ b/test/cases/ast/generic ast.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + variable: 'int' name: x init: diff --git a/test/cases/ast/native half type.c b/test/cases/ast/native half type.c index 8725fdf0..6271203d 100644 --- a/test/cases/ast/native half type.c +++ b/test/cases/ast/native half type.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + fn_def: 'fn () void' name: foo body: @@ -44,5 +47,5 @@ fn_def: 'fn () void' decl_ref_expr: '__fp16' lvalue name: y - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/promotion edge cases.c b/test/cases/ast/promotion edge cases.c index 430e31b6..63282b7a 100644 --- a/test/cases/ast/promotion edge cases.c +++ b/test/cases/ast/promotion edge cases.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + struct_decl: 'struct S' record_field: 'unsigned int' name: x @@ -118,5 +121,5 @@ fn_def: 'fn () void' decl_ref_expr: '__fp16' lvalue name: fp16 - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/stdckdint_ast.c b/test/cases/ast/stdckdint_ast.c index ac54ce63..9fad2483 100644 --- a/test/cases/ast/stdckdint_ast.c +++ b/test/cases/ast/stdckdint_ast.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + fn_def: 'fn () void' name: foo body: @@ -92,5 +95,5 @@ fn_def: 'fn () void' decl_ref_expr: 'long' lvalue name: res - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/ast/typeof_unqual.c b/test/cases/ast/typeof_unqual.c index 476aa217..be58fcd4 100644 --- a/test/cases/ast/typeof_unqual.c +++ b/test/cases/ast/typeof_unqual.c @@ -16,6 +16,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + variable: 'const int' name: a diff --git a/test/cases/ast/types.c b/test/cases/ast/types.c index 314736bd..82413762 100644 --- a/test/cases/ast/types.c +++ b/test/cases/ast/types.c @@ -79,7 +79,7 @@ fn_def: 'fn (a: *d[2]const int, b: *d[2]const int) void' implicit cast: (int_to_pointer) 'I': '*d[2]const int' int_literal: 'int' (value: 1) - implicit implicit_return: 'void' + implicit return_stmt: 'void' enum_decl: 'enum E: unsigned int' enum_field: 'int' (value: 2) diff --git a/test/cases/ast/vectors.c b/test/cases/ast/vectors.c index d217b910..c3a02a33 100644 --- a/test/cases/ast/vectors.c +++ b/test/cases/ast/vectors.c @@ -13,6 +13,9 @@ implicit typedef: '[1]struct __va_list_tag' implicit typedef: 'struct __NSConstantString_tag' name: __NSConstantString +implicit typedef: 'long double' + name: __float80 + variable: 'float' name: invalid2 @@ -47,5 +50,5 @@ fn_def: 'fn () void' implicit cast: (int_to_float) 'float' (value: 2) int_literal: 'int' (value: 2) - implicit implicit_return: 'void' + implicit return_stmt: 'void' diff --git a/test/cases/attributed record fields.c b/test/cases/attributed record fields.c index 3ee38c1e..ea1e34d4 100644 --- a/test/cases/attributed record fields.c +++ b/test/cases/attributed record fields.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-windows-msvc struct S1 {}; struct S2 { diff --git a/test/cases/c23 auto.c b/test/cases/c23 auto.c index 24508f73..214b69c6 100644 --- a/test/cases/c23 auto.c +++ b/test/cases/c23 auto.c @@ -1,4 +1,4 @@ -//aro-args -std=c23 +//aro-args -std=c23 --target=x86_64-linux-gnu auto a(); void bad() { diff --git a/test/cases/c23 true false ast.c b/test/cases/c23 true false ast.c index 60933a1a..2404e505 100644 --- a/test/cases/c23 true false ast.c +++ b/test/cases/c23 true false ast.c @@ -1,4 +1,4 @@ -//aro-args -std=c23 +//aro-args -std=c23 --target=x86_64-linux-gnu bool a = true; bool b = false; bool c = 0; diff --git a/test/cases/cast kinds.c b/test/cases/cast kinds.c index fb306a6a..724f15e9 100644 --- a/test/cases/cast kinds.c +++ b/test/cases/cast kinds.c @@ -1,4 +1,4 @@ -//aro-args -Wno-int-conversion +//aro-args -Wno-int-conversion --target=x86_64-linux-gnu union U { int x; float y; diff --git a/test/cases/complex init.c b/test/cases/complex init.c index 013d1e73..2f825a82 100644 --- a/test/cases/complex init.c +++ b/test/cases/complex init.c @@ -1,3 +1,4 @@ +//aro-args --target=aarch64-macos-musl void foo(void) { _Complex double cd = { 1.0, 2.0 }; _Complex float cf = { 1.0f, 2.0f }; diff --git a/test/cases/decayed attributed array.c b/test/cases/decayed attributed array.c index 8b21370f..22b0e285 100644 --- a/test/cases/decayed attributed array.c +++ b/test/cases/decayed attributed array.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-linux-gnu __attribute__((aligned)) int arr[1] = {0}; int *ptr = arr; diff --git a/test/cases/for decl stmt.c b/test/cases/for decl stmt.c index 15c4c2db..f8279c69 100644 --- a/test/cases/for decl stmt.c +++ b/test/cases/for decl stmt.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-linux-gnu int main(void) { for (int x=0, y=1; ; x++); } diff --git a/test/cases/forever stmt.c b/test/cases/forever stmt.c index 66e8fa17..2b31471d 100644 --- a/test/cases/forever stmt.c +++ b/test/cases/forever stmt.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-linux-gnu int main(void) { for (;;); } diff --git a/test/cases/generic ast.c b/test/cases/generic ast.c index 1cfb857b..10bf6997 100644 --- a/test/cases/generic ast.c +++ b/test/cases/generic ast.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-linux-gnu int x = _Generic(5, int: 42, double: 32.5 diff --git a/test/cases/native half type.c b/test/cases/native half type.c index 31aa2a4b..b9a85c4a 100644 --- a/test/cases/native half type.c +++ b/test/cases/native half type.c @@ -1,4 +1,4 @@ -//aro-args -fnative-half-type +//aro-args -fnative-half-type --target=x86_64-linux-gnu void foo(void) { __fp16 x = 1.0f; __fp16 y = 2.0f; diff --git a/test/cases/promotion edge cases.c b/test/cases/promotion edge cases.c index 05c70be8..7458127f 100644 --- a/test/cases/promotion edge cases.c +++ b/test/cases/promotion edge cases.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-linux-gnu struct S { unsigned x: 3; long y: 5; diff --git a/test/cases/stdckdint_ast.c b/test/cases/stdckdint_ast.c index fb0160e6..330d37b8 100644 --- a/test/cases/stdckdint_ast.c +++ b/test/cases/stdckdint_ast.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-linux-gnu #include void foo(void) { diff --git a/test/cases/typeof_unqual.c b/test/cases/typeof_unqual.c index 406f3f99..ed9f2e72 100644 --- a/test/cases/typeof_unqual.c +++ b/test/cases/typeof_unqual.c @@ -1,4 +1,4 @@ -//aro-args -std=c23 +//aro-args -std=c23 --target=x86_64-linux-gnu const int a; typeof(a) b; typeof_unqual(a) c; diff --git a/test/cases/vectors.c b/test/cases/vectors.c index c262c518..7f3401f4 100644 --- a/test/cases/vectors.c +++ b/test/cases/vectors.c @@ -1,3 +1,4 @@ +//aro-args --target=x86_64-linux-gnu typedef float *invalid1 __attribute__((vector_size(8))); typedef float invalid2 __attribute__((vector_size(9))); typedef float f2v __attribute__((vector_size(8))); @@ -9,6 +10,6 @@ void foo(void) { (f2v)1; } -#define EXPECTED_ERRORS "vectors.c:1:40: error: invalid vector element type 'float *'" \ - "vectors.c:2:39: error: vector size not an integral multiple of component size" \ - "vectors.c:9:5: error: cannot cast to non arithmetic or pointer type '__attribute__((__vector_size__(2 * sizeof(float)))) float (vector of 2 'float' values)'" \ +#define EXPECTED_ERRORS "vectors.c:2:40: error: invalid vector element type 'float *'" \ + "vectors.c:3:39: error: vector size not an integral multiple of component size" \ + "vectors.c:10:5: error: cannot cast to non arithmetic or pointer type '__attribute__((__vector_size__(2 * sizeof(float)))) float (vector of 2 'float' values)'" \ diff --git a/test/runner.zig b/test/runner.zig index 37f70b4d..e2f827ac 100644 --- a/test/runner.zig +++ b/test/runner.zig @@ -622,7 +622,8 @@ const StmtTypeDumper = struct { } fn dumpNode(self: *StmtTypeDumper, tree: *const aro.Tree, mapper: aro.TypeMapper, node: Node.Index, m: *MsgWriter) AllocatorError!void { - if (node.get(tree) == .implicit_return) return; + const maybe_ret = node.get(tree); + if (maybe_ret == .return_stmt and maybe_ret.return_stmt.operand == .implicit) return; const ty = node.type(tree); ty.dump(mapper, tree.comp.langopts, m.buf.writer()) catch {}; const owned = try m.buf.toOwnedSlice(); From 58af450197df117a7e81cb893204567550107c54 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 1 Jan 2025 23:57:38 +0200 Subject: [PATCH 4/5] Parser: reserve empty_decl instead of null_stmt for decls --- src/aro/CodeGen.zig | 1 + src/aro/Parser.zig | 18 ++++++++---------- src/aro/Tree.zig | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/aro/CodeGen.zig b/src/aro/CodeGen.zig index f78a23e8..3ce4d87b 100644 --- a/src/aro/CodeGen.zig +++ b/src/aro/CodeGen.zig @@ -86,6 +86,7 @@ pub fn genIr(tree: *const Tree) Compilation.Error!Ir { c.builder.arena = std.heap.ArenaAllocator.init(gpa); switch (decl.get(c.tree)) { + .empty_decl, .static_assert, .typedef, .struct_decl, diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 649fe039..9d9f5f29 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -795,6 +795,10 @@ pub fn parse(pp: *Preprocessor) Compilation.Error!Tree { } if (p.eatToken(.semicolon)) |tok| { try p.errTok(.extra_semi, tok); + const empty = try p.tree.addNode(.{ .empty_decl = .{ + .semicolon = tok, + } }); + try p.decl_buf.append(empty); continue; } try p.err(.expected_external_decl); @@ -984,9 +988,8 @@ fn decl(p: *Parser) Error!bool { try p.attr_buf.append(p.gpa, .{ .attr = attr, .tok = tok }); } - var decl_node = try p.tree.addNode(.{ .null_stmt = .{ - .semicolon_or_r_brace_tok = first_tok, - .type = Type.invalid, + var decl_node = try p.tree.addNode(.{ .empty_decl = .{ + .semicolon = first_tok, } }); var init_d = (try p.initDeclarator(&decl_spec, attr_buf_top, decl_node)) orelse { _ = try p.expectToken(.semicolon); @@ -1010,10 +1013,6 @@ fn decl(p: *Parser) Error!bool { return true; } - if (p.tree.nodes.len == @intFromEnum(decl_node)) { - p.tree.nodes.len -= 1; - } - try p.errTok(.missing_declaration, first_tok); return true; }; @@ -1256,9 +1255,8 @@ fn decl(p: *Parser) Error!bool { } } - decl_node = try p.tree.addNode(.{ .null_stmt = .{ - .semicolon_or_r_brace_tok = first_tok, - .type = Type.invalid, + decl_node = try p.tree.addNode(.{ .empty_decl = .{ + .semicolon = p.tok_i - 1, } }); init_d = (try p.initDeclarator(&decl_spec, attr_buf_top, decl_node)) orelse { try p.err(.expected_ident_or_l_paren); diff --git a/src/aro/Tree.zig b/src/aro/Tree.zig index adc9b59d..e2f86235 100644 --- a/src/aro/Tree.zig +++ b/src/aro/Tree.zig @@ -223,6 +223,9 @@ pub const GNUAssemblyQualifiers = struct { }; pub const Node = union(enum) { + empty_decl: struct { + semicolon: TokenIndex, + }, static_assert: struct { assert_tok: TokenIndex, cond: Node.Index, @@ -691,6 +694,11 @@ pub const Node = union(enum) { const node_tok = tree.nodes.items(.tok)[@intFromEnum(index)]; const node_data = &tree.nodes.items(.data)[@intFromEnum(index)]; return switch (tree.nodes.items(.tag)[@intFromEnum(index)]) { + .empty_decl => .{ + .empty_decl = .{ + .semicolon = node_tok, + }, + }, .static_assert => .{ .static_assert = .{ .assert_tok = node_tok, @@ -1672,6 +1680,7 @@ pub const Node = union(enum) { }; pub const Tag = enum(u8) { + empty_decl, static_assert, fn_proto, fn_def, @@ -1796,6 +1805,7 @@ pub const Node = union(enum) { pub fn isTyped(tag: Tag) bool { return switch (tag) { + .empty_decl, .static_assert, .compound_stmt, .compound_stmt_three, @@ -1846,6 +1856,10 @@ pub fn addNode(tree: *Tree, node: Node) !Node.Index { pub fn setNode(tree: *Tree, node: Node, index: usize) !void { var repr: Node.Repr = undefined; switch (node) { + .empty_decl => |empty| { + repr.tag = .empty_decl; + repr.tok = empty.semicolon; + }, .static_assert => |assert| { repr.tag = .static_assert; repr.data[0] = @intFromEnum(assert.cond); @@ -2936,6 +2950,7 @@ fn dumpNode( } switch (node) { + .empty_decl => {}, .global_asm, .gnu_asm_simple => |@"asm"| { try w.writeByteNTimes(' ', level + 1); try tree.dumpNode(@"asm".asm_str, level + delta, mapper, config, w); From 5d722ec80890a2d0b43ab52a512d33a479f9c10e Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 2 Jan 2025 00:26:56 +0200 Subject: [PATCH 5/5] Tree: do not define Node field types inline --- src/aro/CodeGen.zig | 6 +- src/aro/Parser.zig | 4 +- src/aro/Tree.zig | 537 +++++++++++++++++++++++++------------------- 3 files changed, 308 insertions(+), 239 deletions(-) diff --git a/src/aro/CodeGen.zig b/src/aro/CodeGen.zig index 3ce4d87b..9989689b 100644 --- a/src/aro/CodeGen.zig +++ b/src/aro/CodeGen.zig @@ -1115,7 +1115,7 @@ fn genCall(c: *CodeGen, call: Node.Call) Error!Ir.Ref { return c.builder.addInst(.call, .{ .call = call_inst }, try c.genType(call.type)); } -fn genCompoundAssign(c: *CodeGen, bin: Node.BinaryExpr, tag: Ir.Inst.Tag) Error!Ir.Ref { +fn genCompoundAssign(c: *CodeGen, bin: Node.Binary, tag: Ir.Inst.Tag) Error!Ir.Ref { const rhs = try c.genExpr(bin.rhs); const lhs = try c.genLval(bin.lhs); const res = try c.addBin(tag, lhs, rhs, bin.type); @@ -1123,13 +1123,13 @@ fn genCompoundAssign(c: *CodeGen, bin: Node.BinaryExpr, tag: Ir.Inst.Tag) Error! return res; } -fn genBinOp(c: *CodeGen, bin: Node.BinaryExpr, tag: Ir.Inst.Tag) Error!Ir.Ref { +fn genBinOp(c: *CodeGen, bin: Node.Binary, tag: Ir.Inst.Tag) Error!Ir.Ref { const lhs = try c.genExpr(bin.lhs); const rhs = try c.genExpr(bin.rhs); return c.addBin(tag, lhs, rhs, bin.type); } -fn genComparison(c: *CodeGen, bin: Node.BinaryExpr, tag: Ir.Inst.Tag) Error!Ir.Ref { +fn genComparison(c: *CodeGen, bin: Node.Binary, tag: Ir.Inst.Tag) Error!Ir.Ref { const lhs = try c.genExpr(bin.lhs); const rhs = try c.genExpr(bin.rhs); diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 9d9f5f29..9e76dc89 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -5234,7 +5234,7 @@ pub const Result = struct { } fn bin(lhs: *Result, p: *Parser, rt_tag: std.meta.Tag(Node), rhs: Result, tok_i: TokenIndex) !void { - const bin_data: Node.BinaryExpr = .{ + const bin_data: Node.Binary = .{ .op_tok = tok_i, .lhs = lhs.node, .rhs = rhs.node, @@ -5257,7 +5257,7 @@ pub const Result = struct { } fn un(operand: *Result, p: *Parser, rt_tag: std.meta.Tag(Node), tok_i: TokenIndex) Error!void { - const un_data: Node.UnaryExpr = .{ + const un_data: Node.Unary = .{ .op_tok = tok_i, .operand = operand.node, .type = operand.ty, diff --git a/src/aro/Tree.zig b/src/aro/Tree.zig index e2f86235..24c19825 100644 --- a/src/aro/Tree.zig +++ b/src/aro/Tree.zig @@ -223,30 +223,13 @@ pub const GNUAssemblyQualifiers = struct { }; pub const Node = union(enum) { - empty_decl: struct { - semicolon: TokenIndex, - }, - static_assert: struct { - assert_tok: TokenIndex, - cond: Node.Index, - message: ?Node.Index, - }, - fn_proto: struct { - name_tok: TokenIndex, - type: Type, - static: bool, - @"inline": bool, - /// The definition for this prototype if one exists. - definition: ?Node.Index, - }, + empty_decl: EmptyDecl, + static_assert: StaticAssert, + fn_proto: FnProto, fn_def: FnDef, param: Param, variable: Variable, - typedef: struct { - name_tok: TokenIndex, - type: Type, - implicit: bool, - }, + typedef: Typedef, global_asm: SimpleAsm, struct_decl: ContainerDecl, @@ -256,166 +239,89 @@ pub const Node = union(enum) { union_forward_decl: ContainerForwardDecl, enum_forward_decl: ContainerForwardDecl, - enum_field: struct { - name_tok: TokenIndex, - type: Type, - init: ?Node.Index, - }, - record_field: struct { - name_or_first_tok: TokenIndex, - type: Type, - bit_width: ?Node.Index, - }, - - labeled_stmt: struct { - label_tok: TokenIndex, - body: Node.Index, - type: Type, - }, - compound_stmt: struct { - l_brace_tok: TokenIndex, - body: []const Node.Index, - }, - if_stmt: struct { - if_tok: TokenIndex, - cond: Node.Index, - then_body: Node.Index, - else_body: ?Node.Index, - }, - switch_stmt: struct { - switch_tok: TokenIndex, - cond: Node.Index, - body: Node.Index, - }, - case_stmt: struct { - case_tok: TokenIndex, - start: Node.Index, - end: ?Node.Index, - body: Node.Index, - }, - default_stmt: struct { - default_tok: TokenIndex, - body: Node.Index, - }, - while_stmt: struct { - while_tok: TokenIndex, - cond: Node.Index, - body: Node.Index, - }, - do_while_stmt: struct { - do_tok: TokenIndex, - cond: Node.Index, - body: Node.Index, - }, - for_stmt: struct { - for_tok: TokenIndex, - init: union(enum) { - decls: []const Node.Index, - expr: ?Node.Index, - }, - cond: ?Node.Index, - incr: ?Node.Index, - body: Node.Index, - }, - goto_stmt: struct { - label_tok: TokenIndex, - }, - computed_goto_stmt: struct { - goto_tok: TokenIndex, - expr: Node.Index, - }, - continue_stmt: struct { - continue_tok: TokenIndex, - }, - break_stmt: struct { - break_tok: TokenIndex, - }, - null_stmt: struct { - semicolon_or_r_brace_tok: TokenIndex, - type: Type, - }, - return_stmt: struct { - return_tok: TokenIndex, - return_type: Type, - operand: union(enum) { - expr: Node.Index, - /// True if the function is called "main" and return_type is compatible with int - implicit: bool, - none, - }, - }, + enum_field: EnumField, + record_field: RecordField, + + labeled_stmt: LabeledStmt, + compound_stmt: CompoundStmt, + if_stmt: IfStmt, + switch_stmt: SwitchStmt, + case_stmt: CaseStmt, + default_stmt: DefaultStmt, + while_stmt: WhileStmt, + do_while_stmt: DoWhileStmt, + for_stmt: ForStmt, + goto_stmt: GotoStmt, + computed_goto_stmt: CompoutedGotoStmt, + continue_stmt: ContinueStmt, + break_stmt: BreakStmt, + null_stmt: NullStmt, + return_stmt: ReturnStmt, gnu_asm_simple: SimpleAsm, - comma_expr: BinaryExpr, - assign_expr: BinaryExpr, - mul_assign_expr: BinaryExpr, - div_assign_expr: BinaryExpr, - mod_assign_expr: BinaryExpr, - add_assign_expr: BinaryExpr, - sub_assign_expr: BinaryExpr, - shl_assign_expr: BinaryExpr, - shr_assign_expr: BinaryExpr, - bit_and_assign_expr: BinaryExpr, - bit_xor_assign_expr: BinaryExpr, - bit_or_assign_expr: BinaryExpr, - bool_or_expr: BinaryExpr, - bool_and_expr: BinaryExpr, - bit_or_expr: BinaryExpr, - bit_xor_expr: BinaryExpr, - bit_and_expr: BinaryExpr, - equal_expr: BinaryExpr, - not_equal_expr: BinaryExpr, - less_than_expr: BinaryExpr, - less_than_equal_expr: BinaryExpr, - greater_than_expr: BinaryExpr, - greater_than_equal_expr: BinaryExpr, - shl_expr: BinaryExpr, - shr_expr: BinaryExpr, - add_expr: BinaryExpr, - sub_expr: BinaryExpr, - mul_expr: BinaryExpr, - div_expr: BinaryExpr, - mod_expr: BinaryExpr, + comma_expr: Binary, + assign_expr: Binary, + mul_assign_expr: Binary, + div_assign_expr: Binary, + mod_assign_expr: Binary, + add_assign_expr: Binary, + sub_assign_expr: Binary, + shl_assign_expr: Binary, + shr_assign_expr: Binary, + bit_and_assign_expr: Binary, + bit_xor_assign_expr: Binary, + bit_or_assign_expr: Binary, + bool_or_expr: Binary, + bool_and_expr: Binary, + bit_or_expr: Binary, + bit_xor_expr: Binary, + bit_and_expr: Binary, + equal_expr: Binary, + not_equal_expr: Binary, + less_than_expr: Binary, + less_than_equal_expr: Binary, + greater_than_expr: Binary, + greater_than_equal_expr: Binary, + shl_expr: Binary, + shr_expr: Binary, + add_expr: Binary, + sub_expr: Binary, + mul_expr: Binary, + div_expr: Binary, + mod_expr: Binary, cast: Cast, - addr_of_expr: UnaryExpr, - deref_expr: UnaryExpr, - plus_expr: UnaryExpr, - negate_expr: UnaryExpr, - bit_not_expr: UnaryExpr, - bool_not_expr: UnaryExpr, - pre_inc_expr: UnaryExpr, - pre_dec_expr: UnaryExpr, - imag_expr: UnaryExpr, - real_expr: UnaryExpr, - post_inc_expr: UnaryExpr, - post_dec_expr: UnaryExpr, - paren_expr: UnaryExpr, - stmt_expr: UnaryExpr, - - addr_of_label: struct { - label_tok: TokenIndex, - type: Type, - }, - - array_access_expr: struct { - l_bracket_tok: TokenIndex, - type: Type, - base: Node.Index, - index: Node.Index, - }, - call_expr: Call, - builtin_call_expr: struct { - builtin_tok: TokenIndex, - type: Type, - args: []const Node.Index, - }, + addr_of_expr: Unary, + deref_expr: Unary, + plus_expr: Unary, + negate_expr: Unary, + bit_not_expr: Unary, + bool_not_expr: Unary, + pre_inc_expr: Unary, + pre_dec_expr: Unary, + imag_expr: Unary, + real_expr: Unary, + post_inc_expr: Unary, + post_dec_expr: Unary, + paren_expr: Unary, + stmt_expr: Unary, + + addr_of_label: AddrOfLabel, + + array_access_expr: ArrayAccess, member_access_expr: MemberAccess, member_access_ptr_expr: MemberAccess, + + call_expr: Call, + decl_ref_expr: DeclRef, enumeration_ref: DeclRef, - builtin_ref: NoDeclRef, + + builtin_call_expr: BuiltinCall, + builtin_ref: BuiltinRef, + builtin_types_compatible_p: TypesCompatible, + builtin_choose_expr: Conditional, /// C23 bool literal `true` / `false` bool_literal: Literal, @@ -428,72 +334,50 @@ pub const Node = union(enum) { /// a floating point literal float_literal: Literal, string_literal_expr: Literal, - /// wraps a float or double literal: un - imaginary_literal: UnaryExpr, + /// wraps a float or double literal + imaginary_literal: Unary, + /// A compound literal (type){ init } + compound_literal_expr: CompoundLiteral, sizeof_expr: TypeInfo, alignof_expr: TypeInfo, - generic_expr: struct { - generic_tok: TokenIndex, - type: Type, - controlling: Node.Index, - chosen: Node.Index, - rest: []const Node.Index, - }, - generic_association_expr: struct { - colon_tok: TokenIndex, - association_type: Type, - expr: Node.Index, - }, - generic_default_expr: struct { - default_tok: TokenIndex, - expr: Node.Index, - }, + generic_expr: Generic, + generic_association_expr: Generic.Association, + generic_default_expr: Generic.Default, binary_cond_expr: Conditional, /// Used as the base for casts of the lhs in `binary_cond_expr`. - cond_dummy_expr: UnaryExpr, + cond_dummy_expr: Unary, cond_expr: Conditional, - builtin_choose_expr: Conditional, - builtin_types_compatible_p: struct { - builtin_tok: TokenIndex, - lhs: Type, - rhs: Type, - }, array_init_expr: ContainerInit, struct_init_expr: ContainerInit, - union_init_expr: struct { - l_brace_tok: TokenIndex, - union_type: Type, - field_index: u32, - initializer: ?Node.Index, - }, + union_init_expr: UnionInit, /// Inserted in array_init_expr to represent unspecified elements. /// data.int contains the amount of elements. - array_filler_expr: struct { - last_tok: TokenIndex, - type: Type, - count: u64, - }, + array_filler_expr: ArrayFiller, /// Inserted in record and scalar initializers for unspecified elements. - default_init_expr: struct { - last_tok: TokenIndex, - type: Type, - }, + default_init_expr: DefaultInit, - compound_literal_expr: struct { - l_paren_tok: TokenIndex, + pub const EmptyDecl = struct { + semicolon: TokenIndex, + }; + + pub const StaticAssert = struct { + assert_tok: TokenIndex, + cond: Node.Index, + message: ?Node.Index, + }; + + pub const FnProto = struct { + name_tok: TokenIndex, type: Type, - thread_local: bool, - storage_class: enum { - auto, - static, - register, - }, - initializer: Node.Index, - }, + static: bool, + @"inline": bool, + /// The definition for this prototype if one exists. + definition: ?Node.Index, + }; pub const FnDef = struct { name_tok: TokenIndex, @@ -528,6 +412,12 @@ pub const Node = union(enum) { initializer: ?Node.Index, }; + pub const Typedef = struct { + name_tok: TokenIndex, + type: Type, + implicit: bool, + }; + pub const SimpleAsm = struct { asm_tok: TokenIndex, asm_str: Node.Index, @@ -546,7 +436,111 @@ pub const Node = union(enum) { definition: ?Node.Index, }; - pub const BinaryExpr = struct { + pub const EnumField = struct { + name_tok: TokenIndex, + type: Type, + init: ?Node.Index, + }; + + pub const RecordField = struct { + name_or_first_tok: TokenIndex, + type: Type, + bit_width: ?Node.Index, + }; + + pub const LabeledStmt = struct { + label_tok: TokenIndex, + body: Node.Index, + type: Type, + }; + + pub const CompoundStmt = struct { + l_brace_tok: TokenIndex, + body: []const Node.Index, + }; + + pub const IfStmt = struct { + if_tok: TokenIndex, + cond: Node.Index, + then_body: Node.Index, + else_body: ?Node.Index, + }; + + pub const SwitchStmt = struct { + switch_tok: TokenIndex, + cond: Node.Index, + body: Node.Index, + }; + + pub const CaseStmt = struct { + case_tok: TokenIndex, + start: Node.Index, + end: ?Node.Index, + body: Node.Index, + }; + + pub const DefaultStmt = struct { + default_tok: TokenIndex, + body: Node.Index, + }; + + pub const WhileStmt = struct { + while_tok: TokenIndex, + cond: Node.Index, + body: Node.Index, + }; + + pub const DoWhileStmt = struct { + do_tok: TokenIndex, + cond: Node.Index, + body: Node.Index, + }; + + pub const ForStmt = struct { + for_tok: TokenIndex, + init: union(enum) { + decls: []const Node.Index, + expr: ?Node.Index, + }, + cond: ?Node.Index, + incr: ?Node.Index, + body: Node.Index, + }; + + pub const GotoStmt = struct { + label_tok: TokenIndex, + }; + + pub const CompoutedGotoStmt = struct { + goto_tok: TokenIndex, + expr: Node.Index, + }; + + pub const ContinueStmt = struct { + continue_tok: TokenIndex, + }; + + pub const BreakStmt = struct { + break_tok: TokenIndex, + }; + + pub const NullStmt = struct { + semicolon_or_r_brace_tok: TokenIndex, + type: Type, + }; + + pub const ReturnStmt = struct { + return_tok: TokenIndex, + return_type: Type, + operand: union(enum) { + expr: Node.Index, + /// True if the function is called "main" and return_type is compatible with int + implicit: bool, + none, + }, + }; + + pub const Binary = struct { type: Type, lhs: Node.Index, op_tok: TokenIndex, @@ -623,17 +617,22 @@ pub const Node = union(enum) { }; }; - pub const UnaryExpr = struct { + pub const Unary = struct { type: Type, op_tok: TokenIndex, operand: Node.Index, }; - pub const Call = struct { - l_paren_tok: TokenIndex, + pub const AddrOfLabel = struct { + label_tok: TokenIndex, type: Type, - callee: Node.Index, - args: []const Node.Index, + }; + + pub const ArrayAccess = struct { + l_bracket_tok: TokenIndex, + type: Type, + base: Node.Index, + index: Node.Index, }; pub const MemberAccess = struct { @@ -651,17 +650,80 @@ pub const Node = union(enum) { } }; + pub const Call = struct { + l_paren_tok: TokenIndex, + type: Type, + callee: Node.Index, + args: []const Node.Index, + }; + pub const DeclRef = struct { name_tok: TokenIndex, type: Type, decl: Node.Index, }; - pub const NoDeclRef = struct { + pub const BuiltinCall = struct { + builtin_tok: TokenIndex, + type: Type, + args: []const Node.Index, + }; + + pub const BuiltinRef = struct { name_tok: TokenIndex, type: Type, }; + pub const TypesCompatible = struct { + builtin_tok: TokenIndex, + lhs: Type, + rhs: Type, + }; + + pub const Literal = struct { + literal_tok: TokenIndex, + type: Type, + }; + + pub const CompoundLiteral = struct { + l_paren_tok: TokenIndex, + type: Type, + thread_local: bool, + storage_class: enum { + auto, + static, + register, + }, + initializer: Node.Index, + }; + + pub const TypeInfo = struct { + type: Type, + op_tok: TokenIndex, + expr: ?Node.Index, + }; + + pub const Generic = struct { + generic_tok: TokenIndex, + type: Type, + + // `Generic` child nodes are either an `Association` a `Default` + controlling: Node.Index, + chosen: Node.Index, + rest: []const Node.Index, + + pub const Association = struct { + colon_tok: TokenIndex, + association_type: Type, + expr: Node.Index, + }; + + pub const Default = struct { + default_tok: TokenIndex, + expr: Node.Index, + }; + }; + pub const Conditional = struct { cond_tok: TokenIndex, type: Type, @@ -676,15 +738,22 @@ pub const Node = union(enum) { items: []const Node.Index, }; - pub const Literal = struct { - literal_tok: TokenIndex, + pub const UnionInit = struct { + l_brace_tok: TokenIndex, + union_type: Type, + field_index: u32, + initializer: ?Node.Index, + }; + + pub const ArrayFiller = struct { + last_tok: TokenIndex, type: Type, + count: u64, }; - pub const TypeInfo = struct { + pub const DefaultInit = struct { + last_tok: TokenIndex, type: Type, - op_tok: TokenIndex, - expr: ?Node.Index, }; pub const Index = enum(u32) {