diff --git a/src/Compilation.zig b/src/Compilation.zig index 89c047065c..b3ee73f03f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1334,7 +1334,7 @@ pub fn update(self: *Compilation) !void { self.c_object_work_queue.writeItemAssumeCapacity(entry.key); } - const use_stage1 = build_options.is_stage1 and self.bin_file.options.use_llvm; + const use_stage1 = build_options.omit_stage2 or build_options.is_stage1 and self.bin_file.options.use_llvm; if (!use_stage1) { if (self.bin_file.options.module) |module| { module.compile_log_text.shrinkAndFree(module.gpa, 0); diff --git a/src/translate_c.zig b/src/translate_c.zig index 894502ecc5..ce8fea7a71 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -1689,7 +1689,10 @@ fn transStringLiteralAsArray( init_list[i] = try transCreateNodeNumber(c, 0, .int); } - return Tag.array_init.create(c.arena, init_list); + return Tag.array_init.create(c.arena, .{ + .cond = arr_type, + .cases = init_list, + }); } fn cIsEnum(qt: clang.QualType) bool { @@ -1880,6 +1883,7 @@ fn transInitListExprArray( ) TransError!Node { const arr_type = ty.getAsArrayTypeUnsafe(); const child_qt = arr_type.getElementType(); + const child_type = try transQualType(c, child_qt, loc); const init_count = expr.getNumInits(); assert(@ptrCast(*const clang.Type, arr_type).isConstantArrayType()); const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, arr_type); @@ -1888,18 +1892,20 @@ fn transInitListExprArray( const leftover_count = all_count - init_count; if (all_count == 0) { - return Tag.empty_array.create(c.arena, try transQualType(c, child_qt, loc)); + return Tag.empty_array.create(c.arena, child_type); } - const ty_node = try transType(c, ty, loc); const init_node = if (init_count != 0) blk: { const init_list = try c.arena.alloc(Node, init_count); for (init_list) |*init, i| { const elem_expr = expr.getInit(@intCast(c_uint, i)); - init.* = try transExpr(c, scope, elem_expr, .used); + init.* = try transExprCoercing(c, scope, elem_expr, .used); } - const init_node = try Tag.array_init.create(c.arena, init_list); + const init_node = try Tag.array_init.create(c.arena, .{ + .cond = try Tag.array_type.create(c.arena, .{ .len = init_count, .elem_type = child_type }), + .cases = init_list, + }); if (leftover_count == 0) { return init_node; } @@ -1908,8 +1914,8 @@ fn transInitListExprArray( const filler_val_expr = expr.getArrayFiller(); const filler_node = try Tag.array_filler.create(c.arena, .{ - .type = ty_node, - .filler = try transExpr(c, scope, filler_val_expr, .used), + .type = child_type, + .filler = try transExprCoercing(c, scope, filler_val_expr, .used), .count = leftover_count, }); @@ -2422,9 +2428,7 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re const decl = @ptrCast(*const clang.NamedDecl, member_decl); break :blk try c.str(decl.getName_bytes_begin()); }; - const ident = try Tag.identifier.create(c.arena, name); - - const node = try Tag.field_access.create(c.arena, .{ .lhs = container_node, .rhs = ident }); + const node = try Tag.field_access.create(c.arena, .{ .lhs = container_node, .field_name = name }); return maybeSuppressResult(c, scope, result_used, node); } @@ -2698,14 +2702,14 @@ fn transCreatePreCrement( defer block_scope.deinit(); const ref = try block_scope.makeMangledName(c, "ref"); - const expr = try transExpr(c, scope, op_expr, .used); + const expr = try transExpr(c, &block_scope.base, op_expr, .used); const addr_of = try Tag.address_of.create(c.arena, expr); const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of }); try block_scope.statements.append(ref_decl); const lhs_node = try Tag.identifier.create(c.arena, ref); const ref_node = try Tag.deref.create(c.arena, lhs_node); - const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used); + const node = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, Tag.one_literal.init(), .used); try block_scope.statements.append(node); const break_node = try Tag.break_val.create(c.arena, .{ @@ -2745,7 +2749,7 @@ fn transCreatePostCrement( defer block_scope.deinit(); const ref = try block_scope.makeMangledName(c, "ref"); - const expr = try transExpr(c, scope, op_expr, .used); + const expr = try transExpr(c, &block_scope.base, op_expr, .used); const addr_of = try Tag.address_of.create(c.arena, expr); const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of }); try block_scope.statements.append(ref_decl); @@ -2757,7 +2761,7 @@ fn transCreatePostCrement( const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node }); try block_scope.statements.append(tmp_decl); - const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used); + const node = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, Tag.one_literal.init(), .used); try block_scope.statements.append(node); const break_node = try Tag.break_val.create(c.arena, .{ @@ -2864,7 +2868,7 @@ fn transCreateCompoundAssign( defer block_scope.deinit(); const ref = try block_scope.makeMangledName(c, "ref"); - const expr = try transExpr(c, scope, lhs, .used); + const expr = try transExpr(c, &block_scope.base, lhs, .used); const addr_of = try Tag.address_of.create(c.arena, expr); const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of }); try block_scope.statements.append(ref_decl); @@ -2873,16 +2877,16 @@ fn transCreateCompoundAssign( const ref_node = try Tag.deref.create(c.arena, lhs_node); if ((is_mod or is_div) and is_signed) { - const rhs_node = try transExpr(c, scope, rhs, .used); + const rhs_node = try transExpr(c, &block_scope.base, rhs, .used); const builtin = if (is_mod) try Tag.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node }) else try Tag.div_trunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node }); - const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used); + const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs_node, builtin, .used); try block_scope.statements.append(assign); } else { - var rhs_node = try transExpr(c, scope, rhs, .used); + var rhs_node = try transExpr(c, &block_scope.base, rhs, .used); if (is_shift or requires_int_cast) { // @intCast(rhs) @@ -2894,7 +2898,7 @@ fn transCreateCompoundAssign( rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); } - const assign = try transCreateNodeInfixOp(c, scope, op, ref_node, rhs_node, .used); + const assign = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, rhs_node, .used); try block_scope.statements.append(assign); } @@ -3395,7 +3399,7 @@ fn transCreateNodeAssign( defer block_scope.deinit(); const tmp = try block_scope.makeMangledName(c, "tmp"); - const rhs_node = try transExpr(c, scope, rhs, .used); + const rhs_node = try transExpr(c, &block_scope.base, rhs, .used); const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = rhs_node }); try block_scope.statements.append(tmp_decl); @@ -4756,8 +4760,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { return error.ParseError; } - const ident = try Tag.identifier.create(c.arena, m.slice()); - node = try Tag.field_access.create(c.arena, .{ .lhs = node, .rhs = ident }); + node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() }); }, .Arrow => { if (m.next().? != .Identifier) { @@ -4766,8 +4769,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { } const deref = try Tag.deref.create(c.arena, node); - const ident = try Tag.identifier.create(c.arena, m.slice()); - node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident }); + node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() }); }, .LBracket => { const index = try macroBoolToInt(c, try parseCExpr(c, m, scope)); @@ -4914,13 +4916,12 @@ fn getContainer(c: *Context, node: Node) ?Node { }, .field_access => { - const infix = node.castTag(.field_access).?; + const field_access = node.castTag(.field_access).?; - if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| { + if (getContainerTypeOf(c, field_access.data.lhs)) |ty_node| { if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| { for (container.data.fields) |field| { - const ident = infix.data.rhs.castTag(.identifier).?; - if (mem.eql(u8, field.name, ident.data)) { + if (mem.eql(u8, field.name, field_access.data.field_name)) { return getContainer(c, field.type); } } @@ -4940,12 +4941,11 @@ fn getContainerTypeOf(c: *Context, ref: Node) ?Node { return getContainer(c, var_decl.data.type); } } - } else if (ref.castTag(.field_access)) |infix| { - if (getContainerTypeOf(c, infix.data.lhs)) |ty_node| { + } else if (ref.castTag(.field_access)) |field_access| { + if (getContainerTypeOf(c, field_access.data.lhs)) |ty_node| { if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| { for (container.data.fields) |field| { - const ident = infix.data.rhs.castTag(.identifier).?; - if (mem.eql(u8, field.name, ident.data)) { + if (mem.eql(u8, field.name, field_access.data.field_name)) { return getContainer(c, field.type); } } diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index d108a2852e..014236e002 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -291,7 +291,6 @@ pub const Node = extern union { .array_cat, .ellipsis3, .switch_prong, - .field_access, .assign, .align_cast, .array_access, @@ -309,7 +308,7 @@ pub const Node = extern union { => Payload.Value, .@"if" => Payload.If, .@"while" => Payload.While, - .@"switch" => Payload.Switch, + .@"switch", .array_init => Payload.Switch, .@"break" => Payload.Break, .break_val => Payload.BreakVal, .call => Payload.Call, @@ -317,7 +316,7 @@ pub const Node = extern union { .func => Payload.Func, .@"enum" => Payload.Enum, .@"struct", .@"union" => Payload.Record, - .array_init, .tuple => Payload.ArrayInit, + .tuple => Payload.TupleInit, .container_init => Payload.ContainerInit, .std_meta_cast => Payload.Infix, .block => Payload.Block, @@ -329,6 +328,7 @@ pub const Node = extern union { .enum_redecl => Payload.EnumRedecl, .array_filler => Payload.ArrayFiller, .pub_inline_fn => Payload.PubInlineFn, + .field_access => Payload.FieldAccess, }; } @@ -513,7 +513,7 @@ pub const Payload = struct { }; }; - pub const ArrayInit = struct { + pub const TupleInit = struct { base: Payload, data: []Node, }; @@ -601,6 +601,14 @@ pub const Payload = struct { body: Node, }, }; + + pub const FieldAccess = struct { + base: Payload, + data: struct { + lhs: Node, + field_name: []const u8, + }, + }; }; /// Converts the nodes into a Zig ast. @@ -995,6 +1003,32 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { }); }, .var_decl => return renderVar(c, node), + .arg_redecl, .alias => { + const payload = @fieldParentPtr(Payload.ArgRedecl, "base", node.ptr_otherwise).data; + if (node.tag() == .alias) _ = try c.addToken(.keyword_pub, "pub"); + const mut_tok = if (node.tag() == .alias) + try c.addToken(.keyword_const, "const") + else + try c.addToken(.keyword_var, "var"); + _ = try c.addIdentifier(payload.actual); + _ = try c.addToken(.equal, "="); + + const init = try c.addNode(.{ + .tag = .identifier, + .main_token = try c.addIdentifier(payload.mangled), + .data = undefined, + }); + _ = try c.addToken(.semicolon, ";"); + + return c.addNode(.{ + .tag = .simple_var_decl, + .main_token = mut_tok, + .data = .{ + .lhs = 0, + .rhs = init, + }, + }); + }, .int_cast => { const payload = node.castTag(.int_cast).?.data; return renderBuiltinCall(c, "@intCast", &.{ payload.lhs, payload.rhs }); @@ -1339,7 +1373,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { _ = try c.addToken(.l_paren, "("); const cond = try c.addNode(.{ .tag = .bool_not, - .main_token = try c.addToken(.bang, "!"), + .main_token = try c.addToken(.bang, "!"), .data = .{ .lhs = try renderNodeGrouped(c, payload), .rhs = undefined, @@ -1430,7 +1464,77 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { }, }); }, - else => return c.addNode(.{ + .array_access => { + const payload = node.castTag(.array_access).?.data; + const lhs = try renderNode(c, payload.lhs); + const l_bracket = try c.addToken(.l_bracket, "["); + const index_expr = try renderNode(c, payload.rhs); + _ = try c.addToken(.r_bracket, "]"); + return c.addNode(.{ + .tag = .array_access, + .main_token = l_bracket, + .data = .{ + .lhs = lhs, + .rhs = index_expr, + }, + }); + }, + .array_type => { + const payload = node.castTag(.array_type).?.data; + return renderArrayType(c, payload.len, payload.elem_type); + }, + .array_filler => { + const payload = node.castTag(.array_filler).?.data; + + const type_expr = try renderArrayType(c, 1, payload.type); + const l_brace = try c.addToken(.l_brace, "{"); + const val = try renderNode(c, payload.filler); + _ = try c.addToken(.r_brace, "}"); + + const init = try c.addNode(.{ + .tag = .array_init_one, + .main_token = l_brace, + .data = .{ + .lhs = type_expr, + .rhs = val, + }, + }); + return c.addNode(.{ + .tag = .array_cat, + .main_token = try c.addToken(.asterisk_asterisk, "**"), + .data = .{ + .lhs = init, + .rhs = try c.addNode(.{ + .tag = .integer_literal, + .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{payload.count}), + .data = .{ .lhs = undefined, .rhs = undefined }, + }), + }, + }); + }, + .empty_array => { + const payload = node.castTag(.empty_array).?.data; + + const type_expr = try renderArrayType(c, 0, payload); + return renderArrayInit(c, 0, &.{}); + }, + .array_init => { + const payload = node.castTag(.array_init).?.data; + const type_expr = try renderNode(c, payload.cond); + return renderArrayInit(c, type_expr, payload.cases); + }, + .field_access => { + const payload = node.castTag(.field_access).?.data; + const lhs = try renderNode(c, payload.lhs); + return renderFieldAccess(c, lhs, payload.field_name); + }, + .tuple, + .@"enum", + .@"struct", + .@"union", + .container_init, + .enum_redecl, + => return c.addNode(.{ .tag = .identifier, .main_token = try c.addTokenFmt(.identifier, "@\"TODO {}\"", .{node.tag()}), .data = .{ @@ -1441,10 +1545,88 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { } } +fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeIndex { + return c.addNode(.{ + .tag = .field_access, + .main_token = try c.addToken(.period, "."), + .data = .{ + .lhs = lhs, + .rhs = try c.addIdentifier(field_name), + }, + }); +} + +fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex { + const l_brace = try c.addToken(.l_brace, "{"); + const res = switch (inits.len) { + 0 => try c.addNode(.{ + .tag = .struct_init_one, + .main_token = l_brace, + .data = .{ + .lhs = lhs, + .rhs = 0, + }, + }), + 1 => blk: { + const init = try renderNode(c, inits[0]); + break :blk try c.addNode(.{ + .tag = .array_init_one, + .main_token = l_brace, + .data = .{ + .lhs = lhs, + .rhs = init, + }, + }); + }, + else => blk: { + var rendered = try c.gpa.alloc(NodeIndex, inits.len); + defer c.gpa.free(rendered); + + for (inits) |init, i| { + if (i != 0) _ = try c.addToken(.comma, ","); + rendered[i] = try renderNode(c, init); + } + const span = try c.listToSpan(rendered); + break :blk try c.addNode(.{ + .tag = .array_init, + .main_token = l_brace, + .data = .{ + .lhs = lhs, + .rhs = try c.addExtra(NodeSubRange{ + .start = span.start, + .end = span.end, + }), + }, + }); + }, + }; + _ = try c.addToken(.r_brace, "}"); + return res; +} + +fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex { + const l_bracket = try c.addToken(.l_bracket, "["); + const len_expr = try c.addNode(.{ + .tag = .integer_literal, + .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{len}), + .data = .{ .lhs = undefined, .rhs = undefined }, + }); + _ = try c.addToken(.r_bracket, "]"); + const elem_type_expr = try renderNode(c, elem_type); + return c.addNode(.{ + .tag = .array_type, + .main_token = l_bracket, + .data = .{ + .lhs = len_expr, + .rhs = elem_type_expr, + }, + }); +} + fn addSemicolonIfNeeded(c: *Context, node: Node) !void { switch (node.tag()) { .warning => unreachable, - .var_decl, .var_simple, .block, .empty_block, .@"switch" => {}, + .var_decl, .var_simple, .arg_redecl, .alias, .enum_redecl, .block, .empty_block, .@"switch" => {}, .while_true => { const payload = node.castTag(.while_true).?.data; return addSemicolonIfNeeded(c, payload); @@ -1517,6 +1699,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { .negate, .negate_wrap, .bit_not, + .func, => { // no grouping needed return renderNode(c, node); @@ -1572,7 +1755,6 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { .switch_prong, .warning, .var_decl, - .func, .fail_decl, .arg_redecl, .alias, @@ -1658,22 +1840,8 @@ fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeInde }); var access_chain = import_node; - access_chain = try c.addNode(.{ - .tag = .field_access, - .main_token = try c.addToken(.period, "."), - .data = .{ - .lhs = access_chain, - .rhs = try c.addIdentifier(first), - }, - }); - access_chain = try c.addNode(.{ - .tag = .field_access, - .main_token = try c.addToken(.period, "."), - .data = .{ - .lhs = access_chain, - .rhs = try c.addIdentifier(second), - }, - }); + access_chain = try renderFieldAccess(c, access_chain, first); + access_chain = try renderFieldAccess(c, access_chain, second); return access_chain; } @@ -1974,10 +2142,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { const body = if (payload.body) |some| try renderNode(c, some) - else blk: { + else if (payload.is_extern) blk: { _ = try c.addToken(.semicolon, ";"); break :blk 0; - }; + } else return fn_proto; return c.addNode(.{ .tag = .fn_decl,