aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2021-02-12 11:23:15 +0200
committerVeikka Tuominen <git@vexu.eu>2021-02-16 16:40:06 +0200
commit2a74a1ebaace8b5de1796b1756f65e421eb479a4 (patch)
tree94967e6c0d2016ccb370c29845e04a4150a1cd76
parent66bbd75a8346b8a292f0d95d4b60a5d7d11b73b2 (diff)
downloadzig-2a74a1ebaace8b5de1796b1756f65e421eb479a4.tar.gz
zig-2a74a1ebaace8b5de1796b1756f65e421eb479a4.zip
translate-c: bunch of small fixes to get it compiling
-rw-r--r--src/translate_c.zig1190
-rw-r--r--src/translate_c/ast.zig108
-rw-r--r--src/type.zig4
3 files changed, 647 insertions, 655 deletions
diff --git a/src/translate_c.zig b/src/translate_c.zig
index 9ef4788ba7..c7a30ff919 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -10,12 +10,13 @@ const mem = std.mem;
const math = std.math;
const ast = @import("translate_c/ast.zig");
const Node = ast.Node;
+const Tag = Node.Tag;
const CallingConvention = std.builtin.CallingConvention;
pub const ClangErrMsg = clang.Stage2ErrorMsg;
-pub const Error = error{OutOfMemory};
+pub const Error = std.mem.Allocator.Error;
const TypeError = Error || error{UnsupportedType};
const TransError = TypeError || error{UnsupportedTranslation};
@@ -30,11 +31,11 @@ const Scope = struct {
parent: ?*Scope,
const Id = enum {
- Switch,
- Block,
- Root,
- Condition,
- Loop,
+ @"switch",
+ block,
+ root,
+ condition,
+ loop,
};
/// Represents an in-progress Node.Switch. This struct is stack-allocated.
@@ -44,7 +45,6 @@ const Scope = struct {
base: Scope,
pending_block: Block,
cases: std.ArrayList(Node),
- case_index: usize,
switch_label: ?[]const u8,
default_label: ?[]const u8,
};
@@ -84,7 +84,7 @@ const Scope = struct {
fn init(c: *Context, parent: *Scope, labeled: bool) !Block {
var blk = Block{
.base = .{
- .id = .Block,
+ .id = .block,
.parent = parent,
},
.statements = std.ArrayList(Node).init(c.gpa),
@@ -105,12 +105,12 @@ const Scope = struct {
fn complete(self: *Block, c: *Context) !Node {
// We reserve 1 extra statement if the parent is a Loop. This is in case of
// do while, we want to put `if (cond) break;` at the end.
- const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop);
- const stmts = try c.arena.alloc(Node, alloc_len);
+ const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .loop);
+ var stmts = try c.arena.alloc(Node, alloc_len);
stmts.len -= 1;
mem.copy(Node, stmts, self.statements.items);
- return Node.block.create(c.arena, .{
- .lable = self.label,
+ return Tag.block.create(c.arena, .{
+ .label = self.label,
.stmts = stmts,
});
}
@@ -161,7 +161,7 @@ const Scope = struct {
fn init(c: *Context) Root {
return .{
.base = .{
- .id = .Root,
+ .id = .root,
.parent = null,
},
.sym_table = SymbolTable.init(c.gpa),
@@ -195,9 +195,9 @@ const Scope = struct {
var scope = inner;
while (true) {
switch (scope.id) {
- .Root => unreachable,
- .Block => return @fieldParentPtr(Block, "base", scope),
- .Condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c),
+ .root => unreachable,
+ .block => return @fieldParentPtr(Block, "base", scope),
+ .condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c),
else => scope = scope.parent.?,
}
}
@@ -207,8 +207,8 @@ const Scope = struct {
var scope = inner;
while (true) {
switch (scope.id) {
- .Root => unreachable,
- .Block => {
+ .root => unreachable,
+ .block => {
const block = @fieldParentPtr(Block, "base", scope);
if (block.return_type) |qt| return qt;
scope = scope.parent.?;
@@ -220,17 +220,17 @@ const Scope = struct {
fn getAlias(scope: *Scope, name: []const u8) []const u8 {
return switch (scope.id) {
- .Root => return name,
- .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
- .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
+ .root => return name,
+ .block => @fieldParentPtr(Block, "base", scope).getAlias(name),
+ .@"switch", .loop, .condition => scope.parent.?.getAlias(name),
};
}
fn contains(scope: *Scope, name: []const u8) bool {
return switch (scope.id) {
- .Root => @fieldParentPtr(Root, "base", scope).contains(name),
- .Block => @fieldParentPtr(Block, "base", scope).contains(name),
- .Switch, .Loop, .Condition => scope.parent.?.contains(name),
+ .root => @fieldParentPtr(Root, "base", scope).contains(name),
+ .block => @fieldParentPtr(Block, "base", scope).contains(name),
+ .@"switch", .loop, .condition => scope.parent.?.contains(name),
};
}
@@ -238,9 +238,9 @@ const Scope = struct {
var scope = inner;
while (true) {
switch (scope.id) {
- .Root => unreachable,
- .Switch => return scope,
- .Loop => return scope,
+ .root => unreachable,
+ .@"switch" => return scope,
+ .loop => return scope,
else => scope = scope.parent.?,
}
}
@@ -250,24 +250,24 @@ const Scope = struct {
var scope = inner;
while (true) {
switch (scope.id) {
- .Root => unreachable,
- .Switch => return @fieldParentPtr(Switch, "base", scope),
+ .root => unreachable,
+ .@"switch" => return @fieldParentPtr(Switch, "base", scope),
else => scope = scope.parent.?,
}
}
}
/// Appends a node to the first block scope if inside a function, or to the root tree if not.
- fn appendNode(scope: *Scope, node: Node) !void {
+ fn appendNode(inner: *Scope, node: Node) !void {
var scope = inner;
while (true) {
switch (scope.id) {
- .Root => {
- const root = @fieldParentPtr(Root, "base", scope).contains(name);
+ .root => {
+ const root = @fieldParentPtr(Root, "base", scope);
return root.nodes.append(node);
},
- .Block => {
- const block = @fieldParentPtr(Block, "base", scope).contains(name);
+ .block => {
+ const block = @fieldParentPtr(Block, "base", scope);
return block.statements.append(node);
},
else => scope = scope.parent.?,
@@ -321,7 +321,7 @@ pub fn translate(
args_end: [*]?[*]const u8,
errors: *[]ClangErrMsg,
resources_path: [*:0]const u8,
-) !ast.Tree {
+) !std.zig.ast.Tree {
const ast_unit = clang.LoadFromCommandLine(
args_begin,
args_end,
@@ -339,14 +339,6 @@ pub fn translate(
var arena = std.heap.ArenaAllocator.init(gpa);
errdefer arena.deinit();
- if (true) {
- var x = false;
- if (x) {
- return error.OutOfMemory;
- }
- @panic("TODO update translate-c");
- }
-
var context = Context{
.gpa = gpa,
.arena = &arena.allocator,
@@ -361,15 +353,15 @@ pub fn translate(
context.alias_list.deinit();
context.global_names.deinit(gpa);
context.opaque_demotes.deinit(gpa);
- context.global_scope.deini();
+ context.global_scope.deinit();
}
- try context.global_scope.nodes.append(try Node.usingnamespace_builtins.init());
+ try context.global_scope.nodes.append(Tag.usingnamespace_builtins.init());
try prepopulateGlobalNameTable(ast_unit, &context);
if (!ast_unit.visitLocalTopLevelDecls(&context, declVisitorC)) {
- return context.err;
+ return error.OutOfMemory;
}
try transPreprocessorEntities(&context, ast_unit);
@@ -377,16 +369,17 @@ pub fn translate(
try addMacros(&context);
for (context.alias_list.items) |alias| {
if (!context.global_scope.sym_table.contains(alias.alias)) {
- try createAlias(&context, alias);
+ const node = try Tag.alias.create(context.arena, .{ .actual = alias.alias, .mangled = alias.name });
+ try addTopLevelDecl(&context, alias.alias, node);
}
}
- return ast.render(context.global_scope.nodes.items);
+ return ast.render(gpa, context.global_scope.nodes.items);
}
fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void {
if (!ast_unit.visitLocalTopLevelDecls(c, declVisitorNamesOnlyC)) {
- return c.err;
+ return error.OutOfMemory;
}
// TODO if we see #undef, delete it from the table
@@ -409,19 +402,13 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void {
fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool {
const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
- declVisitorNamesOnly(c, decl) catch |err| {
- c.err = err;
- return false;
- };
+ declVisitorNamesOnly(c, decl) catch return false;
return true;
}
fn declVisitorC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool {
const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
- declVisitor(c, decl) catch |err| {
- c.err = err;
- return false;
- };
+ declVisitor(c, decl) catch return false;
return true;
}
@@ -454,7 +441,7 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void {
},
else => {
const decl_name = try c.str(decl.getDeclKindName());
- try warn(c, decl.getLocation(), "ignoring {s} declaration", .{decl_name});
+ try warn(c, &c.global_scope.base, decl.getLocation(), "ignoring {s} declaration", .{decl_name});
},
}
}
@@ -513,7 +500,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
decl_ctx.has_body = false;
decl_ctx.storage_class = .Extern;
decl_ctx.is_export = false;
- try warn(c, fn_decl_loc, "TODO unable to translate variadic function, demoted to declaration", .{});
+ try warn(c, &c.global_scope.base, fn_decl_loc, "TODO unable to translate variadic function, demoted to declaration", .{});
}
break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
error.UnsupportedType => {
@@ -535,7 +522,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
};
if (!decl_ctx.has_body) {
- return addTopLevelDecl(c, fn_name, &proto_node.base);
+ return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
}
// actual function definition with body
@@ -547,10 +534,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
var scope = &block_scope.base;
var param_id: c_uint = 0;
- for (proto_node.params()) |*param, i| {
- const param_name = if (param.name_token) |name_tok|
- tokenSlice(c, name_tok)
- else
+ for (proto_node.data.params) |*param, i| {
+ const param_name = param.name orelse
return failDecl(c, fn_decl_loc, fn_name, "function {s} parameter has no name", .{fn_name});
const c_param = fn_decl.getParamDecl(param_id);
@@ -565,7 +550,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
const arg_name = try block_scope.makeMangledName(c, bare_arg_name);
param.name = arg_name;
- const redecl_node = try Node.arg_redecl.create(c.arena, .{ .actual = mangled_param_name, .mangled = arg_name });
+ const redecl_node = try Tag.arg_redecl.create(c.arena, .{ .actual = mangled_param_name, .mangled = arg_name });
try block_scope.statements.append(redecl_node);
}
@@ -607,12 +592,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
error.UnsupportedType,
=> return failDecl(c, fn_decl_loc, fn_name, "unable to create a return value for function", .{}),
};
- const ret = try Node.@"return".create(c.arena, rhs);
+ const ret = try Tag.@"return".create(c.arena, rhs);
try block_scope.statements.append(ret);
}
- proto_node.body = try block_scope.complete(c);
- return addTopLevelDecl(c, fn_name, &proto_node.base);
+ proto_node.data.body = try block_scope.complete(c);
+ return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
}
fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node {
@@ -668,7 +653,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
const node_or_error = if (expr.getStmtClass() == .StringLiteralClass)
transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0)
else
- transExprCoercing(c, scope, expr, .used, .r_value);
+ transExprCoercing(c, scope, expr, .used);
init_node = node_or_error catch |err| switch (err) {
error.UnsupportedTranslation,
error.UnsupportedType,
@@ -677,18 +662,18 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
},
error.OutOfMemory => |e| return e,
};
- if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
- init_node = try Node.bool_to_int.create(c.arena, init_node);
+ if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node.?)) {
+ init_node = try Tag.bool_to_int.create(c.arena, init_node.?);
}
} else {
- init_node = Node.undefined_literal.init();
+ init_node = Tag.undefined_literal.init();
}
} else if (storage_class != .Extern) {
// The C language specification states that variables with static or threadlocal
// storage without an initializer are initialized to a zero value.
// @import("std").mem.zeroes(T)
- init_node = try Node.std_mem_zeroes.create(c.arena, type_node);
+ init_node = try Tag.std_mem_zeroes.create(c.arena, type_node);
}
const linksection_string = blk: {
@@ -708,7 +693,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
break :blk null;
};
- const node = try Node.var_decl.create(c.arena, .{
+ const node = try Tag.var_decl.create(c.arena, .{
.is_pub = is_pub,
.is_const = is_const,
.is_extern = is_extern,
@@ -719,12 +704,12 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
.type = type_node,
.init = init_node,
});
- return addTopLevelDecl(c, checked_name, &node.base);
+ return addTopLevelDecl(c, checked_name, node);
}
fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node {
_ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);
- return Node.identifier.create(c.arena, builtin_name);
+ return Tag.identifier.create(c.arena, builtin_name);
}
const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
@@ -744,7 +729,7 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node {
if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|
- return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
+ return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
@@ -753,17 +738,17 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev
const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name;
if (builtin_typedef_map.get(checked_name)) |builtin| {
_ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
- return Node.identifier.create(c.arena, builtin);
+ return try Tag.identifier.create(c.arena, builtin);
}
if (!top_level_visit) {
- return transCreateNodeIdentifier(c, checked_name);
+ return try Tag.identifier.create(c.arena, checked_name);
}
_ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name);
const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null;
try addTopLevelDecl(c, checked_name, node);
- return transCreateNodeIdentifier(c, checked_name);
+ return try Tag.identifier.create(c.arena, checked_name);
}
fn transCreateNodeTypedef(
@@ -782,9 +767,9 @@ fn transCreateNodeTypedef(
error.OutOfMemory => |e| return e,
};
- const payload = try c.arena.create(ast.Payload.Typedef);
+ const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
payload.* = .{
- .base = .{ .tag = ([2]ast.Node.Tag{ .typedef, .pub_typedef })[@boolToInt(toplevel)] },
+ .base = .{ .tag = ([2]Tag{ .typedef, .pub_typedef })[@boolToInt(toplevel)] },
.data = .{
.name = checked_name,
.init = init_node,
@@ -795,7 +780,7 @@ fn transCreateNodeTypedef(
fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node {
if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name|
- return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
+ return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
const record_loc = record_decl.getLocation();
var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin());
@@ -815,7 +800,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
} else if (record_decl.isStruct()) {
container_kind_name = "struct";
} else {
- try warn(c, record_loc, "record {s} is not a struct or union", .{bare_name});
+ try warn(c, &c.global_scope.base, record_loc, "record {s} is not a struct or union", .{bare_name});
return null;
}
@@ -826,7 +811,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
const init_node = blk: {
const record_def = record_decl.getDefinition() orelse {
_ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
- break :blk Node.opaque_literal.init();
+ break :blk Tag.opaque_literal.init();
};
const is_packed = record_decl.getPackedAttribute();
@@ -843,14 +828,14 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
if (field_decl.isBitField()) {
_ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
- try warn(c, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
- break :blk Node.opaque_literal.init();
+ try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
+ break :blk Tag.opaque_literal.init();
}
if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) {
_ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
- try warn(c, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
- break :blk Node.opaque_literal.init();
+ try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
+ break :blk Tag.opaque_literal.init();
}
var is_anon = false;
@@ -864,8 +849,8 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
const field_type = transQualType(c, field_qt, field_loc) catch |err| switch (err) {
error.UnsupportedType => {
_ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
- try warn(c, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, raw_name });
- break :blk Node.opaque_literal.init();
+ try warn(c, &c.global_scope.base, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, field_name });
+ break :blk Tag.opaque_literal.init();
},
else => |e| return e,
};
@@ -890,20 +875,20 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
});
}
- const payload = try c.arena.create(ast.Payload.Record);
- container_node.* = .{
- .base = .{ .tag = ([2]ast.Node.Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] },
+ const record_payload = try c.arena.create(ast.Payload.Record);
+ record_payload.* = .{
+ .base = .{ .tag = ([2]Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] },
.data = .{
.is_packed = is_packed,
.fields = try c.arena.dupe(ast.Payload.Record.Field, fields.items),
},
};
- break :blk Node.initPayload(&container_node.base);
+ break :blk Node.initPayload(&record_payload.base);
};
const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
payload.* = .{
- .base = .{ .tag = ([2]ast.Node.Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
+ .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
.data = .{
.name = name,
.init = init_node,
@@ -913,12 +898,12 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
if (!is_unnamed)
try c.alias_list.append(.{ .alias = bare_name, .name = name });
- return Node.identifier.create(c.arena, name);
+ return try Tag.identifier.create(c.arena, name);
}
fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name|
- return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice
+ return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
const enum_loc = enum_decl.getLocation();
var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin());
@@ -965,7 +950,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
else => |e| return e,
}
else
- try Node.type.create(c.arena, "c_int");
+ try Tag.type.create(c.arena, "c_int");
it = enum_def.enumerator_begin();
end_it = enum_def.enumerator_end();
@@ -983,29 +968,29 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
else
null;
- try fields_and_decls.append(.{
+ try fields.append(.{
.name = field_name,
.value = int_node,
});
// In C each enum value is in the global namespace. So we put them there too.
// At this point we can rely on the enum emitting successfully.
- try addTopLevelDecl(c, field_name, try Node.enum_redecl.create(c.arena, .{
+ try addTopLevelDecl(c, field_name, try Tag.enum_redecl.create(c.arena, .{
.enum_val_name = enum_val_name,
.field_name = field_name,
.enum_name = name,
}));
}
- break :blk try Node.@"enum".create(c.arena, try c.arena.dupe(ast.Payload.Enum.Field, fields.items));
+ break :blk try Tag.@"enum".create(c.arena, try c.arena.dupe(ast.Payload.Enum.Field, fields.items));
} else blk: {
_ = try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});
- break :blk Node.opaque_literal.init();
+ break :blk Tag.opaque_literal.init();
};
const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
payload.* = .{
- .base = .{ .tag = ([2]ast.Node.Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
+ .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
.data = .{
.name = name,
.init = init_node,
@@ -1015,7 +1000,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
if (!is_unnamed)
try c.alias_list.append(.{ .alias = bare_name, .name = name });
- return transCreateNodeIdentifier(c, name);
+ return try Tag.identifier.create(c.arena, name);
}
const ResultUsed = enum {
@@ -1023,31 +1008,25 @@ const ResultUsed = enum {
unused,
};
-const LRValue = enum {
- l_value,
- r_value,
-};
-
fn transStmt(
c: *Context,
scope: *Scope,
stmt: *const clang.Stmt,
result_used: ResultUsed,
- lrvalue: LRValue,
) TransError!Node {
const sc = stmt.getStmtClass();
switch (sc) {
.BinaryOperatorClass => return transBinaryOperator(c, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used),
.CompoundStmtClass => return transCompoundStmt(c, scope, @ptrCast(*const clang.CompoundStmt, stmt)),
- .CStyleCastExprClass => return transCStyleCastExprClass(c, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used, lrvalue),
+ .CStyleCastExprClass => return transCStyleCastExprClass(c, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used),
.DeclStmtClass => return transDeclStmt(c, scope, @ptrCast(*const clang.DeclStmt, stmt)),
- .DeclRefExprClass => return transDeclRefExpr(c, scope, @ptrCast(*const clang.DeclRefExpr, stmt), lrvalue),
+ .DeclRefExprClass => return transDeclRefExpr(c, scope, @ptrCast(*const clang.DeclRefExpr, stmt)),
.ImplicitCastExprClass => return transImplicitCastExpr(c, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used),
.IntegerLiteralClass => return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as),
.ReturnStmtClass => return transReturnStmt(c, scope, @ptrCast(*const clang.ReturnStmt, stmt)),
.StringLiteralClass => return transStringLiteral(c, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used),
.ParenExprClass => {
- const expr = try transExpr(c, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used, lrvalue);
+ const expr = try transExpr(c, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used);
return maybeSuppressResult(c, scope, result_used, expr);
},
.InitListExprClass => return transInitListExpr(c, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used),
@@ -1056,9 +1035,9 @@ fn transStmt(
.WhileStmtClass => return transWhileLoop(c, scope, @ptrCast(*const clang.WhileStmt, stmt)),
.DoStmtClass => return transDoWhileLoop(c, scope, @ptrCast(*const clang.DoStmt, stmt)),
.NullStmtClass => {
- return Node.empty_block.init();
+ return Tag.empty_block.init();
},
- .ContinueStmtClass => return try transCreateNodeContinue(c),
+ .ContinueStmtClass => return Tag.@"continue".init(),
.BreakStmtClass => return transBreak(c, scope),
.ForStmtClass => return transForLoop(c, scope, @ptrCast(*const clang.ForStmt, stmt)),
.FloatingLiteralClass => return transFloatingLiteral(c, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used),
@@ -1083,12 +1062,12 @@ fn transStmt(
.CompoundAssignOperatorClass => return transCompoundAssignOperator(c, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used),
.OpaqueValueExprClass => {
const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?;
- const expr = try transExpr(c, scope, source_expr, .used, lrvalue);
+ const expr = try transExpr(c, scope, source_expr, .used);
return maybeSuppressResult(c, scope, result_used, expr);
},
else => {
return fail(
- rp,
+ c,
error.UnsupportedTranslation,
stmt.getBeginLoc(),
"TODO implement translation of stmt class {s}",
@@ -1109,37 +1088,36 @@ fn transBinaryOperator(
switch (op) {
.Assign => return try transCreateNodeAssign(c, scope, result_used, stmt.getLHS(), stmt.getRHS()),
.Comma => {
- var block_scope = try Scope.Block.init(rp.c, scope, true);
+ var block_scope = try Scope.Block.init(c, scope, true);
defer block_scope.deinit();
-
- const lhs = try transExpr(c, &block_scope.base, stmt.getLHS(), .unused, .r_value);
+ const lhs = try transExpr(c, &block_scope.base, stmt.getLHS(), .unused);
try block_scope.statements.append(lhs);
- const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value);
- const break_node = try Node.break_val.create(c.arena, .{
+ const rhs = try transExpr(c, &block_scope.base, stmt.getRHS(), .used);
+ const break_node = try Tag.break_val.create(c.arena, .{
.label = block_scope.label,
.val = rhs,
});
try block_scope.statements.append(break_node);
- const block_node = try block_scope.complete(rp.c);
- return maybeSuppressResult(rp, scope, result_used, block_node);
+ const block_node = try block_scope.complete(c);
+ return maybeSuppressResult(c, scope, result_used, block_node);
},
.Div => {
if (cIsSignedInteger(qt)) {
// signed integer division uses @divTrunc
- const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
- const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
- const div_trunc = try Node.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ const lhs = try transExpr(c, scope, stmt.getLHS(), .used);
+ const rhs = try transExpr(c, scope, stmt.getRHS(), .used);
+ const div_trunc = try Tag.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
return maybeSuppressResult(c, scope, result_used, div_trunc);
}
},
.Rem => {
if (cIsSignedInteger(qt)) {
// signed integer division uses @rem
- const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
- const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
- const rem = try Node.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ const lhs = try transExpr(c, scope, stmt.getLHS(), .used);
+ const rhs = try transExpr(c, scope, stmt.getRHS(), .used);
+ const rem = try Tag.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
return maybeSuppressResult(c, scope, result_used, rem);
}
},
@@ -1150,14 +1128,14 @@ fn transBinaryOperator(
return transCreateNodeShiftOp(c, scope, stmt, .shr, result_used);
},
.LAnd => {
- return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used);
+ return transCreateNodeBoolInfixOp(c, scope, stmt, .@"and", result_used);
},
.LOr => {
- return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used);
+ return transCreateNodeBoolInfixOp(c, scope, stmt, .@"or", result_used);
},
else => {},
}
- var op_id: Node.Tag = undefined;
+ var op_id: Tag = undefined;
switch (op) {
.Add => {
if (cIsUnsignedInteger(qt)) {
@@ -1218,20 +1196,20 @@ fn transBinaryOperator(
else => unreachable,
}
- const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);
- const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);
+ const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used);
+ const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used);
const lhs = if (isBoolRes(lhs_uncasted))
- try Node.bool_to_int.create(c.arena, lhs_uncasted)
+ try Tag.bool_to_int.create(c.arena, lhs_uncasted)
else
lhs_uncasted;
const rhs = if (isBoolRes(rhs_uncasted))
- try Node.bool_to_int.create(c.arena, rhs_uncasted)
+ try Tag.bool_to_int.create(c.arena, rhs_uncasted)
else
rhs_uncasted;
- return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, used);
+ return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, result_used);
}
fn transCompoundStmtInline(
@@ -1243,7 +1221,7 @@ fn transCompoundStmtInline(
var it = stmt.body_begin();
const end_it = stmt.body_end();
while (it != end_it) : (it += 1) {
- const result = try transStmt(c, parent_scope, it[0], .unused, .r_value);
+ const result = try transStmt(c, parent_scope, it[0], .unused);
try block.statements.append(result);
}
}
@@ -1260,7 +1238,6 @@ fn transCStyleCastExprClass(
scope: *Scope,
stmt: *const clang.CStyleCastExpr,
result_used: ResultUsed,
- lrvalue: LRValue,
) TransError!Node {
const sub_expr = stmt.getSubExpr();
const cast_node = (try transCCast(
@@ -1269,7 +1246,7 @@ fn transCStyleCastExprClass(
stmt.getBeginLoc(),
stmt.getType(),
sub_expr.getType(),
- try transExpr(c, scope, sub_expr, .used, lrvalue),
+ try transExpr(c, scope, sub_expr, .used),
));
return maybeSuppressResult(c, scope, result_used, cast_node);
}
@@ -1294,7 +1271,7 @@ fn transDeclStmtOne(
// This is actually a global variable, put it in the global scope and reference it.
// `_ = mangled_name;`
try visitVarDecl(c, var_decl, mangled_name);
- return try maybeSuppressResult(c, scope, .unused, try Node.identifier.create(c.arena, mangled_name));
+ return try maybeSuppressResult(c, scope, .unused, try Tag.identifier.create(c.arena, mangled_name));
},
else => {},
}
@@ -1308,13 +1285,13 @@ fn transDeclStmtOne(
if (expr.getStmtClass() == .StringLiteralClass)
try transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(c, type_node))
else
- try transExprCoercing(c, scope, expr, .used, .r_value)
+ try transExprCoercing(c, scope, expr, .used)
else
- try transCreateNodeUndefinedLiteral(c);
+ Tag.undefined_literal.init();
if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
- init_node = try Node.bool_to_int.create(c.arena, init_node);
+ init_node = try Tag.bool_to_int.create(c.arena, init_node);
}
- return Node.var_decl.create(c.arena, .{
+ return Tag.var_decl.create(c.arena, .{
.is_pub = false,
.is_const = is_const,
.is_extern = false,
@@ -1339,7 +1316,7 @@ fn transDeclStmtOne(
return node;
},
else => |kind| return fail(
- rp,
+ c,
error.UnsupportedTranslation,
decl.getLocation(),
"TODO implement translation of DeclStmt kind {s}",
@@ -1370,12 +1347,11 @@ fn transDeclRefExpr(
c: *Context,
scope: *Scope,
expr: *const clang.DeclRefExpr,
- lrvalue: LRValue,
) TransError!Node {
const value_decl = expr.getDecl();
const name = try c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin());
const mangled_name = scope.getAlias(name);
- return Node.identifier.create(c.arena, mangled_name);
+ return Tag.identifier.create(c.arena, mangled_name);
}
fn transImplicitCastExpr(
@@ -1389,49 +1365,49 @@ fn transImplicitCastExpr(
const src_type = getExprQualType(c, sub_expr);
switch (expr.getCastKind()) {
.BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {
- const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
+ const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node);
return maybeSuppressResult(c, scope, result_used, casted);
},
.LValueToRValue, .NoOp, .FunctionToPointerDecay => {
- const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
+ const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
return maybeSuppressResult(c, scope, result_used, sub_expr_node);
},
.ArrayToPointerDecay => {
if (exprIsNarrowStringLiteral(sub_expr)) {
- const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
+ const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
return maybeSuppressResult(c, scope, result_used, sub_expr_node);
}
- const addr = try Node.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value));
+ const addr = try Tag.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used));
return maybeSuppressResult(c, scope, result_used, addr);
},
.NullToPointer => {
- return Node.null_literal.init();
+ return Tag.null_literal.init();
},
.PointerToBoolean => {
// @ptrToInt(val) != 0
- const ptr_to_int = try Node.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value));
+ const ptr_to_int = try Tag.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used));
- const ne = try Node.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Node.zero_literal.init() });
+ const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() });
return maybeSuppressResult(c, scope, result_used, ne);
},
.IntegralToBoolean => {
- const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);
+ const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
// The expression is already a boolean one, return it as-is
if (isBoolRes(sub_expr_node))
return maybeSuppressResult(c, scope, result_used, sub_expr_node);
// val != 0
- const ne = try Node.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Node.zero_literal.init() });
+ const ne = try Tag.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Tag.zero_literal.init() });
return maybeSuppressResult(c, scope, result_used, ne);
},
.BuiltinFnToFnPtr => {
- return transExpr(rp, scope, sub_expr, result_used, .r_value);
+ return transExpr(c, scope, sub_expr, result_used);
},
else => |kind| return fail(
- rp,
+ c,
error.UnsupportedTranslation,
@ptrCast(*const clang.Stmt, expr).getBeginLoc(),
"TODO implement translation of CastKind {s}",
@@ -1445,17 +1421,16 @@ fn transBoolExpr(
scope: *Scope,
expr: *const clang.Expr,
used: ResultUsed,
- lrvalue: LRValue,
) TransError!Node {
if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {
var is_zero: bool = undefined;
if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {
return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
}
- return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)] };
+ return Node{ .tag_if_small_enough = @enumToInt(([2]Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)]) };
}
- var res = try transExpr(c, scope, expr, used, lrvalue);
+ var res = try transExpr(c, scope, expr, used);
if (isBoolRes(res)) {
return maybeSuppressResult(c, scope, used, res);
}
@@ -1494,7 +1469,7 @@ fn isBoolRes(res: Node) bool {
.@"or",
.@"and",
.equal,
- .note_equal,
+ .not_equal,
.less_than,
.less_than_equal,
.greater_than,
@@ -1547,18 +1522,18 @@ fn finishBoolExpr(
.Float16,
=> {
// node != 0
- return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
+ return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
},
.NullPtr => {
// node == null
- return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() });
+ return Tag.equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
},
else => {},
}
},
.Pointer => {
// node == null
- return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() });
+ return Tag.equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
},
.Typedef => {
const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
@@ -1568,8 +1543,7 @@ fn finishBoolExpr(
},
.Enum => {
// node != 0
- return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
- const op_token = try appendToken(c, .BangEqual, "!=");
+ return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
},
.Elaborated => {
const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
@@ -1614,9 +1588,10 @@ fn transIntegerLiteral(
// But the first step is to be correct, and the next step is to make the output more elegant.
// @as(T, x)
+ const expr_base = @ptrCast(*const clang.Expr, expr);
const ty_node = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc());
const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt());
- const as = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs });
+ const as = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs });
return maybeSuppressResult(c, scope, result_used, as);
}
@@ -1624,16 +1599,16 @@ fn transReturnStmt(
c: *Context,
scope: *Scope,
expr: *const clang.ReturnStmt,
-) TransError!*ast.Node {
+) TransError!Node {
const val_expr = expr.getRetValue() orelse
- return Node.return_void.init();
+ return Tag.return_void.init();
- var rhs = try transExprCoercing(c, scope, val_expr, .used, .r_value);
+ var rhs = try transExprCoercing(c, scope, val_expr, .used);
const return_qt = scope.findBlockReturnType(c);
if (isBoolRes(rhs) and !qualTypeIsBoolean(return_qt)) {
- rhs = try Node.bool_to_int.create(c.arena, rhs);
+ rhs = try Tag.bool_to_int.create(c.arena, rhs);
}
- return Node.@"return".create(c.arena, rhs);
+ return Tag.@"return".create(c.arena, rhs);
}
fn transStringLiteral(
@@ -1647,10 +1622,9 @@ fn transStringLiteral(
.Ascii, .UTF8 => {
var len: usize = undefined;
const bytes_ptr = stmt.getString_bytes_begin_size(&len);
- const str = bytes_ptr[0..len];
- const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(str)});
- const node = try Node.string_literal.create(c.arena, str);
+ const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});
+ const node = try Tag.string_literal.create(c.arena, str);
return maybeSuppressResult(c, scope, result_used, node);
},
.UTF16, .UTF32, .Wide => {
@@ -1658,9 +1632,9 @@ fn transStringLiteral(
const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() });
const lit_array = try transStringLiteralAsArray(c, scope, stmt, stmt.getLength() + 1);
- const decl = try Node.var_simple.create(c.arena, .{ .name = name, .init = lit_array });
- try scope.appendNode(name, decl);
- const node = try Node.identifier.create(c.arena, name);
+ const decl = try Tag.var_simple.create(c.arena, .{ .name = name, .init = lit_array });
+ try scope.appendNode(decl);
+ const node = try Tag.identifier.create(c.arena, name);
return maybeSuppressResult(c, scope, result_used, node);
},
}
@@ -1669,9 +1643,7 @@ fn transStringLiteral(
/// Parse the size of an array back out from an ast Node.
fn zigArraySize(c: *Context, node: Node) TransError!usize {
if (node.castTag(.array_type)) |array| {
- if (array.data.len.castTag(.int_literal)) |int_lit| {
- return std.fmt.parseUnsigned(usize, int_lit.data, 10) catch error.UnsupportedTranslation;
- }
+ return array.data.len;
}
return error.UnsupportedTranslation;
}
@@ -1709,7 +1681,7 @@ fn transStringLiteralAsArray(
init_list[i] = try transCreateNodeNumber(c, 0);
}
- return Node.array_init.create(c.arena, init_list);
+ return Tag.array_init.create(c.arena, init_list);
}
fn cIsEnum(qt: clang.QualType) bool {
@@ -1747,89 +1719,77 @@ fn transCCast(
// 3. Bit-cast to correct signed-ness
const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);
const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
- var src_int_expr = if (cIsInteger(src_type)) expr else Node.enum_to_int.create(c.arena, expr);
+ var src_int_expr = if (cIsInteger(src_type)) expr else try Tag.enum_to_int.create(c.arena, expr);
if (isBoolRes(src_int_expr)) {
- src_int_expr = try Node.bool_to_int.create(c.arena, src_int_expr);
+ src_int_expr = try Tag.bool_to_int.create(c.arena, src_int_expr);
}
switch (cIntTypeCmp(dst_type, src_int_type)) {
.lt => {
// @truncate(SameSignSmallerInt, src_int_expr)
const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
- src_int_expr = try Node.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
+ src_int_expr = try Tag.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
},
.gt => {
// @as(SameSignBiggerInt, src_int_expr)
const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
- src_int_expr = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
+ src_int_expr = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
},
.eq => {
// src_int_expr = src_int_expr
},
}
// @bitCast(dest_type, intermediate_value)
- return Node.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr });
+ return Tag.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr });
}
if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {
// @intCast(dest_type, @ptrToInt(val))
- const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr);
- return Node.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });
+ const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
+ return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });
}
if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {
// @intToPtr(dest_type, val)
- return Node.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
+ return Tag.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
}
if (cIsFloating(src_type) and cIsFloating(dst_type)) {
// @floatCast(dest_type, val)
- return Node.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
+ return Tag.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
}
if (cIsFloating(src_type) and !cIsFloating(dst_type)) {
// @floatToInt(dest_type, val)
- return Node.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
+ return Tag.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
}
if (!cIsFloating(src_type) and cIsFloating(dst_type)) {
// @intToFloat(dest_type, val)
- return Node.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
+ return Tag.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
}
if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) {
// @boolToInt returns either a comptime_int or a u1
// TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast
// instead of @as
- const bool_to_int = Node.bool_to_int.create(c.arena, expr);
- return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });
+ const bool_to_int = try Tag.bool_to_int.create(c.arena, expr);
+ return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });
}
if (cIsEnum(dst_type)) {
// @intToEnum(dest_type, val)
- return Node.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
+ return Tag.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
}
if (cIsEnum(src_type) and !cIsEnum(dst_type)) {
// @enumToInt(val)
- return Node.enum_to_int.create(c.arena, expr);
+ return Tag.enum_to_int.create(c.arena, expr);
}
// @as(dest_type, val)
- return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
+ return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
}
-fn transExpr(
- c: *Context,
- scope: *Scope,
- expr: *const clang.Expr,
- used: ResultUsed,
- lrvalue: LRValue,
-) TransError!Node {
- return transStmt(c, scope, @ptrCast(*const clang.Stmt, expr), used, lrvalue);
+fn transExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
+ return transStmt(c, scope, @ptrCast(*const clang.Stmt, expr), used);
}
/// Same as `transExpr` but with the knowledge that the operand will be type coerced, and therefore
/// an `@as` would be redundant. This is used to prevent redundant `@as` in integer literals.
-fn transExprCoercing(
- c: *Context,
- scope: *Scope,
- expr: *const clang.Expr,
- used: ResultUsed,
- lrvalue: LRValue,
-) TransError!Node {
+fn transExprCoercing(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) {
.IntegerLiteralClass => {
return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, expr), .used, .no_as);
@@ -1840,12 +1800,12 @@ fn transExprCoercing(
.UnaryOperatorClass => {
const un_expr = @ptrCast(*const clang.UnaryOperator, expr);
if (un_expr.getOpcode() == .Extension) {
- return transExprCoercing(c, scope, un_expr.getSubExpr(), used, lrvalue);
+ return transExprCoercing(c, scope, un_expr.getSubExpr(), used);
}
},
else => {},
}
- return transExpr(c, scope, expr, .used, .r_value);
+ return transExpr(c, scope, expr, .used);
}
fn transInitListExprRecord(
@@ -1896,11 +1856,11 @@ fn transInitListExprRecord(
try field_inits.append(.{
.name = raw_name,
- .value = try transExpr(c, scope, elem_expr, .used, .r_value),
+ .value = try transExpr(c, scope, elem_expr, .used),
});
}
- return Node.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items));
+ return Tag.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items));
}
fn transInitListExprArray(
@@ -1920,18 +1880,18 @@ fn transInitListExprArray(
const leftover_count = all_count - init_count;
if (all_count == 0) {
- return Node.empty_array.create(c.arena, try transQualType(c, child_qt, source_loc));
+ return Tag.empty_array.create(c.arena, try transQualType(c, child_qt, loc));
}
- const ty_node = try transType(ty);
+ 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(i);
- init.* = try transExpr(c, scope, elem_expr, .used, .r_value);
+ const elem_expr = expr.getInit(@intCast(c_uint, i));
+ init.* = try transExpr(c, scope, elem_expr, .used);
}
- const init_node = try Node.array_init.create(c.arena, init_list);
+ const init_node = try Tag.array_init.create(c.arena, init_list);
if (leftover_count == 0) {
return init_node;
}
@@ -1939,14 +1899,14 @@ fn transInitListExprArray(
} else null;
const filler_val_expr = expr.getArrayFiller();
- const filler_node = try Node.array_filler.create(c.arena, .{
+ const filler_node = try Tag.array_filler.create(c.arena, .{
.type = ty_node,
- .filler = try transExpr(c, scope, filler_val_expr, .used, .r_value),
+ .filler = try transExpr(c, scope, filler_val_expr, .used),
.count = leftover_count,
});
if (init_node) |some| {
- return Node.array_cat.create(c.arena, some, filler_node);
+ return Tag.array_cat.create(c.arena, .{ .lhs = some, .rhs = filler_node });
} else {
return filler_node;
}
@@ -1964,7 +1924,7 @@ fn transInitListExpr(
if (qual_type.isRecordType()) {
return maybeSuppressResult(c, scope, used, try transInitListExprRecord(
- rp,
+ c,
scope,
source_loc,
expr,
@@ -1972,7 +1932,7 @@ fn transInitListExpr(
));
} else if (qual_type.isArrayType()) {
return maybeSuppressResult(c, scope, used, try transInitListExprArray(
- rp,
+ c,
scope,
source_loc,
expr,
@@ -1994,7 +1954,7 @@ fn transZeroInitExpr(
.Builtin => {
const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
switch (builtin_ty.getKind()) {
- .Bool => return Node.false_literal.init(),
+ .Bool => return Tag.false_literal.init(),
.Char_U,
.UChar,
.Char_S,
@@ -2015,11 +1975,11 @@ fn transZeroInitExpr(
.Float128,
.Float16,
.LongDouble,
- => return Node.zero_literal.init(),
+ => return Tag.zero_literal.init(),
else => return fail(c, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),
}
},
- .Pointer => return Node.null_literal.init(),
+ .Pointer => return Tag.null_literal.init(),
.Typedef => {
const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
const typedef_decl = typedef_ty.getDecl();
@@ -2058,19 +2018,19 @@ fn transIfStmt(
var cond_scope = Scope.Condition{
.base = .{
.parent = scope,
- .id = .Condition,
+ .id = .condition,
},
};
defer cond_scope.deinit();
const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());
- const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value);
+ const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
- const then_body = try transStmt(c, scope, stmt.getThen(), .unused, .r_value);
+ const then_body = try transStmt(c, scope, stmt.getThen(), .unused);
const else_body = if (stmt.getElse()) |expr|
- try transStmt(c, scope, expr, .unused, .r_value)
+ try transStmt(c, scope, expr, .unused)
else
null;
- return Node.@"if".create(c.arena, .{ .cond = cond, .then = then_body, .@"else" = else_body });
+ return Tag.@"if".create(c.arena, .{ .cond = cond, .then = then_body, .@"else" = else_body });
}
fn transWhileLoop(
@@ -2081,19 +2041,19 @@ fn transWhileLoop(
var cond_scope = Scope.Condition{
.base = .{
.parent = scope,
- .id = .Condition,
+ .id = .condition,
},
};
defer cond_scope.deinit();
const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());
- const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value);
+ const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
var loop_scope = Scope{
.parent = scope,
- .id = .Loop,
+ .id = .loop,
};
- const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);
- return Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null });
+ const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
+ return Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null });
}
fn transDoWhileLoop(
@@ -2103,20 +2063,19 @@ fn transDoWhileLoop(
) TransError!Node {
var loop_scope = Scope{
.parent = scope,
- .id = .Loop,
+ .id = .loop,
};
// if (!cond) break;
- const if_node = try transCreateNodeIf(c);
var cond_scope = Scope.Condition{
.base = .{
.parent = scope,
- .id = .Condition,
+ .id = .condition,
},
};
defer cond_scope.deinit();
- const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used, .r_value);
- const if_not_break = try Node.if_not_break.create(c.arena, cond);
+ const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used);
+ const if_not_break = try Tag.if_not_break.create(c.arena, cond);
const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: {
// there's already a block in C, so we'll append our condition to it.
@@ -2129,8 +2088,8 @@ fn transDoWhileLoop(
// zig: b;
// zig: if (!cond) break;
// zig: }
- const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);
- const block = node.castTag(.block);
+ const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
+ const block = node.castTag(.block).?;
block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete.
block.data.stmts[block.data.stmts.len - 1] = if_not_break;
break :blk node;
@@ -2143,12 +2102,12 @@ fn transDoWhileLoop(
// zig: a;
// zig: if (!cond) break;
// zig: }
- const statements = try c.arena.create(Node, 2);
- statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);
+ const statements = try c.arena.alloc(Node, 2);
+ statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
statements[1] = if_not_break;
- break :blk try Node.block.create(c.arena, .{ .label = null, .stmts = statements });
+ break :blk try Tag.block.create(c.arena, .{ .label = null, .stmts = statements });
};
- return Node.while_true.create(c.arena, body_node);
+ return Tag.while_true.create(c.arena, body_node);
}
fn transForLoop(
@@ -2158,7 +2117,7 @@ fn transForLoop(
) TransError!Node {
var loop_scope = Scope{
.parent = scope,
- .id = .Loop,
+ .id = .loop,
};
var block_scope: ?Scope.Block = null;
@@ -2167,29 +2126,29 @@ fn transForLoop(
if (stmt.getInit()) |init| {
block_scope = try Scope.Block.init(c, scope, false);
loop_scope.parent = &block_scope.?.base;
- const init_node = try transStmt(c, &block_scope.?.base, init, .unused, .r_value);
+ const init_node = try transStmt(c, &block_scope.?.base, init, .unused);
try block_scope.?.statements.append(init_node);
}
var cond_scope = Scope.Condition{
.base = .{
.parent = &loop_scope,
- .id = .Condition,
+ .id = .condition,
},
};
defer cond_scope.deinit();
const cond = if (stmt.getCond()) |cond|
- try transBoolExpr(c, &cond_scope.base, cond, .used, .r_value)
+ try transBoolExpr(c, &cond_scope.base, cond, .used)
else
- Node.true_literal.init();
+ Tag.true_literal.init();
const cont_expr = if (stmt.getInc()) |incr|
- try transExpr(c, &cond_scope.base, incr, .unused, .r_value)
+ try transExpr(c, &cond_scope.base, incr, .unused)
else
null;
- const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);
- const while_node = try Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr });
+ const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
+ const while_node = try Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr });
if (block_scope) |*bs| {
try bs.statements.append(while_node);
return try bs.complete(c);
@@ -2206,13 +2165,14 @@ fn transSwitch(
var cond_scope = Scope.Condition{
.base = .{
.parent = scope,
- .id = .Condition,
+ .id = .condition,
},
};
defer cond_scope.deinit();
- const switch_expr = try transExpr(c, &cond_scope.base, stmt.getCond(), .used, .r_value);
+ const switch_expr = try transExpr(c, &cond_scope.base, stmt.getCond(), .used);
const switch_node = try c.arena.create(ast.Payload.Switch);
switch_node.* = .{
+ .base = .{ .tag = .@"switch" },
.data = .{
.cond = switch_expr,
.cases = undefined, // set later
@@ -2221,7 +2181,7 @@ fn transSwitch(
var switch_scope = Scope.Switch{
.base = .{
- .id = .Switch,
+ .id = .@"switch",
.parent = scope,
},
.cases = std.ArrayList(Node).init(c.gpa),
@@ -2229,11 +2189,7 @@ fn transSwitch(
.default_label = null,
.switch_label = null,
};
- defer {
- switch_node.data.cases = try c.arena.dupe(Node, switch_scope.cases.items);
- switch_node.data.default = switch_scope.switch_label;
- switch_scope.cases.deinit();
- }
+ defer switch_scope.cases.deinit();
// tmp block that all statements will go before being picked up by a case or default
var block_scope = try Scope.Block.init(c, &switch_scope.base, false);
@@ -2246,7 +2202,7 @@ fn transSwitch(
switch_scope.pending_block = try Scope.Block.init(c, scope, false);
try switch_scope.pending_block.statements.append(Node.initPayload(&switch_node.base));
- const last = try transStmt(c, &block_scope.base, stmt.getBody(), .unused, .r_value);
+ const last = try transStmt(c, &block_scope.base, stmt.getBody(), .unused);
// take all pending statements
const last_block_stmts = last.castTag(.block).?.data.stmts;
@@ -2264,13 +2220,14 @@ fn transSwitch(
switch_scope.pending_block.label = l;
}
if (switch_scope.default_label == null) {
- const else_prong = try Node.switch_else.create(
+ const else_prong = try Tag.switch_else.create(
c.arena,
- try Node.@"break".create(c.arena, switch_scope.switch_label.?),
+ try Tag.@"break".create(c.arena, switch_scope.switch_label.?),
);
- switch_scope.cases.append(else_prong);
+ try switch_scope.cases.append(else_prong);
}
+ switch_node.data.cases = try c.arena.dupe(Node, switch_scope.cases.items);
const result_node = try switch_scope.pending_block.complete(c);
switch_scope.pending_block.deinit();
return result_node;
@@ -2286,18 +2243,18 @@ fn transCase(
const label = try block_scope.makeMangledName(c, "case");
const expr = if (stmt.getRHS()) |rhs| blk: {
- const lhs_node = try transExpr(c, scope, stmt.getLHS(), .used, .r_value);
- const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);
+ const lhs_node = try transExpr(c, scope, stmt.getLHS(), .used);
+ const rhs_node = try transExpr(c, scope, rhs, .used);
- break :blk Node.ellipsis3.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
+ break :blk try Tag.ellipsis3.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
} else
- try transExpr(c, scope, stmt.getLHS(), .used, .r_value);
+ try transExpr(c, scope, stmt.getLHS(), .used);
- const switch_prong = try Node.switch_prong.create(
- c.arena,
- try Node.@"break".create(c.arena, label),
- );
- switch_scope.cases.append(switch_prong);
+ const switch_prong = try Tag.switch_prong.create(c.arena, .{
+ .lhs = expr,
+ .rhs = try Tag.@"break".create(c.arena, label),
+ });
+ try switch_scope.cases.append(switch_prong);
switch_scope.pending_block.label = label;
@@ -2311,7 +2268,7 @@ fn transCase(
try switch_scope.pending_block.statements.append(pending_node);
- return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value);
+ return transStmt(c, scope, stmt.getSubStmt(), .unused);
}
fn transDefault(
@@ -2323,12 +2280,12 @@ fn transDefault(
const switch_scope = scope.getSwitch();
switch_scope.default_label = try block_scope.makeMangledName(c, "default");
- const else_prong = try Node.switch_else.create(
+ const else_prong = try Tag.switch_else.create(
c.arena,
- try Node.@"break".create(c.arena, switch_scope.default_label.?),
+ try Tag.@"break".create(c.arena, switch_scope.default_label.?),
);
- switch_scope.cases.append(else_prong);
- switch_scope.pending_block.label = try appendIdentifier(c, switch_scope.default_label.?);
+ try switch_scope.cases.append(else_prong);
+ switch_scope.pending_block.label = switch_scope.default_label.?;
// take all pending statements
try switch_scope.pending_block.statements.appendSlice(block_scope.statements.items);
@@ -2339,7 +2296,7 @@ fn transDefault(
switch_scope.pending_block = try Scope.Block.init(c, scope, false);
try switch_scope.pending_block.statements.append(pending_node);
- return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value);
+ return transStmt(c, scope, stmt.getSubStmt(), .unused);
}
fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
@@ -2352,7 +2309,7 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
// See comment in `transIntegerLiteral` for why this code is here.
// @as(T, x)
const expr_base = @ptrCast(*const clang.Expr, expr);
- const as_node = try Node.as.create(c.arena, .{
+ const as_node = try Tag.as.create(c.arena, .{
.lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
.rhs = try transCreateNodeAPInt(c, result.Val.getInt()),
});
@@ -2369,10 +2326,10 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined
}
fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
- return Node.char_literal.create(c.arena, if (narrow)
- try std.fmt.bufPrint(c.arena, "'{}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})})
+ return Tag.char_literal.create(c.arena, if (narrow)
+ try std.fmt.allocPrint(c.arena, "'{s}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})})
else
- try std.fmt.bufPrint(c.arena, "'\\u{{{x}}}'", .{val}));
+ try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));
}
fn transCharLiteral(
@@ -2398,7 +2355,7 @@ fn transCharLiteral(
// See comment in `transIntegerLiteral` for why this code is here.
// @as(T, x)
const expr_base = @ptrCast(*const clang.Expr, stmt);
- const as_node = Node.as.create(c.arena, .{
+ const as_node = try Tag.as.create(c.arena, .{
.lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
.rhs = int_lit_node,
});
@@ -2416,12 +2373,12 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
var it = comp.body_begin();
const end_it = comp.body_end();
while (it != end_it - 1) : (it += 1) {
- const result = try transStmt(rp, &block_scope.base, it[0], .unused, .r_value);
+ const result = try transStmt(c, &block_scope.base, it[0], .unused);
try block_scope.statements.append(result);
}
- const break_node = try Node.break_val.create(c.arena, .{
- .label = block_scope.label,
- .val = try transStmt(c, &block_scope.base, it[0], .used, .r_value),
+ const break_node = try Tag.break_val.create(c.arena, .{
+ .label = block_scope.label,
+ .val = try transStmt(c, &block_scope.base, it[0], .used),
});
try block_scope.statements.append(break_node);
const res = try block_scope.complete(c);
@@ -2429,10 +2386,10 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
}
fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node {
- var container_node = try transExpr(c, scope, stmt.getBase(), .used, .r_value);
+ var container_node = try transExpr(c, scope, stmt.getBase(), .used);
if (stmt.isArrow()) {
- container_node = try Node.deref.create(c.arena, container_node);
+ container_node = try Tag.deref.create(c.arena, container_node);
}
const member_decl = stmt.getMemberDecl();
@@ -2450,9 +2407,9 @@ 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 Node.identifier.create(c.arena, name);
+ const ident = try Tag.identifier.create(c.arena, name);
- const node = try Node.field_access.create(c.arena, .{ .lhs = container_node, .rhs = ident});
+ const node = try Tag.field_access.create(c.arena, .{ .lhs = container_node, .rhs = ident });
return maybeSuppressResult(c, scope, result_used, node);
}
@@ -2469,7 +2426,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
}
}
- const container_node = try transExpr(c, scope, base_stmt, .used, .r_value);
+ const container_node = try transExpr(c, scope, base_stmt, .used);
// cast if the index is long long or signed
const subscr_expr = stmt.getIdx();
@@ -2477,14 +2434,17 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
const is_longlong = cIsLongLongInteger(qt);
const is_signed = cIsSignedInteger(qt);
-
- const node = try Node.array_access.create(c.arena, .{ .lhs = container_node, .rhs = if (is_longlong or is_signed) blk: {
- const cast_node = try c.createBuiltinCall("@intCast", 2);
+ const rhs = if (is_longlong or is_signed) blk: {
// check if long long first so that signed long long doesn't just become unsigned long long
- var typeid_node = if (is_longlong) try transCreateNodeIdentifier(c, "usize") else try transQualTypeIntWidthOf(c, qt, false);
- break :blk try Node.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used, .r_value)});
+ var typeid_node = if (is_longlong) try Tag.identifier.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, qt, false);
+ break :blk try Tag.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used) });
} else
- try transExpr(c, scope, subscr_expr, .used, .r_value)});
+ try transExpr(c, scope, subscr_expr, .used);
+
+ const node = try Tag.array_access.create(c.arena, .{
+ .lhs = container_node,
+ .rhs = rhs,
+ });
return maybeSuppressResult(c, scope, result_used, node);
}
@@ -2522,23 +2482,23 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {
fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!Node {
const callee = stmt.getCallee();
- var raw_fn_expr = try transExpr(c, scope, callee, .used, .r_value);
+ var raw_fn_expr = try transExpr(c, scope, callee, .used);
var is_ptr = false;
const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr);
const fn_expr = if (is_ptr and fn_ty != null and !cIsFunctionDeclRef(callee))
- try transCreateNodeUnwrapNull(rp.c, raw_fn_expr)
+ try Tag.unwrap.create(c.arena, raw_fn_expr)
else
raw_fn_expr;
const num_args = stmt.getNumArgs();
- const call_params = try c.arena.alloc(Node, num_args);
+ const args = try c.arena.alloc(Node, num_args);
- const args = stmt.getArgs();
+ const c_args = stmt.getArgs();
var i: usize = 0;
while (i < num_args) : (i += 1) {
- var call_param = try transExpr(c, scope, args[i], .used, .r_value);
+ var arg = try transExpr(c, scope, c_args[i], .used);
// In C the result type of a boolean expression is int. If this result is passed as
// an argument to a function whose parameter is also int, there is no cast. Therefore
@@ -2549,17 +2509,17 @@ fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result
const param_count = fn_proto.getNumParams();
if (i < param_count) {
const param_qt = fn_proto.getParamType(@intCast(c_uint, i));
- if (isBoolRes(call_param) and cIsNativeInt(param_qt)) {
- call_param = try Node.bool_to_int.create(c.arena, call_param);
+ if (isBoolRes(arg) and cIsNativeInt(param_qt)) {
+ arg = try Tag.bool_to_int.create(c.arena, arg);
}
}
},
else => {},
}
}
- call_params[i] = call_param;
+ args[i] = arg;
}
- const node = try Node.call.create(c.arena, .{ .lhs = fn_expr, .args = call_params });
+ const node = try Tag.call.create(c.arena, .{ .lhs = fn_expr, .args = args });
if (fn_ty) |ty| {
const canon = ty.getReturnType().getCanonicalType();
const ret_ty = canon.getTypePtr();
@@ -2609,17 +2569,17 @@ fn transUnaryExprOrTypeTraitExpr(
result_used: ResultUsed,
) TransError!Node {
const loc = stmt.getBeginLoc();
- const type_node = try transQualType(rp, stmt.getTypeOfArgument(), loc);
+ const type_node = try transQualType(c, stmt.getTypeOfArgument(), loc);
const kind = stmt.getKind();
switch (kind) {
- .SizeOf => return Node.sizeof.create(c.arena, type_node),
- .AlignOf => return Node.alignof.create(c.arena, type_node),
+ .SizeOf => return Tag.sizeof.create(c.arena, type_node),
+ .AlignOf => return Tag.alignof.create(c.arena, type_node),
.PreferredAlignOf,
.VecStep,
.OpenMPRequiredSimdAlign,
- => return revertAndWarn(
- rp,
+ => return fail(
+ c,
error.UnsupportedTranslation,
loc,
"Unsupported type trait kind {}",
@@ -2642,53 +2602,54 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
const op_expr = stmt.getSubExpr();
switch (stmt.getOpcode()) {
.PostInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
- return transCreatePostCrement(c, scope, stmt, .assign_add_wrap, used)
+ return transCreatePostCrement(c, scope, stmt, .add_wrap_assign, used)
else
- return transCreatePostCrement(c, scope, stmt, .assign_add, used),
+ return transCreatePostCrement(c, scope, stmt, .add_assign, used),
.PostDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
- return transCreatePostCrement(c, scope, stmt, .assign_sub_wrap, used)
+ return transCreatePostCrement(c, scope, stmt, .sub_wrap_assign, used)
else
- return transCreatePostCrement(c, scope, stmt, .assign_sub, used),
+ return transCreatePostCrement(c, scope, stmt, .sub_assign, used),
.PreInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
- return transCreatePreCrement(c, scope, stmt, .assign_add_wrap, used)
+ return transCreatePreCrement(c, scope, stmt, .add_wrap_assign, used)
else
- return transCreatePreCrement(c, scope, stmt, .assign_add, used),
+ return transCreatePreCrement(c, scope, stmt, .add_assign, used),
.PreDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
- return transCreatePreCrement(c, scope, stmt, .assign_sub_wrap, used)
+ return transCreatePreCrement(c, scope, stmt, .sub_wrap_assign, used)
else
- return transCreatePreCrement(c, scope, stmt, .assign_sub, used),
+ return transCreatePreCrement(c, scope, stmt, .sub_assign, used),
.AddrOf => {
if (cIsFunctionDeclRef(op_expr)) {
- return transExpr(rp, scope, op_expr, used, .r_value);
+ return transExpr(c, scope, op_expr, used);
}
- return Node.address_of.create(c.arena, try transExpr(c, scope, op_expr, used, .r_value));
+ return Tag.address_of.create(c.arena, try transExpr(c, scope, op_expr, used));
},
.Deref => {
- const node = try transExpr(c, scope, op_expr, used, .r_value);
+ const node = try transExpr(c, scope, op_expr, used);
var is_ptr = false;
const fn_ty = qualTypeGetFnProto(op_expr.getType(), &is_ptr);
if (fn_ty != null and is_ptr)
return node;
- return Node.unwrap_deref.create(c.arena, node);
+ const unwrapped = try Tag.unwrap.create(c.arena, node);
+ return Tag.deref.create(c.arena, unwrapped);
},
- .Plus => return transExpr(c, scope, op_expr, used, .r_value),
+ .Plus => return transExpr(c, scope, op_expr, used),
.Minus => {
if (!qualTypeHasWrappingOverflow(op_expr.getType())) {
- return Node.negate.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));
+ return Tag.negate.create(c.arena, try transExpr(c, scope, op_expr, .used));
} else if (cIsUnsignedInteger(op_expr.getType())) {
// use -% x for unsigned integers
- return Node.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));
+ return Tag.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used));
} else
return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{});
},
.Not => {
- return Node.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));
+ return Tag.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used));
},
.LNot => {
- return Node.not.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));
+ return Tag.not.create(c.arena, try transExpr(c, scope, op_expr, .used));
},
.Extension => {
- return transExpr(c, scope, stmt.getSubExpr(), used, .l_value);
+ return transExpr(c, scope, stmt.getSubExpr(), used);
},
else => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}),
}
@@ -2698,7 +2659,7 @@ fn transCreatePreCrement(
c: *Context,
scope: *Scope,
stmt: *const clang.UnaryOperator,
- op: Node.Tag,
+ op: Tag,
used: ResultUsed,
) TransError!Node {
const op_expr = stmt.getSubExpr();
@@ -2707,8 +2668,8 @@ fn transCreatePreCrement(
// common case
// c: ++expr
// zig: expr += 1
- const lhs = try transExpr(c, scope, op_expr, .used, .r_value);
- const rhs = Node.one_literal.init();
+ const lhs = try transExpr(c, scope, op_expr, .used);
+ const rhs = Tag.one_literal.init();
return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);
}
// worst case
@@ -2722,17 +2683,17 @@ fn transCreatePreCrement(
defer block_scope.deinit();
const ref = try block_scope.makeMangledName(c, "ref");
- const expr = try transExpr(c, scope, op_expr, .used, .r_value);
- const addr_of = try Node.address_of.create(c.arena, expr);
- const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});
+ const expr = try transExpr(c, scope, 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 Node.identifier.create(c.arena, ref);
- const ref_node = try Node.deref.create(c.arena, lhs_node);
- const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used);
+ 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);
try block_scope.statements.append(node);
- const break_node = try Node.break_val.create(c.arena, .{
+ const break_node = try Tag.break_val.create(c.arena, .{
.label = block_scope.label,
.val = ref_node,
});
@@ -2744,7 +2705,7 @@ fn transCreatePostCrement(
c: *Context,
scope: *Scope,
stmt: *const clang.UnaryOperator,
- op: Node.Tag,
+ op: Tag,
used: ResultUsed,
) TransError!Node {
const op_expr = stmt.getSubExpr();
@@ -2753,8 +2714,8 @@ fn transCreatePostCrement(
// common case
// c: expr++
// zig: expr += 1
- const lhs = try transExpr(c, scope, op_expr, .used, .r_value);
- const rhs = Node.one_literal.init();
+ const lhs = try transExpr(c, scope, op_expr, .used);
+ const rhs = Tag.one_literal.init();
return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);
}
// worst case
@@ -2769,24 +2730,24 @@ fn transCreatePostCrement(
defer block_scope.deinit();
const ref = try block_scope.makeMangledName(c, "ref");
- const expr = try transExpr(c, scope, op_expr, .used, .r_value);
- const addr_of = try Node.address_of.create(c.arena, expr);
- const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});
+ const expr = try transExpr(c, scope, 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 Node.identifier.create(c.arena, ref);
- const ref_node = try Node.deref.create(c.arena, lhs_node);
+ const lhs_node = try Tag.identifier.create(c.arena, ref);
+ const ref_node = try Tag.deref.create(c.arena, lhs_node);
const tmp = try block_scope.makeMangledName(c, "tmp");
- const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node});
+ 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, Node.one_literal.init(), .used);
+ const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used);
try block_scope.statements.append(node);
- const break_node = try Node.break_val.create(c.arena, .{
+ const break_node = try Tag.break_val.create(c.arena, .{
.label = block_scope.label,
- .val = try Node.identifier.create(c.arena, tmp),
+ .val = try Tag.identifier.create(c.arena, tmp),
});
try block_scope.statements.append(break_node);
return block_scope.complete(c);
@@ -2795,26 +2756,26 @@ fn transCreatePostCrement(
fn transCompoundAssignOperator(c: *Context, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!Node {
switch (stmt.getOpcode()) {
.MulAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))
- return transCreateCompoundAssign(c, scope, stmt, .assign_mul_wrap, used)
+ return transCreateCompoundAssign(c, scope, stmt, .mul_wrap_assign, used)
else
- return transCreateCompoundAssign(c, scope, stmt, .assign_mul, used),
+ return transCreateCompoundAssign(c, scope, stmt, .mul_assign, used),
.AddAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))
- return transCreateCompoundAssign(c, scope, stmt, .assign_add_wrap, used)
+ return transCreateCompoundAssign(c, scope, stmt, .add_wrap_assign, used)
else
- return transCreateCompoundAssign(c, scope, stmt, .assign_add, used),
+ return transCreateCompoundAssign(c, scope, stmt, .add_assign, used),
.SubAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))
- return transCreateCompoundAssign(c, scope, stmt, .assign_sub_wrap, used)
+ return transCreateCompoundAssign(c, scope, stmt, .sub_wrap_assign, used)
else
- return transCreateCompoundAssign(c, scope, stmt, .assign_sub, used),
- .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_div, used),
- .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_mod, used),
- .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shl, used),
- .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shr, used),
- .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_and, used),
- .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_xor, used),
- .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_or, used),
+ return transCreateCompoundAssign(c, scope, stmt, .sub_assign, used),
+ .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .div_assign, used),
+ .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .mod_assign, used),
+ .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .shl_assign, used),
+ .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .shr_assign, used),
+ .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_and_assign, used),
+ .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_xor_assign, used),
+ .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_or_assign, used),
else => return fail(
- rp,
+ c,
error.UnsupportedTranslation,
stmt.getBeginLoc(),
"unsupported C translation {}",
@@ -2827,12 +2788,12 @@ fn transCreateCompoundAssign(
c: *Context,
scope: *Scope,
stmt: *const clang.CompoundAssignOperator,
- op: Node.Tag,
+ op: Tag,
used: ResultUsed,
) TransError!Node {
- const is_shift = op == .assign_shl or op == .assign_shr;
- const is_div = op == .assign_div;
- const is_mod = op == .assign_mod;
+ const is_shift = op == .shl_assign or op == .shr_assign;
+ const is_div = op == .div_assign;
+ const is_mod = op == .mod_assign;
const lhs = stmt.getLHS();
const rhs = stmt.getRHS();
const loc = stmt.getBeginLoc();
@@ -2849,21 +2810,21 @@ fn transCreateCompoundAssign(
// c: lhs += rhs
// zig: lhs += rhs
if ((is_mod or is_div) and is_signed) {
- const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);
- const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);
+ const lhs_node = try transExpr(c, scope, lhs, .used);
+ const rhs_node = try transExpr(c, scope, rhs, .used);
const builtin = if (is_mod)
- try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
+ try Tag.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
else
- try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
+ try Tag.div_trunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
return transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);
}
- const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);
+ const lhs_node = try transExpr(c, scope, lhs, .used);
var rhs_node = if (is_shift or requires_int_cast)
- try transExprCoercing(c, scope, rhs, .used, .r_value)
+ try transExprCoercing(c, scope, rhs, .used)
else
- try transExpr(c, scope, rhs, .used, .r_value);
+ try transExpr(c, scope, rhs, .used);
if (is_shift or requires_int_cast) {
// @intCast(rhs)
@@ -2871,11 +2832,11 @@ fn transCreateCompoundAssign(
try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
else
try transQualType(c, getExprQualType(c, lhs), loc);
-
- rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
+
+ rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
}
- return transCreateNodeInfixOp(c, scope, assign_op, lhs_node, rhs_node, .used);
+ return transCreateNodeInfixOp(c, scope, op, lhs_node, rhs_node, .used);
}
// worst case
// c: lhs += rhs
@@ -2888,25 +2849,25 @@ fn transCreateCompoundAssign(
defer block_scope.deinit();
const ref = try block_scope.makeMangledName(c, "ref");
- const expr = try transExpr(c, scope, op_expr, .used, .r_value);
- const addr_of = try Node.address_of.create(c.arena, expr);
- const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});
+ const expr = try transExpr(c, scope, 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);
- const lhs_node = try Node.identifier.create(c.arena, ref);
- const ref_node = try Node.deref.create(c.arena, lhs_node);
+ const lhs_node = try Tag.identifier.create(c.arena, ref);
+ 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, .r_value);
+ const rhs_node = try transExpr(c, scope, rhs, .used);
const builtin = if (is_mod)
- try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
+ try Tag.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
else
- try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
+ try Tag.div_trunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);
try block_scope.statements.append(assign);
} else {
- var rhs_node = try transExpr(c, scope, rhs, .used, .r_value);
+ var rhs_node = try transExpr(c, scope, rhs, .used);
if (is_shift or requires_int_cast) {
// @intCast(rhs)
@@ -2914,15 +2875,15 @@ fn transCreateCompoundAssign(
try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
else
try transQualType(c, getExprQualType(c, lhs), loc);
-
- rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
+
+ 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);
try block_scope.statements.append(assign);
}
- const break_node = try Node.break_val.create(c.arena, .{
+ const break_node = try Tag.break_val.create(c.arena, .{
.label = block_scope.label,
.val = ref_node,
});
@@ -2941,7 +2902,7 @@ fn transCPtrCast(
const child_type = ty.getPointeeType();
const src_ty = src_type.getTypePtr();
const src_child_type = src_ty.getPointeeType();
- const dst_type = try transType(c, ty, loc);
+ const dst_type_node = try transType(c, ty, loc);
if ((src_child_type.isConstQualified() and
!child_type.isConstQualified()) or
@@ -2949,8 +2910,8 @@ fn transCPtrCast(
!child_type.isVolatileQualified()))
{
// Casting away const or volatile requires us to use @intToPtr
- const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr);
- const int_to_ptr = try Node.int_to_ptr.create(c.arena, .{ .lhs = dst_type, .rhs = ptr_to_int });
+ const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
+ const int_to_ptr = try Tag.int_to_ptr.create(c.arena, .{ .lhs = dst_type_node, .rhs = ptr_to_int });
return int_to_ptr;
} else {
// Implicit downcasting from higher to lower alignment values is forbidden,
@@ -2963,17 +2924,17 @@ fn transCPtrCast(
expr
else blk: {
const child_type_node = try transQualType(c, child_type, loc);
- const alignof = try Node.alignof.create(c.arena, child_type_node);
- const align_cast = try Node.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });
+ const alignof = try Tag.alignof.create(c.arena, child_type_node);
+ const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });
break :blk align_cast;
};
- return Node.ptr_cast.create(c.arena, .{ .lhs = dst_type, .rhs = rhs });
+ return Tag.ptr_cast.create(c.arena, .{ .lhs = dst_type_node, .rhs = rhs });
}
}
fn transBreak(c: *Context, scope: *Scope) TransError!Node {
const break_scope = scope.getBreakableScope();
- const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {
+ const label_text: ?[]const u8 = if (break_scope.id == .@"switch") blk: {
const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);
const block_scope = try scope.findBlockScope(c);
swtch.switch_label = try block_scope.makeMangledName(c, "switch");
@@ -2981,20 +2942,20 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node {
} else
null;
- return Node.@"break".create(c.arena, label_text);
+ return Tag.@"break".create(c.arena, label_text);
}
fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node {
// TODO use something more accurate
const dbl = stmt.getValueAsApproximateDouble();
const node = try transCreateNodeNumber(c, dbl);
- return maybeSuppressResult(c, scope, used, &node.base);
+ return maybeSuppressResult(c, scope, used, node);
}
fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node {
// GNU extension of the ternary operator where the middle expression is
// omitted, the conditition itself is returned if it evaluates to true
- const qt = @ptrCast(*const clang.Stmt, stmt).getType();
+ const qt = @ptrCast(*const clang.Expr, stmt).getType();
const res_is_bool = qualTypeIsBoolean(qt);
const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);
const cond_expr = casted_stmt.getCond();
@@ -3010,26 +2971,33 @@ fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang
defer block_scope.deinit();
const mangled_name = try block_scope.makeMangledName(c, "cond_temp");
- const init_node = try transExpr(c, &block_scope.base, cond_expr, .used, .r_value);
- const ref_decl = try Node.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node});
+ const init_node = try transExpr(c, &block_scope.base, cond_expr, .used);
+ const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node });
try block_scope.statements.append(ref_decl);
+ var cond_scope = Scope.Condition{
+ .base = .{
+ .parent = &block_scope.base,
+ .id = .condition,
+ },
+ };
+ defer cond_scope.deinit();
const cond_node = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
- var then_body = try Node.identifier.create(c.arena, mangled_name);
+ var then_body = try Tag.identifier.create(c.arena, mangled_name);
if (!res_is_bool and isBoolRes(init_node)) {
- then_body = try Node.bool_to_int.create(c.arena, then_body);
+ then_body = try Tag.bool_to_int.create(c.arena, then_body);
}
- var else_body = try transExpr(c, &block_scope.base, false_expr, .used, .r_value);
+ var else_body = try transExpr(c, &block_scope.base, false_expr, .used);
if (!res_is_bool and isBoolRes(else_body)) {
- else_body = try Node.bool_to_int.create(c.arena, else_body);
+ else_body = try Tag.bool_to_int.create(c.arena, else_body);
}
- const if_node = try Node.@"if".create(c.arena, .{
- .cond = cond,
+ const if_node = try Tag.@"if".create(c.arena, .{
+ .cond = cond_node,
.then = then_body,
.@"else" = else_body,
});
- const break_node = try Node.break_val.create(c.arena, .{
+ const break_node = try Tag.break_val.create(c.arena, .{
.label = block_scope.label,
.val = if_node,
});
@@ -3042,31 +3010,31 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi
var cond_scope = Scope.Condition{
.base = .{
.parent = scope,
- .id = .Condition,
+ .id = .condition,
},
};
defer cond_scope.deinit();
- const qt = @ptrCast(*const clang.Stmt, stmt).getType();
+ const qt = @ptrCast(*const clang.Expr, stmt).getType();
const res_is_bool = qualTypeIsBoolean(qt);
const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);
const cond_expr = casted_stmt.getCond();
const true_expr = casted_stmt.getTrueExpr();
const false_expr = casted_stmt.getFalseExpr();
- const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value);
+ const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
- var then_body = try transExpr(c, scope, true_expr, .used, .r_value);
+ var then_body = try transExpr(c, scope, true_expr, .used);
if (!res_is_bool and isBoolRes(then_body)) {
- then_body = try Node.bool_to_int.create(c.arena, then_body);
+ then_body = try Tag.bool_to_int.create(c.arena, then_body);
}
- var else_body = try transExpr(c, scope, false_expr, .used, .r_value);
+ var else_body = try transExpr(c, scope, false_expr, .used);
if (!res_is_bool and isBoolRes(else_body)) {
- else_body = try Node.bool_to_int.create(c.arena, else_body);
+ else_body = try Tag.bool_to_int.create(c.arena, else_body);
}
- const if_node = try Node.@"if".create(c.arena, .{
+ const if_node = try Tag.@"if".create(c.arena, .{
.cond = cond,
.then = then_body,
.@"else" = else_body,
@@ -3081,7 +3049,7 @@ fn maybeSuppressResult(
result: Node,
) TransError!Node {
if (used == .used) return result;
- return Node.ignore.create(c.arena, result);
+ return Tag.ignore.create(c.arena, result);
}
fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
@@ -3100,19 +3068,19 @@ fn transQualTypeInitialized(
const ty = qt.getTypePtr();
if (ty.getTypeClass() == .IncompleteArray) {
const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);
- const elem_ty = incomplete_array_ty.getElementType().getTypePtr();
+ const elem_ty = try transType(c, incomplete_array_ty.getElementType().getTypePtr(), source_loc);
switch (decl_init.getStmtClass()) {
.StringLiteralClass => {
const string_lit = @ptrCast(*const clang.StringLiteral, decl_init);
const string_lit_size = string_lit.getLength() + 1; // +1 for null terminator
const array_size = @intCast(usize, string_lit_size);
- return Node.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty });
+ return Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty });
},
.InitListExprClass => {
const init_expr = @ptrCast(*const clang.InitListExpr, decl_init);
const size = init_expr.getNumInits();
- return Node.array_type.create(c.arena, .{ .len = size, .elem_type = elem_ty });
+ return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_ty });
},
else => {},
}
@@ -3135,7 +3103,7 @@ fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) Typ
fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!Node {
assert(ty.getTypeClass() == .Builtin);
const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
- return Node.type.create(c.arena, switch (builtin_ty.getKind()) {
+ return Tag.type.create(c.arena, switch (builtin_ty.getKind()) {
.Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8",
.UShort, .Short => if (is_signed) "c_short" else "c_ushort",
.UInt, .Int => if (is_signed) "c_int" else "c_uint",
@@ -3214,11 +3182,11 @@ fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.Sourc
if (int_bit_width != 0) {
// we can perform the log2 now.
const cast_bit_width = math.log2_int(u64, int_bit_width);
- return Node.log2_int_type.create(c.arena, cast_bit_width);
+ return Tag.log2_int_type.create(c.arena, cast_bit_width);
}
const zig_type = try transQualType(c, qt, source_loc);
- return Node.std_math_Log2Int.create(c.arena, zig_type);
+ return Tag.std_math_Log2Int.create(c.arena, zig_type);
}
fn qualTypeChildIsFnProto(qt: clang.QualType) bool {
@@ -3392,10 +3360,10 @@ fn transCreateNodeAssign(
// c: lhs = rhs
// zig: lhs = rhs
if (result_used == .unused) {
- const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);
- var rhs_node = try transExprCoercing(c, scope, rhs, .used, .r_value);
+ const lhs_node = try transExpr(c, scope, lhs, .used);
+ var rhs_node = try transExprCoercing(c, scope, rhs, .used);
if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) {
- rhs_node = try Node.bool_to_int.create(c.arena, rhs_node);
+ rhs_node = try Tag.bool_to_int.create(c.arena, rhs_node);
}
return transCreateNodeInfixOp(c, scope, .assign, lhs_node, rhs_node, .used);
}
@@ -3411,17 +3379,16 @@ fn transCreateNodeAssign(
defer block_scope.deinit();
const tmp = try block_scope.makeMangledName(c, "tmp");
- const rhs = try transExpr(c, scope, op_expr, .used, .r_value);
- const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = rhs});
+ const rhs_node = try transExpr(c, scope, rhs, .used);
+ const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = rhs_node });
try block_scope.statements.append(tmp_decl);
-
- const lhs = try transExpr(c, &block_scope.base, lhs, .used, .l_value);
- const tmp_ident = try Node.identifier.create(c.arena, tmp);
- const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs, tmp_iden, .used);
+ const lhs_node = try transExpr(c, &block_scope.base, lhs, .used);
+ const tmp_ident = try Tag.identifier.create(c.arena, tmp);
+ const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs_node, tmp_ident, .used);
try block_scope.statements.append(assign);
- const break_node = try Node.break_val.create(c.arena, .{
+ const break_node = try Tag.break_val.create(c.arena, .{
.label = block_scope.label,
.val = tmp_ident,
});
@@ -3432,7 +3399,7 @@ fn transCreateNodeAssign(
fn transCreateNodeInfixOp(
c: *Context,
scope: *Scope,
- op: ast.Node.Tag,
+ op: Tag,
lhs: Node,
rhs: Node,
used: ResultUsed,
@@ -3452,13 +3419,13 @@ fn transCreateNodeBoolInfixOp(
c: *Context,
scope: *Scope,
stmt: *const clang.BinaryOperator,
- op: ast.Node.Tag,
+ op: Tag,
used: ResultUsed,
) !Node {
- std.debug.assert(op == .bool_and or op == .bool_or);
+ std.debug.assert(op == .@"and" or op == .@"or");
- const lhs = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value);
- const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value);
+ const lhs = try transBoolExpr(c, scope, stmt.getLHS(), .used);
+ const rhs = try transBoolExpr(c, scope, stmt.getRHS(), .used);
return transCreateNodeInfixOp(c, scope, op, lhs, rhs, used);
}
@@ -3503,22 +3470,22 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node {
const str = big.toStringAlloc(c.arena, 10, false) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
};
- return Node.int_literal.create(c.arena, str);
+ return Tag.number_literal.create(c.arena, str);
}
fn transCreateNodeNumber(c: *Context, int: anytype) !Node {
const fmt_s = if (comptime std.meta.trait.isNumber(@TypeOf(int))) "{d}" else "{s}";
const str = try std.fmt.allocPrint(c.arena, fmt_s, .{int});
- return Node.int_literal.create(c.arena, str);
+ return Tag.number_literal.create(c.arena, str);
}
fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: *ast.Payload.Func) !Node {
const scope = &c.global_scope.base;
- var fn_params = std.ArrayList(Node).init(c.gpa);
+ var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
defer fn_params.deinit();
- for (proto_alias.params()) |param, i| {
+ for (proto_alias.data.params) |param, i| {
const param_name = param.name orelse
try std.fmt.allocPrint(c.arena, "arg_{d}", .{c.getMangle()});
@@ -3529,29 +3496,29 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias:
});
}
- const init = if (value.castTag(.var_decl)) |v|
- v.data.init
- else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|
+ const init = if (ref.castTag(.var_decl)) |v|
+ v.data.init.?
+ else if (ref.castTag(.var_simple) orelse ref.castTag(.pub_var_simple)) |v|
v.data.init
else
unreachable;
- const unwrap_expr = try Node.unwrap.create(c.arena, init);
- const call_params = try c.arena.alloc(Node, fn_params.items.len);
+ const unwrap_expr = try Tag.unwrap.create(c.arena, init);
+ const args = try c.arena.alloc(Node, fn_params.items.len);
for (fn_params.items) |param, i| {
- call_params[i] = try Node.identifier.create(c.arena, param.name);
+ args[i] = try Tag.identifier.create(c.arena, param.name.?);
}
- const call_expr = try Node.call.create(c.arean, .{
+ const call_expr = try Tag.call.create(c.arena, .{
.lhs = unwrap_expr,
- .args = call_params,
+ .args = args,
});
- const return_expr = try Node.@"return".create(c.arean, call_expr);
- const block = try Node.block_single.create(c.arean, return_expr);
+ const return_expr = try Tag.@"return".create(c.arena, call_expr);
+ const block = try Tag.block_single.create(c.arena, return_expr);
- return Node.pub_inline_fn.create(c.arena, .{
+ return Tag.pub_inline_fn.create(c.arena, .{
.name = name,
- .params = try c.arena.dupe(ast.Node.Param, fn_params.items),
- .return_type = proto_alias.return_type,
+ .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
+ .return_type = proto_alias.data.return_type,
.body = block,
});
}
@@ -3560,7 +3527,7 @@ fn transCreateNodeShiftOp(
c: *Context,
scope: *Scope,
stmt: *const clang.BinaryOperator,
- op: Node.Tag,
+ op: Tag,
used: ResultUsed,
) !Node {
std.debug.assert(op == .shl or op == .shr);
@@ -3570,11 +3537,11 @@ fn transCreateNodeShiftOp(
const rhs_location = rhs_expr.getBeginLoc();
// lhs >> @as(u5, rh)
- const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value);
+ const lhs = try transExpr(c, scope, lhs_expr, .used);
const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);
- const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value);
- const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
+ const rhs = try transExprCoercing(c, scope, rhs_expr, .used);
+ const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);
}
@@ -3583,7 +3550,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
switch (ty.getTypeClass()) {
.Builtin => {
const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
- return Node.type.create(c.arena, switch (builtin_ty.getKind()) {
+ return Tag.type.create(c.arena, switch (builtin_ty.getKind()) {
.Void => "c_void",
.Bool => "bool",
.Char_U, .UChar, .Char_S, .Char8 => "u8",
@@ -3608,11 +3575,13 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
},
.FunctionProto => {
const fn_proto_ty = @ptrCast(*const clang.FunctionProtoType, ty);
- return transFnProto(c, null, fn_proto_ty, source_loc, null, false);
+ const fn_proto = try transFnProto(c, null, fn_proto_ty, source_loc, null, false);
+ return Node.initPayload(&fn_proto.base);
},
.FunctionNoProto => {
const fn_no_proto_ty = @ptrCast(*const clang.FunctionType, ty);
- return transFnNoProto(c, fn_no_proto_ty, source_loc, null, false);
+ const fn_proto = try transFnNoProto(c, fn_no_proto_ty, source_loc, null, false);
+ return Node.initPayload(&fn_proto.base);
},
.Paren => {
const paren_ty = @ptrCast(*const clang.ParenType, ty);
@@ -3621,16 +3590,16 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
.Pointer => {
const child_qt = ty.getPointeeType();
if (qualTypeChildIsFnProto(child_qt)) {
- return Node.optional_type.create(c.arena, try transQualType(c, child_qt, source_loc));
+ return Tag.optional_type.create(c.arena, try transQualType(c, child_qt, source_loc));
}
const is_const = child_qt.isConstQualified();
const is_volatile = child_qt.isVolatileQualified();
const elem_type = try transQualType(c, child_qt, source_loc);
- if (typeIsOpaque(rp.c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(rp.c, child_qt)) {
- return Node.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
+ if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {
+ return Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
}
- return Node.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
+ return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
},
.ConstantArray => {
const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);
@@ -3639,7 +3608,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
const size = size_ap_int.getLimitedValue(math.maxInt(usize));
const elem_type = try transType(c, const_arr_ty.getElementType().getTypePtr(), source_loc);
- return Node.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });
+ return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });
},
.IncompleteArray => {
const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);
@@ -3649,7 +3618,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
const is_volatile = child_qt.isVolatileQualified();
const elem_type = try transQualType(c, child_qt, source_loc);
- return Node.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
+ return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
},
.Typedef => {
const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
@@ -3690,7 +3659,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
},
else => {
const type_name = c.str(ty.getTypeClassName());
- return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
+ return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name});
},
}
}
@@ -3770,7 +3739,7 @@ fn transCC(
.AAPCS => return CallingConvention.AAPCS,
.AAPCS_VFP => return CallingConvention.AAPCSVFP,
else => return fail(
- rp,
+ c,
error.UnsupportedType,
source_loc,
"unsupported calling convention: {s}",
@@ -3786,7 +3755,7 @@ fn transFnProto(
source_loc: clang.SourceLocation,
fn_decl_context: ?FnDeclContext,
is_pub: bool,
-) !Node.FnProto {
+) !*ast.Payload.Func {
const fn_ty = @ptrCast(*const clang.FunctionType, fn_proto_ty);
const cc = try transCC(c, fn_ty, source_loc);
const is_var_args = fn_proto_ty.isVariadic();
@@ -3799,7 +3768,7 @@ fn transFnNoProto(
source_loc: clang.SourceLocation,
fn_decl_context: ?FnDeclContext,
is_pub: bool,
-) !Node.FnProto {
+) !*ast.Payload.Func {
const cc = try transCC(c, fn_ty, source_loc);
const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static) else true;
return finishTransFnProto(c, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
@@ -3822,7 +3791,7 @@ fn finishTransFnProto(
// TODO check for always_inline attribute
// TODO check for align attribute
- var fn_params = std.ArrayList(ast.Payload.Func.Param).init(c.gpa);
+ var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
defer fn_params.deinit();
const param_count: usize = if (fn_proto_ty != null) fn_proto_ty.?.getNumParams() else 0;
try fn_params.ensureCapacity(param_count);
@@ -3861,7 +3830,7 @@ fn finishTransFnProto(
break :blk null;
};
- const alignment: c_uint = blk: {
+ const alignment = blk: {
if (fn_decl) |decl| {
const alignment = decl.getAlignedAttribute(c.clang_context);
if (alignment != 0) {
@@ -3876,16 +3845,16 @@ fn finishTransFnProto(
const return_type_node = blk: {
if (fn_ty.getNoReturnAttr()) {
- break :blk Node.noreturn_type.init();
+ break :blk Tag.noreturn_type.init();
} else {
const return_qt = fn_ty.getReturnType();
if (isCVoid(return_qt)) {
// convert primitive c_void to actual void (only for return type)
- break :blk Node.void_type.init();
+ break :blk Tag.void_type.init();
} else {
break :blk transQualType(c, return_qt, source_loc) catch |err| switch (err) {
error.UnsupportedType => {
- try warn(c, source_loc, "unsupported function proto return type", .{});
+ try warn(c, &c.global_scope.base, source_loc, "unsupported function proto return type", .{});
return err;
},
error.OutOfMemory => |e| return e,
@@ -3893,26 +3862,31 @@ fn finishTransFnProto(
}
}
};
-
- return Node.func.create(c.arena, .{
- .is_pub = is_pub,
- .is_extern = is_extern,
- .is_export = is_export,
- .is_var_args = is_var_args,
- .name = name,
- .linksection_string = linksection_string,
- .explicit_callconv = explicit_callconv,
- .params = try c.arena.dupe(ast.Payload.Func.Param, fn_params.items),
- .return_type = return_node,
- .body = null,
- .alignment = alignment,
- });
+ const name: ?[]const u8 = if (fn_decl_context) |ctx| ctx.fn_name else null;
+ const payload = try c.arena.create(ast.Payload.Func);
+ payload.* = .{
+ .base = .{ .tag = .func },
+ .data = .{
+ .is_pub = is_pub,
+ .is_extern = is_extern,
+ .is_export = is_export,
+ .is_var_args = is_var_args,
+ .name = name,
+ .linksection_string = linksection_string,
+ .explicit_callconv = explicit_callconv,
+ .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
+ .return_type = return_type_node,
+ .body = null,
+ .alignment = alignment,
+ },
+ };
+ return payload;
}
fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {
const args_prefix = .{c.locStr(loc)};
- const value = std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args);
- try scope.appendNode(c.gpa, try Node.warning.create(c.arena, value));
+ const value = try std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args);
+ try scope.appendNode(try Tag.warning.create(c.arena, value));
}
fn fail(
@@ -3922,17 +3896,17 @@ fn fail(
comptime format: []const u8,
args: anytype,
) (@TypeOf(err) || error{OutOfMemory}) {
- try warn(c, source_loc, format, args);
+ try warn(c, &c.global_scope.base, source_loc, format, args);
return err;
}
-pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, comptime format: []const u8, args: anytype) !void {
+pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, comptime format: []const u8, args: anytype) Error!void {
// location
// pub const name = @compileError(msg);
- const location_comment = std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)});
- try c.global_scope.nodes.append(try Node.warning.create(c.arena, location_comment));
- const fail_msg = std.fmt.allocPrint(c.arena, format, args);
- try c.global_scope.nodes.append(try Node.fail_decl.create(c.arena, fail_msg));
+ const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)});
+ try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment));
+ const fail_msg = try std.fmt.allocPrint(c.arena, format, args);
+ try c.global_scope.nodes.append(try Tag.fail_decl.create(c.arena, fail_msg));
}
pub fn freeErrors(errors: []ClangErrMsg) void {
@@ -4075,7 +4049,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
if (last != .Eof and last != .Nl)
return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
- const var_decl = try Node.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
+ const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
_ = try c.global_scope.macro_table.put(m.name, var_decl);
}
@@ -4099,7 +4073,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
try fn_params.append(.{
.is_noalias = false,
.name = mangled_name,
- .type = Node.@"anytype".init(),
+ .type = Tag.@"anytype".init(),
});
if (m.peek().? != .Comma) break;
@@ -4119,19 +4093,19 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
const stmts = some.data.stmts;
const blk_last = stmts[stmts.len - 1];
const br = blk_last.castTag(.break_val).?;
- break :blk br.data;
+ break :blk br.data.val;
} else expr;
- const typeof = try Node.typeof.create(c.arean, typeof_arg);
- const return_expr = try Node.@"return".create(c.arena, expr);
- try block_scope.statements.append(&return_expr.base);
-
- const fn_decl = try Node.pub_inline_fn.create(c.arena, .{
+ const typeof = try Tag.typeof.create(c.arena, typeof_arg);
+ const return_expr = try Tag.@"return".create(c.arena, expr);
+ try block_scope.statements.append(return_expr);
+
+ const fn_decl = try Tag.pub_inline_fn.create(c.arena, .{
.name = m.name,
.params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
.return_type = typeof,
.body = try block_scope.complete(c),
});
- _ = try c.global_scope.macro_table.put(m.name, &fn_proto.base);
+ _ = try c.global_scope.macro_table.put(m.name, fn_decl);
}
const ParseError = Error || error{ParseError};
@@ -4149,7 +4123,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
var last = node;
while (true) {
// suppress result
- const ignore = try Node.ignore.create(c.arena, last);
+ const ignore = try Tag.ignore.create(c.arena, last);
try block_scope.statements.append(ignore);
last = try parseCCondExpr(c, m, scope);
@@ -4159,7 +4133,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
}
}
- const break_node = try Node.break_val.create(c.arena, .{
+ const break_node = try Tag.break_val.create(c.arena, .{
.label = block_scope.label,
.val = last,
});
@@ -4190,7 +4164,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
return transCreateNodeNumber(c, lit_bytes);
}
- const type_node = try Node.type.create(c.arena, switch (suffix) {
+ const type_node = try Tag.type.create(c.arena, switch (suffix) {
.u => "c_uint",
.l => "c_long",
.lu => "c_ulong",
@@ -4205,7 +4179,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
else => unreachable,
}];
const rhs = try transCreateNodeNumber(c, lit_bytes);
- return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
+ return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
},
.FloatLiteral => |suffix| {
if (lit_bytes[0] == '.')
@@ -4213,13 +4187,13 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
if (suffix == .none) {
return transCreateNodeNumber(c, lit_bytes);
}
- const type_node = try Node.type.create(c.arena, switch (suffix) {
+ const type_node = try Tag.type.create(c.arena, switch (suffix) {
.f => "f32",
.l => "c_longdouble",
else => unreachable,
});
const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1]);
- return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
+ return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
},
else => unreachable,
}
@@ -4391,56 +4365,56 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
switch (tok) {
.CharLiteral => {
if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
- return Node.char_literal.create(c.arena, try zigifyEscapeSequences(c, m));
+ return Tag.char_literal.create(c.arena, try zigifyEscapeSequences(c, m));
} else {
const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});
- return Node.int_literal.create(c.arena, str);
+ return Tag.number_literal.create(c.arena, str);
}
},
.StringLiteral => {
- return Node.string_literal.create(c.arena, try zigifyEscapeSequences(c, m));
+ return Tag.string_literal.create(c.arena, try zigifyEscapeSequences(c, m));
},
.IntegerLiteral, .FloatLiteral => {
return parseCNumLit(c, m);
},
// eventually this will be replaced by std.c.parse which will handle these correctly
- .Keyword_void => return Node.type.create(c.arena, "c_void"),
- .Keyword_bool => return Node.type.create(c.arena, "bool"),
- .Keyword_double => return Node.type.create(c.arena, "f64"),
- .Keyword_long => return Node.type.create(c.arena, "c_long"),
- .Keyword_int => return Node.type.create(c.arena, "c_int"),
- .Keyword_float => return Node.type.create(c.arena, "f32"),
- .Keyword_short => return Node.type.create(c.arena, "c_short"),
- .Keyword_char => return Node.type.create(c.arena, "u8"),
+ .Keyword_void => return Tag.type.create(c.arena, "c_void"),
+ .Keyword_bool => return Tag.type.create(c.arena, "bool"),
+ .Keyword_double => return Tag.type.create(c.arena, "f64"),
+ .Keyword_long => return Tag.type.create(c.arena, "c_long"),
+ .Keyword_int => return Tag.type.create(c.arena, "c_int"),
+ .Keyword_float => return Tag.type.create(c.arena, "f32"),
+ .Keyword_short => return Tag.type.create(c.arena, "c_short"),
+ .Keyword_char => return Tag.type.create(c.arena, "u8"),
.Keyword_unsigned => if (m.next()) |t| switch (t) {
- .Keyword_char => return Node.type.create(c.arena, "u8"),
- .Keyword_short => return Node.type.create(c.arena, "c_ushort"),
- .Keyword_int => return Node.type.create(c.arena, "c_uint"),
+ .Keyword_char => return Tag.type.create(c.arena, "u8"),
+ .Keyword_short => return Tag.type.create(c.arena, "c_ushort"),
+ .Keyword_int => return Tag.type.create(c.arena, "c_uint"),
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
_ = m.next();
- return Node.type.create(c.arena, "c_ulonglong");
- } else return Node.type.create(c.arena, "c_ulong"),
+ return Tag.type.create(c.arena, "c_ulonglong");
+ } else return Tag.type.create(c.arena, "c_ulong"),
else => {
m.i -= 1;
- return Node.type.create(c.arena, "c_uint");
+ return Tag.type.create(c.arena, "c_uint");
},
} else {
- return Node.type.create(c.arena, "c_uint");
+ return Tag.type.create(c.arena, "c_uint");
},
.Keyword_signed => if (m.next()) |t| switch (t) {
- .Keyword_char => return Node.type.create(c.arena, "i8"),
- .Keyword_short => return Node.type.create(c.arena, "c_short"),
- .Keyword_int => return Node.type.create(c.arena, "c_int"),
+ .Keyword_char => return Tag.type.create(c.arena, "i8"),
+ .Keyword_short => return Tag.type.create(c.arena, "c_short"),
+ .Keyword_int => return Tag.type.create(c.arena, "c_int"),
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
_ = m.next();
- return Node.type.create(c.arena, "c_longlong");
- } else return Node.type.create(c.arena, "c_long"),
+ return Tag.type.create(c.arena, "c_longlong");
+ } else return Tag.type.create(c.arena, "c_long"),
else => {
m.i -= 1;
- return Node.type.create(c.arena, "c_int");
+ return Tag.type.create(c.arena, "c_int");
},
} else {
- return Node.type.create(c.arena, "c_int");
+ return Tag.type.create(c.arena, "c_int");
},
.Keyword_enum, .Keyword_struct, .Keyword_union => {
// struct Foo will be declared as struct_Foo by transRecordDecl
@@ -4451,11 +4425,11 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
}
const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
- return Node.identifier.create(c.arena, name);
+ return Tag.identifier.create(c.arena, name);
},
.Identifier => {
const mangled_name = scope.getAlias(slice);
- return Node.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
+ return Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
},
.LParen => {
const inner_node = try parseCExpr(c, m, scope);
@@ -4492,7 +4466,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
return error.ParseError;
}
- return Node.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });
+ return Tag.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });
},
else => {
try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});
@@ -4511,7 +4485,7 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
.StringLiteral, .Identifier => {},
else => break,
}
- node = try Node.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });
+ node = try Tag.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });
}
return node;
}
@@ -4521,7 +4495,7 @@ fn macroBoolToInt(c: *Context, node: Node) !Node {
return node;
}
- return Node.bool_to_int.create(c.arena, node);
+ return Tag.bool_to_int.create(c.arena, node);
}
fn macroIntToBool(c: *Context, node: Node) !Node {
@@ -4529,7 +4503,7 @@ fn macroIntToBool(c: *Context, node: Node) !Node {
return node;
}
- return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });
+ return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
}
fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
@@ -4545,7 +4519,7 @@ fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
return error.ParseError;
}
const else_body = try parseCCondExpr(c, m, scope);
- return Node.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });
+ return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });
}
fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
@@ -4553,7 +4527,7 @@ fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
while (m.next().? == .PipePipe) {
const lhs = try macroIntToBool(c, node);
const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope));
- node = try Node.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
@@ -4564,7 +4538,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
while (m.next().? == .AmpersandAmpersand) {
const lhs = try macroIntToBool(c, node);
const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope));
- node = try Node.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
@@ -4575,7 +4549,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
while (m.next().? == .Pipe) {
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCBitXorExpr(c, m, scope));
- node = try Node.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
@@ -4586,7 +4560,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
while (m.next().? == .Caret) {
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCBitAndExpr(c, m, scope));
- node = try Node.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
@@ -4597,7 +4571,7 @@ fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
while (m.next().? == .Ampersand) {
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCEqExpr(c, m, scope));
- node = try Node.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
m.i -= 1;
return node;
@@ -4611,13 +4585,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
- node = try Node.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.EqualEqual => {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
- node = try Node.equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
@@ -4632,25 +4606,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
- node = try Node.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketRightEqual => {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
- node = try Node.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketLeft => {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
- node = try Node.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketLeftEqual => {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
- node = try Node.less_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.less_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
@@ -4665,13 +4639,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
- node = try Node.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.AngleBracketAngleBracketRight => {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
- node = try Node.shr.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.shr.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
@@ -4686,13 +4660,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
- node = try Node.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.Minus => {
_ = m.next();
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
- node = try Node.sub.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.sub.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => return node,
}
@@ -4711,14 +4685,14 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
const prev_id = m.list[m.i - 1].id;
if (prev_id == .Keyword_void) {
- const ptr = try Node.single_pointer.create(c.arena, .{
+ const ptr = try Tag.single_pointer.create(c.arena, .{
.is_const = false,
.is_volatile = false,
.elem_type = node,
});
- return Node.optional_type.create(c.arena, ptr);
+ return Tag.optional_type.create(c.arena, ptr);
} else {
- return Node.c_pointer.create(c.arena, .{
+ return Tag.c_pointer.create(c.arena, .{
.is_const = false,
.is_volatile = false,
.elem_type = node,
@@ -4728,18 +4702,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
// expr * expr
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
- node = try Node.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
}
},
.Slash => {
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
- node = try Node.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
.Percent => {
const lhs = try macroBoolToInt(c, node);
const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
- node = try Node.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
+ node = try Tag.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
},
else => {
m.i -= 1;
@@ -4759,8 +4733,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
return error.ParseError;
}
- const ident = try Node.identifier.create(c.arena, m.slice());
- node = try Node.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });
+ const ident = try Tag.identifier.create(c.arena, m.slice());
+ node = try Tag.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });
},
.Arrow => {
if (m.next().? != .Identifier) {
@@ -4768,20 +4742,20 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
return error.ParseError;
}
- const deref = try Node.deref.create(c.arena, node);
- const ident = try Node.identifier.create(c.arena, m.slice());
- node = try Node.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident });
+ 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 });
},
.LBracket => {
const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));
- node = try Node.array_access.create(c.arena, .{ .lhs = node, .rhs = index });
+ node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index });
},
.LParen => {
- var call_params = std.ArrayList(Node).init(c.gpa);
- defer call_params.deinit();
+ var args = std.ArrayList(Node).init(c.gpa);
+ defer args.deinit();
while (true) {
const arg = try parseCCondExpr(c, m, scope);
- try call_params.append(arg);
+ try args.append(arg);
switch (m.next().?) {
.Comma => {},
.RParen => break,
@@ -4791,7 +4765,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
},
}
}
- node = try Node.call.create(c.arena, .{ .lhs = node, .rhs = try c.arena.dupe(Node, call_params.items) });
+ node = try Tag.call.create(c.arena, .{ .lhs = node, .args = try c.arena.dupe(Node, args.items) });
},
.LBrace => {
var init_vals = std.ArrayList(Node).init(c.gpa);
@@ -4809,8 +4783,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
},
}
}
- const tuple_node = try Node.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items));
- node = try Node.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });
+ const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items));
+ node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });
},
.PlusPlus, .MinusMinus => {
try m.fail(c, "TODO postfix inc/dec expr", .{});
@@ -4828,24 +4802,24 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
switch (m.next().?) {
.Bang => {
const operand = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
- return Node.not.create(c.arena, operand);
+ return Tag.not.create(c.arena, operand);
},
.Minus => {
const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
- return Node.negate.create(c.arena, operand);
+ return Tag.negate.create(c.arena, operand);
},
.Plus => return try parseCUnaryExpr(c, m, scope),
.Tilde => {
const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
- return Node.bit_not.create(c.arena, operand);
+ return Tag.bit_not.create(c.arena, operand);
},
.Asterisk => {
const operand = try parseCUnaryExpr(c, m, scope);
- return Node.deref.create(c.arena, operand);
+ return Tag.deref.create(c.arena, operand);
},
.Ampersand => {
const operand = try parseCUnaryExpr(c, m, scope);
- return Node.address_of.create(c.arena, operand);
+ return Tag.address_of.create(c.arena, operand);
},
.Keyword_sizeof => {
const operand = if (m.peek().? == .LParen) blk: {
@@ -4860,7 +4834,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
break :blk inner;
} else try parseCUnaryExpr(c, m, scope);
- return Node.std_meta_sizeof.create(c.arena, operand);
+ return Tag.std_meta_sizeof.create(c.arena, operand);
},
.Keyword_alignof => {
// TODO this won't work if using <stdalign.h>'s
@@ -4877,7 +4851,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
return error.ParseError;
}
- return Node.alignof.create(c.arena, operand);
+ return Tag.alignof.create(c.arena, operand);
},
.PlusPlus, .MinusMinus => {
try m.fail(c, "TODO unary inc/dec expr", .{});
@@ -4902,7 +4876,7 @@ fn getContainer(c: *Context, node: Node) ?Node {
.negate,
.negate_wrap,
.array_type,
- .c_pointer,
+ .c_pointer,
.single_pointer,
=> return node,
@@ -4910,7 +4884,7 @@ fn getContainer(c: *Context, node: Node) ?Node {
const ident = node.castTag(.identifier).?;
if (c.global_scope.sym_table.get(ident.data)) |value| {
if (value.castTag(.var_decl)) |var_decl|
- return getContainer(c, var_decl.data.init);
+ return getContainer(c, var_decl.data.init.?);
if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |var_decl|
return getContainer(c, var_decl.data.init);
}
@@ -4923,8 +4897,8 @@ fn getContainer(c: *Context, node: Node) ?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.data.name, field.data)) {
- return getContainer(c, field.type_expr.?);
+ if (mem.eql(u8, field.name, ident.data)) {
+ return getContainer(c, field.type);
}
}
}
@@ -4960,9 +4934,9 @@ fn getContainerTypeOf(c: *Context, ref: Node) ?Node {
}
fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {
- const init = if (value.castTag(.var_decl)) |v|
- v.data.init
- else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|
+ const init = if (ref.castTag(.var_decl)) |v|
+ v.data.init orelse return null
+ else if (ref.castTag(.var_simple) orelse ref.castTag(.pub_var_simple)) |v|
v.data.init
else
return null;
diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig
index 1cf014e5dc..24689c89db 100644
--- a/src/translate_c/ast.zig
+++ b/src/translate_c/ast.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const Type = @import("../type.zig").Type;
+const Allocator = std.mem.Allocator;
pub const Node = extern union {
/// If the tag value is less than Tag.no_payload_count, then no pointer
@@ -20,6 +21,8 @@ pub const Node = extern union {
one_literal,
void_type,
noreturn_type,
+ @"anytype",
+ @"continue",
/// pub usingnamespace @import("std").c.builtins;
usingnamespace_builtins,
// After this, the tag requires a payload.
@@ -40,7 +43,6 @@ pub const Node = extern union {
switch_else,
/// lhs => rhs,
switch_prong,
- @"continue",
@"break",
break_val,
@"return",
@@ -60,7 +62,6 @@ pub const Node = extern union {
container_init,
std_meta_cast,
discard,
- block,
// a + b
add,
@@ -111,8 +112,11 @@ pub const Node = extern union {
equal,
not_equal,
bit_and,
+ bit_and_assign,
bit_or,
+ bit_or_assign,
bit_xor,
+ bit_xor_assign,
array_cat,
ellipsis3,
assign,
@@ -126,7 +130,7 @@ pub const Node = extern union {
rem,
/// @divTrunc(lhs, rhs)
div_trunc,
- /// @boolToInt(lhs, rhs)
+ /// @boolToInt(operand)
bool_to_int,
/// @as(lhs, rhs)
as,
@@ -150,24 +154,26 @@ pub const Node = extern union {
ptr_to_int,
/// @alignCast(lhs, rhs)
align_cast,
+ /// @ptrCast(lhs, rhs)
+ ptr_cast,
negate,
negate_wrap,
bit_not,
not,
address_of,
- /// operand.?.*
- unwrap_deref,
+ /// .?
+ unwrap,
/// .*
deref,
block,
/// { operand }
block_single,
- @"break",
sizeof,
alignof,
+ typeof,
type,
optional_type,
@@ -185,6 +191,8 @@ pub const Node = extern union {
fail_decl,
// var actual = mangled;
arg_redecl,
+ /// pub const alias = actual;
+ alias,
/// const name = init;
typedef,
var_simple,
@@ -204,18 +212,17 @@ pub const Node = extern union {
/// _ = operand;
ignore,
- @"anytype",
pub const last_no_payload_tag = Tag.usingnamespace_builtins;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
- pub fn Type(tag: Tag) ?type {
- return switch (tag) {
+ pub fn Type(comptime t: Tag) type {
+ return switch (t) {
.null_literal,
.undefined_literal,
.opaque_literal,
.true_literal,
- .false_litral,
+ .false_literal,
.empty_block,
.usingnamespace_builtins,
.return_void,
@@ -224,6 +231,7 @@ pub const Node = extern union {
.void_type,
.noreturn_type,
.@"anytype",
+ .@"continue",
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
.std_mem_zeroes,
@@ -236,7 +244,7 @@ pub const Node = extern union {
.not,
.optional_type,
.address_of,
- .unwrap_deref,
+ .unwrap,
.deref,
.ptr_to_int,
.enum_to_int,
@@ -246,6 +254,11 @@ pub const Node = extern union {
.switch_else,
.ignore,
.block_single,
+ .std_meta_sizeof,
+ .bool_to_int,
+ .sizeof,
+ .alignof,
+ .typeof,
=> Payload.UnOp,
.add,
@@ -294,12 +307,14 @@ pub const Node = extern union {
.equal,
.not_equal,
.bit_and,
+ .bit_and_assign,
.bit_or,
+ .bit_or_assign,
.bit_xor,
+ .bit_xor_assign,
.div_trunc,
.rem,
.int_cast,
- .bool_to_int,
.as,
.truncate,
.bit_cast,
@@ -316,6 +331,7 @@ pub const Node = extern union {
.align_cast,
.array_access,
.std_mem_zeroinit,
+ .ptr_cast,
=> Payload.BinOp,
.number_literal,
@@ -324,8 +340,6 @@ pub const Node = extern union {
.identifier,
.warning,
.failed_decl,
- .sizeof,
- .alignof,
.type,
.fail_decl,
=> Payload.Value,
@@ -345,7 +359,7 @@ pub const Node = extern union {
.block => Payload.Block,
.c_pointer, .single_pointer => Payload.Pointer,
.array_type => Payload.Array,
- .arg_redecl => Payload.ArgRedecl,
+ .arg_redecl, .alias => Payload.ArgRedecl,
.log2_int_type => Payload.Log2IntType,
.typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
.enum_redecl => Payload.EnumRedecl,
@@ -375,7 +389,7 @@ pub const Node = extern union {
pub fn tag(self: Node) Tag {
if (self.tag_if_small_enough < Tag.no_payload_count) {
- return @intToEnum(Tag, @intCast(@TagType(Tag), self.tag_if_small_enough));
+ return @intToEnum(Tag, @intCast(std.meta.Tag(Tag), self.tag_if_small_enough));
} else {
return self.ptr_otherwise.tag;
}
@@ -392,16 +406,16 @@ pub const Node = extern union {
}
pub fn initPayload(payload: *Payload) Node {
- assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
+ std.debug.assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
return .{ .ptr_otherwise = payload };
}
};
pub const Payload = struct {
- tag: Tag,
+ tag: Node.Tag,
pub const Infix = struct {
- base: Node,
+ base: Payload,
data: struct {
lhs: Node,
rhs: Node,
@@ -409,17 +423,17 @@ pub const Payload = struct {
};
pub const Value = struct {
- base: Node,
+ base: Payload,
data: []const u8,
};
pub const UnOp = struct {
- base: Node,
+ base: Payload,
data: Node,
};
pub const BinOp = struct {
- base: Node,
+ base: Payload,
data: struct {
lhs: Node,
rhs: Node,
@@ -427,7 +441,7 @@ pub const Payload = struct {
};
pub const If = struct {
- base: Node = .{ .tag = .@"if" },
+ base: Payload,
data: struct {
cond: Node,
then: Node,
@@ -436,7 +450,7 @@ pub const Payload = struct {
};
pub const While = struct {
- base: Node = .{ .tag = .@"while" },
+ base: Payload,
data: struct {
cond: Node,
body: Node,
@@ -445,7 +459,7 @@ pub const Payload = struct {
};
pub const Switch = struct {
- base: Node = .{ .tag = .@"switch" },
+ base: Payload,
data: struct {
cond: Node,
cases: []Node,
@@ -453,12 +467,12 @@ pub const Payload = struct {
};
pub const Break = struct {
- base: Node = .{ .tag = .@"break" },
+ base: Payload,
data: ?[]const u8,
};
pub const BreakVal = struct {
- base: Node = .{ .tag = .break_val },
+ base: Payload,
data: struct {
label: ?[]const u8,
val: Node,
@@ -466,7 +480,7 @@ pub const Payload = struct {
};
pub const Call = struct {
- base: Node = .{.call},
+ base: Payload,
data: struct {
lhs: Node,
args: []Node,
@@ -474,7 +488,7 @@ pub const Payload = struct {
};
pub const VarDecl = struct {
- base: Node = .{ .tag = .var_decl },
+ base: Payload,
data: struct {
is_pub: bool,
is_const: bool,
@@ -489,13 +503,13 @@ pub const Payload = struct {
};
pub const Func = struct {
- base: Node = .{.func},
+ base: Payload,
data: struct {
is_pub: bool,
is_extern: bool,
is_export: bool,
is_var_args: bool,
- name: []const u8,
+ name: ?[]const u8,
linksection_string: ?[]const u8,
explicit_callconv: ?std.builtin.CallingConvention,
params: []Param,
@@ -512,7 +526,7 @@ pub const Payload = struct {
};
pub const Enum = struct {
- base: Node = .{ .tag = .@"enum" },
+ base: Payload,
data: []Field,
pub const Field = struct {
@@ -522,9 +536,9 @@ pub const Payload = struct {
};
pub const Record = struct {
- base: Node,
+ base: Payload,
data: struct {
- @"packed": bool,
+ is_packed: bool,
fields: []Field,
},
@@ -536,12 +550,12 @@ pub const Payload = struct {
};
pub const ArrayInit = struct {
- base: Node = .{ .tag = .array_init },
+ base: Payload,
data: []Node,
};
pub const ContainerInit = struct {
- base: Node = .{ .tag = .container_init },
+ base: Payload,
data: []Initializer,
pub const Initializer = struct {
@@ -551,7 +565,7 @@ pub const Payload = struct {
};
pub const Block = struct {
- base: Node,
+ base: Payload,
data: struct {
label: ?[]const u8,
stmts: []Node
@@ -559,15 +573,15 @@ pub const Payload = struct {
};
pub const Array = struct {
- base: Node,
+ base: Payload,
data: struct {
elem_type: Node,
- len: Node,
+ len: usize,
},
};
pub const Pointer = struct {
- base: Node,
+ base: Payload,
data: struct {
elem_type: Node,
is_const: bool,
@@ -576,7 +590,7 @@ pub const Payload = struct {
};
pub const ArgRedecl = struct {
- base: Node,
+ base: Payload,
data: struct {
actual: []const u8,
mangled: []const u8,
@@ -584,12 +598,12 @@ pub const Payload = struct {
};
pub const Log2IntType = struct {
- base: Node,
+ base: Payload,
data: std.math.Log2Int(u64),
};
pub const SimpleVarDecl = struct {
- base: Node,
+ base: Payload,
data: struct {
name: []const u8,
init: Node,
@@ -597,7 +611,7 @@ pub const Payload = struct {
};
pub const EnumRedecl = struct {
- base: Node,
+ base: Payload,
data: struct {
enum_val_name: []const u8,
field_name: []const u8,
@@ -606,7 +620,7 @@ pub const Payload = struct {
};
pub const ArrayFiller = struct {
- base: Node,
+ base: Payload,
data: struct {
type: Node,
filler: Node,
@@ -615,7 +629,7 @@ pub const Payload = struct {
};
pub const PubInlineFn = struct {
- base: Node,
+ base: Payload,
data: struct {
name: []const u8,
params: []Param,
@@ -626,6 +640,6 @@ pub const Payload = struct {
};
/// Converts the nodes into a Zig ast.
-pub fn render(allocator: *Allocator, nodes: []const Node) !*ast.Tree {
+pub fn render(allocator: *Allocator, nodes: []const Node) !std.zig.ast.Tree {
@panic("TODO");
}
diff --git a/src/type.zig b/src/type.zig
index 8fcaba6fad..38fe6dd3e6 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1682,6 +1682,8 @@ pub const Type = extern union {
.i32 => unreachable,
.u64 => unreachable,
.i64 => unreachable,
+ .u128 => unreachable,
+ .i128 => unreachable,
.usize => unreachable,
.isize => unreachable,
.c_short => unreachable,
@@ -2197,6 +2199,8 @@ pub const Type = extern union {
.i32 => .{ .signedness = .signed, .bits = 32 },
.u64 => .{ .signedness = .unsigned, .bits = 64 },
.i64 => .{ .signedness = .signed, .bits = 64 },
+ .u128 => .{ .signedness = .unsigned, .bits = 128 },
+ .i128 => .{ .signedness = .signed, .bits = 128 },
.usize => .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
.isize => .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
.c_short => .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },