Commit c0540967e9
Changed files (3)
src
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,
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);
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);
}
}