mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-21 08:32:02 +03:00
translate-c: bunch of small fixes to get it compiling
This commit is contained in:
+582
-608
@@ -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;
|
||||
|
||||
+61
-47
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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) },
|
||||
|
||||
Reference in New Issue
Block a user