authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-12 11:23:15+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-16 16:40:06+02:00
log2a74a1ebaace8b5de1796b1756f65e421eb479a4
tree94967e6c0d2016ccb370c29845e04a4150a1cd76
parent66bbd75a8346b8a292f0d95d4b60a5d7d11b73b2
signature Commit is signed but in an unrecognized format.

translate-c: bunch of small fixes to get it compiling


3 files changed, 647 insertions(+), 655 deletions(-)

src/translate_c.zig+582-608
...@@ -10,12 +10,13 @@ const mem = std.mem;...@@ -10,12 +10,13 @@ const mem = std.mem;
10const math = std.math;10const math = std.math;
11const ast = @import("translate_c/ast.zig");11const ast = @import("translate_c/ast.zig");
12const Node = ast.Node;12const Node = ast.Node;
13const Tag = Node.Tag;
1314
14const CallingConvention = std.builtin.CallingConvention;15const CallingConvention = std.builtin.CallingConvention;
1516
16pub const ClangErrMsg = clang.Stage2ErrorMsg;17pub const ClangErrMsg = clang.Stage2ErrorMsg;
1718
18pub const Error = error{OutOfMemory};19pub const Error = std.mem.Allocator.Error;
19const TypeError = Error || error{UnsupportedType};20const TypeError = Error || error{UnsupportedType};
20const TransError = TypeError || error{UnsupportedTranslation};21const TransError = TypeError || error{UnsupportedTranslation};
2122
...@@ -30,11 +31,11 @@ const Scope = struct {...@@ -30,11 +31,11 @@ const Scope = struct {
30 parent: ?*Scope,31 parent: ?*Scope,
3132
32 const Id = enum {33 const Id = enum {
33 Switch,34 @"switch",
34 Block,35 block,
35 Root,36 root,
36 Condition,37 condition,
37 Loop,38 loop,
38 };39 };
3940
40 /// Represents an in-progress Node.Switch. This struct is stack-allocated.41 /// Represents an in-progress Node.Switch. This struct is stack-allocated.
...@@ -44,7 +45,6 @@ const Scope = struct {...@@ -44,7 +45,6 @@ const Scope = struct {
44 base: Scope,45 base: Scope,
45 pending_block: Block,46 pending_block: Block,
46 cases: std.ArrayList(Node),47 cases: std.ArrayList(Node),
47 case_index: usize,
48 switch_label: ?[]const u8,48 switch_label: ?[]const u8,
49 default_label: ?[]const u8,49 default_label: ?[]const u8,
50 };50 };
...@@ -84,7 +84,7 @@ const Scope = struct {...@@ -84,7 +84,7 @@ const Scope = struct {
84 fn init(c: *Context, parent: *Scope, labeled: bool) !Block {84 fn init(c: *Context, parent: *Scope, labeled: bool) !Block {
85 var blk = Block{85 var blk = Block{
86 .base = .{86 .base = .{
87 .id = .Block,87 .id = .block,
88 .parent = parent,88 .parent = parent,
89 },89 },
90 .statements = std.ArrayList(Node).init(c.gpa),90 .statements = std.ArrayList(Node).init(c.gpa),
...@@ -105,12 +105,12 @@ const Scope = struct {...@@ -105,12 +105,12 @@ const Scope = struct {
105 fn complete(self: *Block, c: *Context) !Node {105 fn complete(self: *Block, c: *Context) !Node {
106 // We reserve 1 extra statement if the parent is a Loop. This is in case of106 // We reserve 1 extra statement if the parent is a Loop. This is in case of
107 // do while, we want to put `if (cond) break;` at the end.107 // do while, we want to put `if (cond) break;` at the end.
108 const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .Loop);108 const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .loop);
109 const stmts = try c.arena.alloc(Node, alloc_len);109 var stmts = try c.arena.alloc(Node, alloc_len);
110 stmts.len -= 1;110 stmts.len -= 1;
111 mem.copy(Node, stmts, self.statements.items);111 mem.copy(Node, stmts, self.statements.items);
112 return Node.block.create(c.arena, .{112 return Tag.block.create(c.arena, .{
113 .lable = self.label,113 .label = self.label,
114 .stmts = stmts,114 .stmts = stmts,
115 });115 });
116 }116 }
...@@ -161,7 +161,7 @@ const Scope = struct {...@@ -161,7 +161,7 @@ const Scope = struct {
161 fn init(c: *Context) Root {161 fn init(c: *Context) Root {
162 return .{162 return .{
163 .base = .{163 .base = .{
164 .id = .Root,164 .id = .root,
165 .parent = null,165 .parent = null,
166 },166 },
167 .sym_table = SymbolTable.init(c.gpa),167 .sym_table = SymbolTable.init(c.gpa),
...@@ -195,9 +195,9 @@ const Scope = struct {...@@ -195,9 +195,9 @@ const Scope = struct {
195 var scope = inner;195 var scope = inner;
196 while (true) {196 while (true) {
197 switch (scope.id) {197 switch (scope.id) {
198 .Root => unreachable,198 .root => unreachable,
199 .Block => return @fieldParentPtr(Block, "base", scope),199 .block => return @fieldParentPtr(Block, "base", scope),
200 .Condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c),200 .condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c),
201 else => scope = scope.parent.?,201 else => scope = scope.parent.?,
202 }202 }
203 }203 }
...@@ -207,8 +207,8 @@ const Scope = struct {...@@ -207,8 +207,8 @@ const Scope = struct {
207 var scope = inner;207 var scope = inner;
208 while (true) {208 while (true) {
209 switch (scope.id) {209 switch (scope.id) {
210 .Root => unreachable,210 .root => unreachable,
211 .Block => {211 .block => {
212 const block = @fieldParentPtr(Block, "base", scope);212 const block = @fieldParentPtr(Block, "base", scope);
213 if (block.return_type) |qt| return qt;213 if (block.return_type) |qt| return qt;
214 scope = scope.parent.?;214 scope = scope.parent.?;
...@@ -220,17 +220,17 @@ const Scope = struct {...@@ -220,17 +220,17 @@ const Scope = struct {
220220
221 fn getAlias(scope: *Scope, name: []const u8) []const u8 {221 fn getAlias(scope: *Scope, name: []const u8) []const u8 {
222 return switch (scope.id) {222 return switch (scope.id) {
223 .Root => return name,223 .root => return name,
224 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),224 .block => @fieldParentPtr(Block, "base", scope).getAlias(name),
225 .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),225 .@"switch", .loop, .condition => scope.parent.?.getAlias(name),
226 };226 };
227 }227 }
228228
229 fn contains(scope: *Scope, name: []const u8) bool {229 fn contains(scope: *Scope, name: []const u8) bool {
230 return switch (scope.id) {230 return switch (scope.id) {
231 .Root => @fieldParentPtr(Root, "base", scope).contains(name),231 .root => @fieldParentPtr(Root, "base", scope).contains(name),
232 .Block => @fieldParentPtr(Block, "base", scope).contains(name),232 .block => @fieldParentPtr(Block, "base", scope).contains(name),
233 .Switch, .Loop, .Condition => scope.parent.?.contains(name),233 .@"switch", .loop, .condition => scope.parent.?.contains(name),
234 };234 };
235 }235 }
236236
...@@ -238,9 +238,9 @@ const Scope = struct {...@@ -238,9 +238,9 @@ const Scope = struct {
238 var scope = inner;238 var scope = inner;
239 while (true) {239 while (true) {
240 switch (scope.id) {240 switch (scope.id) {
241 .Root => unreachable,241 .root => unreachable,
242 .Switch => return scope,242 .@"switch" => return scope,
243 .Loop => return scope,243 .loop => return scope,
244 else => scope = scope.parent.?,244 else => scope = scope.parent.?,
245 }245 }
246 }246 }
...@@ -250,24 +250,24 @@ const Scope = struct {...@@ -250,24 +250,24 @@ const Scope = struct {
250 var scope = inner;250 var scope = inner;
251 while (true) {251 while (true) {
252 switch (scope.id) {252 switch (scope.id) {
253 .Root => unreachable,253 .root => unreachable,
254 .Switch => return @fieldParentPtr(Switch, "base", scope),254 .@"switch" => return @fieldParentPtr(Switch, "base", scope),
255 else => scope = scope.parent.?,255 else => scope = scope.parent.?,
256 }256 }
257 }257 }
258 }258 }
259259
260 /// Appends a node to the first block scope if inside a function, or to the root tree if not.260 /// Appends a node to the first block scope if inside a function, or to the root tree if not.
261 fn appendNode(scope: *Scope, node: Node) !void {261 fn appendNode(inner: *Scope, node: Node) !void {
262 var scope = inner;262 var scope = inner;
263 while (true) {263 while (true) {
264 switch (scope.id) {264 switch (scope.id) {
265 .Root => {265 .root => {
266 const root = @fieldParentPtr(Root, "base", scope).contains(name);266 const root = @fieldParentPtr(Root, "base", scope);
267 return root.nodes.append(node);267 return root.nodes.append(node);
268 },268 },
269 .Block => {269 .block => {
270 const block = @fieldParentPtr(Block, "base", scope).contains(name);270 const block = @fieldParentPtr(Block, "base", scope);
271 return block.statements.append(node);271 return block.statements.append(node);
272 },272 },
273 else => scope = scope.parent.?,273 else => scope = scope.parent.?,
...@@ -321,7 +321,7 @@ pub fn translate(...@@ -321,7 +321,7 @@ pub fn translate(
321 args_end: [*]?[*]const u8,321 args_end: [*]?[*]const u8,
322 errors: *[]ClangErrMsg,322 errors: *[]ClangErrMsg,
323 resources_path: [*:0]const u8,323 resources_path: [*:0]const u8,
324) !ast.Tree {324) !std.zig.ast.Tree {
325 const ast_unit = clang.LoadFromCommandLine(325 const ast_unit = clang.LoadFromCommandLine(
326 args_begin,326 args_begin,
327 args_end,327 args_end,
...@@ -339,14 +339,6 @@ pub fn translate(...@@ -339,14 +339,6 @@ pub fn translate(
339 var arena = std.heap.ArenaAllocator.init(gpa);339 var arena = std.heap.ArenaAllocator.init(gpa);
340 errdefer arena.deinit();340 errdefer arena.deinit();
341341
342 if (true) {
343 var x = false;
344 if (x) {
345 return error.OutOfMemory;
346 }
347 @panic("TODO update translate-c");
348 }
349
350 var context = Context{342 var context = Context{
351 .gpa = gpa,343 .gpa = gpa,
352 .arena = &arena.allocator,344 .arena = &arena.allocator,
...@@ -361,15 +353,15 @@ pub fn translate(...@@ -361,15 +353,15 @@ pub fn translate(
361 context.alias_list.deinit();353 context.alias_list.deinit();
362 context.global_names.deinit(gpa);354 context.global_names.deinit(gpa);
363 context.opaque_demotes.deinit(gpa);355 context.opaque_demotes.deinit(gpa);
364 context.global_scope.deini();356 context.global_scope.deinit();
365 }357 }
366358
367 try context.global_scope.nodes.append(try Node.usingnamespace_builtins.init());359 try context.global_scope.nodes.append(Tag.usingnamespace_builtins.init());
368360
369 try prepopulateGlobalNameTable(ast_unit, &context);361 try prepopulateGlobalNameTable(ast_unit, &context);
370362
371 if (!ast_unit.visitLocalTopLevelDecls(&context, declVisitorC)) {363 if (!ast_unit.visitLocalTopLevelDecls(&context, declVisitorC)) {
372 return context.err;364 return error.OutOfMemory;
373 }365 }
374366
375 try transPreprocessorEntities(&context, ast_unit);367 try transPreprocessorEntities(&context, ast_unit);
...@@ -377,16 +369,17 @@ pub fn translate(...@@ -377,16 +369,17 @@ pub fn translate(
377 try addMacros(&context);369 try addMacros(&context);
378 for (context.alias_list.items) |alias| {370 for (context.alias_list.items) |alias| {
379 if (!context.global_scope.sym_table.contains(alias.alias)) {371 if (!context.global_scope.sym_table.contains(alias.alias)) {
380 try createAlias(&context, alias);372 const node = try Tag.alias.create(context.arena, .{ .actual = alias.alias, .mangled = alias.name });
373 try addTopLevelDecl(&context, alias.alias, node);
381 }374 }
382 }375 }
383376
384 return ast.render(context.global_scope.nodes.items);377 return ast.render(gpa, context.global_scope.nodes.items);
385}378}
386379
387fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void {380fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void {
388 if (!ast_unit.visitLocalTopLevelDecls(c, declVisitorNamesOnlyC)) {381 if (!ast_unit.visitLocalTopLevelDecls(c, declVisitorNamesOnlyC)) {
389 return c.err;382 return error.OutOfMemory;
390 }383 }
391384
392 // TODO if we see #undef, delete it from the table385 // TODO if we see #undef, delete it from the table
...@@ -409,19 +402,13 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void {...@@ -409,19 +402,13 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void {
409402
410fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool {403fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool {
411 const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));404 const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
412 declVisitorNamesOnly(c, decl) catch |err| {405 declVisitorNamesOnly(c, decl) catch return false;
413 c.err = err;
414 return false;
415 };
416 return true;406 return true;
417}407}
418408
419fn declVisitorC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool {409fn declVisitorC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool {
420 const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));410 const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
421 declVisitor(c, decl) catch |err| {411 declVisitor(c, decl) catch return false;
422 c.err = err;
423 return false;
424 };
425 return true;412 return true;
426}413}
427414
...@@ -454,7 +441,7 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void {...@@ -454,7 +441,7 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void {
454 },441 },
455 else => {442 else => {
456 const decl_name = try c.str(decl.getDeclKindName());443 const decl_name = try c.str(decl.getDeclKindName());
457 try warn(c, decl.getLocation(), "ignoring {s} declaration", .{decl_name});444 try warn(c, &c.global_scope.base, decl.getLocation(), "ignoring {s} declaration", .{decl_name});
458 },445 },
459 }446 }
460}447}
...@@ -513,7 +500,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -513,7 +500,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
513 decl_ctx.has_body = false;500 decl_ctx.has_body = false;
514 decl_ctx.storage_class = .Extern;501 decl_ctx.storage_class = .Extern;
515 decl_ctx.is_export = false;502 decl_ctx.is_export = false;
516 try warn(c, fn_decl_loc, "TODO unable to translate variadic function, demoted to declaration", .{});503 try warn(c, &c.global_scope.base, fn_decl_loc, "TODO unable to translate variadic function, demoted to declaration", .{});
517 }504 }
518 break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {505 break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
519 error.UnsupportedType => {506 error.UnsupportedType => {
...@@ -535,7 +522,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -535,7 +522,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
535 };522 };
536523
537 if (!decl_ctx.has_body) {524 if (!decl_ctx.has_body) {
538 return addTopLevelDecl(c, fn_name, &proto_node.base);525 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
539 }526 }
540527
541 // actual function definition with body528 // actual function definition with body
...@@ -547,10 +534,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -547,10 +534,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
547 var scope = &block_scope.base;534 var scope = &block_scope.base;
548535
549 var param_id: c_uint = 0;536 var param_id: c_uint = 0;
550 for (proto_node.params()) |*param, i| {537 for (proto_node.data.params) |*param, i| {
551 const param_name = if (param.name_token) |name_tok|538 const param_name = param.name orelse
552 tokenSlice(c, name_tok)
553 else
554 return failDecl(c, fn_decl_loc, fn_name, "function {s} parameter has no name", .{fn_name});539 return failDecl(c, fn_decl_loc, fn_name, "function {s} parameter has no name", .{fn_name});
555540
556 const c_param = fn_decl.getParamDecl(param_id);541 const c_param = fn_decl.getParamDecl(param_id);
...@@ -565,7 +550,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -565,7 +550,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
565 const arg_name = try block_scope.makeMangledName(c, bare_arg_name);550 const arg_name = try block_scope.makeMangledName(c, bare_arg_name);
566 param.name = arg_name;551 param.name = arg_name;
567552
568 const redecl_node = try Node.arg_redecl.create(c.arena, .{ .actual = mangled_param_name, .mangled = arg_name });553 const redecl_node = try Tag.arg_redecl.create(c.arena, .{ .actual = mangled_param_name, .mangled = arg_name });
569 try block_scope.statements.append(redecl_node);554 try block_scope.statements.append(redecl_node);
570 }555 }
571556
...@@ -607,12 +592,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {...@@ -607,12 +592,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void {
607 error.UnsupportedType,592 error.UnsupportedType,
608 => return failDecl(c, fn_decl_loc, fn_name, "unable to create a return value for function", .{}),593 => return failDecl(c, fn_decl_loc, fn_name, "unable to create a return value for function", .{}),
609 };594 };
610 const ret = try Node.@"return".create(c.arena, rhs);595 const ret = try Tag.@"return".create(c.arena, rhs);
611 try block_scope.statements.append(ret);596 try block_scope.statements.append(ret);
612 }597 }
613598
614 proto_node.body = try block_scope.complete(c);599 proto_node.data.body = try block_scope.complete(c);
615 return addTopLevelDecl(c, fn_name, &proto_node.base);600 return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base));
616}601}
617602
618fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node {603fn 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...@@ -668,7 +653,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
668 const node_or_error = if (expr.getStmtClass() == .StringLiteralClass)653 const node_or_error = if (expr.getStmtClass() == .StringLiteralClass)
669 transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0)654 transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0)
670 else655 else
671 transExprCoercing(c, scope, expr, .used, .r_value);656 transExprCoercing(c, scope, expr, .used);
672 init_node = node_or_error catch |err| switch (err) {657 init_node = node_or_error catch |err| switch (err) {
673 error.UnsupportedTranslation,658 error.UnsupportedTranslation,
674 error.UnsupportedType,659 error.UnsupportedType,
...@@ -677,18 +662,18 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -677,18 +662,18 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
677 },662 },
678 error.OutOfMemory => |e| return e,663 error.OutOfMemory => |e| return e,
679 };664 };
680 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {665 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node.?)) {
681 init_node = try Node.bool_to_int.create(c.arena, init_node);666 init_node = try Tag.bool_to_int.create(c.arena, init_node.?);
682 }667 }
683 } else {668 } else {
684 init_node = Node.undefined_literal.init();669 init_node = Tag.undefined_literal.init();
685 }670 }
686 } else if (storage_class != .Extern) {671 } else if (storage_class != .Extern) {
687 // The C language specification states that variables with static or threadlocal672 // The C language specification states that variables with static or threadlocal
688 // storage without an initializer are initialized to a zero value.673 // storage without an initializer are initialized to a zero value.
689674
690 // @import("std").mem.zeroes(T)675 // @import("std").mem.zeroes(T)
691 init_node = try Node.std_mem_zeroes.create(c.arena, type_node);676 init_node = try Tag.std_mem_zeroes.create(c.arena, type_node);
692 }677 }
693678
694 const linksection_string = blk: {679 const linksection_string = blk: {
...@@ -708,7 +693,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -708,7 +693,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
708 break :blk null;693 break :blk null;
709 };694 };
710695
711 const node = try Node.var_decl.create(c.arena, .{696 const node = try Tag.var_decl.create(c.arena, .{
712 .is_pub = is_pub,697 .is_pub = is_pub,
713 .is_const = is_const,698 .is_const = is_const,
714 .is_extern = is_extern,699 .is_extern = is_extern,
...@@ -719,12 +704,12 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co...@@ -719,12 +704,12 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
719 .type = type_node,704 .type = type_node,
720 .init = init_node,705 .init = init_node,
721 });706 });
722 return addTopLevelDecl(c, checked_name, &node.base);707 return addTopLevelDecl(c, checked_name, node);
723}708}
724709
725fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node {710fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node {
726 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);711 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name);
727 return Node.identifier.create(c.arena, builtin_name);712 return Tag.identifier.create(c.arena, builtin_name);
728}713}
729714
730const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{715const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
...@@ -744,7 +729,7 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{...@@ -744,7 +729,7 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{
744729
745fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node {730fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node {
746 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|731 if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name|
747 return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice732 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
748733
749 const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());734 const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin());
750735
...@@ -753,17 +738,17 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev...@@ -753,17 +738,17 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev
753 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name;738 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name;
754 if (builtin_typedef_map.get(checked_name)) |builtin| {739 if (builtin_typedef_map.get(checked_name)) |builtin| {
755 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);740 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
756 return Node.identifier.create(c.arena, builtin);741 return try Tag.identifier.create(c.arena, builtin);
757 }742 }
758743
759 if (!top_level_visit) {744 if (!top_level_visit) {
760 return transCreateNodeIdentifier(c, checked_name);745 return try Tag.identifier.create(c.arena, checked_name);
761 }746 }
762747
763 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name);748 _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name);
764 const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null;749 const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null;
765 try addTopLevelDecl(c, checked_name, node);750 try addTopLevelDecl(c, checked_name, node);
766 return transCreateNodeIdentifier(c, checked_name);751 return try Tag.identifier.create(c.arena, checked_name);
767}752}
768753
769fn transCreateNodeTypedef(754fn transCreateNodeTypedef(
...@@ -782,9 +767,9 @@ fn transCreateNodeTypedef(...@@ -782,9 +767,9 @@ fn transCreateNodeTypedef(
782 error.OutOfMemory => |e| return e,767 error.OutOfMemory => |e| return e,
783 };768 };
784769
785 const payload = try c.arena.create(ast.Payload.Typedef);770 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
786 payload.* = .{771 payload.* = .{
787 .base = .{ .tag = ([2]ast.Node.Tag{ .typedef, .pub_typedef })[@boolToInt(toplevel)] },772 .base = .{ .tag = ([2]Tag{ .typedef, .pub_typedef })[@boolToInt(toplevel)] },
788 .data = .{773 .data = .{
789 .name = checked_name,774 .name = checked_name,
790 .init = init_node,775 .init = init_node,
...@@ -795,7 +780,7 @@ fn transCreateNodeTypedef(...@@ -795,7 +780,7 @@ fn transCreateNodeTypedef(
795780
796fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node {781fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node {
797 if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name|782 if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name|
798 return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice783 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
799 const record_loc = record_decl.getLocation();784 const record_loc = record_decl.getLocation();
800785
801 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, record_decl).getName_bytes_begin());786 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...@@ -815,7 +800,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
815 } else if (record_decl.isStruct()) {800 } else if (record_decl.isStruct()) {
816 container_kind_name = "struct";801 container_kind_name = "struct";
817 } else {802 } else {
818 try warn(c, record_loc, "record {s} is not a struct or union", .{bare_name});803 try warn(c, &c.global_scope.base, record_loc, "record {s} is not a struct or union", .{bare_name});
819 return null;804 return null;
820 }805 }
821806
...@@ -826,7 +811,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -826,7 +811,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
826 const init_node = blk: {811 const init_node = blk: {
827 const record_def = record_decl.getDefinition() orelse {812 const record_def = record_decl.getDefinition() orelse {
828 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});813 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
829 break :blk Node.opaque_literal.init();814 break :blk Tag.opaque_literal.init();
830 };815 };
831816
832 const is_packed = record_decl.getPackedAttribute();817 const is_packed = record_decl.getPackedAttribute();
...@@ -843,14 +828,14 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -843,14 +828,14 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
843828
844 if (field_decl.isBitField()) {829 if (field_decl.isBitField()) {
845 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});830 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
846 try warn(c, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});831 try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name});
847 break :blk Node.opaque_literal.init();832 break :blk Tag.opaque_literal.init();
848 }833 }
849834
850 if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) {835 if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) {
851 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});836 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
852 try warn(c, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});837 try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name});
853 break :blk Node.opaque_literal.init();838 break :blk Tag.opaque_literal.init();
854 }839 }
855840
856 var is_anon = false;841 var is_anon = false;
...@@ -864,8 +849,8 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -864,8 +849,8 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
864 const field_type = transQualType(c, field_qt, field_loc) catch |err| switch (err) {849 const field_type = transQualType(c, field_qt, field_loc) catch |err| switch (err) {
865 error.UnsupportedType => {850 error.UnsupportedType => {
866 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});851 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {});
867 try warn(c, record_loc, "{s} demoted to opaque type - unable to translate type of field {s}", .{ container_kind_name, raw_name });852 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 });
868 break :blk Node.opaque_literal.init();853 break :blk Tag.opaque_literal.init();
869 },854 },
870 else => |e| return e,855 else => |e| return e,
871 };856 };
...@@ -890,20 +875,20 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -890,20 +875,20 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
890 });875 });
891 }876 }
892877
893 const payload = try c.arena.create(ast.Payload.Record);878 const record_payload = try c.arena.create(ast.Payload.Record);
894 container_node.* = .{879 record_payload.* = .{
895 .base = .{ .tag = ([2]ast.Node.Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] },880 .base = .{ .tag = ([2]Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] },
896 .data = .{881 .data = .{
897 .is_packed = is_packed,882 .is_packed = is_packed,
898 .fields = try c.arena.dupe(ast.Payload.Record.Field, fields.items),883 .fields = try c.arena.dupe(ast.Payload.Record.Field, fields.items),
899 },884 },
900 };885 };
901 break :blk Node.initPayload(&container_node.base);886 break :blk Node.initPayload(&record_payload.base);
902 };887 };
903888
904 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);889 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
905 payload.* = .{890 payload.* = .{
906 .base = .{ .tag = ([2]ast.Node.Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },891 .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
907 .data = .{892 .data = .{
908 .name = name,893 .name = name,
909 .init = init_node,894 .init = init_node,
...@@ -913,12 +898,12 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod...@@ -913,12 +898,12 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod
913 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));898 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
914 if (!is_unnamed)899 if (!is_unnamed)
915 try c.alias_list.append(.{ .alias = bare_name, .name = name });900 try c.alias_list.append(.{ .alias = bare_name, .name = name });
916 return Node.identifier.create(c.arena, name);901 return try Tag.identifier.create(c.arena, name);
917}902}
918903
919fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {904fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
920 if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name|905 if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name|
921 return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice906 return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice
922 const enum_loc = enum_decl.getLocation();907 const enum_loc = enum_decl.getLocation();
923908
924 var bare_name = try c.str(@ptrCast(*const clang.NamedDecl, enum_decl).getName_bytes_begin());909 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 {...@@ -965,7 +950,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
965 else => |e| return e,950 else => |e| return e,
966 }951 }
967 else952 else
968 try Node.type.create(c.arena, "c_int");953 try Tag.type.create(c.arena, "c_int");
969954
970 it = enum_def.enumerator_begin();955 it = enum_def.enumerator_begin();
971 end_it = enum_def.enumerator_end();956 end_it = enum_def.enumerator_end();
...@@ -983,29 +968,29 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {...@@ -983,29 +968,29 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
983 else968 else
984 null;969 null;
985970
986 try fields_and_decls.append(.{971 try fields.append(.{
987 .name = field_name,972 .name = field_name,
988 .value = int_node,973 .value = int_node,
989 });974 });
990975
991 // In C each enum value is in the global namespace. So we put them there too.976 // In C each enum value is in the global namespace. So we put them there too.
992 // At this point we can rely on the enum emitting successfully.977 // At this point we can rely on the enum emitting successfully.
993 try addTopLevelDecl(c, field_name, try Node.enum_redecl.create(c.arena, .{978 try addTopLevelDecl(c, field_name, try Tag.enum_redecl.create(c.arena, .{
994 .enum_val_name = enum_val_name,979 .enum_val_name = enum_val_name,
995 .field_name = field_name,980 .field_name = field_name,
996 .enum_name = name,981 .enum_name = name,
997 }));982 }));
998 }983 }
999984
1000 break :blk try Node.@"enum".create(c.arena, try c.arena.dupe(ast.Payload.Enum.Field, fields.items));985 break :blk try Tag.@"enum".create(c.arena, try c.arena.dupe(ast.Payload.Enum.Field, fields.items));
1001 } else blk: {986 } else blk: {
1002 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});987 _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {});
1003 break :blk Node.opaque_literal.init();988 break :blk Tag.opaque_literal.init();
1004 };989 };
1005990
1006 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);991 const payload = try c.arena.create(ast.Payload.SimpleVarDecl);
1007 payload.* = .{992 payload.* = .{
1008 .base = .{ .tag = ([2]ast.Node.Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },993 .base = .{ .tag = ([2]Tag{ .var_simple, .pub_var_simple })[@boolToInt(is_pub)] },
1009 .data = .{994 .data = .{
1010 .name = name,995 .name = name,
1011 .init = init_node,996 .init = init_node,
...@@ -1015,7 +1000,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {...@@ -1015,7 +1000,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node {
1015 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));1000 try addTopLevelDecl(c, name, Node.initPayload(&payload.base));
1016 if (!is_unnamed)1001 if (!is_unnamed)
1017 try c.alias_list.append(.{ .alias = bare_name, .name = name });1002 try c.alias_list.append(.{ .alias = bare_name, .name = name });
1018 return transCreateNodeIdentifier(c, name);1003 return try Tag.identifier.create(c.arena, name);
1019}1004}
10201005
1021const ResultUsed = enum {1006const ResultUsed = enum {
...@@ -1023,31 +1008,25 @@ const ResultUsed = enum {...@@ -1023,31 +1008,25 @@ const ResultUsed = enum {
1023 unused,1008 unused,
1024};1009};
10251010
1026const LRValue = enum {
1027 l_value,
1028 r_value,
1029};
1030
1031fn transStmt(1011fn transStmt(
1032 c: *Context,1012 c: *Context,
1033 scope: *Scope,1013 scope: *Scope,
1034 stmt: *const clang.Stmt,1014 stmt: *const clang.Stmt,
1035 result_used: ResultUsed,1015 result_used: ResultUsed,
1036 lrvalue: LRValue,
1037) TransError!Node {1016) TransError!Node {
1038 const sc = stmt.getStmtClass();1017 const sc = stmt.getStmtClass();
1039 switch (sc) {1018 switch (sc) {
1040 .BinaryOperatorClass => return transBinaryOperator(c, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used),1019 .BinaryOperatorClass => return transBinaryOperator(c, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used),
1041 .CompoundStmtClass => return transCompoundStmt(c, scope, @ptrCast(*const clang.CompoundStmt, stmt)),1020 .CompoundStmtClass => return transCompoundStmt(c, scope, @ptrCast(*const clang.CompoundStmt, stmt)),
1042 .CStyleCastExprClass => return transCStyleCastExprClass(c, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used, lrvalue),1021 .CStyleCastExprClass => return transCStyleCastExprClass(c, scope, @ptrCast(*const clang.CStyleCastExpr, stmt), result_used),
1043 .DeclStmtClass => return transDeclStmt(c, scope, @ptrCast(*const clang.DeclStmt, stmt)),1022 .DeclStmtClass => return transDeclStmt(c, scope, @ptrCast(*const clang.DeclStmt, stmt)),
1044 .DeclRefExprClass => return transDeclRefExpr(c, scope, @ptrCast(*const clang.DeclRefExpr, stmt), lrvalue),1023 .DeclRefExprClass => return transDeclRefExpr(c, scope, @ptrCast(*const clang.DeclRefExpr, stmt)),
1045 .ImplicitCastExprClass => return transImplicitCastExpr(c, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used),1024 .ImplicitCastExprClass => return transImplicitCastExpr(c, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used),
1046 .IntegerLiteralClass => return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as),1025 .IntegerLiteralClass => return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as),
1047 .ReturnStmtClass => return transReturnStmt(c, scope, @ptrCast(*const clang.ReturnStmt, stmt)),1026 .ReturnStmtClass => return transReturnStmt(c, scope, @ptrCast(*const clang.ReturnStmt, stmt)),
1048 .StringLiteralClass => return transStringLiteral(c, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used),1027 .StringLiteralClass => return transStringLiteral(c, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used),
1049 .ParenExprClass => {1028 .ParenExprClass => {
1050 const expr = try transExpr(c, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used, lrvalue);1029 const expr = try transExpr(c, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used);
1051 return maybeSuppressResult(c, scope, result_used, expr);1030 return maybeSuppressResult(c, scope, result_used, expr);
1052 },1031 },
1053 .InitListExprClass => return transInitListExpr(c, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used),1032 .InitListExprClass => return transInitListExpr(c, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used),
...@@ -1056,9 +1035,9 @@ fn transStmt(...@@ -1056,9 +1035,9 @@ fn transStmt(
1056 .WhileStmtClass => return transWhileLoop(c, scope, @ptrCast(*const clang.WhileStmt, stmt)),1035 .WhileStmtClass => return transWhileLoop(c, scope, @ptrCast(*const clang.WhileStmt, stmt)),
1057 .DoStmtClass => return transDoWhileLoop(c, scope, @ptrCast(*const clang.DoStmt, stmt)),1036 .DoStmtClass => return transDoWhileLoop(c, scope, @ptrCast(*const clang.DoStmt, stmt)),
1058 .NullStmtClass => {1037 .NullStmtClass => {
1059 return Node.empty_block.init();1038 return Tag.empty_block.init();
1060 },1039 },
1061 .ContinueStmtClass => return try transCreateNodeContinue(c),1040 .ContinueStmtClass => return Tag.@"continue".init(),
1062 .BreakStmtClass => return transBreak(c, scope),1041 .BreakStmtClass => return transBreak(c, scope),
1063 .ForStmtClass => return transForLoop(c, scope, @ptrCast(*const clang.ForStmt, stmt)),1042 .ForStmtClass => return transForLoop(c, scope, @ptrCast(*const clang.ForStmt, stmt)),
1064 .FloatingLiteralClass => return transFloatingLiteral(c, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used),1043 .FloatingLiteralClass => return transFloatingLiteral(c, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used),
...@@ -1083,12 +1062,12 @@ fn transStmt(...@@ -1083,12 +1062,12 @@ fn transStmt(
1083 .CompoundAssignOperatorClass => return transCompoundAssignOperator(c, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used),1062 .CompoundAssignOperatorClass => return transCompoundAssignOperator(c, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used),
1084 .OpaqueValueExprClass => {1063 .OpaqueValueExprClass => {
1085 const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?;1064 const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?;
1086 const expr = try transExpr(c, scope, source_expr, .used, lrvalue);1065 const expr = try transExpr(c, scope, source_expr, .used);
1087 return maybeSuppressResult(c, scope, result_used, expr);1066 return maybeSuppressResult(c, scope, result_used, expr);
1088 },1067 },
1089 else => {1068 else => {
1090 return fail(1069 return fail(
1091 rp,1070 c,
1092 error.UnsupportedTranslation,1071 error.UnsupportedTranslation,
1093 stmt.getBeginLoc(),1072 stmt.getBeginLoc(),
1094 "TODO implement translation of stmt class {s}",1073 "TODO implement translation of stmt class {s}",
...@@ -1109,37 +1088,36 @@ fn transBinaryOperator(...@@ -1109,37 +1088,36 @@ fn transBinaryOperator(
1109 switch (op) {1088 switch (op) {
1110 .Assign => return try transCreateNodeAssign(c, scope, result_used, stmt.getLHS(), stmt.getRHS()),1089 .Assign => return try transCreateNodeAssign(c, scope, result_used, stmt.getLHS(), stmt.getRHS()),
1111 .Comma => {1090 .Comma => {
1112 var block_scope = try Scope.Block.init(rp.c, scope, true);1091 var block_scope = try Scope.Block.init(c, scope, true);
1113 defer block_scope.deinit();1092 defer block_scope.deinit();
11141093
11151094 const lhs = try transExpr(c, &block_scope.base, stmt.getLHS(), .unused);
1116 const lhs = try transExpr(c, &block_scope.base, stmt.getLHS(), .unused, .r_value);
1117 try block_scope.statements.append(lhs);1095 try block_scope.statements.append(lhs);
11181096
1119 const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value);1097 const rhs = try transExpr(c, &block_scope.base, stmt.getRHS(), .used);
1120 const break_node = try Node.break_val.create(c.arena, .{1098 const break_node = try Tag.break_val.create(c.arena, .{
1121 .label = block_scope.label,1099 .label = block_scope.label,
1122 .val = rhs,1100 .val = rhs,
1123 });1101 });
1124 try block_scope.statements.append(break_node);1102 try block_scope.statements.append(break_node);
1125 const block_node = try block_scope.complete(rp.c);1103 const block_node = try block_scope.complete(c);
1126 return maybeSuppressResult(rp, scope, result_used, block_node);1104 return maybeSuppressResult(c, scope, result_used, block_node);
1127 },1105 },
1128 .Div => {1106 .Div => {
1129 if (cIsSignedInteger(qt)) {1107 if (cIsSignedInteger(qt)) {
1130 // signed integer division uses @divTrunc1108 // signed integer division uses @divTrunc
1131 const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);1109 const lhs = try transExpr(c, scope, stmt.getLHS(), .used);
1132 const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);1110 const rhs = try transExpr(c, scope, stmt.getRHS(), .used);
1133 const div_trunc = try Node.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs });1111 const div_trunc = try Tag.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
1134 return maybeSuppressResult(c, scope, result_used, div_trunc);1112 return maybeSuppressResult(c, scope, result_used, div_trunc);
1135 }1113 }
1136 },1114 },
1137 .Rem => {1115 .Rem => {
1138 if (cIsSignedInteger(qt)) {1116 if (cIsSignedInteger(qt)) {
1139 // signed integer division uses @rem1117 // signed integer division uses @rem
1140 const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);1118 const lhs = try transExpr(c, scope, stmt.getLHS(), .used);
1141 const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);1119 const rhs = try transExpr(c, scope, stmt.getRHS(), .used);
1142 const rem = try Node.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs });1120 const rem = try Tag.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
1143 return maybeSuppressResult(c, scope, result_used, rem);1121 return maybeSuppressResult(c, scope, result_used, rem);
1144 }1122 }
1145 },1123 },
...@@ -1150,14 +1128,14 @@ fn transBinaryOperator(...@@ -1150,14 +1128,14 @@ fn transBinaryOperator(
1150 return transCreateNodeShiftOp(c, scope, stmt, .shr, result_used);1128 return transCreateNodeShiftOp(c, scope, stmt, .shr, result_used);
1151 },1129 },
1152 .LAnd => {1130 .LAnd => {
1153 return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used);1131 return transCreateNodeBoolInfixOp(c, scope, stmt, .@"and", result_used);
1154 },1132 },
1155 .LOr => {1133 .LOr => {
1156 return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used);1134 return transCreateNodeBoolInfixOp(c, scope, stmt, .@"or", result_used);
1157 },1135 },
1158 else => {},1136 else => {},
1159 }1137 }
1160 var op_id: Node.Tag = undefined;1138 var op_id: Tag = undefined;
1161 switch (op) {1139 switch (op) {
1162 .Add => {1140 .Add => {
1163 if (cIsUnsignedInteger(qt)) {1141 if (cIsUnsignedInteger(qt)) {
...@@ -1218,20 +1196,20 @@ fn transBinaryOperator(...@@ -1218,20 +1196,20 @@ fn transBinaryOperator(
1218 else => unreachable,1196 else => unreachable,
1219 }1197 }
12201198
1221 const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value);1199 const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used);
1222 const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used, .r_value);1200 const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used);
12231201
1224 const lhs = if (isBoolRes(lhs_uncasted))1202 const lhs = if (isBoolRes(lhs_uncasted))
1225 try Node.bool_to_int.create(c.arena, lhs_uncasted)1203 try Tag.bool_to_int.create(c.arena, lhs_uncasted)
1226 else1204 else
1227 lhs_uncasted;1205 lhs_uncasted;
12281206
1229 const rhs = if (isBoolRes(rhs_uncasted))1207 const rhs = if (isBoolRes(rhs_uncasted))
1230 try Node.bool_to_int.create(c.arena, rhs_uncasted)1208 try Tag.bool_to_int.create(c.arena, rhs_uncasted)
1231 else1209 else
1232 rhs_uncasted;1210 rhs_uncasted;
12331211
1234 return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, used);1212 return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, result_used);
1235}1213}
12361214
1237fn transCompoundStmtInline(1215fn transCompoundStmtInline(
...@@ -1243,7 +1221,7 @@ fn transCompoundStmtInline(...@@ -1243,7 +1221,7 @@ fn transCompoundStmtInline(
1243 var it = stmt.body_begin();1221 var it = stmt.body_begin();
1244 const end_it = stmt.body_end();1222 const end_it = stmt.body_end();
1245 while (it != end_it) : (it += 1) {1223 while (it != end_it) : (it += 1) {
1246 const result = try transStmt(c, parent_scope, it[0], .unused, .r_value);1224 const result = try transStmt(c, parent_scope, it[0], .unused);
1247 try block.statements.append(result);1225 try block.statements.append(result);
1248 }1226 }
1249}1227}
...@@ -1260,7 +1238,6 @@ fn transCStyleCastExprClass(...@@ -1260,7 +1238,6 @@ fn transCStyleCastExprClass(
1260 scope: *Scope,1238 scope: *Scope,
1261 stmt: *const clang.CStyleCastExpr,1239 stmt: *const clang.CStyleCastExpr,
1262 result_used: ResultUsed,1240 result_used: ResultUsed,
1263 lrvalue: LRValue,
1264) TransError!Node {1241) TransError!Node {
1265 const sub_expr = stmt.getSubExpr();1242 const sub_expr = stmt.getSubExpr();
1266 const cast_node = (try transCCast(1243 const cast_node = (try transCCast(
...@@ -1269,7 +1246,7 @@ fn transCStyleCastExprClass(...@@ -1269,7 +1246,7 @@ fn transCStyleCastExprClass(
1269 stmt.getBeginLoc(),1246 stmt.getBeginLoc(),
1270 stmt.getType(),1247 stmt.getType(),
1271 sub_expr.getType(),1248 sub_expr.getType(),
1272 try transExpr(c, scope, sub_expr, .used, lrvalue),1249 try transExpr(c, scope, sub_expr, .used),
1273 ));1250 ));
1274 return maybeSuppressResult(c, scope, result_used, cast_node);1251 return maybeSuppressResult(c, scope, result_used, cast_node);
1275}1252}
...@@ -1294,7 +1271,7 @@ fn transDeclStmtOne(...@@ -1294,7 +1271,7 @@ fn transDeclStmtOne(
1294 // This is actually a global variable, put it in the global scope and reference it.1271 // This is actually a global variable, put it in the global scope and reference it.
1295 // `_ = mangled_name;`1272 // `_ = mangled_name;`
1296 try visitVarDecl(c, var_decl, mangled_name);1273 try visitVarDecl(c, var_decl, mangled_name);
1297 return try maybeSuppressResult(c, scope, .unused, try Node.identifier.create(c.arena, mangled_name));1274 return try maybeSuppressResult(c, scope, .unused, try Tag.identifier.create(c.arena, mangled_name));
1298 },1275 },
1299 else => {},1276 else => {},
1300 }1277 }
...@@ -1308,13 +1285,13 @@ fn transDeclStmtOne(...@@ -1308,13 +1285,13 @@ fn transDeclStmtOne(
1308 if (expr.getStmtClass() == .StringLiteralClass)1285 if (expr.getStmtClass() == .StringLiteralClass)
1309 try transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(c, type_node))1286 try transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(c, type_node))
1310 else1287 else
1311 try transExprCoercing(c, scope, expr, .used, .r_value)1288 try transExprCoercing(c, scope, expr, .used)
1312 else1289 else
1313 try transCreateNodeUndefinedLiteral(c);1290 Tag.undefined_literal.init();
1314 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {1291 if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) {
1315 init_node = try Node.bool_to_int.create(c.arena, init_node);1292 init_node = try Tag.bool_to_int.create(c.arena, init_node);
1316 }1293 }
1317 return Node.var_decl.create(c.arena, .{1294 return Tag.var_decl.create(c.arena, .{
1318 .is_pub = false,1295 .is_pub = false,
1319 .is_const = is_const,1296 .is_const = is_const,
1320 .is_extern = false,1297 .is_extern = false,
...@@ -1339,7 +1316,7 @@ fn transDeclStmtOne(...@@ -1339,7 +1316,7 @@ fn transDeclStmtOne(
1339 return node;1316 return node;
1340 },1317 },
1341 else => |kind| return fail(1318 else => |kind| return fail(
1342 rp,1319 c,
1343 error.UnsupportedTranslation,1320 error.UnsupportedTranslation,
1344 decl.getLocation(),1321 decl.getLocation(),
1345 "TODO implement translation of DeclStmt kind {s}",1322 "TODO implement translation of DeclStmt kind {s}",
...@@ -1370,12 +1347,11 @@ fn transDeclRefExpr(...@@ -1370,12 +1347,11 @@ fn transDeclRefExpr(
1370 c: *Context,1347 c: *Context,
1371 scope: *Scope,1348 scope: *Scope,
1372 expr: *const clang.DeclRefExpr,1349 expr: *const clang.DeclRefExpr,
1373 lrvalue: LRValue,
1374) TransError!Node {1350) TransError!Node {
1375 const value_decl = expr.getDecl();1351 const value_decl = expr.getDecl();
1376 const name = try c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin());1352 const name = try c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin());
1377 const mangled_name = scope.getAlias(name);1353 const mangled_name = scope.getAlias(name);
1378 return Node.identifier.create(c.arena, mangled_name);1354 return Tag.identifier.create(c.arena, mangled_name);
1379}1355}
13801356
1381fn transImplicitCastExpr(1357fn transImplicitCastExpr(
...@@ -1389,49 +1365,49 @@ fn transImplicitCastExpr(...@@ -1389,49 +1365,49 @@ fn transImplicitCastExpr(
1389 const src_type = getExprQualType(c, sub_expr);1365 const src_type = getExprQualType(c, sub_expr);
1390 switch (expr.getCastKind()) {1366 switch (expr.getCastKind()) {
1391 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {1367 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {
1392 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);1368 const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
1393 const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node);1369 const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node);
1394 return maybeSuppressResult(c, scope, result_used, casted);1370 return maybeSuppressResult(c, scope, result_used, casted);
1395 },1371 },
1396 .LValueToRValue, .NoOp, .FunctionToPointerDecay => {1372 .LValueToRValue, .NoOp, .FunctionToPointerDecay => {
1397 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);1373 const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
1398 return maybeSuppressResult(c, scope, result_used, sub_expr_node);1374 return maybeSuppressResult(c, scope, result_used, sub_expr_node);
1399 },1375 },
1400 .ArrayToPointerDecay => {1376 .ArrayToPointerDecay => {
1401 if (exprIsNarrowStringLiteral(sub_expr)) {1377 if (exprIsNarrowStringLiteral(sub_expr)) {
1402 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);1378 const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
1403 return maybeSuppressResult(c, scope, result_used, sub_expr_node);1379 return maybeSuppressResult(c, scope, result_used, sub_expr_node);
1404 }1380 }
14051381
1406 const addr = try Node.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value));1382 const addr = try Tag.address_of.create(c.arena, try transExpr(c, scope, sub_expr, .used));
1407 return maybeSuppressResult(c, scope, result_used, addr);1383 return maybeSuppressResult(c, scope, result_used, addr);
1408 },1384 },
1409 .NullToPointer => {1385 .NullToPointer => {
1410 return Node.null_literal.init();1386 return Tag.null_literal.init();
1411 },1387 },
1412 .PointerToBoolean => {1388 .PointerToBoolean => {
1413 // @ptrToInt(val) != 01389 // @ptrToInt(val) != 0
1414 const ptr_to_int = try Node.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used, .r_value));1390 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, try transExpr(c, scope, sub_expr, .used));
14151391
1416 const ne = try Node.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Node.zero_literal.init() });1392 const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() });
1417 return maybeSuppressResult(c, scope, result_used, ne);1393 return maybeSuppressResult(c, scope, result_used, ne);
1418 },1394 },
1419 .IntegralToBoolean => {1395 .IntegralToBoolean => {
1420 const sub_expr_node = try transExpr(c, scope, sub_expr, .used, .r_value);1396 const sub_expr_node = try transExpr(c, scope, sub_expr, .used);
14211397
1422 // The expression is already a boolean one, return it as-is1398 // The expression is already a boolean one, return it as-is
1423 if (isBoolRes(sub_expr_node))1399 if (isBoolRes(sub_expr_node))
1424 return maybeSuppressResult(c, scope, result_used, sub_expr_node);1400 return maybeSuppressResult(c, scope, result_used, sub_expr_node);
14251401
1426 // val != 01402 // val != 0
1427 const ne = try Node.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Node.zero_literal.init() });1403 const ne = try Tag.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Tag.zero_literal.init() });
1428 return maybeSuppressResult(c, scope, result_used, ne);1404 return maybeSuppressResult(c, scope, result_used, ne);
1429 },1405 },
1430 .BuiltinFnToFnPtr => {1406 .BuiltinFnToFnPtr => {
1431 return transExpr(rp, scope, sub_expr, result_used, .r_value);1407 return transExpr(c, scope, sub_expr, result_used);
1432 },1408 },
1433 else => |kind| return fail(1409 else => |kind| return fail(
1434 rp,1410 c,
1435 error.UnsupportedTranslation,1411 error.UnsupportedTranslation,
1436 @ptrCast(*const clang.Stmt, expr).getBeginLoc(),1412 @ptrCast(*const clang.Stmt, expr).getBeginLoc(),
1437 "TODO implement translation of CastKind {s}",1413 "TODO implement translation of CastKind {s}",
...@@ -1445,17 +1421,16 @@ fn transBoolExpr(...@@ -1445,17 +1421,16 @@ fn transBoolExpr(
1445 scope: *Scope,1421 scope: *Scope,
1446 expr: *const clang.Expr,1422 expr: *const clang.Expr,
1447 used: ResultUsed,1423 used: ResultUsed,
1448 lrvalue: LRValue,
1449) TransError!Node {1424) TransError!Node {
1450 if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {1425 if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) {
1451 var is_zero: bool = undefined;1426 var is_zero: bool = undefined;
1452 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {1427 if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) {
1453 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});1428 return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "invalid integer literal", .{});
1454 }1429 }
1455 return Node{ .tag = ([2]ast.Node.Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)] };1430 return Node{ .tag_if_small_enough = @enumToInt(([2]Tag{ .true_literal, .false_literal })[@boolToInt(is_zero)]) };
1456 }1431 }
14571432
1458 var res = try transExpr(c, scope, expr, used, lrvalue);1433 var res = try transExpr(c, scope, expr, used);
1459 if (isBoolRes(res)) {1434 if (isBoolRes(res)) {
1460 return maybeSuppressResult(c, scope, used, res);1435 return maybeSuppressResult(c, scope, used, res);
1461 }1436 }
...@@ -1494,7 +1469,7 @@ fn isBoolRes(res: Node) bool {...@@ -1494,7 +1469,7 @@ fn isBoolRes(res: Node) bool {
1494 .@"or",1469 .@"or",
1495 .@"and",1470 .@"and",
1496 .equal,1471 .equal,
1497 .note_equal,1472 .not_equal,
1498 .less_than,1473 .less_than,
1499 .less_than_equal,1474 .less_than_equal,
1500 .greater_than,1475 .greater_than,
...@@ -1547,18 +1522,18 @@ fn finishBoolExpr(...@@ -1547,18 +1522,18 @@ fn finishBoolExpr(
1547 .Float16,1522 .Float16,
1548 => {1523 => {
1549 // node != 01524 // node != 0
1550 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });1525 return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
1551 },1526 },
1552 .NullPtr => {1527 .NullPtr => {
1553 // node == null1528 // node == null
1554 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() });1529 return Tag.equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
1555 },1530 },
1556 else => {},1531 else => {},
1557 }1532 }
1558 },1533 },
1559 .Pointer => {1534 .Pointer => {
1560 // node == null1535 // node == null
1561 return Node.equal.create(c.arena, .{ .lhs = node, .rhs = Node.null_literal.init() });1536 return Tag.equal.create(c.arena, .{ .lhs = node, .rhs = Tag.null_literal.init() });
1562 },1537 },
1563 .Typedef => {1538 .Typedef => {
1564 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);1539 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
...@@ -1568,8 +1543,7 @@ fn finishBoolExpr(...@@ -1568,8 +1543,7 @@ fn finishBoolExpr(
1568 },1543 },
1569 .Enum => {1544 .Enum => {
1570 // node != 01545 // node != 0
1571 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });1546 return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
1572 const op_token = try appendToken(c, .BangEqual, "!=");
1573 },1547 },
1574 .Elaborated => {1548 .Elaborated => {
1575 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);1549 const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty);
...@@ -1614,9 +1588,10 @@ fn transIntegerLiteral(...@@ -1614,9 +1588,10 @@ fn transIntegerLiteral(
1614 // But the first step is to be correct, and the next step is to make the output more elegant.1588 // But the first step is to be correct, and the next step is to make the output more elegant.
16151589
1616 // @as(T, x)1590 // @as(T, x)
1591 const expr_base = @ptrCast(*const clang.Expr, expr);
1617 const ty_node = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc());1592 const ty_node = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc());
1618 const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt());1593 const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt());
1619 const as = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs });1594 const as = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs });
1620 return maybeSuppressResult(c, scope, result_used, as);1595 return maybeSuppressResult(c, scope, result_used, as);
1621}1596}
16221597
...@@ -1624,16 +1599,16 @@ fn transReturnStmt(...@@ -1624,16 +1599,16 @@ fn transReturnStmt(
1624 c: *Context,1599 c: *Context,
1625 scope: *Scope,1600 scope: *Scope,
1626 expr: *const clang.ReturnStmt,1601 expr: *const clang.ReturnStmt,
1627) TransError!*ast.Node {1602) TransError!Node {
1628 const val_expr = expr.getRetValue() orelse1603 const val_expr = expr.getRetValue() orelse
1629 return Node.return_void.init();1604 return Tag.return_void.init();
16301605
1631 var rhs = try transExprCoercing(c, scope, val_expr, .used, .r_value);1606 var rhs = try transExprCoercing(c, scope, val_expr, .used);
1632 const return_qt = scope.findBlockReturnType(c);1607 const return_qt = scope.findBlockReturnType(c);
1633 if (isBoolRes(rhs) and !qualTypeIsBoolean(return_qt)) {1608 if (isBoolRes(rhs) and !qualTypeIsBoolean(return_qt)) {
1634 rhs = try Node.bool_to_int.create(c.arena, rhs);1609 rhs = try Tag.bool_to_int.create(c.arena, rhs);
1635 }1610 }
1636 return Node.@"return".create(c.arena, rhs);1611 return Tag.@"return".create(c.arena, rhs);
1637}1612}
16381613
1639fn transStringLiteral(1614fn transStringLiteral(
...@@ -1647,10 +1622,9 @@ fn transStringLiteral(...@@ -1647,10 +1622,9 @@ fn transStringLiteral(
1647 .Ascii, .UTF8 => {1622 .Ascii, .UTF8 => {
1648 var len: usize = undefined;1623 var len: usize = undefined;
1649 const bytes_ptr = stmt.getString_bytes_begin_size(&len);1624 const bytes_ptr = stmt.getString_bytes_begin_size(&len);
1650 const str = bytes_ptr[0..len];
16511625
1652 const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(str)});1626 const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])});
1653 const node = try Node.string_literal.create(c.arena, str);1627 const node = try Tag.string_literal.create(c.arena, str);
1654 return maybeSuppressResult(c, scope, result_used, node);1628 return maybeSuppressResult(c, scope, result_used, node);
1655 },1629 },
1656 .UTF16, .UTF32, .Wide => {1630 .UTF16, .UTF32, .Wide => {
...@@ -1658,9 +1632,9 @@ fn transStringLiteral(...@@ -1658,9 +1632,9 @@ fn transStringLiteral(
1658 const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() });1632 const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() });
1659 const lit_array = try transStringLiteralAsArray(c, scope, stmt, stmt.getLength() + 1);1633 const lit_array = try transStringLiteralAsArray(c, scope, stmt, stmt.getLength() + 1);
16601634
1661 const decl = try Node.var_simple.create(c.arena, .{ .name = name, .init = lit_array });1635 const decl = try Tag.var_simple.create(c.arena, .{ .name = name, .init = lit_array });
1662 try scope.appendNode(name, decl);1636 try scope.appendNode(decl);
1663 const node = try Node.identifier.create(c.arena, name);1637 const node = try Tag.identifier.create(c.arena, name);
1664 return maybeSuppressResult(c, scope, result_used, node);1638 return maybeSuppressResult(c, scope, result_used, node);
1665 },1639 },
1666 }1640 }
...@@ -1669,9 +1643,7 @@ fn transStringLiteral(...@@ -1669,9 +1643,7 @@ fn transStringLiteral(
1669/// Parse the size of an array back out from an ast Node.1643/// Parse the size of an array back out from an ast Node.
1670fn zigArraySize(c: *Context, node: Node) TransError!usize {1644fn zigArraySize(c: *Context, node: Node) TransError!usize {
1671 if (node.castTag(.array_type)) |array| {1645 if (node.castTag(.array_type)) |array| {
1672 if (array.data.len.castTag(.int_literal)) |int_lit| {1646 return array.data.len;
1673 return std.fmt.parseUnsigned(usize, int_lit.data, 10) catch error.UnsupportedTranslation;
1674 }
1675 }1647 }
1676 return error.UnsupportedTranslation;1648 return error.UnsupportedTranslation;
1677}1649}
...@@ -1709,7 +1681,7 @@ fn transStringLiteralAsArray(...@@ -1709,7 +1681,7 @@ fn transStringLiteralAsArray(
1709 init_list[i] = try transCreateNodeNumber(c, 0);1681 init_list[i] = try transCreateNodeNumber(c, 0);
1710 }1682 }
17111683
1712 return Node.array_init.create(c.arena, init_list);1684 return Tag.array_init.create(c.arena, init_list);
1713}1685}
17141686
1715fn cIsEnum(qt: clang.QualType) bool {1687fn cIsEnum(qt: clang.QualType) bool {
...@@ -1747,89 +1719,77 @@ fn transCCast(...@@ -1747,89 +1719,77 @@ fn transCCast(
1747 // 3. Bit-cast to correct signed-ness1719 // 3. Bit-cast to correct signed-ness
1748 const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);1720 const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);
1749 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);1721 const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
1750 var src_int_expr = if (cIsInteger(src_type)) expr else Node.enum_to_int.create(c.arena, expr);1722 var src_int_expr = if (cIsInteger(src_type)) expr else try Tag.enum_to_int.create(c.arena, expr);
17511723
1752 if (isBoolRes(src_int_expr)) {1724 if (isBoolRes(src_int_expr)) {
1753 src_int_expr = try Node.bool_to_int.create(c.arena, src_int_expr);1725 src_int_expr = try Tag.bool_to_int.create(c.arena, src_int_expr);
1754 }1726 }
17551727
1756 switch (cIntTypeCmp(dst_type, src_int_type)) {1728 switch (cIntTypeCmp(dst_type, src_int_type)) {
1757 .lt => {1729 .lt => {
1758 // @truncate(SameSignSmallerInt, src_int_expr)1730 // @truncate(SameSignSmallerInt, src_int_expr)
1759 const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);1731 const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
1760 src_int_expr = try Node.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });1732 src_int_expr = try Tag.truncate.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
1761 },1733 },
1762 .gt => {1734 .gt => {
1763 // @as(SameSignBiggerInt, src_int_expr)1735 // @as(SameSignBiggerInt, src_int_expr)
1764 const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);1736 const ty_node = try transQualTypeIntWidthOf(c, dst_type, src_type_is_signed);
1765 src_int_expr = try Node.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });1737 src_int_expr = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = src_int_expr });
1766 },1738 },
1767 .eq => {1739 .eq => {
1768 // src_int_expr = src_int_expr1740 // src_int_expr = src_int_expr
1769 },1741 },
1770 }1742 }
1771 // @bitCast(dest_type, intermediate_value)1743 // @bitCast(dest_type, intermediate_value)
1772 return Node.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr });1744 return Tag.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr });
1773 }1745 }
1774 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {1746 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {
1775 // @intCast(dest_type, @ptrToInt(val))1747 // @intCast(dest_type, @ptrToInt(val))
1776 const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr);1748 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
1777 return Node.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });1749 return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int });
1778 }1750 }
1779 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {1751 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {
1780 // @intToPtr(dest_type, val)1752 // @intToPtr(dest_type, val)
1781 return Node.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr });1753 return Tag.int_to_ptr.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1782 }1754 }
1783 if (cIsFloating(src_type) and cIsFloating(dst_type)) {1755 if (cIsFloating(src_type) and cIsFloating(dst_type)) {
1784 // @floatCast(dest_type, val)1756 // @floatCast(dest_type, val)
1785 return Node.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });1757 return Tag.float_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1786 }1758 }
1787 if (cIsFloating(src_type) and !cIsFloating(dst_type)) {1759 if (cIsFloating(src_type) and !cIsFloating(dst_type)) {
1788 // @floatToInt(dest_type, val)1760 // @floatToInt(dest_type, val)
1789 return Node.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr });1761 return Tag.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1790 }1762 }
1791 if (!cIsFloating(src_type) and cIsFloating(dst_type)) {1763 if (!cIsFloating(src_type) and cIsFloating(dst_type)) {
1792 // @intToFloat(dest_type, val)1764 // @intToFloat(dest_type, val)
1793 return Node.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr });1765 return Tag.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1794 }1766 }
1795 if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) {1767 if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) {
1796 // @boolToInt returns either a comptime_int or a u11768 // @boolToInt returns either a comptime_int or a u1
1797 // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast1769 // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast
1798 // instead of @as1770 // instead of @as
1799 const bool_to_int = Node.bool_to_int.create(c.arena, expr);1771 const bool_to_int = try Tag.bool_to_int.create(c.arena, expr);
1800 return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });1772 return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int });
1801 }1773 }
1802 if (cIsEnum(dst_type)) {1774 if (cIsEnum(dst_type)) {
1803 // @intToEnum(dest_type, val)1775 // @intToEnum(dest_type, val)
1804 return Node.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr });1776 return Tag.int_to_enum.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1805 }1777 }
1806 if (cIsEnum(src_type) and !cIsEnum(dst_type)) {1778 if (cIsEnum(src_type) and !cIsEnum(dst_type)) {
1807 // @enumToInt(val)1779 // @enumToInt(val)
1808 return Node.enum_to_int.create(c.arena, expr);1780 return Tag.enum_to_int.create(c.arena, expr);
1809 }1781 }
1810 // @as(dest_type, val)1782 // @as(dest_type, val)
1811 return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr });1783 return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
1812}1784}
18131785
1814fn transExpr(1786fn transExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
1815 c: *Context,1787 return transStmt(c, scope, @ptrCast(*const clang.Stmt, expr), used);
1816 scope: *Scope,
1817 expr: *const clang.Expr,
1818 used: ResultUsed,
1819 lrvalue: LRValue,
1820) TransError!Node {
1821 return transStmt(c, scope, @ptrCast(*const clang.Stmt, expr), used, lrvalue);
1822}1788}
18231789
1824/// Same as `transExpr` but with the knowledge that the operand will be type coerced, and therefore1790/// Same as `transExpr` but with the knowledge that the operand will be type coerced, and therefore
1825/// an `@as` would be redundant. This is used to prevent redundant `@as` in integer literals.1791/// an `@as` would be redundant. This is used to prevent redundant `@as` in integer literals.
1826fn transExprCoercing(1792fn transExprCoercing(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {
1827 c: *Context,
1828 scope: *Scope,
1829 expr: *const clang.Expr,
1830 used: ResultUsed,
1831 lrvalue: LRValue,
1832) TransError!Node {
1833 switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) {1793 switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) {
1834 .IntegerLiteralClass => {1794 .IntegerLiteralClass => {
1835 return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, expr), .used, .no_as);1795 return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, expr), .used, .no_as);
...@@ -1840,12 +1800,12 @@ fn transExprCoercing(...@@ -1840,12 +1800,12 @@ fn transExprCoercing(
1840 .UnaryOperatorClass => {1800 .UnaryOperatorClass => {
1841 const un_expr = @ptrCast(*const clang.UnaryOperator, expr);1801 const un_expr = @ptrCast(*const clang.UnaryOperator, expr);
1842 if (un_expr.getOpcode() == .Extension) {1802 if (un_expr.getOpcode() == .Extension) {
1843 return transExprCoercing(c, scope, un_expr.getSubExpr(), used, lrvalue);1803 return transExprCoercing(c, scope, un_expr.getSubExpr(), used);
1844 }1804 }
1845 },1805 },
1846 else => {},1806 else => {},
1847 }1807 }
1848 return transExpr(c, scope, expr, .used, .r_value);1808 return transExpr(c, scope, expr, .used);
1849}1809}
18501810
1851fn transInitListExprRecord(1811fn transInitListExprRecord(
...@@ -1896,11 +1856,11 @@ fn transInitListExprRecord(...@@ -1896,11 +1856,11 @@ fn transInitListExprRecord(
18961856
1897 try field_inits.append(.{1857 try field_inits.append(.{
1898 .name = raw_name,1858 .name = raw_name,
1899 .value = try transExpr(c, scope, elem_expr, .used, .r_value),1859 .value = try transExpr(c, scope, elem_expr, .used),
1900 });1860 });
1901 }1861 }
19021862
1903 return Node.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items));1863 return Tag.container_init.create(c.arena, try c.arena.dupe(ast.Payload.ContainerInit.Initializer, field_inits.items));
1904}1864}
19051865
1906fn transInitListExprArray(1866fn transInitListExprArray(
...@@ -1920,18 +1880,18 @@ fn transInitListExprArray(...@@ -1920,18 +1880,18 @@ fn transInitListExprArray(
1920 const leftover_count = all_count - init_count;1880 const leftover_count = all_count - init_count;
19211881
1922 if (all_count == 0) {1882 if (all_count == 0) {
1923 return Node.empty_array.create(c.arena, try transQualType(c, child_qt, source_loc));1883 return Tag.empty_array.create(c.arena, try transQualType(c, child_qt, loc));
1924 }1884 }
19251885
1926 const ty_node = try transType(ty);1886 const ty_node = try transType(c, ty, loc);
1927 const init_node = if (init_count != 0) blk: {1887 const init_node = if (init_count != 0) blk: {
1928 const init_list = try c.arena.alloc(Node, init_count);1888 const init_list = try c.arena.alloc(Node, init_count);
19291889
1930 for (init_list) |*init, i| {1890 for (init_list) |*init, i| {
1931 const elem_expr = expr.getInit(i);1891 const elem_expr = expr.getInit(@intCast(c_uint, i));
1932 init.* = try transExpr(c, scope, elem_expr, .used, .r_value);1892 init.* = try transExpr(c, scope, elem_expr, .used);
1933 }1893 }
1934 const init_node = try Node.array_init.create(c.arena, init_list);1894 const init_node = try Tag.array_init.create(c.arena, init_list);
1935 if (leftover_count == 0) {1895 if (leftover_count == 0) {
1936 return init_node;1896 return init_node;
1937 }1897 }
...@@ -1939,14 +1899,14 @@ fn transInitListExprArray(...@@ -1939,14 +1899,14 @@ fn transInitListExprArray(
1939 } else null;1899 } else null;
19401900
1941 const filler_val_expr = expr.getArrayFiller();1901 const filler_val_expr = expr.getArrayFiller();
1942 const filler_node = try Node.array_filler.create(c.arena, .{1902 const filler_node = try Tag.array_filler.create(c.arena, .{
1943 .type = ty_node,1903 .type = ty_node,
1944 .filler = try transExpr(c, scope, filler_val_expr, .used, .r_value),1904 .filler = try transExpr(c, scope, filler_val_expr, .used),
1945 .count = leftover_count,1905 .count = leftover_count,
1946 });1906 });
19471907
1948 if (init_node) |some| {1908 if (init_node) |some| {
1949 return Node.array_cat.create(c.arena, some, filler_node);1909 return Tag.array_cat.create(c.arena, .{ .lhs = some, .rhs = filler_node });
1950 } else {1910 } else {
1951 return filler_node;1911 return filler_node;
1952 }1912 }
...@@ -1964,7 +1924,7 @@ fn transInitListExpr(...@@ -1964,7 +1924,7 @@ fn transInitListExpr(
19641924
1965 if (qual_type.isRecordType()) {1925 if (qual_type.isRecordType()) {
1966 return maybeSuppressResult(c, scope, used, try transInitListExprRecord(1926 return maybeSuppressResult(c, scope, used, try transInitListExprRecord(
1967 rp,1927 c,
1968 scope,1928 scope,
1969 source_loc,1929 source_loc,
1970 expr,1930 expr,
...@@ -1972,7 +1932,7 @@ fn transInitListExpr(...@@ -1972,7 +1932,7 @@ fn transInitListExpr(
1972 ));1932 ));
1973 } else if (qual_type.isArrayType()) {1933 } else if (qual_type.isArrayType()) {
1974 return maybeSuppressResult(c, scope, used, try transInitListExprArray(1934 return maybeSuppressResult(c, scope, used, try transInitListExprArray(
1975 rp,1935 c,
1976 scope,1936 scope,
1977 source_loc,1937 source_loc,
1978 expr,1938 expr,
...@@ -1994,7 +1954,7 @@ fn transZeroInitExpr(...@@ -1994,7 +1954,7 @@ fn transZeroInitExpr(
1994 .Builtin => {1954 .Builtin => {
1995 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);1955 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
1996 switch (builtin_ty.getKind()) {1956 switch (builtin_ty.getKind()) {
1997 .Bool => return Node.false_literal.init(),1957 .Bool => return Tag.false_literal.init(),
1998 .Char_U,1958 .Char_U,
1999 .UChar,1959 .UChar,
2000 .Char_S,1960 .Char_S,
...@@ -2015,11 +1975,11 @@ fn transZeroInitExpr(...@@ -2015,11 +1975,11 @@ fn transZeroInitExpr(
2015 .Float128,1975 .Float128,
2016 .Float16,1976 .Float16,
2017 .LongDouble,1977 .LongDouble,
2018 => return Node.zero_literal.init(),1978 => return Tag.zero_literal.init(),
2019 else => return fail(c, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),1979 else => return fail(c, error.UnsupportedType, source_loc, "unsupported builtin type", .{}),
2020 }1980 }
2021 },1981 },
2022 .Pointer => return Node.null_literal.init(),1982 .Pointer => return Tag.null_literal.init(),
2023 .Typedef => {1983 .Typedef => {
2024 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);1984 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
2025 const typedef_decl = typedef_ty.getDecl();1985 const typedef_decl = typedef_ty.getDecl();
...@@ -2058,19 +2018,19 @@ fn transIfStmt(...@@ -2058,19 +2018,19 @@ fn transIfStmt(
2058 var cond_scope = Scope.Condition{2018 var cond_scope = Scope.Condition{
2059 .base = .{2019 .base = .{
2060 .parent = scope,2020 .parent = scope,
2061 .id = .Condition,2021 .id = .condition,
2062 },2022 },
2063 };2023 };
2064 defer cond_scope.deinit();2024 defer cond_scope.deinit();
2065 const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());2025 const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());
2066 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value);2026 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
20672027
2068 const then_body = try transStmt(c, scope, stmt.getThen(), .unused, .r_value);2028 const then_body = try transStmt(c, scope, stmt.getThen(), .unused);
2069 const else_body = if (stmt.getElse()) |expr|2029 const else_body = if (stmt.getElse()) |expr|
2070 try transStmt(c, scope, expr, .unused, .r_value)2030 try transStmt(c, scope, expr, .unused)
2071 else2031 else
2072 null;2032 null;
2073 return Node.@"if".create(c.arena, .{ .cond = cond, .then = then_body, .@"else" = else_body });2033 return Tag.@"if".create(c.arena, .{ .cond = cond, .then = then_body, .@"else" = else_body });
2074}2034}
20752035
2076fn transWhileLoop(2036fn transWhileLoop(
...@@ -2081,19 +2041,19 @@ fn transWhileLoop(...@@ -2081,19 +2041,19 @@ fn transWhileLoop(
2081 var cond_scope = Scope.Condition{2041 var cond_scope = Scope.Condition{
2082 .base = .{2042 .base = .{
2083 .parent = scope,2043 .parent = scope,
2084 .id = .Condition,2044 .id = .condition,
2085 },2045 },
2086 };2046 };
2087 defer cond_scope.deinit();2047 defer cond_scope.deinit();
2088 const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());2048 const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());
2089 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value);2049 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
20902050
2091 var loop_scope = Scope{2051 var loop_scope = Scope{
2092 .parent = scope,2052 .parent = scope,
2093 .id = .Loop,2053 .id = .loop,
2094 };2054 };
2095 const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);2055 const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
2096 return Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null });2056 return Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null });
2097}2057}
20982058
2099fn transDoWhileLoop(2059fn transDoWhileLoop(
...@@ -2103,20 +2063,19 @@ fn transDoWhileLoop(...@@ -2103,20 +2063,19 @@ fn transDoWhileLoop(
2103) TransError!Node {2063) TransError!Node {
2104 var loop_scope = Scope{2064 var loop_scope = Scope{
2105 .parent = scope,2065 .parent = scope,
2106 .id = .Loop,2066 .id = .loop,
2107 };2067 };
21082068
2109 // if (!cond) break;2069 // if (!cond) break;
2110 const if_node = try transCreateNodeIf(c);
2111 var cond_scope = Scope.Condition{2070 var cond_scope = Scope.Condition{
2112 .base = .{2071 .base = .{
2113 .parent = scope,2072 .parent = scope,
2114 .id = .Condition,2073 .id = .condition,
2115 },2074 },
2116 };2075 };
2117 defer cond_scope.deinit();2076 defer cond_scope.deinit();
2118 const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used, .r_value);2077 const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used);
2119 const if_not_break = try Node.if_not_break.create(c.arena, cond);2078 const if_not_break = try Tag.if_not_break.create(c.arena, cond);
21202079
2121 const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: {2080 const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: {
2122 // there's already a block in C, so we'll append our condition to it.2081 // there's already a block in C, so we'll append our condition to it.
...@@ -2129,8 +2088,8 @@ fn transDoWhileLoop(...@@ -2129,8 +2088,8 @@ fn transDoWhileLoop(
2129 // zig: b;2088 // zig: b;
2130 // zig: if (!cond) break;2089 // zig: if (!cond) break;
2131 // zig: }2090 // zig: }
2132 const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);2091 const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
2133 const block = node.castTag(.block);2092 const block = node.castTag(.block).?;
2134 block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete.2093 block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete.
2135 block.data.stmts[block.data.stmts.len - 1] = if_not_break;2094 block.data.stmts[block.data.stmts.len - 1] = if_not_break;
2136 break :blk node;2095 break :blk node;
...@@ -2143,12 +2102,12 @@ fn transDoWhileLoop(...@@ -2143,12 +2102,12 @@ fn transDoWhileLoop(
2143 // zig: a;2102 // zig: a;
2144 // zig: if (!cond) break;2103 // zig: if (!cond) break;
2145 // zig: }2104 // zig: }
2146 const statements = try c.arena.create(Node, 2);2105 const statements = try c.arena.alloc(Node, 2);
2147 statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);2106 statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
2148 statements[1] = if_not_break;2107 statements[1] = if_not_break;
2149 break :blk try Node.block.create(c.arena, .{ .label = null, .stmts = statements });2108 break :blk try Tag.block.create(c.arena, .{ .label = null, .stmts = statements });
2150 };2109 };
2151 return Node.while_true.create(c.arena, body_node);2110 return Tag.while_true.create(c.arena, body_node);
2152}2111}
21532112
2154fn transForLoop(2113fn transForLoop(
...@@ -2158,7 +2117,7 @@ fn transForLoop(...@@ -2158,7 +2117,7 @@ fn transForLoop(
2158) TransError!Node {2117) TransError!Node {
2159 var loop_scope = Scope{2118 var loop_scope = Scope{
2160 .parent = scope,2119 .parent = scope,
2161 .id = .Loop,2120 .id = .loop,
2162 };2121 };
21632122
2164 var block_scope: ?Scope.Block = null;2123 var block_scope: ?Scope.Block = null;
...@@ -2167,29 +2126,29 @@ fn transForLoop(...@@ -2167,29 +2126,29 @@ fn transForLoop(
2167 if (stmt.getInit()) |init| {2126 if (stmt.getInit()) |init| {
2168 block_scope = try Scope.Block.init(c, scope, false);2127 block_scope = try Scope.Block.init(c, scope, false);
2169 loop_scope.parent = &block_scope.?.base;2128 loop_scope.parent = &block_scope.?.base;
2170 const init_node = try transStmt(c, &block_scope.?.base, init, .unused, .r_value);2129 const init_node = try transStmt(c, &block_scope.?.base, init, .unused);
2171 try block_scope.?.statements.append(init_node);2130 try block_scope.?.statements.append(init_node);
2172 }2131 }
2173 var cond_scope = Scope.Condition{2132 var cond_scope = Scope.Condition{
2174 .base = .{2133 .base = .{
2175 .parent = &loop_scope,2134 .parent = &loop_scope,
2176 .id = .Condition,2135 .id = .condition,
2177 },2136 },
2178 };2137 };
2179 defer cond_scope.deinit();2138 defer cond_scope.deinit();
21802139
2181 const cond = if (stmt.getCond()) |cond|2140 const cond = if (stmt.getCond()) |cond|
2182 try transBoolExpr(c, &cond_scope.base, cond, .used, .r_value)2141 try transBoolExpr(c, &cond_scope.base, cond, .used)
2183 else2142 else
2184 Node.true_literal.init();2143 Tag.true_literal.init();
21852144
2186 const cont_expr = if (stmt.getInc()) |incr|2145 const cont_expr = if (stmt.getInc()) |incr|
2187 try transExpr(c, &cond_scope.base, incr, .unused, .r_value)2146 try transExpr(c, &cond_scope.base, incr, .unused)
2188 else2147 else
2189 null;2148 null;
21902149
2191 const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value);2150 const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
2192 const while_node = try Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr });2151 const while_node = try Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr });
2193 if (block_scope) |*bs| {2152 if (block_scope) |*bs| {
2194 try bs.statements.append(while_node);2153 try bs.statements.append(while_node);
2195 return try bs.complete(c);2154 return try bs.complete(c);
...@@ -2206,13 +2165,14 @@ fn transSwitch(...@@ -2206,13 +2165,14 @@ fn transSwitch(
2206 var cond_scope = Scope.Condition{2165 var cond_scope = Scope.Condition{
2207 .base = .{2166 .base = .{
2208 .parent = scope,2167 .parent = scope,
2209 .id = .Condition,2168 .id = .condition,
2210 },2169 },
2211 };2170 };
2212 defer cond_scope.deinit();2171 defer cond_scope.deinit();
2213 const switch_expr = try transExpr(c, &cond_scope.base, stmt.getCond(), .used, .r_value);2172 const switch_expr = try transExpr(c, &cond_scope.base, stmt.getCond(), .used);
2214 const switch_node = try c.arena.create(ast.Payload.Switch);2173 const switch_node = try c.arena.create(ast.Payload.Switch);
2215 switch_node.* = .{2174 switch_node.* = .{
2175 .base = .{ .tag = .@"switch" },
2216 .data = .{2176 .data = .{
2217 .cond = switch_expr,2177 .cond = switch_expr,
2218 .cases = undefined, // set later2178 .cases = undefined, // set later
...@@ -2221,7 +2181,7 @@ fn transSwitch(...@@ -2221,7 +2181,7 @@ fn transSwitch(
22212181
2222 var switch_scope = Scope.Switch{2182 var switch_scope = Scope.Switch{
2223 .base = .{2183 .base = .{
2224 .id = .Switch,2184 .id = .@"switch",
2225 .parent = scope,2185 .parent = scope,
2226 },2186 },
2227 .cases = std.ArrayList(Node).init(c.gpa),2187 .cases = std.ArrayList(Node).init(c.gpa),
...@@ -2229,11 +2189,7 @@ fn transSwitch(...@@ -2229,11 +2189,7 @@ fn transSwitch(
2229 .default_label = null,2189 .default_label = null,
2230 .switch_label = null,2190 .switch_label = null,
2231 };2191 };
2232 defer {2192 defer switch_scope.cases.deinit();
2233 switch_node.data.cases = try c.arena.dupe(Node, switch_scope.cases.items);
2234 switch_node.data.default = switch_scope.switch_label;
2235 switch_scope.cases.deinit();
2236 }
22372193
2238 // tmp block that all statements will go before being picked up by a case or default2194 // tmp block that all statements will go before being picked up by a case or default
2239 var block_scope = try Scope.Block.init(c, &switch_scope.base, false);2195 var block_scope = try Scope.Block.init(c, &switch_scope.base, false);
...@@ -2246,7 +2202,7 @@ fn transSwitch(...@@ -2246,7 +2202,7 @@ fn transSwitch(
2246 switch_scope.pending_block = try Scope.Block.init(c, scope, false);2202 switch_scope.pending_block = try Scope.Block.init(c, scope, false);
2247 try switch_scope.pending_block.statements.append(Node.initPayload(&switch_node.base));2203 try switch_scope.pending_block.statements.append(Node.initPayload(&switch_node.base));
22482204
2249 const last = try transStmt(c, &block_scope.base, stmt.getBody(), .unused, .r_value);2205 const last = try transStmt(c, &block_scope.base, stmt.getBody(), .unused);
22502206
2251 // take all pending statements2207 // take all pending statements
2252 const last_block_stmts = last.castTag(.block).?.data.stmts;2208 const last_block_stmts = last.castTag(.block).?.data.stmts;
...@@ -2264,13 +2220,14 @@ fn transSwitch(...@@ -2264,13 +2220,14 @@ fn transSwitch(
2264 switch_scope.pending_block.label = l;2220 switch_scope.pending_block.label = l;
2265 }2221 }
2266 if (switch_scope.default_label == null) {2222 if (switch_scope.default_label == null) {
2267 const else_prong = try Node.switch_else.create(2223 const else_prong = try Tag.switch_else.create(
2268 c.arena,2224 c.arena,
2269 try Node.@"break".create(c.arena, switch_scope.switch_label.?),2225 try Tag.@"break".create(c.arena, switch_scope.switch_label.?),
2270 );2226 );
2271 switch_scope.cases.append(else_prong);2227 try switch_scope.cases.append(else_prong);
2272 }2228 }
22732229
2230 switch_node.data.cases = try c.arena.dupe(Node, switch_scope.cases.items);
2274 const result_node = try switch_scope.pending_block.complete(c);2231 const result_node = try switch_scope.pending_block.complete(c);
2275 switch_scope.pending_block.deinit();2232 switch_scope.pending_block.deinit();
2276 return result_node;2233 return result_node;
...@@ -2286,18 +2243,18 @@ fn transCase(...@@ -2286,18 +2243,18 @@ fn transCase(
2286 const label = try block_scope.makeMangledName(c, "case");2243 const label = try block_scope.makeMangledName(c, "case");
22872244
2288 const expr = if (stmt.getRHS()) |rhs| blk: {2245 const expr = if (stmt.getRHS()) |rhs| blk: {
2289 const lhs_node = try transExpr(c, scope, stmt.getLHS(), .used, .r_value);2246 const lhs_node = try transExpr(c, scope, stmt.getLHS(), .used);
2290 const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);2247 const rhs_node = try transExpr(c, scope, rhs, .used);
22912248
2292 break :blk Node.ellipsis3.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });2249 break :blk try Tag.ellipsis3.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
2293 } else2250 } else
2294 try transExpr(c, scope, stmt.getLHS(), .used, .r_value);2251 try transExpr(c, scope, stmt.getLHS(), .used);
22952252
2296 const switch_prong = try Node.switch_prong.create(2253 const switch_prong = try Tag.switch_prong.create(c.arena, .{
2297 c.arena,2254 .lhs = expr,
2298 try Node.@"break".create(c.arena, label),2255 .rhs = try Tag.@"break".create(c.arena, label),
2299 );2256 });
2300 switch_scope.cases.append(switch_prong);2257 try switch_scope.cases.append(switch_prong);
23012258
2302 switch_scope.pending_block.label = label;2259 switch_scope.pending_block.label = label;
23032260
...@@ -2311,7 +2268,7 @@ fn transCase(...@@ -2311,7 +2268,7 @@ fn transCase(
23112268
2312 try switch_scope.pending_block.statements.append(pending_node);2269 try switch_scope.pending_block.statements.append(pending_node);
23132270
2314 return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value);2271 return transStmt(c, scope, stmt.getSubStmt(), .unused);
2315}2272}
23162273
2317fn transDefault(2274fn transDefault(
...@@ -2323,12 +2280,12 @@ fn transDefault(...@@ -2323,12 +2280,12 @@ fn transDefault(
2323 const switch_scope = scope.getSwitch();2280 const switch_scope = scope.getSwitch();
2324 switch_scope.default_label = try block_scope.makeMangledName(c, "default");2281 switch_scope.default_label = try block_scope.makeMangledName(c, "default");
23252282
2326 const else_prong = try Node.switch_else.create(2283 const else_prong = try Tag.switch_else.create(
2327 c.arena,2284 c.arena,
2328 try Node.@"break".create(c.arena, switch_scope.default_label.?),2285 try Tag.@"break".create(c.arena, switch_scope.default_label.?),
2329 );2286 );
2330 switch_scope.cases.append(else_prong);2287 try switch_scope.cases.append(else_prong);
2331 switch_scope.pending_block.label = try appendIdentifier(c, switch_scope.default_label.?);2288 switch_scope.pending_block.label = switch_scope.default_label.?;
23322289
2333 // take all pending statements2290 // take all pending statements
2334 try switch_scope.pending_block.statements.appendSlice(block_scope.statements.items);2291 try switch_scope.pending_block.statements.appendSlice(block_scope.statements.items);
...@@ -2339,7 +2296,7 @@ fn transDefault(...@@ -2339,7 +2296,7 @@ fn transDefault(
2339 switch_scope.pending_block = try Scope.Block.init(c, scope, false);2296 switch_scope.pending_block = try Scope.Block.init(c, scope, false);
2340 try switch_scope.pending_block.statements.append(pending_node);2297 try switch_scope.pending_block.statements.append(pending_node);
23412298
2342 return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value);2299 return transStmt(c, scope, stmt.getSubStmt(), .unused);
2343}2300}
23442301
2345fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node {2302fn 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:...@@ -2352,7 +2309,7 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used:
2352 // See comment in `transIntegerLiteral` for why this code is here.2309 // See comment in `transIntegerLiteral` for why this code is here.
2353 // @as(T, x)2310 // @as(T, x)
2354 const expr_base = @ptrCast(*const clang.Expr, expr);2311 const expr_base = @ptrCast(*const clang.Expr, expr);
2355 const as_node = try Node.as.create(c.arena, .{2312 const as_node = try Tag.as.create(c.arena, .{
2356 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),2313 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
2357 .rhs = try transCreateNodeAPInt(c, result.Val.getInt()),2314 .rhs = try transCreateNodeAPInt(c, result.Val.getInt()),
2358 });2315 });
...@@ -2369,10 +2326,10 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined...@@ -2369,10 +2326,10 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined
2369}2326}
23702327
2371fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {2328fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
2372 return Node.char_literal.create(c.arena, if (narrow)2329 return Tag.char_literal.create(c.arena, if (narrow)
2373 try std.fmt.bufPrint(c.arena, "'{}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})})2330 try std.fmt.allocPrint(c.arena, "'{s}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})})
2374 else2331 else
2375 try std.fmt.bufPrint(c.arena, "'\\u{{{x}}}'", .{val}));2332 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));
2376}2333}
23772334
2378fn transCharLiteral(2335fn transCharLiteral(
...@@ -2398,7 +2355,7 @@ fn transCharLiteral(...@@ -2398,7 +2355,7 @@ fn transCharLiteral(
2398 // See comment in `transIntegerLiteral` for why this code is here.2355 // See comment in `transIntegerLiteral` for why this code is here.
2399 // @as(T, x)2356 // @as(T, x)
2400 const expr_base = @ptrCast(*const clang.Expr, stmt);2357 const expr_base = @ptrCast(*const clang.Expr, stmt);
2401 const as_node = Node.as.create(c.arena, .{2358 const as_node = try Tag.as.create(c.arena, .{
2402 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),2359 .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()),
2403 .rhs = int_lit_node,2360 .rhs = int_lit_node,
2404 });2361 });
...@@ -2416,12 +2373,12 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:...@@ -2416,12 +2373,12 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
2416 var it = comp.body_begin();2373 var it = comp.body_begin();
2417 const end_it = comp.body_end();2374 const end_it = comp.body_end();
2418 while (it != end_it - 1) : (it += 1) {2375 while (it != end_it - 1) : (it += 1) {
2419 const result = try transStmt(rp, &block_scope.base, it[0], .unused, .r_value);2376 const result = try transStmt(c, &block_scope.base, it[0], .unused);
2420 try block_scope.statements.append(result);2377 try block_scope.statements.append(result);
2421 }2378 }
2422 const break_node = try Node.break_val.create(c.arena, .{2379 const break_node = try Tag.break_val.create(c.arena, .{
2423 .label = block_scope.label, 2380 .label = block_scope.label,
2424 .val = try transStmt(c, &block_scope.base, it[0], .used, .r_value),2381 .val = try transStmt(c, &block_scope.base, it[0], .used),
2425 });2382 });
2426 try block_scope.statements.append(break_node);2383 try block_scope.statements.append(break_node);
2427 const res = try block_scope.complete(c);2384 const res = try block_scope.complete(c);
...@@ -2429,10 +2386,10 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:...@@ -2429,10 +2386,10 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
2429}2386}
24302387
2431fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node {2388fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node {
2432 var container_node = try transExpr(c, scope, stmt.getBase(), .used, .r_value);2389 var container_node = try transExpr(c, scope, stmt.getBase(), .used);
24332390
2434 if (stmt.isArrow()) {2391 if (stmt.isArrow()) {
2435 container_node = try Node.deref.create(c.arena, container_node);2392 container_node = try Tag.deref.create(c.arena, container_node);
2436 }2393 }
24372394
2438 const member_decl = stmt.getMemberDecl();2395 const member_decl = stmt.getMemberDecl();
...@@ -2450,9 +2407,9 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re...@@ -2450,9 +2407,9 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re
2450 const decl = @ptrCast(*const clang.NamedDecl, member_decl);2407 const decl = @ptrCast(*const clang.NamedDecl, member_decl);
2451 break :blk try c.str(decl.getName_bytes_begin());2408 break :blk try c.str(decl.getName_bytes_begin());
2452 };2409 };
2453 const ident = try Node.identifier.create(c.arena, name);2410 const ident = try Tag.identifier.create(c.arena, name);
24542411
2455 const node = try Node.field_access.create(c.arena, .{ .lhs = container_node, .rhs = ident});2412 const node = try Tag.field_access.create(c.arena, .{ .lhs = container_node, .rhs = ident });
2456 return maybeSuppressResult(c, scope, result_used, node);2413 return maybeSuppressResult(c, scope, result_used, node);
2457}2414}
24582415
...@@ -2469,7 +2426,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip...@@ -2469,7 +2426,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
2469 }2426 }
2470 }2427 }
24712428
2472 const container_node = try transExpr(c, scope, base_stmt, .used, .r_value);2429 const container_node = try transExpr(c, scope, base_stmt, .used);
24732430
2474 // cast if the index is long long or signed2431 // cast if the index is long long or signed
2475 const subscr_expr = stmt.getIdx();2432 const subscr_expr = stmt.getIdx();
...@@ -2477,14 +2434,17 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip...@@ -2477,14 +2434,17 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip
2477 const is_longlong = cIsLongLongInteger(qt);2434 const is_longlong = cIsLongLongInteger(qt);
2478 const is_signed = cIsSignedInteger(qt);2435 const is_signed = cIsSignedInteger(qt);
24792436
2480 2437 const rhs = if (is_longlong or is_signed) blk: {
2481 const node = try Node.array_access.create(c.arena, .{ .lhs = container_node, .rhs = if (is_longlong or is_signed) blk: {
2482 const cast_node = try c.createBuiltinCall("@intCast", 2);
2483 // check if long long first so that signed long long doesn't just become unsigned long long2438 // check if long long first so that signed long long doesn't just become unsigned long long
2484 var typeid_node = if (is_longlong) try transCreateNodeIdentifier(c, "usize") else try transQualTypeIntWidthOf(c, qt, false);2439 var typeid_node = if (is_longlong) try Tag.identifier.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, qt, false);
2485 break :blk try Node.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used, .r_value)});2440 break :blk try Tag.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used) });
2486 } else2441 } else
2487 try transExpr(c, scope, subscr_expr, .used, .r_value)});2442 try transExpr(c, scope, subscr_expr, .used);
2443
2444 const node = try Tag.array_access.create(c.arena, .{
2445 .lhs = container_node,
2446 .rhs = rhs,
2447 });
2488 return maybeSuppressResult(c, scope, result_used, node);2448 return maybeSuppressResult(c, scope, result_used, node);
2489}2449}
24902450
...@@ -2522,23 +2482,23 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {...@@ -2522,23 +2482,23 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool {
25222482
2523fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!Node {2483fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!Node {
2524 const callee = stmt.getCallee();2484 const callee = stmt.getCallee();
2525 var raw_fn_expr = try transExpr(c, scope, callee, .used, .r_value);2485 var raw_fn_expr = try transExpr(c, scope, callee, .used);
25262486
2527 var is_ptr = false;2487 var is_ptr = false;
2528 const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr);2488 const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr);
25292489
2530 const fn_expr = if (is_ptr and fn_ty != null and !cIsFunctionDeclRef(callee))2490 const fn_expr = if (is_ptr and fn_ty != null and !cIsFunctionDeclRef(callee))
2531 try transCreateNodeUnwrapNull(rp.c, raw_fn_expr)2491 try Tag.unwrap.create(c.arena, raw_fn_expr)
2532 else2492 else
2533 raw_fn_expr;2493 raw_fn_expr;
25342494
2535 const num_args = stmt.getNumArgs();2495 const num_args = stmt.getNumArgs();
2536 const call_params = try c.arena.alloc(Node, num_args);2496 const args = try c.arena.alloc(Node, num_args);
25372497
2538 const args = stmt.getArgs();2498 const c_args = stmt.getArgs();
2539 var i: usize = 0;2499 var i: usize = 0;
2540 while (i < num_args) : (i += 1) {2500 while (i < num_args) : (i += 1) {
2541 var call_param = try transExpr(c, scope, args[i], .used, .r_value);2501 var arg = try transExpr(c, scope, c_args[i], .used);
25422502
2543 // In C the result type of a boolean expression is int. If this result is passed as2503 // In C the result type of a boolean expression is int. If this result is passed as
2544 // an argument to a function whose parameter is also int, there is no cast. Therefore2504 // 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...@@ -2549,17 +2509,17 @@ fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result
2549 const param_count = fn_proto.getNumParams();2509 const param_count = fn_proto.getNumParams();
2550 if (i < param_count) {2510 if (i < param_count) {
2551 const param_qt = fn_proto.getParamType(@intCast(c_uint, i));2511 const param_qt = fn_proto.getParamType(@intCast(c_uint, i));
2552 if (isBoolRes(call_param) and cIsNativeInt(param_qt)) {2512 if (isBoolRes(arg) and cIsNativeInt(param_qt)) {
2553 call_param = try Node.bool_to_int.create(c.arena, call_param);2513 arg = try Tag.bool_to_int.create(c.arena, arg);
2554 }2514 }
2555 }2515 }
2556 },2516 },
2557 else => {},2517 else => {},
2558 }2518 }
2559 }2519 }
2560 call_params[i] = call_param;2520 args[i] = arg;
2561 }2521 }
2562 const node = try Node.call.create(c.arena, .{ .lhs = fn_expr, .args = call_params });2522 const node = try Tag.call.create(c.arena, .{ .lhs = fn_expr, .args = args });
2563 if (fn_ty) |ty| {2523 if (fn_ty) |ty| {
2564 const canon = ty.getReturnType().getCanonicalType();2524 const canon = ty.getReturnType().getCanonicalType();
2565 const ret_ty = canon.getTypePtr();2525 const ret_ty = canon.getTypePtr();
...@@ -2609,17 +2569,17 @@ fn transUnaryExprOrTypeTraitExpr(...@@ -2609,17 +2569,17 @@ fn transUnaryExprOrTypeTraitExpr(
2609 result_used: ResultUsed,2569 result_used: ResultUsed,
2610) TransError!Node {2570) TransError!Node {
2611 const loc = stmt.getBeginLoc();2571 const loc = stmt.getBeginLoc();
2612 const type_node = try transQualType(rp, stmt.getTypeOfArgument(), loc);2572 const type_node = try transQualType(c, stmt.getTypeOfArgument(), loc);
26132573
2614 const kind = stmt.getKind();2574 const kind = stmt.getKind();
2615 switch (kind) {2575 switch (kind) {
2616 .SizeOf => return Node.sizeof.create(c.arena, type_node),2576 .SizeOf => return Tag.sizeof.create(c.arena, type_node),
2617 .AlignOf => return Node.alignof.create(c.arena, type_node),2577 .AlignOf => return Tag.alignof.create(c.arena, type_node),
2618 .PreferredAlignOf,2578 .PreferredAlignOf,
2619 .VecStep,2579 .VecStep,
2620 .OpenMPRequiredSimdAlign,2580 .OpenMPRequiredSimdAlign,
2621 => return revertAndWarn(2581 => return fail(
2622 rp,2582 c,
2623 error.UnsupportedTranslation,2583 error.UnsupportedTranslation,
2624 loc,2584 loc,
2625 "Unsupported type trait kind {}",2585 "Unsupported type trait kind {}",
...@@ -2642,53 +2602,54 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat...@@ -2642,53 +2602,54 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
2642 const op_expr = stmt.getSubExpr();2602 const op_expr = stmt.getSubExpr();
2643 switch (stmt.getOpcode()) {2603 switch (stmt.getOpcode()) {
2644 .PostInc => if (qualTypeHasWrappingOverflow(stmt.getType()))2604 .PostInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
2645 return transCreatePostCrement(c, scope, stmt, .assign_add_wrap, used)2605 return transCreatePostCrement(c, scope, stmt, .add_wrap_assign, used)
2646 else2606 else
2647 return transCreatePostCrement(c, scope, stmt, .assign_add, used),2607 return transCreatePostCrement(c, scope, stmt, .add_assign, used),
2648 .PostDec => if (qualTypeHasWrappingOverflow(stmt.getType()))2608 .PostDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
2649 return transCreatePostCrement(c, scope, stmt, .assign_sub_wrap, used)2609 return transCreatePostCrement(c, scope, stmt, .sub_wrap_assign, used)
2650 else2610 else
2651 return transCreatePostCrement(c, scope, stmt, .assign_sub, used),2611 return transCreatePostCrement(c, scope, stmt, .sub_assign, used),
2652 .PreInc => if (qualTypeHasWrappingOverflow(stmt.getType()))2612 .PreInc => if (qualTypeHasWrappingOverflow(stmt.getType()))
2653 return transCreatePreCrement(c, scope, stmt, .assign_add_wrap, used)2613 return transCreatePreCrement(c, scope, stmt, .add_wrap_assign, used)
2654 else2614 else
2655 return transCreatePreCrement(c, scope, stmt, .assign_add, used),2615 return transCreatePreCrement(c, scope, stmt, .add_assign, used),
2656 .PreDec => if (qualTypeHasWrappingOverflow(stmt.getType()))2616 .PreDec => if (qualTypeHasWrappingOverflow(stmt.getType()))
2657 return transCreatePreCrement(c, scope, stmt, .assign_sub_wrap, used)2617 return transCreatePreCrement(c, scope, stmt, .sub_wrap_assign, used)
2658 else2618 else
2659 return transCreatePreCrement(c, scope, stmt, .assign_sub, used),2619 return transCreatePreCrement(c, scope, stmt, .sub_assign, used),
2660 .AddrOf => {2620 .AddrOf => {
2661 if (cIsFunctionDeclRef(op_expr)) {2621 if (cIsFunctionDeclRef(op_expr)) {
2662 return transExpr(rp, scope, op_expr, used, .r_value);2622 return transExpr(c, scope, op_expr, used);
2663 }2623 }
2664 return Node.address_of.create(c.arena, try transExpr(c, scope, op_expr, used, .r_value));2624 return Tag.address_of.create(c.arena, try transExpr(c, scope, op_expr, used));
2665 },2625 },
2666 .Deref => {2626 .Deref => {
2667 const node = try transExpr(c, scope, op_expr, used, .r_value);2627 const node = try transExpr(c, scope, op_expr, used);
2668 var is_ptr = false;2628 var is_ptr = false;
2669 const fn_ty = qualTypeGetFnProto(op_expr.getType(), &is_ptr);2629 const fn_ty = qualTypeGetFnProto(op_expr.getType(), &is_ptr);
2670 if (fn_ty != null and is_ptr)2630 if (fn_ty != null and is_ptr)
2671 return node;2631 return node;
2672 return Node.unwrap_deref.create(c.arena, node);2632 const unwrapped = try Tag.unwrap.create(c.arena, node);
2633 return Tag.deref.create(c.arena, unwrapped);
2673 },2634 },
2674 .Plus => return transExpr(c, scope, op_expr, used, .r_value),2635 .Plus => return transExpr(c, scope, op_expr, used),
2675 .Minus => {2636 .Minus => {
2676 if (!qualTypeHasWrappingOverflow(op_expr.getType())) {2637 if (!qualTypeHasWrappingOverflow(op_expr.getType())) {
2677 return Node.negate.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));2638 return Tag.negate.create(c.arena, try transExpr(c, scope, op_expr, .used));
2678 } else if (cIsUnsignedInteger(op_expr.getType())) {2639 } else if (cIsUnsignedInteger(op_expr.getType())) {
2679 // use -% x for unsigned integers2640 // use -% x for unsigned integers
2680 return Node.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));2641 return Tag.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used));
2681 } else2642 } else
2682 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{});2643 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{});
2683 },2644 },
2684 .Not => {2645 .Not => {
2685 return Node.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));2646 return Tag.bit_not.create(c.arena, try transExpr(c, scope, op_expr, .used));
2686 },2647 },
2687 .LNot => {2648 .LNot => {
2688 return Node.not.create(c.arena, try transExpr(c, scope, op_expr, .used, .r_value));2649 return Tag.not.create(c.arena, try transExpr(c, scope, op_expr, .used));
2689 },2650 },
2690 .Extension => {2651 .Extension => {
2691 return transExpr(c, scope, stmt.getSubExpr(), used, .l_value);2652 return transExpr(c, scope, stmt.getSubExpr(), used);
2692 },2653 },
2693 else => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}),2654 else => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}),
2694 }2655 }
...@@ -2698,7 +2659,7 @@ fn transCreatePreCrement(...@@ -2698,7 +2659,7 @@ fn transCreatePreCrement(
2698 c: *Context,2659 c: *Context,
2699 scope: *Scope,2660 scope: *Scope,
2700 stmt: *const clang.UnaryOperator,2661 stmt: *const clang.UnaryOperator,
2701 op: Node.Tag,2662 op: Tag,
2702 used: ResultUsed,2663 used: ResultUsed,
2703) TransError!Node {2664) TransError!Node {
2704 const op_expr = stmt.getSubExpr();2665 const op_expr = stmt.getSubExpr();
...@@ -2707,8 +2668,8 @@ fn transCreatePreCrement(...@@ -2707,8 +2668,8 @@ fn transCreatePreCrement(
2707 // common case2668 // common case
2708 // c: ++expr2669 // c: ++expr
2709 // zig: expr += 12670 // zig: expr += 1
2710 const lhs = try transExpr(c, scope, op_expr, .used, .r_value);2671 const lhs = try transExpr(c, scope, op_expr, .used);
2711 const rhs = Node.one_literal.init();2672 const rhs = Tag.one_literal.init();
2712 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);2673 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);
2713 }2674 }
2714 // worst case2675 // worst case
...@@ -2722,17 +2683,17 @@ fn transCreatePreCrement(...@@ -2722,17 +2683,17 @@ fn transCreatePreCrement(
2722 defer block_scope.deinit();2683 defer block_scope.deinit();
2723 const ref = try block_scope.makeMangledName(c, "ref");2684 const ref = try block_scope.makeMangledName(c, "ref");
27242685
2725 const expr = try transExpr(c, scope, op_expr, .used, .r_value);2686 const expr = try transExpr(c, scope, op_expr, .used);
2726 const addr_of = try Node.address_of.create(c.arena, expr);2687 const addr_of = try Tag.address_of.create(c.arena, expr);
2727 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});2688 const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of });
2728 try block_scope.statements.append(ref_decl);2689 try block_scope.statements.append(ref_decl);
27292690
2730 const lhs_node = try Node.identifier.create(c.arena, ref);2691 const lhs_node = try Tag.identifier.create(c.arena, ref);
2731 const ref_node = try Node.deref.create(c.arena, lhs_node);2692 const ref_node = try Tag.deref.create(c.arena, lhs_node);
2732 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used);2693 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used);
2733 try block_scope.statements.append(node);2694 try block_scope.statements.append(node);
27342695
2735 const break_node = try Node.break_val.create(c.arena, .{2696 const break_node = try Tag.break_val.create(c.arena, .{
2736 .label = block_scope.label,2697 .label = block_scope.label,
2737 .val = ref_node,2698 .val = ref_node,
2738 });2699 });
...@@ -2744,7 +2705,7 @@ fn transCreatePostCrement(...@@ -2744,7 +2705,7 @@ fn transCreatePostCrement(
2744 c: *Context,2705 c: *Context,
2745 scope: *Scope,2706 scope: *Scope,
2746 stmt: *const clang.UnaryOperator,2707 stmt: *const clang.UnaryOperator,
2747 op: Node.Tag,2708 op: Tag,
2748 used: ResultUsed,2709 used: ResultUsed,
2749) TransError!Node {2710) TransError!Node {
2750 const op_expr = stmt.getSubExpr();2711 const op_expr = stmt.getSubExpr();
...@@ -2753,8 +2714,8 @@ fn transCreatePostCrement(...@@ -2753,8 +2714,8 @@ fn transCreatePostCrement(
2753 // common case2714 // common case
2754 // c: expr++2715 // c: expr++
2755 // zig: expr += 12716 // zig: expr += 1
2756 const lhs = try transExpr(c, scope, op_expr, .used, .r_value);2717 const lhs = try transExpr(c, scope, op_expr, .used);
2757 const rhs = Node.one_literal.init();2718 const rhs = Tag.one_literal.init();
2758 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);2719 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used);
2759 }2720 }
2760 // worst case2721 // worst case
...@@ -2769,24 +2730,24 @@ fn transCreatePostCrement(...@@ -2769,24 +2730,24 @@ fn transCreatePostCrement(
2769 defer block_scope.deinit();2730 defer block_scope.deinit();
2770 const ref = try block_scope.makeMangledName(c, "ref");2731 const ref = try block_scope.makeMangledName(c, "ref");
27712732
2772 const expr = try transExpr(c, scope, op_expr, .used, .r_value);2733 const expr = try transExpr(c, scope, op_expr, .used);
2773 const addr_of = try Node.address_of.create(c.arena, expr);2734 const addr_of = try Tag.address_of.create(c.arena, expr);
2774 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});2735 const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of });
2775 try block_scope.statements.append(ref_decl);2736 try block_scope.statements.append(ref_decl);
27762737
2777 const lhs_node = try Node.identifier.create(c.arena, ref);2738 const lhs_node = try Tag.identifier.create(c.arena, ref);
2778 const ref_node = try Node.deref.create(c.arena, lhs_node);2739 const ref_node = try Tag.deref.create(c.arena, lhs_node);
27792740
2780 const tmp = try block_scope.makeMangledName(c, "tmp");2741 const tmp = try block_scope.makeMangledName(c, "tmp");
2781 const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node});2742 const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node });
2782 try block_scope.statements.append(tmp_decl);2743 try block_scope.statements.append(tmp_decl);
27832744
2784 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used);2745 const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used);
2785 try block_scope.statements.append(node);2746 try block_scope.statements.append(node);
27862747
2787 const break_node = try Node.break_val.create(c.arena, .{2748 const break_node = try Tag.break_val.create(c.arena, .{
2788 .label = block_scope.label,2749 .label = block_scope.label,
2789 .val = try Node.identifier.create(c.arena, tmp),2750 .val = try Tag.identifier.create(c.arena, tmp),
2790 });2751 });
2791 try block_scope.statements.append(break_node);2752 try block_scope.statements.append(break_node);
2792 return block_scope.complete(c);2753 return block_scope.complete(c);
...@@ -2795,26 +2756,26 @@ fn transCreatePostCrement(...@@ -2795,26 +2756,26 @@ fn transCreatePostCrement(
2795fn transCompoundAssignOperator(c: *Context, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!Node {2756fn transCompoundAssignOperator(c: *Context, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!Node {
2796 switch (stmt.getOpcode()) {2757 switch (stmt.getOpcode()) {
2797 .MulAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))2758 .MulAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))
2798 return transCreateCompoundAssign(c, scope, stmt, .assign_mul_wrap, used)2759 return transCreateCompoundAssign(c, scope, stmt, .mul_wrap_assign, used)
2799 else2760 else
2800 return transCreateCompoundAssign(c, scope, stmt, .assign_mul, used),2761 return transCreateCompoundAssign(c, scope, stmt, .mul_assign, used),
2801 .AddAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))2762 .AddAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))
2802 return transCreateCompoundAssign(c, scope, stmt, .assign_add_wrap, used)2763 return transCreateCompoundAssign(c, scope, stmt, .add_wrap_assign, used)
2803 else2764 else
2804 return transCreateCompoundAssign(c, scope, stmt, .assign_add, used),2765 return transCreateCompoundAssign(c, scope, stmt, .add_assign, used),
2805 .SubAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))2766 .SubAssign => if (qualTypeHasWrappingOverflow(stmt.getType()))
2806 return transCreateCompoundAssign(c, scope, stmt, .assign_sub_wrap, used)2767 return transCreateCompoundAssign(c, scope, stmt, .sub_wrap_assign, used)
2807 else2768 else
2808 return transCreateCompoundAssign(c, scope, stmt, .assign_sub, used),2769 return transCreateCompoundAssign(c, scope, stmt, .sub_assign, used),
2809 .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_div, used),2770 .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .div_assign, used),
2810 .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_mod, used),2771 .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .mod_assign, used),
2811 .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shl, used),2772 .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .shl_assign, used),
2812 .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shr, used),2773 .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .shr_assign, used),
2813 .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_and, used),2774 .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_and_assign, used),
2814 .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_xor, used),2775 .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_xor_assign, used),
2815 .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_or, used),2776 .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_or_assign, used),
2816 else => return fail(2777 else => return fail(
2817 rp,2778 c,
2818 error.UnsupportedTranslation,2779 error.UnsupportedTranslation,
2819 stmt.getBeginLoc(),2780 stmt.getBeginLoc(),
2820 "unsupported C translation {}",2781 "unsupported C translation {}",
...@@ -2827,12 +2788,12 @@ fn transCreateCompoundAssign(...@@ -2827,12 +2788,12 @@ fn transCreateCompoundAssign(
2827 c: *Context,2788 c: *Context,
2828 scope: *Scope,2789 scope: *Scope,
2829 stmt: *const clang.CompoundAssignOperator,2790 stmt: *const clang.CompoundAssignOperator,
2830 op: Node.Tag,2791 op: Tag,
2831 used: ResultUsed,2792 used: ResultUsed,
2832) TransError!Node {2793) TransError!Node {
2833 const is_shift = op == .assign_shl or op == .assign_shr;2794 const is_shift = op == .shl_assign or op == .shr_assign;
2834 const is_div = op == .assign_div;2795 const is_div = op == .div_assign;
2835 const is_mod = op == .assign_mod;2796 const is_mod = op == .mod_assign;
2836 const lhs = stmt.getLHS();2797 const lhs = stmt.getLHS();
2837 const rhs = stmt.getRHS();2798 const rhs = stmt.getRHS();
2838 const loc = stmt.getBeginLoc();2799 const loc = stmt.getBeginLoc();
...@@ -2849,21 +2810,21 @@ fn transCreateCompoundAssign(...@@ -2849,21 +2810,21 @@ fn transCreateCompoundAssign(
2849 // c: lhs += rhs2810 // c: lhs += rhs
2850 // zig: lhs += rhs2811 // zig: lhs += rhs
2851 if ((is_mod or is_div) and is_signed) {2812 if ((is_mod or is_div) and is_signed) {
2852 const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);2813 const lhs_node = try transExpr(c, scope, lhs, .used);
2853 const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);2814 const rhs_node = try transExpr(c, scope, rhs, .used);
2854 const builtin = if (is_mod)2815 const builtin = if (is_mod)
2855 try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })2816 try Tag.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
2856 else2817 else
2857 try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });2818 try Tag.div_trunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
28582819
2859 return transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);2820 return transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);
2860 }2821 }
28612822
2862 const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);2823 const lhs_node = try transExpr(c, scope, lhs, .used);
2863 var rhs_node = if (is_shift or requires_int_cast)2824 var rhs_node = if (is_shift or requires_int_cast)
2864 try transExprCoercing(c, scope, rhs, .used, .r_value)2825 try transExprCoercing(c, scope, rhs, .used)
2865 else2826 else
2866 try transExpr(c, scope, rhs, .used, .r_value);2827 try transExpr(c, scope, rhs, .used);
28672828
2868 if (is_shift or requires_int_cast) {2829 if (is_shift or requires_int_cast) {
2869 // @intCast(rhs)2830 // @intCast(rhs)
...@@ -2871,11 +2832,11 @@ fn transCreateCompoundAssign(...@@ -2871,11 +2832,11 @@ fn transCreateCompoundAssign(
2871 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)2832 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
2872 else2833 else
2873 try transQualType(c, getExprQualType(c, lhs), loc);2834 try transQualType(c, getExprQualType(c, lhs), loc);
2874 2835
2875 rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });2836 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
2876 }2837 }
28772838
2878 return transCreateNodeInfixOp(c, scope, assign_op, lhs_node, rhs_node, .used);2839 return transCreateNodeInfixOp(c, scope, op, lhs_node, rhs_node, .used);
2879 }2840 }
2880 // worst case2841 // worst case
2881 // c: lhs += rhs2842 // c: lhs += rhs
...@@ -2888,25 +2849,25 @@ fn transCreateCompoundAssign(...@@ -2888,25 +2849,25 @@ fn transCreateCompoundAssign(
2888 defer block_scope.deinit();2849 defer block_scope.deinit();
2889 const ref = try block_scope.makeMangledName(c, "ref");2850 const ref = try block_scope.makeMangledName(c, "ref");
28902851
2891 const expr = try transExpr(c, scope, op_expr, .used, .r_value);2852 const expr = try transExpr(c, scope, lhs, .used);
2892 const addr_of = try Node.address_of.create(c.arena, expr);2853 const addr_of = try Tag.address_of.create(c.arena, expr);
2893 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of});2854 const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of });
2894 try block_scope.statements.append(ref_decl);2855 try block_scope.statements.append(ref_decl);
28952856
2896 const lhs_node = try Node.identifier.create(c.arena, ref);2857 const lhs_node = try Tag.identifier.create(c.arena, ref);
2897 const ref_node = try Node.deref.create(c.arena, lhs_node);2858 const ref_node = try Tag.deref.create(c.arena, lhs_node);
28982859
2899 if ((is_mod or is_div) and is_signed) {2860 if ((is_mod or is_div) and is_signed) {
2900 const rhs_node = try transExpr(c, scope, rhs, .used, .r_value);2861 const rhs_node = try transExpr(c, scope, rhs, .used);
2901 const builtin = if (is_mod)2862 const builtin = if (is_mod)
2902 try Node.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })2863 try Tag.rem.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node })
2903 else2864 else
2904 try Node.divTrunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });2865 try Tag.div_trunc.create(c.arena, .{ .lhs = lhs_node, .rhs = rhs_node });
29052866
2906 const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);2867 const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used);
2907 try block_scope.statements.append(assign);2868 try block_scope.statements.append(assign);
2908 } else {2869 } else {
2909 var rhs_node = try transExpr(c, scope, rhs, .used, .r_value);2870 var rhs_node = try transExpr(c, scope, rhs, .used);
29102871
2911 if (is_shift or requires_int_cast) {2872 if (is_shift or requires_int_cast) {
2912 // @intCast(rhs)2873 // @intCast(rhs)
...@@ -2914,15 +2875,15 @@ fn transCreateCompoundAssign(...@@ -2914,15 +2875,15 @@ fn transCreateCompoundAssign(
2914 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)2875 try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc)
2915 else2876 else
2916 try transQualType(c, getExprQualType(c, lhs), loc);2877 try transQualType(c, getExprQualType(c, lhs), loc);
2917 2878
2918 rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });2879 rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node });
2919 }2880 }
29202881
2921 const assign = try transCreateNodeInfixOp(c, scope, op, ref_node, rhs_node, .used);2882 const assign = try transCreateNodeInfixOp(c, scope, op, ref_node, rhs_node, .used);
2922 try block_scope.statements.append(assign);2883 try block_scope.statements.append(assign);
2923 }2884 }
29242885
2925 const break_node = try Node.break_val.create(c.arena, .{2886 const break_node = try Tag.break_val.create(c.arena, .{
2926 .label = block_scope.label,2887 .label = block_scope.label,
2927 .val = ref_node,2888 .val = ref_node,
2928 });2889 });
...@@ -2941,7 +2902,7 @@ fn transCPtrCast(...@@ -2941,7 +2902,7 @@ fn transCPtrCast(
2941 const child_type = ty.getPointeeType();2902 const child_type = ty.getPointeeType();
2942 const src_ty = src_type.getTypePtr();2903 const src_ty = src_type.getTypePtr();
2943 const src_child_type = src_ty.getPointeeType();2904 const src_child_type = src_ty.getPointeeType();
2944 const dst_type = try transType(c, ty, loc);2905 const dst_type_node = try transType(c, ty, loc);
29452906
2946 if ((src_child_type.isConstQualified() and2907 if ((src_child_type.isConstQualified() and
2947 !child_type.isConstQualified()) or2908 !child_type.isConstQualified()) or
...@@ -2949,8 +2910,8 @@ fn transCPtrCast(...@@ -2949,8 +2910,8 @@ fn transCPtrCast(
2949 !child_type.isVolatileQualified()))2910 !child_type.isVolatileQualified()))
2950 {2911 {
2951 // Casting away const or volatile requires us to use @intToPtr2912 // Casting away const or volatile requires us to use @intToPtr
2952 const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr);2913 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
2953 const int_to_ptr = try Node.int_to_ptr.create(c.arena, .{ .lhs = dst_type, .rhs = ptr_to_int });2914 const int_to_ptr = try Tag.int_to_ptr.create(c.arena, .{ .lhs = dst_type_node, .rhs = ptr_to_int });
2954 return int_to_ptr;2915 return int_to_ptr;
2955 } else {2916 } else {
2956 // Implicit downcasting from higher to lower alignment values is forbidden,2917 // Implicit downcasting from higher to lower alignment values is forbidden,
...@@ -2963,17 +2924,17 @@ fn transCPtrCast(...@@ -2963,17 +2924,17 @@ fn transCPtrCast(
2963 expr2924 expr
2964 else blk: {2925 else blk: {
2965 const child_type_node = try transQualType(c, child_type, loc);2926 const child_type_node = try transQualType(c, child_type, loc);
2966 const alignof = try Node.alignof.create(c.arena, child_type_node);2927 const alignof = try Tag.alignof.create(c.arena, child_type_node);
2967 const align_cast = try Node.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });2928 const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr });
2968 break :blk align_cast;2929 break :blk align_cast;
2969 };2930 };
2970 return Node.ptr_cast.create(c.arena, .{ .lhs = dst_type, .rhs = rhs });2931 return Tag.ptr_cast.create(c.arena, .{ .lhs = dst_type_node, .rhs = rhs });
2971 }2932 }
2972}2933}
29732934
2974fn transBreak(c: *Context, scope: *Scope) TransError!Node {2935fn transBreak(c: *Context, scope: *Scope) TransError!Node {
2975 const break_scope = scope.getBreakableScope();2936 const break_scope = scope.getBreakableScope();
2976 const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {2937 const label_text: ?[]const u8 = if (break_scope.id == .@"switch") blk: {
2977 const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);2938 const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);
2978 const block_scope = try scope.findBlockScope(c);2939 const block_scope = try scope.findBlockScope(c);
2979 swtch.switch_label = try block_scope.makeMangledName(c, "switch");2940 swtch.switch_label = try block_scope.makeMangledName(c, "switch");
...@@ -2981,20 +2942,20 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node {...@@ -2981,20 +2942,20 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node {
2981 } else2942 } else
2982 null;2943 null;
29832944
2984 return Node.@"break".create(c.arena, label_text);2945 return Tag.@"break".create(c.arena, label_text);
2985}2946}
29862947
2987fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node {2948fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node {
2988 // TODO use something more accurate2949 // TODO use something more accurate
2989 const dbl = stmt.getValueAsApproximateDouble();2950 const dbl = stmt.getValueAsApproximateDouble();
2990 const node = try transCreateNodeNumber(c, dbl);2951 const node = try transCreateNodeNumber(c, dbl);
2991 return maybeSuppressResult(c, scope, used, &node.base);2952 return maybeSuppressResult(c, scope, used, node);
2992}2953}
29932954
2994fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node {2955fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node {
2995 // GNU extension of the ternary operator where the middle expression is2956 // GNU extension of the ternary operator where the middle expression is
2996 // omitted, the conditition itself is returned if it evaluates to true2957 // omitted, the conditition itself is returned if it evaluates to true
2997 const qt = @ptrCast(*const clang.Stmt, stmt).getType();2958 const qt = @ptrCast(*const clang.Expr, stmt).getType();
2998 const res_is_bool = qualTypeIsBoolean(qt);2959 const res_is_bool = qualTypeIsBoolean(qt);
2999 const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);2960 const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);
3000 const cond_expr = casted_stmt.getCond();2961 const cond_expr = casted_stmt.getCond();
...@@ -3010,26 +2971,33 @@ fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang...@@ -3010,26 +2971,33 @@ fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang
3010 defer block_scope.deinit();2971 defer block_scope.deinit();
30112972
3012 const mangled_name = try block_scope.makeMangledName(c, "cond_temp");2973 const mangled_name = try block_scope.makeMangledName(c, "cond_temp");
3013 const init_node = try transExpr(c, &block_scope.base, cond_expr, .used, .r_value);2974 const init_node = try transExpr(c, &block_scope.base, cond_expr, .used);
3014 const ref_decl = try Node.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node});2975 const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node });
3015 try block_scope.statements.append(ref_decl);2976 try block_scope.statements.append(ref_decl);
30162977
2978 var cond_scope = Scope.Condition{
2979 .base = .{
2980 .parent = &block_scope.base,
2981 .id = .condition,
2982 },
2983 };
2984 defer cond_scope.deinit();
3017 const cond_node = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);2985 const cond_node = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
3018 var then_body = try Node.identifier.create(c.arena, mangled_name);2986 var then_body = try Tag.identifier.create(c.arena, mangled_name);
3019 if (!res_is_bool and isBoolRes(init_node)) {2987 if (!res_is_bool and isBoolRes(init_node)) {
3020 then_body = try Node.bool_to_int.create(c.arena, then_body);2988 then_body = try Tag.bool_to_int.create(c.arena, then_body);
3021 }2989 }
30222990
3023 var else_body = try transExpr(c, &block_scope.base, false_expr, .used, .r_value);2991 var else_body = try transExpr(c, &block_scope.base, false_expr, .used);
3024 if (!res_is_bool and isBoolRes(else_body)) {2992 if (!res_is_bool and isBoolRes(else_body)) {
3025 else_body = try Node.bool_to_int.create(c.arena, else_body);2993 else_body = try Tag.bool_to_int.create(c.arena, else_body);
3026 }2994 }
3027 const if_node = try Node.@"if".create(c.arena, .{2995 const if_node = try Tag.@"if".create(c.arena, .{
3028 .cond = cond,2996 .cond = cond_node,
3029 .then = then_body,2997 .then = then_body,
3030 .@"else" = else_body,2998 .@"else" = else_body,
3031 });2999 });
3032 const break_node = try Node.break_val.create(c.arena, .{3000 const break_node = try Tag.break_val.create(c.arena, .{
3033 .label = block_scope.label,3001 .label = block_scope.label,
3034 .val = if_node,3002 .val = if_node,
3035 });3003 });
...@@ -3042,31 +3010,31 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi...@@ -3042,31 +3010,31 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi
3042 var cond_scope = Scope.Condition{3010 var cond_scope = Scope.Condition{
3043 .base = .{3011 .base = .{
3044 .parent = scope,3012 .parent = scope,
3045 .id = .Condition,3013 .id = .condition,
3046 },3014 },
3047 };3015 };
3048 defer cond_scope.deinit();3016 defer cond_scope.deinit();
30493017
3050 const qt = @ptrCast(*const clang.Stmt, stmt).getType();3018 const qt = @ptrCast(*const clang.Expr, stmt).getType();
3051 const res_is_bool = qualTypeIsBoolean(qt);3019 const res_is_bool = qualTypeIsBoolean(qt);
3052 const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);3020 const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt);
3053 const cond_expr = casted_stmt.getCond();3021 const cond_expr = casted_stmt.getCond();
3054 const true_expr = casted_stmt.getTrueExpr();3022 const true_expr = casted_stmt.getTrueExpr();
3055 const false_expr = casted_stmt.getFalseExpr();3023 const false_expr = casted_stmt.getFalseExpr();
30563024
3057 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used, .r_value);3025 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
30583026
3059 var then_body = try transExpr(c, scope, true_expr, .used, .r_value);3027 var then_body = try transExpr(c, scope, true_expr, .used);
3060 if (!res_is_bool and isBoolRes(then_body)) {3028 if (!res_is_bool and isBoolRes(then_body)) {
3061 then_body = try Node.bool_to_int.create(c.arena, then_body);3029 then_body = try Tag.bool_to_int.create(c.arena, then_body);
3062 }3030 }
30633031
3064 var else_body = try transExpr(c, scope, false_expr, .used, .r_value);3032 var else_body = try transExpr(c, scope, false_expr, .used);
3065 if (!res_is_bool and isBoolRes(else_body)) {3033 if (!res_is_bool and isBoolRes(else_body)) {
3066 else_body = try Node.bool_to_int.create(c.arena, else_body);3034 else_body = try Tag.bool_to_int.create(c.arena, else_body);
3067 }3035 }
30683036
3069 const if_node = try Node.@"if".create(c.arena, .{3037 const if_node = try Tag.@"if".create(c.arena, .{
3070 .cond = cond,3038 .cond = cond,
3071 .then = then_body,3039 .then = then_body,
3072 .@"else" = else_body,3040 .@"else" = else_body,
...@@ -3081,7 +3049,7 @@ fn maybeSuppressResult(...@@ -3081,7 +3049,7 @@ fn maybeSuppressResult(
3081 result: Node,3049 result: Node,
3082) TransError!Node {3050) TransError!Node {
3083 if (used == .used) return result;3051 if (used == .used) return result;
3084 return Node.ignore.create(c.arena, result);3052 return Tag.ignore.create(c.arena, result);
3085}3053}
30863054
3087fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {3055fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
...@@ -3100,19 +3068,19 @@ fn transQualTypeInitialized(...@@ -3100,19 +3068,19 @@ fn transQualTypeInitialized(
3100 const ty = qt.getTypePtr();3068 const ty = qt.getTypePtr();
3101 if (ty.getTypeClass() == .IncompleteArray) {3069 if (ty.getTypeClass() == .IncompleteArray) {
3102 const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);3070 const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);
3103 const elem_ty = incomplete_array_ty.getElementType().getTypePtr();3071 const elem_ty = try transType(c, incomplete_array_ty.getElementType().getTypePtr(), source_loc);
31043072
3105 switch (decl_init.getStmtClass()) {3073 switch (decl_init.getStmtClass()) {
3106 .StringLiteralClass => {3074 .StringLiteralClass => {
3107 const string_lit = @ptrCast(*const clang.StringLiteral, decl_init);3075 const string_lit = @ptrCast(*const clang.StringLiteral, decl_init);
3108 const string_lit_size = string_lit.getLength() + 1; // +1 for null terminator3076 const string_lit_size = string_lit.getLength() + 1; // +1 for null terminator
3109 const array_size = @intCast(usize, string_lit_size);3077 const array_size = @intCast(usize, string_lit_size);
3110 return Node.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty });3078 return Tag.array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty });
3111 },3079 },
3112 .InitListExprClass => {3080 .InitListExprClass => {
3113 const init_expr = @ptrCast(*const clang.InitListExpr, decl_init);3081 const init_expr = @ptrCast(*const clang.InitListExpr, decl_init);
3114 const size = init_expr.getNumInits();3082 const size = init_expr.getNumInits();
3115 return Node.array_type.create(c.arena, .{ .len = size, .elem_type = elem_ty });3083 return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_ty });
3116 },3084 },
3117 else => {},3085 else => {},
3118 }3086 }
...@@ -3135,7 +3103,7 @@ fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) Typ...@@ -3135,7 +3103,7 @@ fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) Typ
3135fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!Node {3103fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!Node {
3136 assert(ty.getTypeClass() == .Builtin);3104 assert(ty.getTypeClass() == .Builtin);
3137 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);3105 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
3138 return Node.type.create(c.arena, switch (builtin_ty.getKind()) {3106 return Tag.type.create(c.arena, switch (builtin_ty.getKind()) {
3139 .Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8",3107 .Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8",
3140 .UShort, .Short => if (is_signed) "c_short" else "c_ushort",3108 .UShort, .Short => if (is_signed) "c_short" else "c_ushort",
3141 .UInt, .Int => if (is_signed) "c_int" else "c_uint",3109 .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...@@ -3214,11 +3182,11 @@ fn qualTypeToLog2IntRef(c: *Context, qt: clang.QualType, source_loc: clang.Sourc
3214 if (int_bit_width != 0) {3182 if (int_bit_width != 0) {
3215 // we can perform the log2 now.3183 // we can perform the log2 now.
3216 const cast_bit_width = math.log2_int(u64, int_bit_width);3184 const cast_bit_width = math.log2_int(u64, int_bit_width);
3217 return Node.log2_int_type.create(c.arena, cast_bit_width);3185 return Tag.log2_int_type.create(c.arena, cast_bit_width);
3218 }3186 }
32193187
3220 const zig_type = try transQualType(c, qt, source_loc);3188 const zig_type = try transQualType(c, qt, source_loc);
3221 return Node.std_math_Log2Int.create(c.arena, zig_type);3189 return Tag.std_math_Log2Int.create(c.arena, zig_type);
3222}3190}
32233191
3224fn qualTypeChildIsFnProto(qt: clang.QualType) bool {3192fn qualTypeChildIsFnProto(qt: clang.QualType) bool {
...@@ -3392,10 +3360,10 @@ fn transCreateNodeAssign(...@@ -3392,10 +3360,10 @@ fn transCreateNodeAssign(
3392 // c: lhs = rhs3360 // c: lhs = rhs
3393 // zig: lhs = rhs3361 // zig: lhs = rhs
3394 if (result_used == .unused) {3362 if (result_used == .unused) {
3395 const lhs_node = try transExpr(c, scope, lhs, .used, .l_value);3363 const lhs_node = try transExpr(c, scope, lhs, .used);
3396 var rhs_node = try transExprCoercing(c, scope, rhs, .used, .r_value);3364 var rhs_node = try transExprCoercing(c, scope, rhs, .used);
3397 if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) {3365 if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) {
3398 rhs_node = try Node.bool_to_int.create(c.arena, rhs_node);3366 rhs_node = try Tag.bool_to_int.create(c.arena, rhs_node);
3399 }3367 }
3400 return transCreateNodeInfixOp(c, scope, .assign, lhs_node, rhs_node, .used);3368 return transCreateNodeInfixOp(c, scope, .assign, lhs_node, rhs_node, .used);
3401 }3369 }
...@@ -3411,17 +3379,16 @@ fn transCreateNodeAssign(...@@ -3411,17 +3379,16 @@ fn transCreateNodeAssign(
3411 defer block_scope.deinit();3379 defer block_scope.deinit();
34123380
3413 const tmp = try block_scope.makeMangledName(c, "tmp");3381 const tmp = try block_scope.makeMangledName(c, "tmp");
3414 const rhs = try transExpr(c, scope, op_expr, .used, .r_value);3382 const rhs_node = try transExpr(c, scope, rhs, .used);
3415 const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = rhs});3383 const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = rhs_node });
3416 try block_scope.statements.append(tmp_decl);3384 try block_scope.statements.append(tmp_decl);
34173385
34183386 const lhs_node = try transExpr(c, &block_scope.base, lhs, .used);
3419 const lhs = try transExpr(c, &block_scope.base, lhs, .used, .l_value);3387 const tmp_ident = try Tag.identifier.create(c.arena, tmp);
3420 const tmp_ident = try Node.identifier.create(c.arena, tmp);3388 const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs_node, tmp_ident, .used);
3421 const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs, tmp_iden, .used);
3422 try block_scope.statements.append(assign);3389 try block_scope.statements.append(assign);
34233390
3424 const break_node = try Node.break_val.create(c.arena, .{3391 const break_node = try Tag.break_val.create(c.arena, .{
3425 .label = block_scope.label,3392 .label = block_scope.label,
3426 .val = tmp_ident,3393 .val = tmp_ident,
3427 });3394 });
...@@ -3432,7 +3399,7 @@ fn transCreateNodeAssign(...@@ -3432,7 +3399,7 @@ fn transCreateNodeAssign(
3432fn transCreateNodeInfixOp(3399fn transCreateNodeInfixOp(
3433 c: *Context,3400 c: *Context,
3434 scope: *Scope,3401 scope: *Scope,
3435 op: ast.Node.Tag,3402 op: Tag,
3436 lhs: Node,3403 lhs: Node,
3437 rhs: Node,3404 rhs: Node,
3438 used: ResultUsed,3405 used: ResultUsed,
...@@ -3452,13 +3419,13 @@ fn transCreateNodeBoolInfixOp(...@@ -3452,13 +3419,13 @@ fn transCreateNodeBoolInfixOp(
3452 c: *Context,3419 c: *Context,
3453 scope: *Scope,3420 scope: *Scope,
3454 stmt: *const clang.BinaryOperator,3421 stmt: *const clang.BinaryOperator,
3455 op: ast.Node.Tag,3422 op: Tag,
3456 used: ResultUsed,3423 used: ResultUsed,
3457) !Node {3424) !Node {
3458 std.debug.assert(op == .bool_and or op == .bool_or);3425 std.debug.assert(op == .@"and" or op == .@"or");
34593426
3460 const lhs = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value);3427 const lhs = try transBoolExpr(c, scope, stmt.getLHS(), .used);
3461 const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value);3428 const rhs = try transBoolExpr(c, scope, stmt.getRHS(), .used);
34623429
3463 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, used);3430 return transCreateNodeInfixOp(c, scope, op, lhs, rhs, used);
3464}3431}
...@@ -3503,22 +3470,22 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node {...@@ -3503,22 +3470,22 @@ fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node {
3503 const str = big.toStringAlloc(c.arena, 10, false) catch |err| switch (err) {3470 const str = big.toStringAlloc(c.arena, 10, false) catch |err| switch (err) {
3504 error.OutOfMemory => return error.OutOfMemory,3471 error.OutOfMemory => return error.OutOfMemory,
3505 };3472 };
3506 return Node.int_literal.create(c.arena, str);3473 return Tag.number_literal.create(c.arena, str);
3507}3474}
35083475
3509fn transCreateNodeNumber(c: *Context, int: anytype) !Node {3476fn transCreateNodeNumber(c: *Context, int: anytype) !Node {
3510 const fmt_s = if (comptime std.meta.trait.isNumber(@TypeOf(int))) "{d}" else "{s}";3477 const fmt_s = if (comptime std.meta.trait.isNumber(@TypeOf(int))) "{d}" else "{s}";
3511 const str = try std.fmt.allocPrint(c.arena, fmt_s, .{int});3478 const str = try std.fmt.allocPrint(c.arena, fmt_s, .{int});
3512 return Node.int_literal.create(c.arena, str);3479 return Tag.number_literal.create(c.arena, str);
3513}3480}
35143481
3515fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: *ast.Payload.Func) !Node {3482fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: *ast.Payload.Func) !Node {
3516 const scope = &c.global_scope.base;3483 const scope = &c.global_scope.base;
35173484
3518 var fn_params = std.ArrayList(Node).init(c.gpa);3485 var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
3519 defer fn_params.deinit();3486 defer fn_params.deinit();
35203487
3521 for (proto_alias.params()) |param, i| {3488 for (proto_alias.data.params) |param, i| {
3522 const param_name = param.name orelse3489 const param_name = param.name orelse
3523 try std.fmt.allocPrint(c.arena, "arg_{d}", .{c.getMangle()});3490 try std.fmt.allocPrint(c.arena, "arg_{d}", .{c.getMangle()});
35243491
...@@ -3529,29 +3496,29 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias:...@@ -3529,29 +3496,29 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias:
3529 });3496 });
3530 }3497 }
35313498
3532 const init = if (value.castTag(.var_decl)) |v|3499 const init = if (ref.castTag(.var_decl)) |v|
3533 v.data.init3500 v.data.init.?
3534 else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|3501 else if (ref.castTag(.var_simple) orelse ref.castTag(.pub_var_simple)) |v|
3535 v.data.init3502 v.data.init
3536 else3503 else
3537 unreachable;3504 unreachable;
35383505
3539 const unwrap_expr = try Node.unwrap.create(c.arena, init);3506 const unwrap_expr = try Tag.unwrap.create(c.arena, init);
3540 const call_params = try c.arena.alloc(Node, fn_params.items.len);3507 const args = try c.arena.alloc(Node, fn_params.items.len);
3541 for (fn_params.items) |param, i| {3508 for (fn_params.items) |param, i| {
3542 call_params[i] = try Node.identifier.create(c.arena, param.name);3509 args[i] = try Tag.identifier.create(c.arena, param.name.?);
3543 }3510 }
3544 const call_expr = try Node.call.create(c.arean, .{3511 const call_expr = try Tag.call.create(c.arena, .{
3545 .lhs = unwrap_expr,3512 .lhs = unwrap_expr,
3546 .args = call_params,3513 .args = args,
3547 });3514 });
3548 const return_expr = try Node.@"return".create(c.arean, call_expr);3515 const return_expr = try Tag.@"return".create(c.arena, call_expr);
3549 const block = try Node.block_single.create(c.arean, return_expr);3516 const block = try Tag.block_single.create(c.arena, return_expr);
35503517
3551 return Node.pub_inline_fn.create(c.arena, .{3518 return Tag.pub_inline_fn.create(c.arena, .{
3552 .name = name,3519 .name = name,
3553 .params = try c.arena.dupe(ast.Node.Param, fn_params.items),3520 .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
3554 .return_type = proto_alias.return_type,3521 .return_type = proto_alias.data.return_type,
3555 .body = block,3522 .body = block,
3556 });3523 });
3557}3524}
...@@ -3560,7 +3527,7 @@ fn transCreateNodeShiftOp(...@@ -3560,7 +3527,7 @@ fn transCreateNodeShiftOp(
3560 c: *Context,3527 c: *Context,
3561 scope: *Scope,3528 scope: *Scope,
3562 stmt: *const clang.BinaryOperator,3529 stmt: *const clang.BinaryOperator,
3563 op: Node.Tag,3530 op: Tag,
3564 used: ResultUsed,3531 used: ResultUsed,
3565) !Node {3532) !Node {
3566 std.debug.assert(op == .shl or op == .shr);3533 std.debug.assert(op == .shl or op == .shr);
...@@ -3570,11 +3537,11 @@ fn transCreateNodeShiftOp(...@@ -3570,11 +3537,11 @@ fn transCreateNodeShiftOp(
3570 const rhs_location = rhs_expr.getBeginLoc();3537 const rhs_location = rhs_expr.getBeginLoc();
3571 // lhs >> @as(u5, rh)3538 // lhs >> @as(u5, rh)
35723539
3573 const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value);3540 const lhs = try transExpr(c, scope, lhs_expr, .used);
35743541
3575 const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);3542 const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location);
3576 const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value);3543 const rhs = try transExprCoercing(c, scope, rhs_expr, .used);
3577 const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });3544 const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type });
35783545
3579 return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);3546 return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used);
3580}3547}
...@@ -3583,7 +3550,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3583,7 +3550,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3583 switch (ty.getTypeClass()) {3550 switch (ty.getTypeClass()) {
3584 .Builtin => {3551 .Builtin => {
3585 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);3552 const builtin_ty = @ptrCast(*const clang.BuiltinType, ty);
3586 return Node.type.create(c.arena, switch (builtin_ty.getKind()) {3553 return Tag.type.create(c.arena, switch (builtin_ty.getKind()) {
3587 .Void => "c_void",3554 .Void => "c_void",
3588 .Bool => "bool",3555 .Bool => "bool",
3589 .Char_U, .UChar, .Char_S, .Char8 => "u8",3556 .Char_U, .UChar, .Char_S, .Char8 => "u8",
...@@ -3608,11 +3575,13 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3608,11 +3575,13 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3608 },3575 },
3609 .FunctionProto => {3576 .FunctionProto => {
3610 const fn_proto_ty = @ptrCast(*const clang.FunctionProtoType, ty);3577 const fn_proto_ty = @ptrCast(*const clang.FunctionProtoType, ty);
3611 return transFnProto(c, null, fn_proto_ty, source_loc, null, false);3578 const fn_proto = try transFnProto(c, null, fn_proto_ty, source_loc, null, false);
3579 return Node.initPayload(&fn_proto.base);
3612 },3580 },
3613 .FunctionNoProto => {3581 .FunctionNoProto => {
3614 const fn_no_proto_ty = @ptrCast(*const clang.FunctionType, ty);3582 const fn_no_proto_ty = @ptrCast(*const clang.FunctionType, ty);
3615 return transFnNoProto(c, fn_no_proto_ty, source_loc, null, false);3583 const fn_proto = try transFnNoProto(c, fn_no_proto_ty, source_loc, null, false);
3584 return Node.initPayload(&fn_proto.base);
3616 },3585 },
3617 .Paren => {3586 .Paren => {
3618 const paren_ty = @ptrCast(*const clang.ParenType, ty);3587 const paren_ty = @ptrCast(*const clang.ParenType, ty);
...@@ -3621,16 +3590,16 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3621,16 +3590,16 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3621 .Pointer => {3590 .Pointer => {
3622 const child_qt = ty.getPointeeType();3591 const child_qt = ty.getPointeeType();
3623 if (qualTypeChildIsFnProto(child_qt)) {3592 if (qualTypeChildIsFnProto(child_qt)) {
3624 return Node.optional_type.create(c.arena, try transQualType(c, child_qt, source_loc));3593 return Tag.optional_type.create(c.arena, try transQualType(c, child_qt, source_loc));
3625 }3594 }
3626 const is_const = child_qt.isConstQualified();3595 const is_const = child_qt.isConstQualified();
3627 const is_volatile = child_qt.isVolatileQualified();3596 const is_volatile = child_qt.isVolatileQualified();
3628 const elem_type = try transQualType(c, child_qt, source_loc);3597 const elem_type = try transQualType(c, child_qt, source_loc);
3629 if (typeIsOpaque(rp.c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(rp.c, child_qt)) {3598 if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) {
3630 return Node.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });3599 return Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
3631 }3600 }
36323601
3633 return Node.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });3602 return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
3634 },3603 },
3635 .ConstantArray => {3604 .ConstantArray => {
3636 const const_arr_ty = @ptrCast(*const clang.ConstantArrayType, ty);3605 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...@@ -3639,7 +3608,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3639 const size = size_ap_int.getLimitedValue(math.maxInt(usize));3608 const size = size_ap_int.getLimitedValue(math.maxInt(usize));
3640 const elem_type = try transType(c, const_arr_ty.getElementType().getTypePtr(), source_loc);3609 const elem_type = try transType(c, const_arr_ty.getElementType().getTypePtr(), source_loc);
36413610
3642 return Node.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });3611 return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_type });
3643 },3612 },
3644 .IncompleteArray => {3613 .IncompleteArray => {
3645 const incomplete_array_ty = @ptrCast(*const clang.IncompleteArrayType, ty);3614 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...@@ -3649,7 +3618,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3649 const is_volatile = child_qt.isVolatileQualified();3618 const is_volatile = child_qt.isVolatileQualified();
3650 const elem_type = try transQualType(c, child_qt, source_loc);3619 const elem_type = try transQualType(c, child_qt, source_loc);
36513620
3652 return Node.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });3621 return Tag.c_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type });
3653 },3622 },
3654 .Typedef => {3623 .Typedef => {
3655 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);3624 const typedef_ty = @ptrCast(*const clang.TypedefType, ty);
...@@ -3690,7 +3659,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio...@@ -3690,7 +3659,7 @@ fn transType(c: *Context, ty: *const clang.Type, source_loc: clang.SourceLocatio
3690 },3659 },
3691 else => {3660 else => {
3692 const type_name = c.str(ty.getTypeClassName());3661 const type_name = c.str(ty.getTypeClassName());
3693 return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});3662 return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name});
3694 },3663 },
3695 }3664 }
3696}3665}
...@@ -3770,7 +3739,7 @@ fn transCC(...@@ -3770,7 +3739,7 @@ fn transCC(
3770 .AAPCS => return CallingConvention.AAPCS,3739 .AAPCS => return CallingConvention.AAPCS,
3771 .AAPCS_VFP => return CallingConvention.AAPCSVFP,3740 .AAPCS_VFP => return CallingConvention.AAPCSVFP,
3772 else => return fail(3741 else => return fail(
3773 rp,3742 c,
3774 error.UnsupportedType,3743 error.UnsupportedType,
3775 source_loc,3744 source_loc,
3776 "unsupported calling convention: {s}",3745 "unsupported calling convention: {s}",
...@@ -3786,7 +3755,7 @@ fn transFnProto(...@@ -3786,7 +3755,7 @@ fn transFnProto(
3786 source_loc: clang.SourceLocation,3755 source_loc: clang.SourceLocation,
3787 fn_decl_context: ?FnDeclContext,3756 fn_decl_context: ?FnDeclContext,
3788 is_pub: bool,3757 is_pub: bool,
3789) !Node.FnProto {3758) !*ast.Payload.Func {
3790 const fn_ty = @ptrCast(*const clang.FunctionType, fn_proto_ty);3759 const fn_ty = @ptrCast(*const clang.FunctionType, fn_proto_ty);
3791 const cc = try transCC(c, fn_ty, source_loc);3760 const cc = try transCC(c, fn_ty, source_loc);
3792 const is_var_args = fn_proto_ty.isVariadic();3761 const is_var_args = fn_proto_ty.isVariadic();
...@@ -3799,7 +3768,7 @@ fn transFnNoProto(...@@ -3799,7 +3768,7 @@ fn transFnNoProto(
3799 source_loc: clang.SourceLocation,3768 source_loc: clang.SourceLocation,
3800 fn_decl_context: ?FnDeclContext,3769 fn_decl_context: ?FnDeclContext,
3801 is_pub: bool,3770 is_pub: bool,
3802) !Node.FnProto {3771) !*ast.Payload.Func {
3803 const cc = try transCC(c, fn_ty, source_loc);3772 const cc = try transCC(c, fn_ty, source_loc);
3804 const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static) else true;3773 const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static) else true;
3805 return finishTransFnProto(c, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);3774 return finishTransFnProto(c, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
...@@ -3822,7 +3791,7 @@ fn finishTransFnProto(...@@ -3822,7 +3791,7 @@ fn finishTransFnProto(
3822 // TODO check for always_inline attribute3791 // TODO check for always_inline attribute
3823 // TODO check for align attribute3792 // TODO check for align attribute
38243793
3825 var fn_params = std.ArrayList(ast.Payload.Func.Param).init(c.gpa);3794 var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
3826 defer fn_params.deinit();3795 defer fn_params.deinit();
3827 const param_count: usize = if (fn_proto_ty != null) fn_proto_ty.?.getNumParams() else 0;3796 const param_count: usize = if (fn_proto_ty != null) fn_proto_ty.?.getNumParams() else 0;
3828 try fn_params.ensureCapacity(param_count);3797 try fn_params.ensureCapacity(param_count);
...@@ -3861,7 +3830,7 @@ fn finishTransFnProto(...@@ -3861,7 +3830,7 @@ fn finishTransFnProto(
3861 break :blk null;3830 break :blk null;
3862 };3831 };
38633832
3864 const alignment: c_uint = blk: {3833 const alignment = blk: {
3865 if (fn_decl) |decl| {3834 if (fn_decl) |decl| {
3866 const alignment = decl.getAlignedAttribute(c.clang_context);3835 const alignment = decl.getAlignedAttribute(c.clang_context);
3867 if (alignment != 0) {3836 if (alignment != 0) {
...@@ -3876,16 +3845,16 @@ fn finishTransFnProto(...@@ -3876,16 +3845,16 @@ fn finishTransFnProto(
38763845
3877 const return_type_node = blk: {3846 const return_type_node = blk: {
3878 if (fn_ty.getNoReturnAttr()) {3847 if (fn_ty.getNoReturnAttr()) {
3879 break :blk Node.noreturn_type.init();3848 break :blk Tag.noreturn_type.init();
3880 } else {3849 } else {
3881 const return_qt = fn_ty.getReturnType();3850 const return_qt = fn_ty.getReturnType();
3882 if (isCVoid(return_qt)) {3851 if (isCVoid(return_qt)) {
3883 // convert primitive c_void to actual void (only for return type)3852 // convert primitive c_void to actual void (only for return type)
3884 break :blk Node.void_type.init();3853 break :blk Tag.void_type.init();
3885 } else {3854 } else {
3886 break :blk transQualType(c, return_qt, source_loc) catch |err| switch (err) {3855 break :blk transQualType(c, return_qt, source_loc) catch |err| switch (err) {
3887 error.UnsupportedType => {3856 error.UnsupportedType => {
3888 try warn(c, source_loc, "unsupported function proto return type", .{});3857 try warn(c, &c.global_scope.base, source_loc, "unsupported function proto return type", .{});
3889 return err;3858 return err;
3890 },3859 },
3891 error.OutOfMemory => |e| return e,3860 error.OutOfMemory => |e| return e,
...@@ -3893,26 +3862,31 @@ fn finishTransFnProto(...@@ -3893,26 +3862,31 @@ fn finishTransFnProto(
3893 }3862 }
3894 }3863 }
3895 };3864 };
38963865 const name: ?[]const u8 = if (fn_decl_context) |ctx| ctx.fn_name else null;
3897 return Node.func.create(c.arena, .{3866 const payload = try c.arena.create(ast.Payload.Func);
3898 .is_pub = is_pub,3867 payload.* = .{
3899 .is_extern = is_extern,3868 .base = .{ .tag = .func },
3900 .is_export = is_export,3869 .data = .{
3901 .is_var_args = is_var_args,3870 .is_pub = is_pub,
3902 .name = name,3871 .is_extern = is_extern,
3903 .linksection_string = linksection_string,3872 .is_export = is_export,
3904 .explicit_callconv = explicit_callconv,3873 .is_var_args = is_var_args,
3905 .params = try c.arena.dupe(ast.Payload.Func.Param, fn_params.items),3874 .name = name,
3906 .return_type = return_node,3875 .linksection_string = linksection_string,
3907 .body = null,3876 .explicit_callconv = explicit_callconv,
3908 .alignment = alignment,3877 .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
3909 });3878 .return_type = return_type_node,
3879 .body = null,
3880 .alignment = alignment,
3881 },
3882 };
3883 return payload;
3910}3884}
39113885
3912fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {3886fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void {
3913 const args_prefix = .{c.locStr(loc)};3887 const args_prefix = .{c.locStr(loc)};
3914 const value = std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args);3888 const value = try std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args);
3915 try scope.appendNode(c.gpa, try Node.warning.create(c.arena, value));3889 try scope.appendNode(try Tag.warning.create(c.arena, value));
3916}3890}
39173891
3918fn fail(3892fn fail(
...@@ -3922,17 +3896,17 @@ fn fail(...@@ -3922,17 +3896,17 @@ fn fail(
3922 comptime format: []const u8,3896 comptime format: []const u8,
3923 args: anytype,3897 args: anytype,
3924) (@TypeOf(err) || error{OutOfMemory}) {3898) (@TypeOf(err) || error{OutOfMemory}) {
3925 try warn(c, source_loc, format, args);3899 try warn(c, &c.global_scope.base, source_loc, format, args);
3926 return err;3900 return err;
3927}3901}
39283902
3929pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, comptime format: []const u8, args: anytype) !void {3903pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, comptime format: []const u8, args: anytype) Error!void {
3930 // location3904 // location
3931 // pub const name = @compileError(msg);3905 // pub const name = @compileError(msg);
3932 const location_comment = std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)});3906 const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)});
3933 try c.global_scope.nodes.append(try Node.warning.create(c.arena, location_comment));3907 try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment));
3934 const fail_msg = std.fmt.allocPrint(c.arena, format, args);3908 const fail_msg = try std.fmt.allocPrint(c.arena, format, args);
3935 try c.global_scope.nodes.append(try Node.fail_decl.create(c.arena, fail_msg));3909 try c.global_scope.nodes.append(try Tag.fail_decl.create(c.arena, fail_msg));
3936}3910}
39373911
3938pub fn freeErrors(errors: []ClangErrMsg) void {3912pub fn freeErrors(errors: []ClangErrMsg) void {
...@@ -4075,7 +4049,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -4075,7 +4049,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
4075 if (last != .Eof and last != .Nl)4049 if (last != .Eof and last != .Nl)
4076 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});4050 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
40774051
4078 const var_decl = try Node.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });4052 const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
4079 _ = try c.global_scope.macro_table.put(m.name, var_decl);4053 _ = try c.global_scope.macro_table.put(m.name, var_decl);
4080}4054}
40814055
...@@ -4099,7 +4073,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -4099,7 +4073,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
4099 try fn_params.append(.{4073 try fn_params.append(.{
4100 .is_noalias = false,4074 .is_noalias = false,
4101 .name = mangled_name,4075 .name = mangled_name,
4102 .type = Node.@"anytype".init(),4076 .type = Tag.@"anytype".init(),
4103 });4077 });
41044078
4105 if (m.peek().? != .Comma) break;4079 if (m.peek().? != .Comma) break;
...@@ -4119,19 +4093,19 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {...@@ -4119,19 +4093,19 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
4119 const stmts = some.data.stmts;4093 const stmts = some.data.stmts;
4120 const blk_last = stmts[stmts.len - 1];4094 const blk_last = stmts[stmts.len - 1];
4121 const br = blk_last.castTag(.break_val).?;4095 const br = blk_last.castTag(.break_val).?;
4122 break :blk br.data;4096 break :blk br.data.val;
4123 } else expr;4097 } else expr;
4124 const typeof = try Node.typeof.create(c.arean, typeof_arg);4098 const typeof = try Tag.typeof.create(c.arena, typeof_arg);
4125 const return_expr = try Node.@"return".create(c.arena, expr);4099 const return_expr = try Tag.@"return".create(c.arena, expr);
4126 try block_scope.statements.append(&return_expr.base);4100 try block_scope.statements.append(return_expr);
4127 4101
4128 const fn_decl = try Node.pub_inline_fn.create(c.arena, .{4102 const fn_decl = try Tag.pub_inline_fn.create(c.arena, .{
4129 .name = m.name,4103 .name = m.name,
4130 .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),4104 .params = try c.arena.dupe(ast.Payload.Param, fn_params.items),
4131 .return_type = typeof,4105 .return_type = typeof,
4132 .body = try block_scope.complete(c),4106 .body = try block_scope.complete(c),
4133 });4107 });
4134 _ = try c.global_scope.macro_table.put(m.name, &fn_proto.base);4108 _ = try c.global_scope.macro_table.put(m.name, fn_decl);
4135}4109}
41364110
4137const ParseError = Error || error{ParseError};4111const ParseError = Error || error{ParseError};
...@@ -4149,7 +4123,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4149,7 +4123,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4149 var last = node;4123 var last = node;
4150 while (true) {4124 while (true) {
4151 // suppress result4125 // suppress result
4152 const ignore = try Node.ignore.create(c.arena, last);4126 const ignore = try Tag.ignore.create(c.arena, last);
4153 try block_scope.statements.append(ignore);4127 try block_scope.statements.append(ignore);
41544128
4155 last = try parseCCondExpr(c, m, scope);4129 last = try parseCCondExpr(c, m, scope);
...@@ -4159,7 +4133,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4159,7 +4133,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4159 }4133 }
4160 }4134 }
41614135
4162 const break_node = try Node.break_val.create(c.arena, .{4136 const break_node = try Tag.break_val.create(c.arena, .{
4163 .label = block_scope.label,4137 .label = block_scope.label,
4164 .val = last,4138 .val = last,
4165 });4139 });
...@@ -4190,7 +4164,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -4190,7 +4164,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
4190 return transCreateNodeNumber(c, lit_bytes);4164 return transCreateNodeNumber(c, lit_bytes);
4191 }4165 }
41924166
4193 const type_node = try Node.type.create(c.arena, switch (suffix) {4167 const type_node = try Tag.type.create(c.arena, switch (suffix) {
4194 .u => "c_uint",4168 .u => "c_uint",
4195 .l => "c_long",4169 .l => "c_long",
4196 .lu => "c_ulong",4170 .lu => "c_ulong",
...@@ -4205,7 +4179,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -4205,7 +4179,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
4205 else => unreachable,4179 else => unreachable,
4206 }];4180 }];
4207 const rhs = try transCreateNodeNumber(c, lit_bytes);4181 const rhs = try transCreateNodeNumber(c, lit_bytes);
4208 return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });4182 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
4209 },4183 },
4210 .FloatLiteral => |suffix| {4184 .FloatLiteral => |suffix| {
4211 if (lit_bytes[0] == '.')4185 if (lit_bytes[0] == '.')
...@@ -4213,13 +4187,13 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -4213,13 +4187,13 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
4213 if (suffix == .none) {4187 if (suffix == .none) {
4214 return transCreateNodeNumber(c, lit_bytes);4188 return transCreateNodeNumber(c, lit_bytes);
4215 }4189 }
4216 const type_node = try Node.type.create(c.arena, switch (suffix) {4190 const type_node = try Tag.type.create(c.arena, switch (suffix) {
4217 .f => "f32",4191 .f => "f32",
4218 .l => "c_longdouble",4192 .l => "c_longdouble",
4219 else => unreachable,4193 else => unreachable,
4220 });4194 });
4221 const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1]);4195 const rhs = try transCreateNodeNumber(c, lit_bytes[0 .. lit_bytes.len - 1]);
4222 return Node.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });4196 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });
4223 },4197 },
4224 else => unreachable,4198 else => unreachable,
4225 }4199 }
...@@ -4391,56 +4365,56 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N...@@ -4391,56 +4365,56 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
4391 switch (tok) {4365 switch (tok) {
4392 .CharLiteral => {4366 .CharLiteral => {
4393 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {4367 if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
4394 return Node.char_literal.create(c.arena, try zigifyEscapeSequences(c, m));4368 return Tag.char_literal.create(c.arena, try zigifyEscapeSequences(c, m));
4395 } else {4369 } else {
4396 const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});4370 const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});
4397 return Node.int_literal.create(c.arena, str);4371 return Tag.number_literal.create(c.arena, str);
4398 }4372 }
4399 },4373 },
4400 .StringLiteral => {4374 .StringLiteral => {
4401 return Node.string_literal.create(c.arena, try zigifyEscapeSequences(c, m));4375 return Tag.string_literal.create(c.arena, try zigifyEscapeSequences(c, m));
4402 },4376 },
4403 .IntegerLiteral, .FloatLiteral => {4377 .IntegerLiteral, .FloatLiteral => {
4404 return parseCNumLit(c, m);4378 return parseCNumLit(c, m);
4405 },4379 },
4406 // eventually this will be replaced by std.c.parse which will handle these correctly4380 // eventually this will be replaced by std.c.parse which will handle these correctly
4407 .Keyword_void => return Node.type.create(c.arena, "c_void"),4381 .Keyword_void => return Tag.type.create(c.arena, "c_void"),
4408 .Keyword_bool => return Node.type.create(c.arena, "bool"),4382 .Keyword_bool => return Tag.type.create(c.arena, "bool"),
4409 .Keyword_double => return Node.type.create(c.arena, "f64"),4383 .Keyword_double => return Tag.type.create(c.arena, "f64"),
4410 .Keyword_long => return Node.type.create(c.arena, "c_long"),4384 .Keyword_long => return Tag.type.create(c.arena, "c_long"),
4411 .Keyword_int => return Node.type.create(c.arena, "c_int"),4385 .Keyword_int => return Tag.type.create(c.arena, "c_int"),
4412 .Keyword_float => return Node.type.create(c.arena, "f32"),4386 .Keyword_float => return Tag.type.create(c.arena, "f32"),
4413 .Keyword_short => return Node.type.create(c.arena, "c_short"),4387 .Keyword_short => return Tag.type.create(c.arena, "c_short"),
4414 .Keyword_char => return Node.type.create(c.arena, "u8"),4388 .Keyword_char => return Tag.type.create(c.arena, "u8"),
4415 .Keyword_unsigned => if (m.next()) |t| switch (t) {4389 .Keyword_unsigned => if (m.next()) |t| switch (t) {
4416 .Keyword_char => return Node.type.create(c.arena, "u8"),4390 .Keyword_char => return Tag.type.create(c.arena, "u8"),
4417 .Keyword_short => return Node.type.create(c.arena, "c_ushort"),4391 .Keyword_short => return Tag.type.create(c.arena, "c_ushort"),
4418 .Keyword_int => return Node.type.create(c.arena, "c_uint"),4392 .Keyword_int => return Tag.type.create(c.arena, "c_uint"),
4419 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {4393 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
4420 _ = m.next();4394 _ = m.next();
4421 return Node.type.create(c.arena, "c_ulonglong");4395 return Tag.type.create(c.arena, "c_ulonglong");
4422 } else return Node.type.create(c.arena, "c_ulong"),4396 } else return Tag.type.create(c.arena, "c_ulong"),
4423 else => {4397 else => {
4424 m.i -= 1;4398 m.i -= 1;
4425 return Node.type.create(c.arena, "c_uint");4399 return Tag.type.create(c.arena, "c_uint");
4426 },4400 },
4427 } else {4401 } else {
4428 return Node.type.create(c.arena, "c_uint");4402 return Tag.type.create(c.arena, "c_uint");
4429 },4403 },
4430 .Keyword_signed => if (m.next()) |t| switch (t) {4404 .Keyword_signed => if (m.next()) |t| switch (t) {
4431 .Keyword_char => return Node.type.create(c.arena, "i8"),4405 .Keyword_char => return Tag.type.create(c.arena, "i8"),
4432 .Keyword_short => return Node.type.create(c.arena, "c_short"),4406 .Keyword_short => return Tag.type.create(c.arena, "c_short"),
4433 .Keyword_int => return Node.type.create(c.arena, "c_int"),4407 .Keyword_int => return Tag.type.create(c.arena, "c_int"),
4434 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {4408 .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
4435 _ = m.next();4409 _ = m.next();
4436 return Node.type.create(c.arena, "c_longlong");4410 return Tag.type.create(c.arena, "c_longlong");
4437 } else return Node.type.create(c.arena, "c_long"),4411 } else return Tag.type.create(c.arena, "c_long"),
4438 else => {4412 else => {
4439 m.i -= 1;4413 m.i -= 1;
4440 return Node.type.create(c.arena, "c_int");4414 return Tag.type.create(c.arena, "c_int");
4441 },4415 },
4442 } else {4416 } else {
4443 return Node.type.create(c.arena, "c_int");4417 return Tag.type.create(c.arena, "c_int");
4444 },4418 },
4445 .Keyword_enum, .Keyword_struct, .Keyword_union => {4419 .Keyword_enum, .Keyword_struct, .Keyword_union => {
4446 // struct Foo will be declared as struct_Foo by transRecordDecl4420 // struct Foo will be declared as struct_Foo by transRecordDecl
...@@ -4451,11 +4425,11 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N...@@ -4451,11 +4425,11 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
4451 }4425 }
44524426
4453 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });4427 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
4454 return Node.identifier.create(c.arena, name);4428 return Tag.identifier.create(c.arena, name);
4455 },4429 },
4456 .Identifier => {4430 .Identifier => {
4457 const mangled_name = scope.getAlias(slice);4431 const mangled_name = scope.getAlias(slice);
4458 return Node.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);4432 return Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
4459 },4433 },
4460 .LParen => {4434 .LParen => {
4461 const inner_node = try parseCExpr(c, m, scope);4435 const inner_node = try parseCExpr(c, m, scope);
...@@ -4492,7 +4466,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N...@@ -4492,7 +4466,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
4492 return error.ParseError;4466 return error.ParseError;
4493 }4467 }
44944468
4495 return Node.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });4469 return Tag.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });
4496 },4470 },
4497 else => {4471 else => {
4498 try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});4472 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 {...@@ -4511,7 +4485,7 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4511 .StringLiteral, .Identifier => {},4485 .StringLiteral, .Identifier => {},
4512 else => break,4486 else => break,
4513 }4487 }
4514 node = try Node.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });4488 node = try Tag.array_cat.create(c.arena, .{ .lhs = node, .rhs = try parseCPrimaryExprInner(c, m, scope) });
4515 }4489 }
4516 return node;4490 return node;
4517}4491}
...@@ -4521,7 +4495,7 @@ fn macroBoolToInt(c: *Context, node: Node) !Node {...@@ -4521,7 +4495,7 @@ fn macroBoolToInt(c: *Context, node: Node) !Node {
4521 return node;4495 return node;
4522 }4496 }
45234497
4524 return Node.bool_to_int.create(c.arena, node);4498 return Tag.bool_to_int.create(c.arena, node);
4525}4499}
45264500
4527fn macroIntToBool(c: *Context, node: Node) !Node {4501fn macroIntToBool(c: *Context, node: Node) !Node {
...@@ -4529,7 +4503,7 @@ fn macroIntToBool(c: *Context, node: Node) !Node {...@@ -4529,7 +4503,7 @@ fn macroIntToBool(c: *Context, node: Node) !Node {
4529 return node;4503 return node;
4530 }4504 }
45314505
4532 return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() });4506 return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() });
4533}4507}
45344508
4535fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {4509fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
...@@ -4545,7 +4519,7 @@ fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4545,7 +4519,7 @@ fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4545 return error.ParseError;4519 return error.ParseError;
4546 }4520 }
4547 const else_body = try parseCCondExpr(c, m, scope);4521 const else_body = try parseCCondExpr(c, m, scope);
4548 return Node.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });4522 return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });
4549}4523}
45504524
4551fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {4525fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
...@@ -4553,7 +4527,7 @@ fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4553,7 +4527,7 @@ fn parseCOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4553 while (m.next().? == .PipePipe) {4527 while (m.next().? == .PipePipe) {
4554 const lhs = try macroIntToBool(c, node);4528 const lhs = try macroIntToBool(c, node);
4555 const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope));4529 const rhs = try macroIntToBool(c, try parseCAndExpr(c, m, scope));
4556 node = try Node.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs });4530 node = try Tag.@"or".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4557 }4531 }
4558 m.i -= 1;4532 m.i -= 1;
4559 return node;4533 return node;
...@@ -4564,7 +4538,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4564,7 +4538,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4564 while (m.next().? == .AmpersandAmpersand) {4538 while (m.next().? == .AmpersandAmpersand) {
4565 const lhs = try macroIntToBool(c, node);4539 const lhs = try macroIntToBool(c, node);
4566 const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope));4540 const rhs = try macroIntToBool(c, try parseCBitOrExpr(c, m, scope));
4567 node = try Node.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs });4541 node = try Tag.@"and".create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4568 }4542 }
4569 m.i -= 1;4543 m.i -= 1;
4570 return node;4544 return node;
...@@ -4575,7 +4549,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4575,7 +4549,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4575 while (m.next().? == .Pipe) {4549 while (m.next().? == .Pipe) {
4576 const lhs = try macroBoolToInt(c, node);4550 const lhs = try macroBoolToInt(c, node);
4577 const rhs = try macroBoolToInt(c, try parseCBitXorExpr(c, m, scope));4551 const rhs = try macroBoolToInt(c, try parseCBitXorExpr(c, m, scope));
4578 node = try Node.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4552 node = try Tag.bit_or.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4579 }4553 }
4580 m.i -= 1;4554 m.i -= 1;
4581 return node;4555 return node;
...@@ -4586,7 +4560,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4586,7 +4560,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4586 while (m.next().? == .Caret) {4560 while (m.next().? == .Caret) {
4587 const lhs = try macroBoolToInt(c, node);4561 const lhs = try macroBoolToInt(c, node);
4588 const rhs = try macroBoolToInt(c, try parseCBitAndExpr(c, m, scope));4562 const rhs = try macroBoolToInt(c, try parseCBitAndExpr(c, m, scope));
4589 node = try Node.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4563 node = try Tag.bit_xor.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4590 }4564 }
4591 m.i -= 1;4565 m.i -= 1;
4592 return node;4566 return node;
...@@ -4597,7 +4571,7 @@ fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4597,7 +4571,7 @@ fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4597 while (m.next().? == .Ampersand) {4571 while (m.next().? == .Ampersand) {
4598 const lhs = try macroBoolToInt(c, node);4572 const lhs = try macroBoolToInt(c, node);
4599 const rhs = try macroBoolToInt(c, try parseCEqExpr(c, m, scope));4573 const rhs = try macroBoolToInt(c, try parseCEqExpr(c, m, scope));
4600 node = try Node.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4574 node = try Tag.bit_and.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4601 }4575 }
4602 m.i -= 1;4576 m.i -= 1;
4603 return node;4577 return node;
...@@ -4611,13 +4585,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4611,13 +4585,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4611 _ = m.next();4585 _ = m.next();
4612 const lhs = try macroBoolToInt(c, node);4586 const lhs = try macroBoolToInt(c, node);
4613 const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));4587 const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
4614 node = try Node.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4588 node = try Tag.not_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4615 },4589 },
4616 .EqualEqual => {4590 .EqualEqual => {
4617 _ = m.next();4591 _ = m.next();
4618 const lhs = try macroBoolToInt(c, node);4592 const lhs = try macroBoolToInt(c, node);
4619 const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));4593 const rhs = try macroBoolToInt(c, try parseCRelExpr(c, m, scope));
4620 node = try Node.equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4594 node = try Tag.equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4621 },4595 },
4622 else => return node,4596 else => return node,
4623 }4597 }
...@@ -4632,25 +4606,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4632,25 +4606,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4632 _ = m.next();4606 _ = m.next();
4633 const lhs = try macroBoolToInt(c, node);4607 const lhs = try macroBoolToInt(c, node);
4634 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));4608 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4635 node = try Node.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4609 node = try Tag.greater_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4636 },4610 },
4637 .AngleBracketRightEqual => {4611 .AngleBracketRightEqual => {
4638 _ = m.next();4612 _ = m.next();
4639 const lhs = try macroBoolToInt(c, node);4613 const lhs = try macroBoolToInt(c, node);
4640 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));4614 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4641 node = try Node.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4615 node = try Tag.greater_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4642 },4616 },
4643 .AngleBracketLeft => {4617 .AngleBracketLeft => {
4644 _ = m.next();4618 _ = m.next();
4645 const lhs = try macroBoolToInt(c, node);4619 const lhs = try macroBoolToInt(c, node);
4646 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));4620 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4647 node = try Node.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4621 node = try Tag.less_than.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4648 },4622 },
4649 .AngleBracketLeftEqual => {4623 .AngleBracketLeftEqual => {
4650 _ = m.next();4624 _ = m.next();
4651 const lhs = try macroBoolToInt(c, node);4625 const lhs = try macroBoolToInt(c, node);
4652 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));4626 const rhs = try macroBoolToInt(c, try parseCShiftExpr(c, m, scope));
4653 node = try Node.less_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4627 node = try Tag.less_than_equal.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4654 },4628 },
4655 else => return node,4629 else => return node,
4656 }4630 }
...@@ -4665,13 +4639,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4665,13 +4639,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4665 _ = m.next();4639 _ = m.next();
4666 const lhs = try macroBoolToInt(c, node);4640 const lhs = try macroBoolToInt(c, node);
4667 const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));4641 const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
4668 node = try Node.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4642 node = try Tag.shl.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4669 },4643 },
4670 .AngleBracketAngleBracketRight => {4644 .AngleBracketAngleBracketRight => {
4671 _ = m.next();4645 _ = m.next();
4672 const lhs = try macroBoolToInt(c, node);4646 const lhs = try macroBoolToInt(c, node);
4673 const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));4647 const rhs = try macroBoolToInt(c, try parseCAddSubExpr(c, m, scope));
4674 node = try Node.shr.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4648 node = try Tag.shr.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4675 },4649 },
4676 else => return node,4650 else => return node,
4677 }4651 }
...@@ -4686,13 +4660,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4686,13 +4660,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4686 _ = m.next();4660 _ = m.next();
4687 const lhs = try macroBoolToInt(c, node);4661 const lhs = try macroBoolToInt(c, node);
4688 const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));4662 const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
4689 node = try Node.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4663 node = try Tag.add.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4690 },4664 },
4691 .Minus => {4665 .Minus => {
4692 _ = m.next();4666 _ = m.next();
4693 const lhs = try macroBoolToInt(c, node);4667 const lhs = try macroBoolToInt(c, node);
4694 const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));4668 const rhs = try macroBoolToInt(c, try parseCMulExpr(c, m, scope));
4695 node = try Node.sub.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4669 node = try Tag.sub.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4696 },4670 },
4697 else => return node,4671 else => return node,
4698 }4672 }
...@@ -4711,14 +4685,14 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4711,14 +4685,14 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4711 const prev_id = m.list[m.i - 1].id;4685 const prev_id = m.list[m.i - 1].id;
47124686
4713 if (prev_id == .Keyword_void) {4687 if (prev_id == .Keyword_void) {
4714 const ptr = try Node.single_pointer.create(c.arena, .{4688 const ptr = try Tag.single_pointer.create(c.arena, .{
4715 .is_const = false,4689 .is_const = false,
4716 .is_volatile = false,4690 .is_volatile = false,
4717 .elem_type = node,4691 .elem_type = node,
4718 });4692 });
4719 return Node.optional_type.create(c.arena, ptr);4693 return Tag.optional_type.create(c.arena, ptr);
4720 } else {4694 } else {
4721 return Node.c_pointer.create(c.arena, .{4695 return Tag.c_pointer.create(c.arena, .{
4722 .is_const = false,4696 .is_const = false,
4723 .is_volatile = false,4697 .is_volatile = false,
4724 .elem_type = node,4698 .elem_type = node,
...@@ -4728,18 +4702,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4728,18 +4702,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4728 // expr * expr4702 // expr * expr
4729 const lhs = try macroBoolToInt(c, node);4703 const lhs = try macroBoolToInt(c, node);
4730 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));4704 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4731 node = try Node.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4705 node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4732 }4706 }
4733 },4707 },
4734 .Slash => {4708 .Slash => {
4735 const lhs = try macroBoolToInt(c, node);4709 const lhs = try macroBoolToInt(c, node);
4736 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));4710 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4737 node = try Node.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4711 node = try Tag.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4738 },4712 },
4739 .Percent => {4713 .Percent => {
4740 const lhs = try macroBoolToInt(c, node);4714 const lhs = try macroBoolToInt(c, node);
4741 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));4715 const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4742 node = try Node.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });4716 node = try Tag.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
4743 },4717 },
4744 else => {4718 else => {
4745 m.i -= 1;4719 m.i -= 1;
...@@ -4759,8 +4733,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4759,8 +4733,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4759 return error.ParseError;4733 return error.ParseError;
4760 }4734 }
47614735
4762 const ident = try Node.identifier.create(c.arena, m.slice());4736 const ident = try Tag.identifier.create(c.arena, m.slice());
4763 node = try Node.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });4737 node = try Tag.field_access.create(c.arena, .{ .lhs = node, .rhs = ident });
4764 },4738 },
4765 .Arrow => {4739 .Arrow => {
4766 if (m.next().? != .Identifier) {4740 if (m.next().? != .Identifier) {
...@@ -4768,20 +4742,20 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4768,20 +4742,20 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4768 return error.ParseError;4742 return error.ParseError;
4769 }4743 }
47704744
4771 const deref = try Node.deref.create(c.arena, node);4745 const deref = try Tag.deref.create(c.arena, node);
4772 const ident = try Node.identifier.create(c.arena, m.slice());4746 const ident = try Tag.identifier.create(c.arena, m.slice());
4773 node = try Node.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident });4747 node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident });
4774 },4748 },
4775 .LBracket => {4749 .LBracket => {
4776 const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));4750 const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));
4777 node = try Node.array_access.create(c.arena, .{ .lhs = node, .rhs = index });4751 node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index });
4778 },4752 },
4779 .LParen => {4753 .LParen => {
4780 var call_params = std.ArrayList(Node).init(c.gpa);4754 var args = std.ArrayList(Node).init(c.gpa);
4781 defer call_params.deinit();4755 defer args.deinit();
4782 while (true) {4756 while (true) {
4783 const arg = try parseCCondExpr(c, m, scope);4757 const arg = try parseCCondExpr(c, m, scope);
4784 try call_params.append(arg);4758 try args.append(arg);
4785 switch (m.next().?) {4759 switch (m.next().?) {
4786 .Comma => {},4760 .Comma => {},
4787 .RParen => break,4761 .RParen => break,
...@@ -4791,7 +4765,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4791,7 +4765,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4791 },4765 },
4792 }4766 }
4793 }4767 }
4794 node = try Node.call.create(c.arena, .{ .lhs = node, .rhs = try c.arena.dupe(Node, call_params.items) });4768 node = try Tag.call.create(c.arena, .{ .lhs = node, .args = try c.arena.dupe(Node, args.items) });
4795 },4769 },
4796 .LBrace => {4770 .LBrace => {
4797 var init_vals = std.ArrayList(Node).init(c.gpa);4771 var init_vals = std.ArrayList(Node).init(c.gpa);
...@@ -4809,8 +4783,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4809,8 +4783,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4809 },4783 },
4810 }4784 }
4811 }4785 }
4812 const tuple_node = try Node.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items));4786 const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items));
4813 node = try Node.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });4787 node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node });
4814 },4788 },
4815 .PlusPlus, .MinusMinus => {4789 .PlusPlus, .MinusMinus => {
4816 try m.fail(c, "TODO postfix inc/dec expr", .{});4790 try m.fail(c, "TODO postfix inc/dec expr", .{});
...@@ -4828,24 +4802,24 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4828,24 +4802,24 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4828 switch (m.next().?) {4802 switch (m.next().?) {
4829 .Bang => {4803 .Bang => {
4830 const operand = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));4804 const operand = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
4831 return Node.not.create(c.arena, operand);4805 return Tag.not.create(c.arena, operand);
4832 },4806 },
4833 .Minus => {4807 .Minus => {
4834 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));4808 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4835 return Node.negate.create(c.arena, operand);4809 return Tag.negate.create(c.arena, operand);
4836 },4810 },
4837 .Plus => return try parseCUnaryExpr(c, m, scope),4811 .Plus => return try parseCUnaryExpr(c, m, scope),
4838 .Tilde => {4812 .Tilde => {
4839 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));4813 const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
4840 return Node.bit_not.create(c.arena, operand);4814 return Tag.bit_not.create(c.arena, operand);
4841 },4815 },
4842 .Asterisk => {4816 .Asterisk => {
4843 const operand = try parseCUnaryExpr(c, m, scope);4817 const operand = try parseCUnaryExpr(c, m, scope);
4844 return Node.deref.create(c.arena, operand);4818 return Tag.deref.create(c.arena, operand);
4845 },4819 },
4846 .Ampersand => {4820 .Ampersand => {
4847 const operand = try parseCUnaryExpr(c, m, scope);4821 const operand = try parseCUnaryExpr(c, m, scope);
4848 return Node.address_of.create(c.arena, operand);4822 return Tag.address_of.create(c.arena, operand);
4849 },4823 },
4850 .Keyword_sizeof => {4824 .Keyword_sizeof => {
4851 const operand = if (m.peek().? == .LParen) blk: {4825 const operand = if (m.peek().? == .LParen) blk: {
...@@ -4860,7 +4834,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4860,7 +4834,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4860 break :blk inner;4834 break :blk inner;
4861 } else try parseCUnaryExpr(c, m, scope);4835 } else try parseCUnaryExpr(c, m, scope);
48624836
4863 return Node.std_meta_sizeof.create(c.arena, operand);4837 return Tag.std_meta_sizeof.create(c.arena, operand);
4864 },4838 },
4865 .Keyword_alignof => {4839 .Keyword_alignof => {
4866 // TODO this won't work if using <stdalign.h>'s4840 // TODO this won't work if using <stdalign.h>'s
...@@ -4877,7 +4851,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4877,7 +4851,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4877 return error.ParseError;4851 return error.ParseError;
4878 }4852 }
48794853
4880 return Node.alignof.create(c.arena, operand);4854 return Tag.alignof.create(c.arena, operand);
4881 },4855 },
4882 .PlusPlus, .MinusMinus => {4856 .PlusPlus, .MinusMinus => {
4883 try m.fail(c, "TODO unary inc/dec expr", .{});4857 try m.fail(c, "TODO unary inc/dec expr", .{});
...@@ -4902,7 +4876,7 @@ fn getContainer(c: *Context, node: Node) ?Node {...@@ -4902,7 +4876,7 @@ fn getContainer(c: *Context, node: Node) ?Node {
4902 .negate,4876 .negate,
4903 .negate_wrap,4877 .negate_wrap,
4904 .array_type,4878 .array_type,
4905 .c_pointer, 4879 .c_pointer,
4906 .single_pointer,4880 .single_pointer,
4907 => return node,4881 => return node,
49084882
...@@ -4910,7 +4884,7 @@ fn getContainer(c: *Context, node: Node) ?Node {...@@ -4910,7 +4884,7 @@ fn getContainer(c: *Context, node: Node) ?Node {
4910 const ident = node.castTag(.identifier).?;4884 const ident = node.castTag(.identifier).?;
4911 if (c.global_scope.sym_table.get(ident.data)) |value| {4885 if (c.global_scope.sym_table.get(ident.data)) |value| {
4912 if (value.castTag(.var_decl)) |var_decl|4886 if (value.castTag(.var_decl)) |var_decl|
4913 return getContainer(c, var_decl.data.init);4887 return getContainer(c, var_decl.data.init.?);
4914 if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |var_decl|4888 if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |var_decl|
4915 return getContainer(c, var_decl.data.init);4889 return getContainer(c, var_decl.data.init);
4916 }4890 }
...@@ -4923,8 +4897,8 @@ fn getContainer(c: *Context, node: Node) ?Node {...@@ -4923,8 +4897,8 @@ fn getContainer(c: *Context, node: Node) ?Node {
4923 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {4897 if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| {
4924 for (container.data.fields) |field| {4898 for (container.data.fields) |field| {
4925 const ident = infix.data.rhs.castTag(.identifier).?;4899 const ident = infix.data.rhs.castTag(.identifier).?;
4926 if (mem.eql(u8, field.data.name, field.data)) {4900 if (mem.eql(u8, field.name, ident.data)) {
4927 return getContainer(c, field.type_expr.?);4901 return getContainer(c, field.type);
4928 }4902 }
4929 }4903 }
4930 }4904 }
...@@ -4960,9 +4934,9 @@ fn getContainerTypeOf(c: *Context, ref: Node) ?Node {...@@ -4960,9 +4934,9 @@ fn getContainerTypeOf(c: *Context, ref: Node) ?Node {
4960}4934}
49614935
4962fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {4936fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func {
4963 const init = if (value.castTag(.var_decl)) |v|4937 const init = if (ref.castTag(.var_decl)) |v|
4964 v.data.init4938 v.data.init orelse return null
4965 else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v|4939 else if (ref.castTag(.var_simple) orelse ref.castTag(.pub_var_simple)) |v|
4966 v.data.init4940 v.data.init
4967 else4941 else
4968 return null;4942 return null;
src/translate_c/ast.zig+61-47
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const Type = @import("../type.zig").Type;2const Type = @import("../type.zig").Type;
3const Allocator = std.mem.Allocator;
34
4pub const Node = extern union {5pub const Node = extern union {
5 /// If the tag value is less than Tag.no_payload_count, then no pointer6 /// If the tag value is less than Tag.no_payload_count, then no pointer
...@@ -20,6 +21,8 @@ pub const Node = extern union {...@@ -20,6 +21,8 @@ pub const Node = extern union {
20 one_literal,21 one_literal,
21 void_type,22 void_type,
22 noreturn_type,23 noreturn_type,
24 @"anytype",
25 @"continue",
23 /// pub usingnamespace @import("std").c.builtins;26 /// pub usingnamespace @import("std").c.builtins;
24 usingnamespace_builtins,27 usingnamespace_builtins,
25 // After this, the tag requires a payload.28 // After this, the tag requires a payload.
...@@ -40,7 +43,6 @@ pub const Node = extern union {...@@ -40,7 +43,6 @@ pub const Node = extern union {
40 switch_else,43 switch_else,
41 /// lhs => rhs,44 /// lhs => rhs,
42 switch_prong,45 switch_prong,
43 @"continue",
44 @"break",46 @"break",
45 break_val,47 break_val,
46 @"return",48 @"return",
...@@ -60,7 +62,6 @@ pub const Node = extern union {...@@ -60,7 +62,6 @@ pub const Node = extern union {
60 container_init,62 container_init,
61 std_meta_cast,63 std_meta_cast,
62 discard,64 discard,
63 block,
6465
65 // a + b66 // a + b
66 add,67 add,
...@@ -111,8 +112,11 @@ pub const Node = extern union {...@@ -111,8 +112,11 @@ pub const Node = extern union {
111 equal,112 equal,
112 not_equal,113 not_equal,
113 bit_and,114 bit_and,
115 bit_and_assign,
114 bit_or,116 bit_or,
117 bit_or_assign,
115 bit_xor,118 bit_xor,
119 bit_xor_assign,
116 array_cat,120 array_cat,
117 ellipsis3,121 ellipsis3,
118 assign,122 assign,
...@@ -126,7 +130,7 @@ pub const Node = extern union {...@@ -126,7 +130,7 @@ pub const Node = extern union {
126 rem,130 rem,
127 /// @divTrunc(lhs, rhs)131 /// @divTrunc(lhs, rhs)
128 div_trunc,132 div_trunc,
129 /// @boolToInt(lhs, rhs)133 /// @boolToInt(operand)
130 bool_to_int,134 bool_to_int,
131 /// @as(lhs, rhs)135 /// @as(lhs, rhs)
132 as,136 as,
...@@ -150,24 +154,26 @@ pub const Node = extern union {...@@ -150,24 +154,26 @@ pub const Node = extern union {
150 ptr_to_int,154 ptr_to_int,
151 /// @alignCast(lhs, rhs)155 /// @alignCast(lhs, rhs)
152 align_cast,156 align_cast,
157 /// @ptrCast(lhs, rhs)
158 ptr_cast,
153159
154 negate,160 negate,
155 negate_wrap,161 negate_wrap,
156 bit_not,162 bit_not,
157 not,163 not,
158 address_of,164 address_of,
159 /// operand.?.*165 /// .?
160 unwrap_deref,166 unwrap,
161 /// .*167 /// .*
162 deref,168 deref,
163169
164 block,170 block,
165 /// { operand }171 /// { operand }
166 block_single,172 block_single,
167 @"break",
168173
169 sizeof,174 sizeof,
170 alignof,175 alignof,
176 typeof,
171 type,177 type,
172178
173 optional_type,179 optional_type,
...@@ -185,6 +191,8 @@ pub const Node = extern union {...@@ -185,6 +191,8 @@ pub const Node = extern union {
185 fail_decl,191 fail_decl,
186 // var actual = mangled;192 // var actual = mangled;
187 arg_redecl,193 arg_redecl,
194 /// pub const alias = actual;
195 alias,
188 /// const name = init;196 /// const name = init;
189 typedef,197 typedef,
190 var_simple,198 var_simple,
...@@ -204,18 +212,17 @@ pub const Node = extern union {...@@ -204,18 +212,17 @@ pub const Node = extern union {
204212
205 /// _ = operand;213 /// _ = operand;
206 ignore,214 ignore,
207 @"anytype",
208215
209 pub const last_no_payload_tag = Tag.usingnamespace_builtins;216 pub const last_no_payload_tag = Tag.usingnamespace_builtins;
210 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;217 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
211218
212 pub fn Type(tag: Tag) ?type {219 pub fn Type(comptime t: Tag) type {
213 return switch (tag) {220 return switch (t) {
214 .null_literal,221 .null_literal,
215 .undefined_literal,222 .undefined_literal,
216 .opaque_literal,223 .opaque_literal,
217 .true_literal,224 .true_literal,
218 .false_litral,225 .false_literal,
219 .empty_block,226 .empty_block,
220 .usingnamespace_builtins,227 .usingnamespace_builtins,
221 .return_void,228 .return_void,
...@@ -224,6 +231,7 @@ pub const Node = extern union {...@@ -224,6 +231,7 @@ pub const Node = extern union {
224 .void_type,231 .void_type,
225 .noreturn_type,232 .noreturn_type,
226 .@"anytype",233 .@"anytype",
234 .@"continue",
227 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),235 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
228236
229 .std_mem_zeroes,237 .std_mem_zeroes,
...@@ -236,7 +244,7 @@ pub const Node = extern union {...@@ -236,7 +244,7 @@ pub const Node = extern union {
236 .not,244 .not,
237 .optional_type,245 .optional_type,
238 .address_of,246 .address_of,
239 .unwrap_deref,247 .unwrap,
240 .deref,248 .deref,
241 .ptr_to_int,249 .ptr_to_int,
242 .enum_to_int,250 .enum_to_int,
...@@ -246,6 +254,11 @@ pub const Node = extern union {...@@ -246,6 +254,11 @@ pub const Node = extern union {
246 .switch_else,254 .switch_else,
247 .ignore,255 .ignore,
248 .block_single,256 .block_single,
257 .std_meta_sizeof,
258 .bool_to_int,
259 .sizeof,
260 .alignof,
261 .typeof,
249 => Payload.UnOp,262 => Payload.UnOp,
250263
251 .add,264 .add,
...@@ -294,12 +307,14 @@ pub const Node = extern union {...@@ -294,12 +307,14 @@ pub const Node = extern union {
294 .equal,307 .equal,
295 .not_equal,308 .not_equal,
296 .bit_and,309 .bit_and,
310 .bit_and_assign,
297 .bit_or,311 .bit_or,
312 .bit_or_assign,
298 .bit_xor,313 .bit_xor,
314 .bit_xor_assign,
299 .div_trunc,315 .div_trunc,
300 .rem,316 .rem,
301 .int_cast,317 .int_cast,
302 .bool_to_int,
303 .as,318 .as,
304 .truncate,319 .truncate,
305 .bit_cast,320 .bit_cast,
...@@ -316,6 +331,7 @@ pub const Node = extern union {...@@ -316,6 +331,7 @@ pub const Node = extern union {
316 .align_cast,331 .align_cast,
317 .array_access,332 .array_access,
318 .std_mem_zeroinit,333 .std_mem_zeroinit,
334 .ptr_cast,
319 => Payload.BinOp,335 => Payload.BinOp,
320336
321 .number_literal,337 .number_literal,
...@@ -324,8 +340,6 @@ pub const Node = extern union {...@@ -324,8 +340,6 @@ pub const Node = extern union {
324 .identifier,340 .identifier,
325 .warning,341 .warning,
326 .failed_decl,342 .failed_decl,
327 .sizeof,
328 .alignof,
329 .type,343 .type,
330 .fail_decl,344 .fail_decl,
331 => Payload.Value,345 => Payload.Value,
...@@ -345,7 +359,7 @@ pub const Node = extern union {...@@ -345,7 +359,7 @@ pub const Node = extern union {
345 .block => Payload.Block,359 .block => Payload.Block,
346 .c_pointer, .single_pointer => Payload.Pointer,360 .c_pointer, .single_pointer => Payload.Pointer,
347 .array_type => Payload.Array,361 .array_type => Payload.Array,
348 .arg_redecl => Payload.ArgRedecl,362 .arg_redecl, .alias => Payload.ArgRedecl,
349 .log2_int_type => Payload.Log2IntType,363 .log2_int_type => Payload.Log2IntType,
350 .typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,364 .typedef, .pub_typedef, .var_simple, .pub_var_simple => Payload.SimpleVarDecl,
351 .enum_redecl => Payload.EnumRedecl,365 .enum_redecl => Payload.EnumRedecl,
...@@ -375,7 +389,7 @@ pub const Node = extern union {...@@ -375,7 +389,7 @@ pub const Node = extern union {
375389
376 pub fn tag(self: Node) Tag {390 pub fn tag(self: Node) Tag {
377 if (self.tag_if_small_enough < Tag.no_payload_count) {391 if (self.tag_if_small_enough < Tag.no_payload_count) {
378 return @intToEnum(Tag, @intCast(@TagType(Tag), self.tag_if_small_enough));392 return @intToEnum(Tag, @intCast(std.meta.Tag(Tag), self.tag_if_small_enough));
379 } else {393 } else {
380 return self.ptr_otherwise.tag;394 return self.ptr_otherwise.tag;
381 }395 }
...@@ -392,16 +406,16 @@ pub const Node = extern union {...@@ -392,16 +406,16 @@ pub const Node = extern union {
392 }406 }
393407
394 pub fn initPayload(payload: *Payload) Node {408 pub fn initPayload(payload: *Payload) Node {
395 assert(@enumToInt(payload.tag) >= Tag.no_payload_count);409 std.debug.assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
396 return .{ .ptr_otherwise = payload };410 return .{ .ptr_otherwise = payload };
397 }411 }
398};412};
399413
400pub const Payload = struct {414pub const Payload = struct {
401 tag: Tag,415 tag: Node.Tag,
402416
403 pub const Infix = struct {417 pub const Infix = struct {
404 base: Node,418 base: Payload,
405 data: struct {419 data: struct {
406 lhs: Node,420 lhs: Node,
407 rhs: Node,421 rhs: Node,
...@@ -409,17 +423,17 @@ pub const Payload = struct {...@@ -409,17 +423,17 @@ pub const Payload = struct {
409 };423 };
410424
411 pub const Value = struct {425 pub const Value = struct {
412 base: Node,426 base: Payload,
413 data: []const u8,427 data: []const u8,
414 };428 };
415429
416 pub const UnOp = struct {430 pub const UnOp = struct {
417 base: Node,431 base: Payload,
418 data: Node,432 data: Node,
419 };433 };
420434
421 pub const BinOp = struct {435 pub const BinOp = struct {
422 base: Node,436 base: Payload,
423 data: struct {437 data: struct {
424 lhs: Node,438 lhs: Node,
425 rhs: Node,439 rhs: Node,
...@@ -427,7 +441,7 @@ pub const Payload = struct {...@@ -427,7 +441,7 @@ pub const Payload = struct {
427 };441 };
428442
429 pub const If = struct {443 pub const If = struct {
430 base: Node = .{ .tag = .@"if" },444 base: Payload,
431 data: struct {445 data: struct {
432 cond: Node,446 cond: Node,
433 then: Node,447 then: Node,
...@@ -436,7 +450,7 @@ pub const Payload = struct {...@@ -436,7 +450,7 @@ pub const Payload = struct {
436 };450 };
437451
438 pub const While = struct {452 pub const While = struct {
439 base: Node = .{ .tag = .@"while" },453 base: Payload,
440 data: struct {454 data: struct {
441 cond: Node,455 cond: Node,
442 body: Node,456 body: Node,
...@@ -445,7 +459,7 @@ pub const Payload = struct {...@@ -445,7 +459,7 @@ pub const Payload = struct {
445 };459 };
446460
447 pub const Switch = struct {461 pub const Switch = struct {
448 base: Node = .{ .tag = .@"switch" },462 base: Payload,
449 data: struct {463 data: struct {
450 cond: Node,464 cond: Node,
451 cases: []Node,465 cases: []Node,
...@@ -453,12 +467,12 @@ pub const Payload = struct {...@@ -453,12 +467,12 @@ pub const Payload = struct {
453 };467 };
454468
455 pub const Break = struct {469 pub const Break = struct {
456 base: Node = .{ .tag = .@"break" },470 base: Payload,
457 data: ?[]const u8,471 data: ?[]const u8,
458 };472 };
459473
460 pub const BreakVal = struct {474 pub const BreakVal = struct {
461 base: Node = .{ .tag = .break_val },475 base: Payload,
462 data: struct {476 data: struct {
463 label: ?[]const u8,477 label: ?[]const u8,
464 val: Node,478 val: Node,
...@@ -466,7 +480,7 @@ pub const Payload = struct {...@@ -466,7 +480,7 @@ pub const Payload = struct {
466 };480 };
467481
468 pub const Call = struct {482 pub const Call = struct {
469 base: Node = .{.call},483 base: Payload,
470 data: struct {484 data: struct {
471 lhs: Node,485 lhs: Node,
472 args: []Node,486 args: []Node,
...@@ -474,7 +488,7 @@ pub const Payload = struct {...@@ -474,7 +488,7 @@ pub const Payload = struct {
474 };488 };
475489
476 pub const VarDecl = struct {490 pub const VarDecl = struct {
477 base: Node = .{ .tag = .var_decl },491 base: Payload,
478 data: struct {492 data: struct {
479 is_pub: bool,493 is_pub: bool,
480 is_const: bool,494 is_const: bool,
...@@ -489,13 +503,13 @@ pub const Payload = struct {...@@ -489,13 +503,13 @@ pub const Payload = struct {
489 };503 };
490504
491 pub const Func = struct {505 pub const Func = struct {
492 base: Node = .{.func},506 base: Payload,
493 data: struct {507 data: struct {
494 is_pub: bool,508 is_pub: bool,
495 is_extern: bool,509 is_extern: bool,
496 is_export: bool,510 is_export: bool,
497 is_var_args: bool,511 is_var_args: bool,
498 name: []const u8,512 name: ?[]const u8,
499 linksection_string: ?[]const u8,513 linksection_string: ?[]const u8,
500 explicit_callconv: ?std.builtin.CallingConvention,514 explicit_callconv: ?std.builtin.CallingConvention,
501 params: []Param,515 params: []Param,
...@@ -512,7 +526,7 @@ pub const Payload = struct {...@@ -512,7 +526,7 @@ pub const Payload = struct {
512 };526 };
513527
514 pub const Enum = struct {528 pub const Enum = struct {
515 base: Node = .{ .tag = .@"enum" },529 base: Payload,
516 data: []Field,530 data: []Field,
517531
518 pub const Field = struct {532 pub const Field = struct {
...@@ -522,9 +536,9 @@ pub const Payload = struct {...@@ -522,9 +536,9 @@ pub const Payload = struct {
522 };536 };
523537
524 pub const Record = struct {538 pub const Record = struct {
525 base: Node,539 base: Payload,
526 data: struct {540 data: struct {
527 @"packed": bool,541 is_packed: bool,
528 fields: []Field,542 fields: []Field,
529 },543 },
530544
...@@ -536,12 +550,12 @@ pub const Payload = struct {...@@ -536,12 +550,12 @@ pub const Payload = struct {
536 };550 };
537551
538 pub const ArrayInit = struct {552 pub const ArrayInit = struct {
539 base: Node = .{ .tag = .array_init },553 base: Payload,
540 data: []Node,554 data: []Node,
541 };555 };
542556
543 pub const ContainerInit = struct {557 pub const ContainerInit = struct {
544 base: Node = .{ .tag = .container_init },558 base: Payload,
545 data: []Initializer,559 data: []Initializer,
546560
547 pub const Initializer = struct {561 pub const Initializer = struct {
...@@ -551,7 +565,7 @@ pub const Payload = struct {...@@ -551,7 +565,7 @@ pub const Payload = struct {
551 };565 };
552566
553 pub const Block = struct {567 pub const Block = struct {
554 base: Node,568 base: Payload,
555 data: struct {569 data: struct {
556 label: ?[]const u8,570 label: ?[]const u8,
557 stmts: []Node571 stmts: []Node
...@@ -559,15 +573,15 @@ pub const Payload = struct {...@@ -559,15 +573,15 @@ pub const Payload = struct {
559 };573 };
560574
561 pub const Array = struct {575 pub const Array = struct {
562 base: Node,576 base: Payload,
563 data: struct {577 data: struct {
564 elem_type: Node,578 elem_type: Node,
565 len: Node,579 len: usize,
566 },580 },
567 };581 };
568582
569 pub const Pointer = struct {583 pub const Pointer = struct {
570 base: Node,584 base: Payload,
571 data: struct {585 data: struct {
572 elem_type: Node,586 elem_type: Node,
573 is_const: bool,587 is_const: bool,
...@@ -576,7 +590,7 @@ pub const Payload = struct {...@@ -576,7 +590,7 @@ pub const Payload = struct {
576 };590 };
577591
578 pub const ArgRedecl = struct {592 pub const ArgRedecl = struct {
579 base: Node,593 base: Payload,
580 data: struct {594 data: struct {
581 actual: []const u8,595 actual: []const u8,
582 mangled: []const u8,596 mangled: []const u8,
...@@ -584,12 +598,12 @@ pub const Payload = struct {...@@ -584,12 +598,12 @@ pub const Payload = struct {
584 };598 };
585599
586 pub const Log2IntType = struct {600 pub const Log2IntType = struct {
587 base: Node,601 base: Payload,
588 data: std.math.Log2Int(u64),602 data: std.math.Log2Int(u64),
589 };603 };
590604
591 pub const SimpleVarDecl = struct {605 pub const SimpleVarDecl = struct {
592 base: Node,606 base: Payload,
593 data: struct {607 data: struct {
594 name: []const u8,608 name: []const u8,
595 init: Node,609 init: Node,
...@@ -597,7 +611,7 @@ pub const Payload = struct {...@@ -597,7 +611,7 @@ pub const Payload = struct {
597 };611 };
598612
599 pub const EnumRedecl = struct {613 pub const EnumRedecl = struct {
600 base: Node,614 base: Payload,
601 data: struct {615 data: struct {
602 enum_val_name: []const u8,616 enum_val_name: []const u8,
603 field_name: []const u8,617 field_name: []const u8,
...@@ -606,7 +620,7 @@ pub const Payload = struct {...@@ -606,7 +620,7 @@ pub const Payload = struct {
606 };620 };
607621
608 pub const ArrayFiller = struct {622 pub const ArrayFiller = struct {
609 base: Node,623 base: Payload,
610 data: struct {624 data: struct {
611 type: Node,625 type: Node,
612 filler: Node,626 filler: Node,
...@@ -615,7 +629,7 @@ pub const Payload = struct {...@@ -615,7 +629,7 @@ pub const Payload = struct {
615 };629 };
616630
617 pub const PubInlineFn = struct {631 pub const PubInlineFn = struct {
618 base: Node,632 base: Payload,
619 data: struct {633 data: struct {
620 name: []const u8,634 name: []const u8,
621 params: []Param,635 params: []Param,
...@@ -626,6 +640,6 @@ pub const Payload = struct {...@@ -626,6 +640,6 @@ pub const Payload = struct {
626};640};
627641
628/// Converts the nodes into a Zig ast.642/// Converts the nodes into a Zig ast.
629pub fn render(allocator: *Allocator, nodes: []const Node) !*ast.Tree {643pub fn render(allocator: *Allocator, nodes: []const Node) !std.zig.ast.Tree {
630 @panic("TODO");644 @panic("TODO");
631}645}
src/type.zig+4
...@@ -1682,6 +1682,8 @@ pub const Type = extern union {...@@ -1682,6 +1682,8 @@ pub const Type = extern union {
1682 .i32 => unreachable,1682 .i32 => unreachable,
1683 .u64 => unreachable,1683 .u64 => unreachable,
1684 .i64 => unreachable,1684 .i64 => unreachable,
1685 .u128 => unreachable,
1686 .i128 => unreachable,
1685 .usize => unreachable,1687 .usize => unreachable,
1686 .isize => unreachable,1688 .isize => unreachable,
1687 .c_short => unreachable,1689 .c_short => unreachable,
...@@ -2197,6 +2199,8 @@ pub const Type = extern union {...@@ -2197,6 +2199,8 @@ pub const Type = extern union {
2197 .i32 => .{ .signedness = .signed, .bits = 32 },2199 .i32 => .{ .signedness = .signed, .bits = 32 },
2198 .u64 => .{ .signedness = .unsigned, .bits = 64 },2200 .u64 => .{ .signedness = .unsigned, .bits = 64 },
2199 .i64 => .{ .signedness = .signed, .bits = 64 },2201 .i64 => .{ .signedness = .signed, .bits = 64 },
2202 .u128 => .{ .signedness = .unsigned, .bits = 128 },
2203 .i128 => .{ .signedness = .signed, .bits = 128 },
2200 .usize => .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },2204 .usize => .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
2201 .isize => .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },2205 .isize => .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
2202 .c_short => .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },2206 .c_short => .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },