| ... | ... | @@ -10,12 +10,13 @@ const mem = std.mem; |
| 10 | 10 | const math = std.math; |
| 11 | 11 | const ast = @import("translate_c/ast.zig"); |
| 12 | 12 | const Node = ast.Node; |
| 13 | const Tag = Node.Tag; |
| 13 | 14 | |
| 14 | 15 | const CallingConvention = std.builtin.CallingConvention; |
| 15 | 16 | |
| 16 | 17 | pub const ClangErrMsg = clang.Stage2ErrorMsg; |
| 17 | 18 | |
| 18 | | pub const Error = error{OutOfMemory}; |
| 19 | pub const Error = std.mem.Allocator.Error; |
| 19 | 20 | const TypeError = Error || error{UnsupportedType}; |
| 20 | 21 | const TransError = TypeError || error{UnsupportedTranslation}; |
| 21 | 22 | |
| ... | ... | @@ -30,11 +31,11 @@ const Scope = struct { |
| 30 | 31 | parent: ?*Scope, |
| 31 | 32 | |
| 32 | 33 | const Id = enum { |
| 33 | | Switch, |
| 34 | | Block, |
| 35 | | Root, |
| 36 | | Condition, |
| 37 | | Loop, |
| 34 | @"switch", |
| 35 | block, |
| 36 | root, |
| 37 | condition, |
| 38 | loop, |
| 38 | 39 | }; |
| 39 | 40 | |
| 40 | 41 | /// Represents an in-progress Node.Switch. This struct is stack-allocated. |
| ... | ... | @@ -44,7 +45,6 @@ const Scope = struct { |
| 44 | 45 | base: Scope, |
| 45 | 46 | pending_block: Block, |
| 46 | 47 | cases: std.ArrayList(Node), |
| 47 | | case_index: usize, |
| 48 | 48 | switch_label: ?[]const u8, |
| 49 | 49 | default_label: ?[]const u8, |
| 50 | 50 | }; |
| ... | ... | @@ -84,7 +84,7 @@ const Scope = struct { |
| 84 | 84 | fn init(c: *Context, parent: *Scope, labeled: bool) !Block { |
| 85 | 85 | var blk = Block{ |
| 86 | 86 | .base = .{ |
| 87 | | .id = .Block, |
| 87 | .id = .block, |
| 88 | 88 | .parent = parent, |
| 89 | 89 | }, |
| 90 | 90 | .statements = std.ArrayList(Node).init(c.gpa), |
| ... | ... | @@ -105,12 +105,12 @@ const Scope = struct { |
| 105 | 105 | fn complete(self: *Block, c: *Context) !Node { |
| 106 | 106 | // We reserve 1 extra statement if the parent is a Loop. This is in case of |
| 107 | 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); |
| 109 | | const stmts = try c.arena.alloc(Node, alloc_len); |
| 108 | const alloc_len = self.statements.items.len + @boolToInt(self.base.parent.?.id == .loop); |
| 109 | var stmts = try c.arena.alloc(Node, alloc_len); |
| 110 | 110 | stmts.len -= 1; |
| 111 | 111 | mem.copy(Node, stmts, self.statements.items); |
| 112 | | return Node.block.create(c.arena, .{ |
| 113 | | .lable = self.label, |
| 112 | return Tag.block.create(c.arena, .{ |
| 113 | .label = self.label, |
| 114 | 114 | .stmts = stmts, |
| 115 | 115 | }); |
| 116 | 116 | } |
| ... | ... | @@ -161,7 +161,7 @@ const Scope = struct { |
| 161 | 161 | fn init(c: *Context) Root { |
| 162 | 162 | return .{ |
| 163 | 163 | .base = .{ |
| 164 | | .id = .Root, |
| 164 | .id = .root, |
| 165 | 165 | .parent = null, |
| 166 | 166 | }, |
| 167 | 167 | .sym_table = SymbolTable.init(c.gpa), |
| ... | ... | @@ -195,9 +195,9 @@ const Scope = struct { |
| 195 | 195 | var scope = inner; |
| 196 | 196 | while (true) { |
| 197 | 197 | switch (scope.id) { |
| 198 | | .Root => unreachable, |
| 199 | | .Block => return @fieldParentPtr(Block, "base", scope), |
| 200 | | .Condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c), |
| 198 | .root => unreachable, |
| 199 | .block => return @fieldParentPtr(Block, "base", scope), |
| 200 | .condition => return @fieldParentPtr(Condition, "base", scope).getBlockScope(c), |
| 201 | 201 | else => scope = scope.parent.?, |
| 202 | 202 | } |
| 203 | 203 | } |
| ... | ... | @@ -207,8 +207,8 @@ const Scope = struct { |
| 207 | 207 | var scope = inner; |
| 208 | 208 | while (true) { |
| 209 | 209 | switch (scope.id) { |
| 210 | | .Root => unreachable, |
| 211 | | .Block => { |
| 210 | .root => unreachable, |
| 211 | .block => { |
| 212 | 212 | const block = @fieldParentPtr(Block, "base", scope); |
| 213 | 213 | if (block.return_type) |qt| return qt; |
| 214 | 214 | scope = scope.parent.?; |
| ... | ... | @@ -220,17 +220,17 @@ const Scope = struct { |
| 220 | 220 | |
| 221 | 221 | fn getAlias(scope: *Scope, name: []const u8) []const u8 { |
| 222 | 222 | return switch (scope.id) { |
| 223 | | .Root => return name, |
| 224 | | .Block => @fieldParentPtr(Block, "base", scope).getAlias(name), |
| 225 | | .Switch, .Loop, .Condition => scope.parent.?.getAlias(name), |
| 223 | .root => return name, |
| 224 | .block => @fieldParentPtr(Block, "base", scope).getAlias(name), |
| 225 | .@"switch", .loop, .condition => scope.parent.?.getAlias(name), |
| 226 | 226 | }; |
| 227 | 227 | } |
| 228 | 228 | |
| 229 | 229 | fn contains(scope: *Scope, name: []const u8) bool { |
| 230 | 230 | return switch (scope.id) { |
| 231 | | .Root => @fieldParentPtr(Root, "base", scope).contains(name), |
| 232 | | .Block => @fieldParentPtr(Block, "base", scope).contains(name), |
| 233 | | .Switch, .Loop, .Condition => scope.parent.?.contains(name), |
| 231 | .root => @fieldParentPtr(Root, "base", scope).contains(name), |
| 232 | .block => @fieldParentPtr(Block, "base", scope).contains(name), |
| 233 | .@"switch", .loop, .condition => scope.parent.?.contains(name), |
| 234 | 234 | }; |
| 235 | 235 | } |
| 236 | 236 | |
| ... | ... | @@ -238,9 +238,9 @@ const Scope = struct { |
| 238 | 238 | var scope = inner; |
| 239 | 239 | while (true) { |
| 240 | 240 | switch (scope.id) { |
| 241 | | .Root => unreachable, |
| 242 | | .Switch => return scope, |
| 243 | | .Loop => return scope, |
| 241 | .root => unreachable, |
| 242 | .@"switch" => return scope, |
| 243 | .loop => return scope, |
| 244 | 244 | else => scope = scope.parent.?, |
| 245 | 245 | } |
| 246 | 246 | } |
| ... | ... | @@ -250,24 +250,24 @@ const Scope = struct { |
| 250 | 250 | var scope = inner; |
| 251 | 251 | while (true) { |
| 252 | 252 | switch (scope.id) { |
| 253 | | .Root => unreachable, |
| 254 | | .Switch => return @fieldParentPtr(Switch, "base", scope), |
| 253 | .root => unreachable, |
| 254 | .@"switch" => return @fieldParentPtr(Switch, "base", scope), |
| 255 | 255 | else => scope = scope.parent.?, |
| 256 | 256 | } |
| 257 | 257 | } |
| 258 | 258 | } |
| 259 | 259 | |
| 260 | 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 | 262 | var scope = inner; |
| 263 | 263 | while (true) { |
| 264 | 264 | switch (scope.id) { |
| 265 | | .Root => { |
| 266 | | const root = @fieldParentPtr(Root, "base", scope).contains(name); |
| 265 | .root => { |
| 266 | const root = @fieldParentPtr(Root, "base", scope); |
| 267 | 267 | return root.nodes.append(node); |
| 268 | 268 | }, |
| 269 | | .Block => { |
| 270 | | const block = @fieldParentPtr(Block, "base", scope).contains(name); |
| 269 | .block => { |
| 270 | const block = @fieldParentPtr(Block, "base", scope); |
| 271 | 271 | return block.statements.append(node); |
| 272 | 272 | }, |
| 273 | 273 | else => scope = scope.parent.?, |
| ... | ... | @@ -321,7 +321,7 @@ pub fn translate( |
| 321 | 321 | args_end: [*]?[*]const u8, |
| 322 | 322 | errors: *[]ClangErrMsg, |
| 323 | 323 | resources_path: [*:0]const u8, |
| 324 | | ) !ast.Tree { |
| 324 | ) !std.zig.ast.Tree { |
| 325 | 325 | const ast_unit = clang.LoadFromCommandLine( |
| 326 | 326 | args_begin, |
| 327 | 327 | args_end, |
| ... | ... | @@ -339,14 +339,6 @@ pub fn translate( |
| 339 | 339 | var arena = std.heap.ArenaAllocator.init(gpa); |
| 340 | 340 | errdefer arena.deinit(); |
| 341 | 341 | |
| 342 | | if (true) { |
| 343 | | var x = false; |
| 344 | | if (x) { |
| 345 | | return error.OutOfMemory; |
| 346 | | } |
| 347 | | @panic("TODO update translate-c"); |
| 348 | | } |
| 349 | | |
| 350 | 342 | var context = Context{ |
| 351 | 343 | .gpa = gpa, |
| 352 | 344 | .arena = &arena.allocator, |
| ... | ... | @@ -361,15 +353,15 @@ pub fn translate( |
| 361 | 353 | context.alias_list.deinit(); |
| 362 | 354 | context.global_names.deinit(gpa); |
| 363 | 355 | context.opaque_demotes.deinit(gpa); |
| 364 | | context.global_scope.deini(); |
| 356 | context.global_scope.deinit(); |
| 365 | 357 | } |
| 366 | 358 | |
| 367 | | try context.global_scope.nodes.append(try Node.usingnamespace_builtins.init()); |
| 359 | try context.global_scope.nodes.append(Tag.usingnamespace_builtins.init()); |
| 368 | 360 | |
| 369 | 361 | try prepopulateGlobalNameTable(ast_unit, &context); |
| 370 | 362 | |
| 371 | 363 | if (!ast_unit.visitLocalTopLevelDecls(&context, declVisitorC)) { |
| 372 | | return context.err; |
| 364 | return error.OutOfMemory; |
| 373 | 365 | } |
| 374 | 366 | |
| 375 | 367 | try transPreprocessorEntities(&context, ast_unit); |
| ... | ... | @@ -377,16 +369,17 @@ pub fn translate( |
| 377 | 369 | try addMacros(&context); |
| 378 | 370 | for (context.alias_list.items) |alias| { |
| 379 | 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 | } |
| 383 | 376 | |
| 384 | | return ast.render(context.global_scope.nodes.items); |
| 377 | return ast.render(gpa, context.global_scope.nodes.items); |
| 385 | 378 | } |
| 386 | 379 | |
| 387 | 380 | fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { |
| 388 | 381 | if (!ast_unit.visitLocalTopLevelDecls(c, declVisitorNamesOnlyC)) { |
| 389 | | return c.err; |
| 382 | return error.OutOfMemory; |
| 390 | 383 | } |
| 391 | 384 | |
| 392 | 385 | // TODO if we see #undef, delete it from the table |
| ... | ... | @@ -409,19 +402,13 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { |
| 409 | 402 | |
| 410 | 403 | fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool { |
| 411 | 404 | const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context)); |
| 412 | | declVisitorNamesOnly(c, decl) catch |err| { |
| 413 | | c.err = err; |
| 414 | | return false; |
| 415 | | }; |
| 405 | declVisitorNamesOnly(c, decl) catch return false; |
| 416 | 406 | return true; |
| 417 | 407 | } |
| 418 | 408 | |
| 419 | 409 | fn declVisitorC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool { |
| 420 | 410 | const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context)); |
| 421 | | declVisitor(c, decl) catch |err| { |
| 422 | | c.err = err; |
| 423 | | return false; |
| 424 | | }; |
| 411 | declVisitor(c, decl) catch return false; |
| 425 | 412 | return true; |
| 426 | 413 | } |
| 427 | 414 | |
| ... | ... | @@ -454,7 +441,7 @@ fn declVisitor(c: *Context, decl: *const clang.Decl) Error!void { |
| 454 | 441 | }, |
| 455 | 442 | else => { |
| 456 | 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 | 500 | decl_ctx.has_body = false; |
| 514 | 501 | decl_ctx.storage_class = .Extern; |
| 515 | 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 | 505 | break :blk transFnProto(c, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) { |
| 519 | 506 | error.UnsupportedType => { |
| ... | ... | @@ -535,7 +522,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 535 | 522 | }; |
| 536 | 523 | |
| 537 | 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 | } |
| 540 | 527 | |
| 541 | 528 | // actual function definition with body |
| ... | ... | @@ -547,10 +534,8 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 547 | 534 | var scope = &block_scope.base; |
| 548 | 535 | |
| 549 | 536 | var param_id: c_uint = 0; |
| 550 | | for (proto_node.params()) |*param, i| { |
| 551 | | const param_name = if (param.name_token) |name_tok| |
| 552 | | tokenSlice(c, name_tok) |
| 553 | | else |
| 537 | for (proto_node.data.params) |*param, i| { |
| 538 | const param_name = param.name orelse |
| 554 | 539 | return failDecl(c, fn_decl_loc, fn_name, "function {s} parameter has no name", .{fn_name}); |
| 555 | 540 | |
| 556 | 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 | 550 | const arg_name = try block_scope.makeMangledName(c, bare_arg_name); |
| 566 | 551 | param.name = arg_name; |
| 567 | 552 | |
| 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 | 554 | try block_scope.statements.append(redecl_node); |
| 570 | 555 | } |
| 571 | 556 | |
| ... | ... | @@ -607,12 +592,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const clang.FunctionDecl) Error!void { |
| 607 | 592 | error.UnsupportedType, |
| 608 | 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 | 596 | try block_scope.statements.append(ret); |
| 612 | 597 | } |
| 613 | 598 | |
| 614 | | proto_node.body = try block_scope.complete(c); |
| 615 | | return addTopLevelDecl(c, fn_name, &proto_node.base); |
| 599 | proto_node.data.body = try block_scope.complete(c); |
| 600 | return addTopLevelDecl(c, fn_name, Node.initPayload(&proto_node.base)); |
| 616 | 601 | } |
| 617 | 602 | |
| 618 | 603 | fn transQualTypeMaybeInitialized(c: *Context, qt: clang.QualType, decl_init: ?*const clang.Expr, loc: clang.SourceLocation) TransError!Node { |
| ... | ... | @@ -668,7 +653,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 668 | 653 | const node_or_error = if (expr.getStmtClass() == .StringLiteralClass) |
| 669 | 654 | transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(c, type_node) catch 0) |
| 670 | 655 | else |
| 671 | | transExprCoercing(c, scope, expr, .used, .r_value); |
| 656 | transExprCoercing(c, scope, expr, .used); |
| 672 | 657 | init_node = node_or_error catch |err| switch (err) { |
| 673 | 658 | error.UnsupportedTranslation, |
| 674 | 659 | error.UnsupportedType, |
| ... | ... | @@ -677,18 +662,18 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 677 | 662 | }, |
| 678 | 663 | error.OutOfMemory => |e| return e, |
| 679 | 664 | }; |
| 680 | | if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node)) { |
| 681 | | init_node = try Node.bool_to_int.create(c.arena, init_node); |
| 665 | if (!qualTypeIsBoolean(qual_type) and isBoolRes(init_node.?)) { |
| 666 | init_node = try Tag.bool_to_int.create(c.arena, init_node.?); |
| 682 | 667 | } |
| 683 | 668 | } else { |
| 684 | | init_node = Node.undefined_literal.init(); |
| 669 | init_node = Tag.undefined_literal.init(); |
| 685 | 670 | } |
| 686 | 671 | } else if (storage_class != .Extern) { |
| 687 | 672 | // The C language specification states that variables with static or threadlocal |
| 688 | 673 | // storage without an initializer are initialized to a zero value. |
| 689 | 674 | |
| 690 | 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 | } |
| 693 | 678 | |
| 694 | 679 | const linksection_string = blk: { |
| ... | ... | @@ -708,7 +693,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 708 | 693 | break :blk null; |
| 709 | 694 | }; |
| 710 | 695 | |
| 711 | | const node = try Node.var_decl.create(c.arena, .{ |
| 696 | const node = try Tag.var_decl.create(c.arena, .{ |
| 712 | 697 | .is_pub = is_pub, |
| 713 | 698 | .is_const = is_const, |
| 714 | 699 | .is_extern = is_extern, |
| ... | ... | @@ -719,12 +704,12 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 719 | 704 | .type = type_node, |
| 720 | 705 | .init = init_node, |
| 721 | 706 | }); |
| 722 | | return addTopLevelDecl(c, checked_name, &node.base); |
| 707 | return addTopLevelDecl(c, checked_name, node); |
| 723 | 708 | } |
| 724 | 709 | |
| 725 | 710 | fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !Node { |
| 726 | 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 | } |
| 729 | 714 | |
| 730 | 715 | const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{ |
| ... | ... | @@ -744,7 +729,7 @@ const builtin_typedef_map = std.ComptimeStringMap([]const u8, .{ |
| 744 | 729 | |
| 745 | 730 | fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_level_visit: bool) Error!?Node { |
| 746 | 731 | if (c.decl_table.get(@ptrToInt(typedef_decl.getCanonicalDecl()))) |name| |
| 747 | | return transCreateNodeIdentifier(c, name); // Avoid processing this decl twice |
| 732 | return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice |
| 748 | 733 | |
| 749 | 734 | const typedef_name = try c.str(@ptrCast(*const clang.NamedDecl, typedef_decl).getName_bytes_begin()); |
| 750 | 735 | |
| ... | ... | @@ -753,17 +738,17 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev |
| 753 | 738 | const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ typedef_name, c.getMangle() }) else typedef_name; |
| 754 | 739 | if (builtin_typedef_map.get(checked_name)) |builtin| { |
| 755 | 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 | } |
| 758 | 743 | |
| 759 | 744 | if (!top_level_visit) { |
| 760 | | return transCreateNodeIdentifier(c, checked_name); |
| 745 | return try Tag.identifier.create(c.arena, checked_name); |
| 761 | 746 | } |
| 762 | 747 | |
| 763 | 748 | _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name); |
| 764 | 749 | const node = (try transCreateNodeTypedef(c, typedef_decl, true, checked_name)) orelse return null; |
| 765 | 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 | } |
| 768 | 753 | |
| 769 | 754 | fn transCreateNodeTypedef( |
| ... | ... | @@ -782,9 +767,9 @@ fn transCreateNodeTypedef( |
| 782 | 767 | error.OutOfMemory => |e| return e, |
| 783 | 768 | }; |
| 784 | 769 | |
| 785 | | const payload = try c.arena.create(ast.Payload.Typedef); |
| 770 | const payload = try c.arena.create(ast.Payload.SimpleVarDecl); |
| 786 | 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 | 773 | .data = .{ |
| 789 | 774 | .name = checked_name, |
| 790 | 775 | .init = init_node, |
| ... | ... | @@ -795,7 +780,7 @@ fn transCreateNodeTypedef( |
| 795 | 780 | |
| 796 | 781 | fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Node { |
| 797 | 782 | if (c.decl_table.get(@ptrToInt(record_decl.getCanonicalDecl()))) |name| |
| 798 | | return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice |
| 783 | return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice |
| 799 | 784 | const record_loc = record_decl.getLocation(); |
| 800 | 785 | |
| 801 | 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 | 800 | } else if (record_decl.isStruct()) { |
| 816 | 801 | container_kind_name = "struct"; |
| 817 | 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 | 804 | return null; |
| 820 | 805 | } |
| 821 | 806 | |
| ... | ... | @@ -826,7 +811,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod |
| 826 | 811 | const init_node = blk: { |
| 827 | 812 | const record_def = record_decl.getDefinition() orelse { |
| 828 | 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 | }; |
| 831 | 816 | |
| 832 | 817 | const is_packed = record_decl.getPackedAttribute(); |
| ... | ... | @@ -843,14 +828,14 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod |
| 843 | 828 | |
| 844 | 829 | if (field_decl.isBitField()) { |
| 845 | 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}); |
| 847 | | break :blk Node.opaque_literal.init(); |
| 831 | try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has bitfield", .{container_kind_name}); |
| 832 | break :blk Tag.opaque_literal.init(); |
| 848 | 833 | } |
| 849 | 834 | |
| 850 | 835 | if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) { |
| 851 | 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}); |
| 853 | | break :blk Node.opaque_literal.init(); |
| 837 | try warn(c, &c.global_scope.base, field_loc, "{s} demoted to opaque type - has variable length array", .{container_kind_name}); |
| 838 | break :blk Tag.opaque_literal.init(); |
| 854 | 839 | } |
| 855 | 840 | |
| 856 | 841 | var is_anon = false; |
| ... | ... | @@ -864,8 +849,8 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod |
| 864 | 849 | const field_type = transQualType(c, field_qt, field_loc) catch |err| switch (err) { |
| 865 | 850 | error.UnsupportedType => { |
| 866 | 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 }); |
| 868 | | break :blk Node.opaque_literal.init(); |
| 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 }); |
| 853 | break :blk Tag.opaque_literal.init(); |
| 869 | 854 | }, |
| 870 | 855 | else => |e| return e, |
| 871 | 856 | }; |
| ... | ... | @@ -890,20 +875,20 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod |
| 890 | 875 | }); |
| 891 | 876 | } |
| 892 | 877 | |
| 893 | | const payload = try c.arena.create(ast.Payload.Record); |
| 894 | | container_node.* = .{ |
| 895 | | .base = .{ .tag = ([2]ast.Node.Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] }, |
| 878 | const record_payload = try c.arena.create(ast.Payload.Record); |
| 879 | record_payload.* = .{ |
| 880 | .base = .{ .tag = ([2]Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] }, |
| 896 | 881 | .data = .{ |
| 897 | 882 | .is_packed = is_packed, |
| 898 | 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 | }; |
| 903 | 888 | |
| 904 | 889 | const payload = try c.arena.create(ast.Payload.SimpleVarDecl); |
| 905 | 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 | 892 | .data = .{ |
| 908 | 893 | .name = name, |
| 909 | 894 | .init = init_node, |
| ... | ... | @@ -913,12 +898,12 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?Nod |
| 913 | 898 | try addTopLevelDecl(c, name, Node.initPayload(&payload.base)); |
| 914 | 899 | if (!is_unnamed) |
| 915 | 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 | } |
| 918 | 903 | |
| 919 | 904 | fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node { |
| 920 | 905 | if (c.decl_table.get(@ptrToInt(enum_decl.getCanonicalDecl()))) |name| |
| 921 | | return try transCreateNodeIdentifier(c, name); // Avoid processing this decl twice |
| 906 | return try Tag.identifier.create(c.arena, name); // Avoid processing this decl twice |
| 922 | 907 | const enum_loc = enum_decl.getLocation(); |
| 923 | 908 | |
| 924 | 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 | 950 | else => |e| return e, |
| 966 | 951 | } |
| 967 | 952 | else |
| 968 | | try Node.type.create(c.arena, "c_int"); |
| 953 | try Tag.type.create(c.arena, "c_int"); |
| 969 | 954 | |
| 970 | 955 | it = enum_def.enumerator_begin(); |
| 971 | 956 | end_it = enum_def.enumerator_end(); |
| ... | ... | @@ -983,29 +968,29 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node { |
| 983 | 968 | else |
| 984 | 969 | null; |
| 985 | 970 | |
| 986 | | try fields_and_decls.append(.{ |
| 971 | try fields.append(.{ |
| 987 | 972 | .name = field_name, |
| 988 | 973 | .value = int_node, |
| 989 | 974 | }); |
| 990 | 975 | |
| 991 | 976 | // In C each enum value is in the global namespace. So we put them there too. |
| 992 | 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 | 979 | .enum_val_name = enum_val_name, |
| 995 | 980 | .field_name = field_name, |
| 996 | 981 | .enum_name = name, |
| 997 | 982 | })); |
| 998 | 983 | } |
| 999 | 984 | |
| 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 | 986 | } else blk: { |
| 1002 | 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 | }; |
| 1005 | 990 | |
| 1006 | 991 | const payload = try c.arena.create(ast.Payload.SimpleVarDecl); |
| 1007 | 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 | 994 | .data = .{ |
| 1010 | 995 | .name = name, |
| 1011 | 996 | .init = init_node, |
| ... | ... | @@ -1015,7 +1000,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?Node { |
| 1015 | 1000 | try addTopLevelDecl(c, name, Node.initPayload(&payload.base)); |
| 1016 | 1001 | if (!is_unnamed) |
| 1017 | 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 | } |
| 1020 | 1005 | |
| 1021 | 1006 | const ResultUsed = enum { |
| ... | ... | @@ -1023,31 +1008,25 @@ const ResultUsed = enum { |
| 1023 | 1008 | unused, |
| 1024 | 1009 | }; |
| 1025 | 1010 | |
| 1026 | | const LRValue = enum { |
| 1027 | | l_value, |
| 1028 | | r_value, |
| 1029 | | }; |
| 1030 | | |
| 1031 | 1011 | fn transStmt( |
| 1032 | 1012 | c: *Context, |
| 1033 | 1013 | scope: *Scope, |
| 1034 | 1014 | stmt: *const clang.Stmt, |
| 1035 | 1015 | result_used: ResultUsed, |
| 1036 | | lrvalue: LRValue, |
| 1037 | 1016 | ) TransError!Node { |
| 1038 | 1017 | const sc = stmt.getStmtClass(); |
| 1039 | 1018 | switch (sc) { |
| 1040 | 1019 | .BinaryOperatorClass => return transBinaryOperator(c, scope, @ptrCast(*const clang.BinaryOperator, stmt), result_used), |
| 1041 | 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 | 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 | 1024 | .ImplicitCastExprClass => return transImplicitCastExpr(c, scope, @ptrCast(*const clang.ImplicitCastExpr, stmt), result_used), |
| 1046 | 1025 | .IntegerLiteralClass => return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, stmt), result_used, .with_as), |
| 1047 | 1026 | .ReturnStmtClass => return transReturnStmt(c, scope, @ptrCast(*const clang.ReturnStmt, stmt)), |
| 1048 | 1027 | .StringLiteralClass => return transStringLiteral(c, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used), |
| 1049 | 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 | 1030 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1052 | 1031 | }, |
| 1053 | 1032 | .InitListExprClass => return transInitListExpr(c, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used), |
| ... | ... | @@ -1056,9 +1035,9 @@ fn transStmt( |
| 1056 | 1035 | .WhileStmtClass => return transWhileLoop(c, scope, @ptrCast(*const clang.WhileStmt, stmt)), |
| 1057 | 1036 | .DoStmtClass => return transDoWhileLoop(c, scope, @ptrCast(*const clang.DoStmt, stmt)), |
| 1058 | 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 | 1041 | .BreakStmtClass => return transBreak(c, scope), |
| 1063 | 1042 | .ForStmtClass => return transForLoop(c, scope, @ptrCast(*const clang.ForStmt, stmt)), |
| 1064 | 1043 | .FloatingLiteralClass => return transFloatingLiteral(c, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used), |
| ... | ... | @@ -1083,12 +1062,12 @@ fn transStmt( |
| 1083 | 1062 | .CompoundAssignOperatorClass => return transCompoundAssignOperator(c, scope, @ptrCast(*const clang.CompoundAssignOperator, stmt), result_used), |
| 1084 | 1063 | .OpaqueValueExprClass => { |
| 1085 | 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 | 1066 | return maybeSuppressResult(c, scope, result_used, expr); |
| 1088 | 1067 | }, |
| 1089 | 1068 | else => { |
| 1090 | 1069 | return fail( |
| 1091 | | rp, |
| 1070 | c, |
| 1092 | 1071 | error.UnsupportedTranslation, |
| 1093 | 1072 | stmt.getBeginLoc(), |
| 1094 | 1073 | "TODO implement translation of stmt class {s}", |
| ... | ... | @@ -1109,37 +1088,36 @@ fn transBinaryOperator( |
| 1109 | 1088 | switch (op) { |
| 1110 | 1089 | .Assign => return try transCreateNodeAssign(c, scope, result_used, stmt.getLHS(), stmt.getRHS()), |
| 1111 | 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 | 1092 | defer block_scope.deinit(); |
| 1114 | 1093 | |
| 1115 | | |
| 1116 | | const lhs = try transExpr(c, &block_scope.base, stmt.getLHS(), .unused, .r_value); |
| 1094 | const lhs = try transExpr(c, &block_scope.base, stmt.getLHS(), .unused); |
| 1117 | 1095 | try block_scope.statements.append(lhs); |
| 1118 | 1096 | |
| 1119 | | const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value); |
| 1120 | | const break_node = try Node.break_val.create(c.arena, .{ |
| 1097 | const rhs = try transExpr(c, &block_scope.base, stmt.getRHS(), .used); |
| 1098 | const break_node = try Tag.break_val.create(c.arena, .{ |
| 1121 | 1099 | .label = block_scope.label, |
| 1122 | 1100 | .val = rhs, |
| 1123 | 1101 | }); |
| 1124 | 1102 | try block_scope.statements.append(break_node); |
| 1125 | | const block_node = try block_scope.complete(rp.c); |
| 1126 | | return maybeSuppressResult(rp, scope, result_used, block_node); |
| 1103 | const block_node = try block_scope.complete(c); |
| 1104 | return maybeSuppressResult(c, scope, result_used, block_node); |
| 1127 | 1105 | }, |
| 1128 | 1106 | .Div => { |
| 1129 | 1107 | if (cIsSignedInteger(qt)) { |
| 1130 | 1108 | // signed integer division uses @divTrunc |
| 1131 | | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1132 | | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1133 | | const div_trunc = try Node.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 1109 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used); |
| 1110 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used); |
| 1111 | const div_trunc = try Tag.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 1134 | 1112 | return maybeSuppressResult(c, scope, result_used, div_trunc); |
| 1135 | 1113 | } |
| 1136 | 1114 | }, |
| 1137 | 1115 | .Rem => { |
| 1138 | 1116 | if (cIsSignedInteger(qt)) { |
| 1139 | 1117 | // signed integer division uses @rem |
| 1140 | | const lhs = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1141 | | const rhs = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1142 | | const rem = try Node.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 1118 | const lhs = try transExpr(c, scope, stmt.getLHS(), .used); |
| 1119 | const rhs = try transExpr(c, scope, stmt.getRHS(), .used); |
| 1120 | const rem = try Tag.rem.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); |
| 1143 | 1121 | return maybeSuppressResult(c, scope, result_used, rem); |
| 1144 | 1122 | } |
| 1145 | 1123 | }, |
| ... | ... | @@ -1150,14 +1128,14 @@ fn transBinaryOperator( |
| 1150 | 1128 | return transCreateNodeShiftOp(c, scope, stmt, .shr, result_used); |
| 1151 | 1129 | }, |
| 1152 | 1130 | .LAnd => { |
| 1153 | | return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_and, result_used); |
| 1131 | return transCreateNodeBoolInfixOp(c, scope, stmt, .@"and", result_used); |
| 1154 | 1132 | }, |
| 1155 | 1133 | .LOr => { |
| 1156 | | return transCreateNodeBoolInfixOp(c, scope, stmt, .bool_or, result_used); |
| 1134 | return transCreateNodeBoolInfixOp(c, scope, stmt, .@"or", result_used); |
| 1157 | 1135 | }, |
| 1158 | 1136 | else => {}, |
| 1159 | 1137 | } |
| 1160 | | var op_id: Node.Tag = undefined; |
| 1138 | var op_id: Tag = undefined; |
| 1161 | 1139 | switch (op) { |
| 1162 | 1140 | .Add => { |
| 1163 | 1141 | if (cIsUnsignedInteger(qt)) { |
| ... | ... | @@ -1218,20 +1196,20 @@ fn transBinaryOperator( |
| 1218 | 1196 | else => unreachable, |
| 1219 | 1197 | } |
| 1220 | 1198 | |
| 1221 | | const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used, .l_value); |
| 1222 | | const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used, .r_value); |
| 1199 | const lhs_uncasted = try transExpr(c, scope, stmt.getLHS(), .used); |
| 1200 | const rhs_uncasted = try transExpr(c, scope, stmt.getRHS(), .used); |
| 1223 | 1201 | |
| 1224 | 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 | 1204 | else |
| 1227 | 1205 | lhs_uncasted; |
| 1228 | 1206 | |
| 1229 | 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 | 1209 | else |
| 1232 | 1210 | rhs_uncasted; |
| 1233 | 1211 | |
| 1234 | | return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, used); |
| 1212 | return transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, result_used); |
| 1235 | 1213 | } |
| 1236 | 1214 | |
| 1237 | 1215 | fn transCompoundStmtInline( |
| ... | ... | @@ -1243,7 +1221,7 @@ fn transCompoundStmtInline( |
| 1243 | 1221 | var it = stmt.body_begin(); |
| 1244 | 1222 | const end_it = stmt.body_end(); |
| 1245 | 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 | 1225 | try block.statements.append(result); |
| 1248 | 1226 | } |
| 1249 | 1227 | } |
| ... | ... | @@ -1260,7 +1238,6 @@ fn transCStyleCastExprClass( |
| 1260 | 1238 | scope: *Scope, |
| 1261 | 1239 | stmt: *const clang.CStyleCastExpr, |
| 1262 | 1240 | result_used: ResultUsed, |
| 1263 | | lrvalue: LRValue, |
| 1264 | 1241 | ) TransError!Node { |
| 1265 | 1242 | const sub_expr = stmt.getSubExpr(); |
| 1266 | 1243 | const cast_node = (try transCCast( |
| ... | ... | @@ -1269,7 +1246,7 @@ fn transCStyleCastExprClass( |
| 1269 | 1246 | stmt.getBeginLoc(), |
| 1270 | 1247 | stmt.getType(), |
| 1271 | 1248 | sub_expr.getType(), |
| 1272 | | try transExpr(c, scope, sub_expr, .used, lrvalue), |
| 1249 | try transExpr(c, scope, sub_expr, .used), |
| 1273 | 1250 | )); |
| 1274 | 1251 | return maybeSuppressResult(c, scope, result_used, cast_node); |
| 1275 | 1252 | } |
| ... | ... | @@ -1294,7 +1271,7 @@ fn transDeclStmtOne( |
| 1294 | 1271 | // This is actually a global variable, put it in the global scope and reference it. |
| 1295 | 1272 | // `_ = mangled_name;` |
| 1296 | 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 | 1276 | else => {}, |
| 1300 | 1277 | } |
| ... | ... | @@ -1308,13 +1285,13 @@ fn transDeclStmtOne( |
| 1308 | 1285 | if (expr.getStmtClass() == .StringLiteralClass) |
| 1309 | 1286 | try transStringLiteralAsArray(c, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(c, type_node)) |
| 1310 | 1287 | else |
| 1311 | | try transExprCoercing(c, scope, expr, .used, .r_value) |
| 1288 | try transExprCoercing(c, scope, expr, .used) |
| 1312 | 1289 | else |
| 1313 | | try transCreateNodeUndefinedLiteral(c); |
| 1290 | Tag.undefined_literal.init(); |
| 1314 | 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 | 1295 | .is_pub = false, |
| 1319 | 1296 | .is_const = is_const, |
| 1320 | 1297 | .is_extern = false, |
| ... | ... | @@ -1339,7 +1316,7 @@ fn transDeclStmtOne( |
| 1339 | 1316 | return node; |
| 1340 | 1317 | }, |
| 1341 | 1318 | else => |kind| return fail( |
| 1342 | | rp, |
| 1319 | c, |
| 1343 | 1320 | error.UnsupportedTranslation, |
| 1344 | 1321 | decl.getLocation(), |
| 1345 | 1322 | "TODO implement translation of DeclStmt kind {s}", |
| ... | ... | @@ -1370,12 +1347,11 @@ fn transDeclRefExpr( |
| 1370 | 1347 | c: *Context, |
| 1371 | 1348 | scope: *Scope, |
| 1372 | 1349 | expr: *const clang.DeclRefExpr, |
| 1373 | | lrvalue: LRValue, |
| 1374 | 1350 | ) TransError!Node { |
| 1375 | 1351 | const value_decl = expr.getDecl(); |
| 1376 | 1352 | const name = try c.str(@ptrCast(*const clang.NamedDecl, value_decl).getName_bytes_begin()); |
| 1377 | 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 | } |
| 1380 | 1356 | |
| 1381 | 1357 | fn transImplicitCastExpr( |
| ... | ... | @@ -1389,49 +1365,49 @@ fn transImplicitCastExpr( |
| 1389 | 1365 | const src_type = getExprQualType(c, sub_expr); |
| 1390 | 1366 | switch (expr.getCastKind()) { |
| 1391 | 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 | 1369 | const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node); |
| 1394 | 1370 | return maybeSuppressResult(c, scope, result_used, casted); |
| 1395 | 1371 | }, |
| 1396 | 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 | 1374 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1399 | 1375 | }, |
| 1400 | 1376 | .ArrayToPointerDecay => { |
| 1401 | 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 | 1379 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1404 | 1380 | } |
| 1405 | 1381 | |
| 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 | 1383 | return maybeSuppressResult(c, scope, result_used, addr); |
| 1408 | 1384 | }, |
| 1409 | 1385 | .NullToPointer => { |
| 1410 | | return Node.null_literal.init(); |
| 1386 | return Tag.null_literal.init(); |
| 1411 | 1387 | }, |
| 1412 | 1388 | .PointerToBoolean => { |
| 1413 | 1389 | // @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)); |
| 1415 | 1391 | |
| 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 | 1393 | return maybeSuppressResult(c, scope, result_used, ne); |
| 1418 | 1394 | }, |
| 1419 | 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); |
| 1421 | 1397 | |
| 1422 | 1398 | // The expression is already a boolean one, return it as-is |
| 1423 | 1399 | if (isBoolRes(sub_expr_node)) |
| 1424 | 1400 | return maybeSuppressResult(c, scope, result_used, sub_expr_node); |
| 1425 | 1401 | |
| 1426 | 1402 | // 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 | 1404 | return maybeSuppressResult(c, scope, result_used, ne); |
| 1429 | 1405 | }, |
| 1430 | 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 | 1409 | else => |kind| return fail( |
| 1434 | | rp, |
| 1410 | c, |
| 1435 | 1411 | error.UnsupportedTranslation, |
| 1436 | 1412 | @ptrCast(*const clang.Stmt, expr).getBeginLoc(), |
| 1437 | 1413 | "TODO implement translation of CastKind {s}", |
| ... | ... | @@ -1445,17 +1421,16 @@ fn transBoolExpr( |
| 1445 | 1421 | scope: *Scope, |
| 1446 | 1422 | expr: *const clang.Expr, |
| 1447 | 1423 | used: ResultUsed, |
| 1448 | | lrvalue: LRValue, |
| 1449 | 1424 | ) TransError!Node { |
| 1450 | 1425 | if (@ptrCast(*const clang.Stmt, expr).getStmtClass() == .IntegerLiteralClass) { |
| 1451 | 1426 | var is_zero: bool = undefined; |
| 1452 | 1427 | if (!(@ptrCast(*const clang.IntegerLiteral, expr).isZero(&is_zero, c.clang_context))) { |
| 1453 | 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 | } |
| 1457 | 1432 | |
| 1458 | | var res = try transExpr(c, scope, expr, used, lrvalue); |
| 1433 | var res = try transExpr(c, scope, expr, used); |
| 1459 | 1434 | if (isBoolRes(res)) { |
| 1460 | 1435 | return maybeSuppressResult(c, scope, used, res); |
| 1461 | 1436 | } |
| ... | ... | @@ -1494,7 +1469,7 @@ fn isBoolRes(res: Node) bool { |
| 1494 | 1469 | .@"or", |
| 1495 | 1470 | .@"and", |
| 1496 | 1471 | .equal, |
| 1497 | | .note_equal, |
| 1472 | .not_equal, |
| 1498 | 1473 | .less_than, |
| 1499 | 1474 | .less_than_equal, |
| 1500 | 1475 | .greater_than, |
| ... | ... | @@ -1547,18 +1522,18 @@ fn finishBoolExpr( |
| 1547 | 1522 | .Float16, |
| 1548 | 1523 | => { |
| 1549 | 1524 | // 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 | 1527 | .NullPtr => { |
| 1553 | 1528 | // 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 | 1531 | else => {}, |
| 1557 | 1532 | } |
| 1558 | 1533 | }, |
| 1559 | 1534 | .Pointer => { |
| 1560 | 1535 | // 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 | 1538 | .Typedef => { |
| 1564 | 1539 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); |
| ... | ... | @@ -1568,8 +1543,7 @@ fn finishBoolExpr( |
| 1568 | 1543 | }, |
| 1569 | 1544 | .Enum => { |
| 1570 | 1545 | // node != 0 |
| 1571 | | return Node.not_equal.create(c.arena, .{ .lhs = node, .rhs = Node.zero_literal.init() }); |
| 1572 | | const op_token = try appendToken(c, .BangEqual, "!="); |
| 1546 | return Tag.not_equal.create(c.arena, .{ .lhs = node, .rhs = Tag.zero_literal.init() }); |
| 1573 | 1547 | }, |
| 1574 | 1548 | .Elaborated => { |
| 1575 | 1549 | const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty); |
| ... | ... | @@ -1614,9 +1588,10 @@ fn transIntegerLiteral( |
| 1614 | 1588 | // But the first step is to be correct, and the next step is to make the output more elegant. |
| 1615 | 1589 | |
| 1616 | 1590 | // @as(T, x) |
| 1591 | const expr_base = @ptrCast(*const clang.Expr, expr); |
| 1617 | 1592 | const ty_node = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()); |
| 1618 | 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 | 1595 | return maybeSuppressResult(c, scope, result_used, as); |
| 1621 | 1596 | } |
| 1622 | 1597 | |
| ... | ... | @@ -1624,16 +1599,16 @@ fn transReturnStmt( |
| 1624 | 1599 | c: *Context, |
| 1625 | 1600 | scope: *Scope, |
| 1626 | 1601 | expr: *const clang.ReturnStmt, |
| 1627 | | ) TransError!*ast.Node { |
| 1602 | ) TransError!Node { |
| 1628 | 1603 | const val_expr = expr.getRetValue() orelse |
| 1629 | | return Node.return_void.init(); |
| 1604 | return Tag.return_void.init(); |
| 1630 | 1605 | |
| 1631 | | var rhs = try transExprCoercing(c, scope, val_expr, .used, .r_value); |
| 1606 | var rhs = try transExprCoercing(c, scope, val_expr, .used); |
| 1632 | 1607 | const return_qt = scope.findBlockReturnType(c); |
| 1633 | 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 | } |
| 1638 | 1613 | |
| 1639 | 1614 | fn transStringLiteral( |
| ... | ... | @@ -1647,10 +1622,9 @@ fn transStringLiteral( |
| 1647 | 1622 | .Ascii, .UTF8 => { |
| 1648 | 1623 | var len: usize = undefined; |
| 1649 | 1624 | const bytes_ptr = stmt.getString_bytes_begin_size(&len); |
| 1650 | | const str = bytes_ptr[0..len]; |
| 1651 | 1625 | |
| 1652 | | const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(str)}); |
| 1653 | | const node = try Node.string_literal.create(c.arena, str); |
| 1626 | const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])}); |
| 1627 | const node = try Tag.string_literal.create(c.arena, str); |
| 1654 | 1628 | return maybeSuppressResult(c, scope, result_used, node); |
| 1655 | 1629 | }, |
| 1656 | 1630 | .UTF16, .UTF32, .Wide => { |
| ... | ... | @@ -1658,9 +1632,9 @@ fn transStringLiteral( |
| 1658 | 1632 | const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() }); |
| 1659 | 1633 | const lit_array = try transStringLiteralAsArray(c, scope, stmt, stmt.getLength() + 1); |
| 1660 | 1634 | |
| 1661 | | const decl = try Node.var_simple.create(c.arena, .{ .name = name, .init = lit_array }); |
| 1662 | | try scope.appendNode(name, decl); |
| 1663 | | const node = try Node.identifier.create(c.arena, name); |
| 1635 | const decl = try Tag.var_simple.create(c.arena, .{ .name = name, .init = lit_array }); |
| 1636 | try scope.appendNode(decl); |
| 1637 | const node = try Tag.identifier.create(c.arena, name); |
| 1664 | 1638 | return maybeSuppressResult(c, scope, result_used, node); |
| 1665 | 1639 | }, |
| 1666 | 1640 | } |
| ... | ... | @@ -1669,9 +1643,7 @@ fn transStringLiteral( |
| 1669 | 1643 | /// Parse the size of an array back out from an ast Node. |
| 1670 | 1644 | fn zigArraySize(c: *Context, node: Node) TransError!usize { |
| 1671 | 1645 | if (node.castTag(.array_type)) |array| { |
| 1672 | | if (array.data.len.castTag(.int_literal)) |int_lit| { |
| 1673 | | return std.fmt.parseUnsigned(usize, int_lit.data, 10) catch error.UnsupportedTranslation; |
| 1674 | | } |
| 1646 | return array.data.len; |
| 1675 | 1647 | } |
| 1676 | 1648 | return error.UnsupportedTranslation; |
| 1677 | 1649 | } |
| ... | ... | @@ -1709,7 +1681,7 @@ fn transStringLiteralAsArray( |
| 1709 | 1681 | init_list[i] = try transCreateNodeNumber(c, 0); |
| 1710 | 1682 | } |
| 1711 | 1683 | |
| 1712 | | return Node.array_init.create(c.arena, init_list); |
| 1684 | return Tag.array_init.create(c.arena, init_list); |
| 1713 | 1685 | } |
| 1714 | 1686 | |
| 1715 | 1687 | fn cIsEnum(qt: clang.QualType) bool { |
| ... | ... | @@ -1747,89 +1719,77 @@ fn transCCast( |
| 1747 | 1719 | // 3. Bit-cast to correct signed-ness |
| 1748 | 1720 | const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type); |
| 1749 | 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); |
| 1751 | 1723 | |
| 1752 | 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 | } |
| 1755 | 1727 | |
| 1756 | 1728 | switch (cIntTypeCmp(dst_type, src_int_type)) { |
| 1757 | 1729 | .lt => { |
| 1758 | 1730 | // @truncate(SameSignSmallerInt, src_int_expr) |
| 1759 | 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 | 1734 | .gt => { |
| 1763 | 1735 | // @as(SameSignBiggerInt, src_int_expr) |
| 1764 | 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 | 1739 | .eq => { |
| 1768 | 1740 | // src_int_expr = src_int_expr |
| 1769 | 1741 | }, |
| 1770 | 1742 | } |
| 1771 | 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 | 1746 | if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) { |
| 1775 | 1747 | // @intCast(dest_type, @ptrToInt(val)) |
| 1776 | | const ptr_to_int = try Node.ptr_to_int.create(c.arena, expr); |
| 1777 | | return Node.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int }); |
| 1748 | const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr); |
| 1749 | return Tag.int_cast.create(c.arena, .{ .lhs = dst_node, .rhs = ptr_to_int }); |
| 1778 | 1750 | } |
| 1779 | 1751 | if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) { |
| 1780 | 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 | 1755 | if (cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 1784 | 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 | 1759 | if (cIsFloating(src_type) and !cIsFloating(dst_type)) { |
| 1788 | 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 | 1763 | if (!cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 1792 | 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 | 1767 | if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) { |
| 1796 | 1768 | // @boolToInt returns either a comptime_int or a u1 |
| 1797 | 1769 | // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast |
| 1798 | 1770 | // instead of @as |
| 1799 | | const bool_to_int = Node.bool_to_int.create(c.arena, expr); |
| 1800 | | return Node.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int }); |
| 1771 | const bool_to_int = try Tag.bool_to_int.create(c.arena, expr); |
| 1772 | return Tag.as.create(c.arena, .{ .lhs = dst_node, .rhs = bool_to_int }); |
| 1801 | 1773 | } |
| 1802 | 1774 | if (cIsEnum(dst_type)) { |
| 1803 | 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 | 1778 | if (cIsEnum(src_type) and !cIsEnum(dst_type)) { |
| 1807 | 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 | 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 | } |
| 1813 | 1785 | |
| 1814 | | fn transExpr( |
| 1815 | | c: *Context, |
| 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); |
| 1786 | fn transExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node { |
| 1787 | return transStmt(c, scope, @ptrCast(*const clang.Stmt, expr), used); |
| 1822 | 1788 | } |
| 1823 | 1789 | |
| 1824 | 1790 | /// Same as `transExpr` but with the knowledge that the operand will be type coerced, and therefore |
| 1825 | 1791 | /// an `@as` would be redundant. This is used to prevent redundant `@as` in integer literals. |
| 1826 | | fn transExprCoercing( |
| 1827 | | c: *Context, |
| 1828 | | scope: *Scope, |
| 1829 | | expr: *const clang.Expr, |
| 1830 | | used: ResultUsed, |
| 1831 | | lrvalue: LRValue, |
| 1832 | | ) TransError!Node { |
| 1792 | fn transExprCoercing(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node { |
| 1833 | 1793 | switch (@ptrCast(*const clang.Stmt, expr).getStmtClass()) { |
| 1834 | 1794 | .IntegerLiteralClass => { |
| 1835 | 1795 | return transIntegerLiteral(c, scope, @ptrCast(*const clang.IntegerLiteral, expr), .used, .no_as); |
| ... | ... | @@ -1840,12 +1800,12 @@ fn transExprCoercing( |
| 1840 | 1800 | .UnaryOperatorClass => { |
| 1841 | 1801 | const un_expr = @ptrCast(*const clang.UnaryOperator, expr); |
| 1842 | 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 | 1806 | else => {}, |
| 1847 | 1807 | } |
| 1848 | | return transExpr(c, scope, expr, .used, .r_value); |
| 1808 | return transExpr(c, scope, expr, .used); |
| 1849 | 1809 | } |
| 1850 | 1810 | |
| 1851 | 1811 | fn transInitListExprRecord( |
| ... | ... | @@ -1896,11 +1856,11 @@ fn transInitListExprRecord( |
| 1896 | 1856 | |
| 1897 | 1857 | try field_inits.append(.{ |
| 1898 | 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 | } |
| 1902 | 1862 | |
| 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 | } |
| 1905 | 1865 | |
| 1906 | 1866 | fn transInitListExprArray( |
| ... | ... | @@ -1920,18 +1880,18 @@ fn transInitListExprArray( |
| 1920 | 1880 | const leftover_count = all_count - init_count; |
| 1921 | 1881 | |
| 1922 | 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 | } |
| 1925 | 1885 | |
| 1926 | | const ty_node = try transType(ty); |
| 1886 | const ty_node = try transType(c, ty, loc); |
| 1927 | 1887 | const init_node = if (init_count != 0) blk: { |
| 1928 | 1888 | const init_list = try c.arena.alloc(Node, init_count); |
| 1929 | 1889 | |
| 1930 | 1890 | for (init_list) |*init, i| { |
| 1931 | | const elem_expr = expr.getInit(i); |
| 1932 | | init.* = try transExpr(c, scope, elem_expr, .used, .r_value); |
| 1891 | const elem_expr = expr.getInit(@intCast(c_uint, i)); |
| 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 | 1895 | if (leftover_count == 0) { |
| 1936 | 1896 | return init_node; |
| 1937 | 1897 | } |
| ... | ... | @@ -1939,14 +1899,14 @@ fn transInitListExprArray( |
| 1939 | 1899 | } else null; |
| 1940 | 1900 | |
| 1941 | 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 | 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 | 1905 | .count = leftover_count, |
| 1946 | 1906 | }); |
| 1947 | 1907 | |
| 1948 | 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 | 1910 | } else { |
| 1951 | 1911 | return filler_node; |
| 1952 | 1912 | } |
| ... | ... | @@ -1964,7 +1924,7 @@ fn transInitListExpr( |
| 1964 | 1924 | |
| 1965 | 1925 | if (qual_type.isRecordType()) { |
| 1966 | 1926 | return maybeSuppressResult(c, scope, used, try transInitListExprRecord( |
| 1967 | | rp, |
| 1927 | c, |
| 1968 | 1928 | scope, |
| 1969 | 1929 | source_loc, |
| 1970 | 1930 | expr, |
| ... | ... | @@ -1972,7 +1932,7 @@ fn transInitListExpr( |
| 1972 | 1932 | )); |
| 1973 | 1933 | } else if (qual_type.isArrayType()) { |
| 1974 | 1934 | return maybeSuppressResult(c, scope, used, try transInitListExprArray( |
| 1975 | | rp, |
| 1935 | c, |
| 1976 | 1936 | scope, |
| 1977 | 1937 | source_loc, |
| 1978 | 1938 | expr, |
| ... | ... | @@ -1994,7 +1954,7 @@ fn transZeroInitExpr( |
| 1994 | 1954 | .Builtin => { |
| 1995 | 1955 | const builtin_ty = @ptrCast(*const clang.BuiltinType, ty); |
| 1996 | 1956 | switch (builtin_ty.getKind()) { |
| 1997 | | .Bool => return Node.false_literal.init(), |
| 1957 | .Bool => return Tag.false_literal.init(), |
| 1998 | 1958 | .Char_U, |
| 1999 | 1959 | .UChar, |
| 2000 | 1960 | .Char_S, |
| ... | ... | @@ -2015,11 +1975,11 @@ fn transZeroInitExpr( |
| 2015 | 1975 | .Float128, |
| 2016 | 1976 | .Float16, |
| 2017 | 1977 | .LongDouble, |
| 2018 | | => return Node.zero_literal.init(), |
| 1978 | => return Tag.zero_literal.init(), |
| 2019 | 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 | 1983 | .Typedef => { |
| 2024 | 1984 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); |
| 2025 | 1985 | const typedef_decl = typedef_ty.getDecl(); |
| ... | ... | @@ -2058,19 +2018,19 @@ fn transIfStmt( |
| 2058 | 2018 | var cond_scope = Scope.Condition{ |
| 2059 | 2019 | .base = .{ |
| 2060 | 2020 | .parent = scope, |
| 2061 | | .id = .Condition, |
| 2021 | .id = .condition, |
| 2062 | 2022 | }, |
| 2063 | 2023 | }; |
| 2064 | 2024 | defer cond_scope.deinit(); |
| 2065 | 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); |
| 2067 | 2027 | |
| 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 | 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 | 2031 | else |
| 2072 | 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 | } |
| 2075 | 2035 | |
| 2076 | 2036 | fn transWhileLoop( |
| ... | ... | @@ -2081,19 +2041,19 @@ fn transWhileLoop( |
| 2081 | 2041 | var cond_scope = Scope.Condition{ |
| 2082 | 2042 | .base = .{ |
| 2083 | 2043 | .parent = scope, |
| 2084 | | .id = .Condition, |
| 2044 | .id = .condition, |
| 2085 | 2045 | }, |
| 2086 | 2046 | }; |
| 2087 | 2047 | defer cond_scope.deinit(); |
| 2088 | 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); |
| 2090 | 2050 | |
| 2091 | 2051 | var loop_scope = Scope{ |
| 2092 | 2052 | .parent = scope, |
| 2093 | | .id = .Loop, |
| 2053 | .id = .loop, |
| 2094 | 2054 | }; |
| 2095 | | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| 2096 | | return Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null }); |
| 2055 | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused); |
| 2056 | return Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = null }); |
| 2097 | 2057 | } |
| 2098 | 2058 | |
| 2099 | 2059 | fn transDoWhileLoop( |
| ... | ... | @@ -2103,20 +2063,19 @@ fn transDoWhileLoop( |
| 2103 | 2063 | ) TransError!Node { |
| 2104 | 2064 | var loop_scope = Scope{ |
| 2105 | 2065 | .parent = scope, |
| 2106 | | .id = .Loop, |
| 2066 | .id = .loop, |
| 2107 | 2067 | }; |
| 2108 | 2068 | |
| 2109 | 2069 | // if (!cond) break; |
| 2110 | | const if_node = try transCreateNodeIf(c); |
| 2111 | 2070 | var cond_scope = Scope.Condition{ |
| 2112 | 2071 | .base = .{ |
| 2113 | 2072 | .parent = scope, |
| 2114 | | .id = .Condition, |
| 2073 | .id = .condition, |
| 2115 | 2074 | }, |
| 2116 | 2075 | }; |
| 2117 | 2076 | defer cond_scope.deinit(); |
| 2118 | | const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used, .r_value); |
| 2119 | | const if_not_break = try Node.if_not_break.create(c.arena, cond); |
| 2077 | const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used); |
| 2078 | const if_not_break = try Tag.if_not_break.create(c.arena, cond); |
| 2120 | 2079 | |
| 2121 | 2080 | const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: { |
| 2122 | 2081 | // there's already a block in C, so we'll append our condition to it. |
| ... | ... | @@ -2129,8 +2088,8 @@ fn transDoWhileLoop( |
| 2129 | 2088 | // zig: b; |
| 2130 | 2089 | // zig: if (!cond) break; |
| 2131 | 2090 | // zig: } |
| 2132 | | const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| 2133 | | const block = node.castTag(.block); |
| 2091 | const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused); |
| 2092 | const block = node.castTag(.block).?; |
| 2134 | 2093 | block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete. |
| 2135 | 2094 | block.data.stmts[block.data.stmts.len - 1] = if_not_break; |
| 2136 | 2095 | break :blk node; |
| ... | ... | @@ -2143,12 +2102,12 @@ fn transDoWhileLoop( |
| 2143 | 2102 | // zig: a; |
| 2144 | 2103 | // zig: if (!cond) break; |
| 2145 | 2104 | // zig: } |
| 2146 | | const statements = try c.arena.create(Node, 2); |
| 2147 | | statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| 2105 | const statements = try c.arena.alloc(Node, 2); |
| 2106 | statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused); |
| 2148 | 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 | } |
| 2153 | 2112 | |
| 2154 | 2113 | fn transForLoop( |
| ... | ... | @@ -2158,7 +2117,7 @@ fn transForLoop( |
| 2158 | 2117 | ) TransError!Node { |
| 2159 | 2118 | var loop_scope = Scope{ |
| 2160 | 2119 | .parent = scope, |
| 2161 | | .id = .Loop, |
| 2120 | .id = .loop, |
| 2162 | 2121 | }; |
| 2163 | 2122 | |
| 2164 | 2123 | var block_scope: ?Scope.Block = null; |
| ... | ... | @@ -2167,29 +2126,29 @@ fn transForLoop( |
| 2167 | 2126 | if (stmt.getInit()) |init| { |
| 2168 | 2127 | block_scope = try Scope.Block.init(c, scope, false); |
| 2169 | 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 | 2130 | try block_scope.?.statements.append(init_node); |
| 2172 | 2131 | } |
| 2173 | 2132 | var cond_scope = Scope.Condition{ |
| 2174 | 2133 | .base = .{ |
| 2175 | 2134 | .parent = &loop_scope, |
| 2176 | | .id = .Condition, |
| 2135 | .id = .condition, |
| 2177 | 2136 | }, |
| 2178 | 2137 | }; |
| 2179 | 2138 | defer cond_scope.deinit(); |
| 2180 | 2139 | |
| 2181 | 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 | 2142 | else |
| 2184 | | Node.true_literal.init(); |
| 2143 | Tag.true_literal.init(); |
| 2185 | 2144 | |
| 2186 | 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 | 2147 | else |
| 2189 | 2148 | null; |
| 2190 | 2149 | |
| 2191 | | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused, .r_value); |
| 2192 | | const while_node = try Node.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr }); |
| 2150 | const body = try transStmt(c, &loop_scope, stmt.getBody(), .unused); |
| 2151 | const while_node = try Tag.@"while".create(c.arena, .{ .cond = cond, .body = body, .cont_expr = cont_expr }); |
| 2193 | 2152 | if (block_scope) |*bs| { |
| 2194 | 2153 | try bs.statements.append(while_node); |
| 2195 | 2154 | return try bs.complete(c); |
| ... | ... | @@ -2206,13 +2165,14 @@ fn transSwitch( |
| 2206 | 2165 | var cond_scope = Scope.Condition{ |
| 2207 | 2166 | .base = .{ |
| 2208 | 2167 | .parent = scope, |
| 2209 | | .id = .Condition, |
| 2168 | .id = .condition, |
| 2210 | 2169 | }, |
| 2211 | 2170 | }; |
| 2212 | 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 | 2173 | const switch_node = try c.arena.create(ast.Payload.Switch); |
| 2215 | 2174 | switch_node.* = .{ |
| 2175 | .base = .{ .tag = .@"switch" }, |
| 2216 | 2176 | .data = .{ |
| 2217 | 2177 | .cond = switch_expr, |
| 2218 | 2178 | .cases = undefined, // set later |
| ... | ... | @@ -2221,7 +2181,7 @@ fn transSwitch( |
| 2221 | 2181 | |
| 2222 | 2182 | var switch_scope = Scope.Switch{ |
| 2223 | 2183 | .base = .{ |
| 2224 | | .id = .Switch, |
| 2184 | .id = .@"switch", |
| 2225 | 2185 | .parent = scope, |
| 2226 | 2186 | }, |
| 2227 | 2187 | .cases = std.ArrayList(Node).init(c.gpa), |
| ... | ... | @@ -2229,11 +2189,7 @@ fn transSwitch( |
| 2229 | 2189 | .default_label = null, |
| 2230 | 2190 | .switch_label = null, |
| 2231 | 2191 | }; |
| 2232 | | defer { |
| 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 | | } |
| 2192 | defer switch_scope.cases.deinit(); |
| 2237 | 2193 | |
| 2238 | 2194 | // tmp block that all statements will go before being picked up by a case or default |
| 2239 | 2195 | var block_scope = try Scope.Block.init(c, &switch_scope.base, false); |
| ... | ... | @@ -2246,7 +2202,7 @@ fn transSwitch( |
| 2246 | 2202 | switch_scope.pending_block = try Scope.Block.init(c, scope, false); |
| 2247 | 2203 | try switch_scope.pending_block.statements.append(Node.initPayload(&switch_node.base)); |
| 2248 | 2204 | |
| 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); |
| 2250 | 2206 | |
| 2251 | 2207 | // take all pending statements |
| 2252 | 2208 | const last_block_stmts = last.castTag(.block).?.data.stmts; |
| ... | ... | @@ -2264,13 +2220,14 @@ fn transSwitch( |
| 2264 | 2220 | switch_scope.pending_block.label = l; |
| 2265 | 2221 | } |
| 2266 | 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 | 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 | } |
| 2273 | 2229 | |
| 2230 | switch_node.data.cases = try c.arena.dupe(Node, switch_scope.cases.items); |
| 2274 | 2231 | const result_node = try switch_scope.pending_block.complete(c); |
| 2275 | 2232 | switch_scope.pending_block.deinit(); |
| 2276 | 2233 | return result_node; |
| ... | ... | @@ -2286,18 +2243,18 @@ fn transCase( |
| 2286 | 2243 | const label = try block_scope.makeMangledName(c, "case"); |
| 2287 | 2244 | |
| 2288 | 2245 | const expr = if (stmt.getRHS()) |rhs| blk: { |
| 2289 | | const lhs_node = try transExpr(c, scope, stmt.getLHS(), .used, .r_value); |
| 2290 | | const rhs_node = try transExpr(c, scope, rhs, .used, .r_value); |
| 2246 | const lhs_node = try transExpr(c, scope, stmt.getLHS(), .used); |
| 2247 | const rhs_node = try transExpr(c, scope, rhs, .used); |
| 2291 | 2248 | |
| 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 | 2250 | } else |
| 2294 | | try transExpr(c, scope, stmt.getLHS(), .used, .r_value); |
| 2251 | try transExpr(c, scope, stmt.getLHS(), .used); |
| 2295 | 2252 | |
| 2296 | | const switch_prong = try Node.switch_prong.create( |
| 2297 | | c.arena, |
| 2298 | | try Node.@"break".create(c.arena, label), |
| 2299 | | ); |
| 2300 | | switch_scope.cases.append(switch_prong); |
| 2253 | const switch_prong = try Tag.switch_prong.create(c.arena, .{ |
| 2254 | .lhs = expr, |
| 2255 | .rhs = try Tag.@"break".create(c.arena, label), |
| 2256 | }); |
| 2257 | try switch_scope.cases.append(switch_prong); |
| 2301 | 2258 | |
| 2302 | 2259 | switch_scope.pending_block.label = label; |
| 2303 | 2260 | |
| ... | ... | @@ -2311,7 +2268,7 @@ fn transCase( |
| 2311 | 2268 | |
| 2312 | 2269 | try switch_scope.pending_block.statements.append(pending_node); |
| 2313 | 2270 | |
| 2314 | | return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value); |
| 2271 | return transStmt(c, scope, stmt.getSubStmt(), .unused); |
| 2315 | 2272 | } |
| 2316 | 2273 | |
| 2317 | 2274 | fn transDefault( |
| ... | ... | @@ -2323,12 +2280,12 @@ fn transDefault( |
| 2323 | 2280 | const switch_scope = scope.getSwitch(); |
| 2324 | 2281 | switch_scope.default_label = try block_scope.makeMangledName(c, "default"); |
| 2325 | 2282 | |
| 2326 | | const else_prong = try Node.switch_else.create( |
| 2283 | const else_prong = try Tag.switch_else.create( |
| 2327 | 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); |
| 2331 | | switch_scope.pending_block.label = try appendIdentifier(c, switch_scope.default_label.?); |
| 2287 | try switch_scope.cases.append(else_prong); |
| 2288 | switch_scope.pending_block.label = switch_scope.default_label.?; |
| 2332 | 2289 | |
| 2333 | 2290 | // take all pending statements |
| 2334 | 2291 | try switch_scope.pending_block.statements.appendSlice(block_scope.statements.items); |
| ... | ... | @@ -2339,7 +2296,7 @@ fn transDefault( |
| 2339 | 2296 | switch_scope.pending_block = try Scope.Block.init(c, scope, false); |
| 2340 | 2297 | try switch_scope.pending_block.statements.append(pending_node); |
| 2341 | 2298 | |
| 2342 | | return transStmt(c, scope, stmt.getSubStmt(), .unused, .r_value); |
| 2299 | return transStmt(c, scope, stmt.getSubStmt(), .unused); |
| 2343 | 2300 | } |
| 2344 | 2301 | |
| 2345 | 2302 | fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: ResultUsed) TransError!Node { |
| ... | ... | @@ -2352,7 +2309,7 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: |
| 2352 | 2309 | // See comment in `transIntegerLiteral` for why this code is here. |
| 2353 | 2310 | // @as(T, x) |
| 2354 | 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 | 2313 | .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()), |
| 2357 | 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 | 2326 | } |
| 2370 | 2327 | |
| 2371 | 2328 | fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node { |
| 2372 | | return Node.char_literal.create(c.arena, if (narrow) |
| 2373 | | try std.fmt.bufPrint(c.arena, "'{}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})}) |
| 2329 | return Tag.char_literal.create(c.arena, if (narrow) |
| 2330 | try std.fmt.allocPrint(c.arena, "'{s}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})}) |
| 2374 | 2331 | else |
| 2375 | | try std.fmt.bufPrint(c.arena, "'\\u{{{x}}}'", .{val})); |
| 2332 | try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val})); |
| 2376 | 2333 | } |
| 2377 | 2334 | |
| 2378 | 2335 | fn transCharLiteral( |
| ... | ... | @@ -2398,7 +2355,7 @@ fn transCharLiteral( |
| 2398 | 2355 | // See comment in `transIntegerLiteral` for why this code is here. |
| 2399 | 2356 | // @as(T, x) |
| 2400 | 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 | 2359 | .lhs = try transQualType(c, expr_base.getType(), expr_base.getBeginLoc()), |
| 2403 | 2360 | .rhs = int_lit_node, |
| 2404 | 2361 | }); |
| ... | ... | @@ -2416,12 +2373,12 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: |
| 2416 | 2373 | var it = comp.body_begin(); |
| 2417 | 2374 | const end_it = comp.body_end(); |
| 2418 | 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 | 2377 | try block_scope.statements.append(result); |
| 2421 | 2378 | } |
| 2422 | | const break_node = try Node.break_val.create(c.arena, .{ |
| 2423 | | .label = block_scope.label, |
| 2424 | | .val = try transStmt(c, &block_scope.base, it[0], .used, .r_value), |
| 2379 | const break_node = try Tag.break_val.create(c.arena, .{ |
| 2380 | .label = block_scope.label, |
| 2381 | .val = try transStmt(c, &block_scope.base, it[0], .used), |
| 2425 | 2382 | }); |
| 2426 | 2383 | try block_scope.statements.append(break_node); |
| 2427 | 2384 | const res = try block_scope.complete(c); |
| ... | ... | @@ -2429,10 +2386,10 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: |
| 2429 | 2386 | } |
| 2430 | 2387 | |
| 2431 | 2388 | fn 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); |
| 2433 | 2390 | |
| 2434 | 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 | } |
| 2437 | 2394 | |
| 2438 | 2395 | const member_decl = stmt.getMemberDecl(); |
| ... | ... | @@ -2450,9 +2407,9 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re |
| 2450 | 2407 | const decl = @ptrCast(*const clang.NamedDecl, member_decl); |
| 2451 | 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); |
| 2454 | 2411 | |
| 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 | 2413 | return maybeSuppressResult(c, scope, result_used, node); |
| 2457 | 2414 | } |
| 2458 | 2415 | |
| ... | ... | @@ -2469,7 +2426,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip |
| 2469 | 2426 | } |
| 2470 | 2427 | } |
| 2471 | 2428 | |
| 2472 | | const container_node = try transExpr(c, scope, base_stmt, .used, .r_value); |
| 2429 | const container_node = try transExpr(c, scope, base_stmt, .used); |
| 2473 | 2430 | |
| 2474 | 2431 | // cast if the index is long long or signed |
| 2475 | 2432 | const subscr_expr = stmt.getIdx(); |
| ... | ... | @@ -2477,14 +2434,17 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip |
| 2477 | 2434 | const is_longlong = cIsLongLongInteger(qt); |
| 2478 | 2435 | const is_signed = cIsSignedInteger(qt); |
| 2479 | 2436 | |
| 2480 | | |
| 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); |
| 2437 | const rhs = if (is_longlong or is_signed) blk: { |
| 2483 | 2438 | // 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); |
| 2485 | | break :blk try Node.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used, .r_value)}); |
| 2439 | var typeid_node = if (is_longlong) try Tag.identifier.create(c.arena, "usize") else try transQualTypeIntWidthOf(c, qt, false); |
| 2440 | break :blk try Tag.int_cast.create(c.arena, .{ .lhs = typeid_node, .rhs = try transExpr(c, scope, subscr_expr, .used) }); |
| 2486 | 2441 | } 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 | 2448 | return maybeSuppressResult(c, scope, result_used, node); |
| 2489 | 2449 | } |
| 2490 | 2450 | |
| ... | ... | @@ -2522,23 +2482,23 @@ fn cIsFunctionDeclRef(expr: *const clang.Expr) bool { |
| 2522 | 2482 | |
| 2523 | 2483 | fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result_used: ResultUsed) TransError!Node { |
| 2524 | 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); |
| 2526 | 2486 | |
| 2527 | 2487 | var is_ptr = false; |
| 2528 | 2488 | const fn_ty = qualTypeGetFnProto(callee.getType(), &is_ptr); |
| 2529 | 2489 | |
| 2530 | 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 | 2492 | else |
| 2533 | 2493 | raw_fn_expr; |
| 2534 | 2494 | |
| 2535 | 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); |
| 2537 | 2497 | |
| 2538 | | const args = stmt.getArgs(); |
| 2498 | const c_args = stmt.getArgs(); |
| 2539 | 2499 | var i: usize = 0; |
| 2540 | 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); |
| 2542 | 2502 | |
| 2543 | 2503 | // In C the result type of a boolean expression is int. If this result is passed as |
| 2544 | 2504 | // 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 | 2509 | const param_count = fn_proto.getNumParams(); |
| 2550 | 2510 | if (i < param_count) { |
| 2551 | 2511 | const param_qt = fn_proto.getParamType(@intCast(c_uint, i)); |
| 2552 | | if (isBoolRes(call_param) and cIsNativeInt(param_qt)) { |
| 2553 | | call_param = try Node.bool_to_int.create(c.arena, call_param); |
| 2512 | if (isBoolRes(arg) and cIsNativeInt(param_qt)) { |
| 2513 | arg = try Tag.bool_to_int.create(c.arena, arg); |
| 2554 | 2514 | } |
| 2555 | 2515 | } |
| 2556 | 2516 | }, |
| 2557 | 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 | 2523 | if (fn_ty) |ty| { |
| 2564 | 2524 | const canon = ty.getReturnType().getCanonicalType(); |
| 2565 | 2525 | const ret_ty = canon.getTypePtr(); |
| ... | ... | @@ -2609,17 +2569,17 @@ fn transUnaryExprOrTypeTraitExpr( |
| 2609 | 2569 | result_used: ResultUsed, |
| 2610 | 2570 | ) TransError!Node { |
| 2611 | 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); |
| 2613 | 2573 | |
| 2614 | 2574 | const kind = stmt.getKind(); |
| 2615 | 2575 | switch (kind) { |
| 2616 | | .SizeOf => return Node.sizeof.create(c.arena, type_node), |
| 2617 | | .AlignOf => return Node.alignof.create(c.arena, type_node), |
| 2576 | .SizeOf => return Tag.sizeof.create(c.arena, type_node), |
| 2577 | .AlignOf => return Tag.alignof.create(c.arena, type_node), |
| 2618 | 2578 | .PreferredAlignOf, |
| 2619 | 2579 | .VecStep, |
| 2620 | 2580 | .OpenMPRequiredSimdAlign, |
| 2621 | | => return revertAndWarn( |
| 2622 | | rp, |
| 2581 | => return fail( |
| 2582 | c, |
| 2623 | 2583 | error.UnsupportedTranslation, |
| 2624 | 2584 | loc, |
| 2625 | 2585 | "Unsupported type trait kind {}", |
| ... | ... | @@ -2642,53 +2602,54 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat |
| 2642 | 2602 | const op_expr = stmt.getSubExpr(); |
| 2643 | 2603 | switch (stmt.getOpcode()) { |
| 2644 | 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 | 2606 | else |
| 2647 | | return transCreatePostCrement(c, scope, stmt, .assign_add, used), |
| 2607 | return transCreatePostCrement(c, scope, stmt, .add_assign, used), |
| 2648 | 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 | 2610 | else |
| 2651 | | return transCreatePostCrement(c, scope, stmt, .assign_sub, used), |
| 2611 | return transCreatePostCrement(c, scope, stmt, .sub_assign, used), |
| 2652 | 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 | 2614 | else |
| 2655 | | return transCreatePreCrement(c, scope, stmt, .assign_add, used), |
| 2615 | return transCreatePreCrement(c, scope, stmt, .add_assign, used), |
| 2656 | 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 | 2618 | else |
| 2659 | | return transCreatePreCrement(c, scope, stmt, .assign_sub, used), |
| 2619 | return transCreatePreCrement(c, scope, stmt, .sub_assign, used), |
| 2660 | 2620 | .AddrOf => { |
| 2661 | 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 | 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 | 2628 | var is_ptr = false; |
| 2669 | 2629 | const fn_ty = qualTypeGetFnProto(op_expr.getType(), &is_ptr); |
| 2670 | 2630 | if (fn_ty != null and is_ptr) |
| 2671 | 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 | 2636 | .Minus => { |
| 2676 | 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 | 2639 | } else if (cIsUnsignedInteger(op_expr.getType())) { |
| 2679 | 2640 | // 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 | 2642 | } else |
| 2682 | 2643 | return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "C negation with non float non integer", .{}); |
| 2683 | 2644 | }, |
| 2684 | 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 | 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 | 2651 | .Extension => { |
| 2691 | | return transExpr(c, scope, stmt.getSubExpr(), used, .l_value); |
| 2652 | return transExpr(c, scope, stmt.getSubExpr(), used); |
| 2692 | 2653 | }, |
| 2693 | 2654 | else => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported C translation {}", .{stmt.getOpcode()}), |
| 2694 | 2655 | } |
| ... | ... | @@ -2698,7 +2659,7 @@ fn transCreatePreCrement( |
| 2698 | 2659 | c: *Context, |
| 2699 | 2660 | scope: *Scope, |
| 2700 | 2661 | stmt: *const clang.UnaryOperator, |
| 2701 | | op: Node.Tag, |
| 2662 | op: Tag, |
| 2702 | 2663 | used: ResultUsed, |
| 2703 | 2664 | ) TransError!Node { |
| 2704 | 2665 | const op_expr = stmt.getSubExpr(); |
| ... | ... | @@ -2707,8 +2668,8 @@ fn transCreatePreCrement( |
| 2707 | 2668 | // common case |
| 2708 | 2669 | // c: ++expr |
| 2709 | 2670 | // zig: expr += 1 |
| 2710 | | const lhs = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2711 | | const rhs = Node.one_literal.init(); |
| 2671 | const lhs = try transExpr(c, scope, op_expr, .used); |
| 2672 | const rhs = Tag.one_literal.init(); |
| 2712 | 2673 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used); |
| 2713 | 2674 | } |
| 2714 | 2675 | // worst case |
| ... | ... | @@ -2722,17 +2683,17 @@ fn transCreatePreCrement( |
| 2722 | 2683 | defer block_scope.deinit(); |
| 2723 | 2684 | const ref = try block_scope.makeMangledName(c, "ref"); |
| 2724 | 2685 | |
| 2725 | | const expr = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2726 | | const addr_of = try Node.address_of.create(c.arena, expr); |
| 2727 | | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of}); |
| 2686 | const expr = try transExpr(c, scope, op_expr, .used); |
| 2687 | const addr_of = try Tag.address_of.create(c.arena, expr); |
| 2688 | const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of }); |
| 2728 | 2689 | try block_scope.statements.append(ref_decl); |
| 2729 | 2690 | |
| 2730 | | const lhs_node = try Node.identifier.create(c.arena, ref); |
| 2731 | | const ref_node = try Node.deref.create(c.arena, lhs_node); |
| 2732 | | const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Node.one_literal.init(), .used); |
| 2691 | const lhs_node = try Tag.identifier.create(c.arena, ref); |
| 2692 | const ref_node = try Tag.deref.create(c.arena, lhs_node); |
| 2693 | const node = try transCreateNodeInfixOp(c, scope, op, ref_node, Tag.one_literal.init(), .used); |
| 2733 | 2694 | try block_scope.statements.append(node); |
| 2734 | 2695 | |
| 2735 | | const break_node = try Node.break_val.create(c.arena, .{ |
| 2696 | const break_node = try Tag.break_val.create(c.arena, .{ |
| 2736 | 2697 | .label = block_scope.label, |
| 2737 | 2698 | .val = ref_node, |
| 2738 | 2699 | }); |
| ... | ... | @@ -2744,7 +2705,7 @@ fn transCreatePostCrement( |
| 2744 | 2705 | c: *Context, |
| 2745 | 2706 | scope: *Scope, |
| 2746 | 2707 | stmt: *const clang.UnaryOperator, |
| 2747 | | op: Node.Tag, |
| 2708 | op: Tag, |
| 2748 | 2709 | used: ResultUsed, |
| 2749 | 2710 | ) TransError!Node { |
| 2750 | 2711 | const op_expr = stmt.getSubExpr(); |
| ... | ... | @@ -2753,8 +2714,8 @@ fn transCreatePostCrement( |
| 2753 | 2714 | // common case |
| 2754 | 2715 | // c: expr++ |
| 2755 | 2716 | // zig: expr += 1 |
| 2756 | | const lhs = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2757 | | const rhs = Node.one_literal.init(); |
| 2717 | const lhs = try transExpr(c, scope, op_expr, .used); |
| 2718 | const rhs = Tag.one_literal.init(); |
| 2758 | 2719 | return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used); |
| 2759 | 2720 | } |
| 2760 | 2721 | // worst case |
| ... | ... | @@ -2769,24 +2730,24 @@ fn transCreatePostCrement( |
| 2769 | 2730 | defer block_scope.deinit(); |
| 2770 | 2731 | const ref = try block_scope.makeMangledName(c, "ref"); |
| 2771 | 2732 | |
| 2772 | | const expr = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2773 | | const addr_of = try Node.address_of.create(c.arena, expr); |
| 2774 | | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of}); |
| 2733 | const expr = try transExpr(c, scope, op_expr, .used); |
| 2734 | const addr_of = try Tag.address_of.create(c.arena, expr); |
| 2735 | const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of }); |
| 2775 | 2736 | try block_scope.statements.append(ref_decl); |
| 2776 | 2737 | |
| 2777 | | const lhs_node = try Node.identifier.create(c.arena, ref); |
| 2778 | | const ref_node = try Node.deref.create(c.arena, lhs_node); |
| 2738 | const lhs_node = try Tag.identifier.create(c.arena, ref); |
| 2739 | const ref_node = try Tag.deref.create(c.arena, lhs_node); |
| 2779 | 2740 | |
| 2780 | 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 | 2743 | try block_scope.statements.append(tmp_decl); |
| 2783 | 2744 | |
| 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 | 2746 | try block_scope.statements.append(node); |
| 2786 | 2747 | |
| 2787 | | const break_node = try Node.break_val.create(c.arena, .{ |
| 2748 | const break_node = try Tag.break_val.create(c.arena, .{ |
| 2788 | 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 | 2752 | try block_scope.statements.append(break_node); |
| 2792 | 2753 | return block_scope.complete(c); |
| ... | ... | @@ -2795,26 +2756,26 @@ fn transCreatePostCrement( |
| 2795 | 2756 | fn transCompoundAssignOperator(c: *Context, scope: *Scope, stmt: *const clang.CompoundAssignOperator, used: ResultUsed) TransError!Node { |
| 2796 | 2757 | switch (stmt.getOpcode()) { |
| 2797 | 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 | 2760 | else |
| 2800 | | return transCreateCompoundAssign(c, scope, stmt, .assign_mul, used), |
| 2761 | return transCreateCompoundAssign(c, scope, stmt, .mul_assign, used), |
| 2801 | 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 | 2764 | else |
| 2804 | | return transCreateCompoundAssign(c, scope, stmt, .assign_add, used), |
| 2765 | return transCreateCompoundAssign(c, scope, stmt, .add_assign, used), |
| 2805 | 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 | 2768 | else |
| 2808 | | return transCreateCompoundAssign(c, scope, stmt, .assign_sub, used), |
| 2809 | | .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_div, used), |
| 2810 | | .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_mod, used), |
| 2811 | | .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shl, used), |
| 2812 | | .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_shr, used), |
| 2813 | | .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_and, used), |
| 2814 | | .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_xor, used), |
| 2815 | | .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .assign_bit_or, used), |
| 2769 | return transCreateCompoundAssign(c, scope, stmt, .sub_assign, used), |
| 2770 | .DivAssign => return transCreateCompoundAssign(c, scope, stmt, .div_assign, used), |
| 2771 | .RemAssign => return transCreateCompoundAssign(c, scope, stmt, .mod_assign, used), |
| 2772 | .ShlAssign => return transCreateCompoundAssign(c, scope, stmt, .shl_assign, used), |
| 2773 | .ShrAssign => return transCreateCompoundAssign(c, scope, stmt, .shr_assign, used), |
| 2774 | .AndAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_and_assign, used), |
| 2775 | .XorAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_xor_assign, used), |
| 2776 | .OrAssign => return transCreateCompoundAssign(c, scope, stmt, .bit_or_assign, used), |
| 2816 | 2777 | else => return fail( |
| 2817 | | rp, |
| 2778 | c, |
| 2818 | 2779 | error.UnsupportedTranslation, |
| 2819 | 2780 | stmt.getBeginLoc(), |
| 2820 | 2781 | "unsupported C translation {}", |
| ... | ... | @@ -2827,12 +2788,12 @@ fn transCreateCompoundAssign( |
| 2827 | 2788 | c: *Context, |
| 2828 | 2789 | scope: *Scope, |
| 2829 | 2790 | stmt: *const clang.CompoundAssignOperator, |
| 2830 | | op: Node.Tag, |
| 2791 | op: Tag, |
| 2831 | 2792 | used: ResultUsed, |
| 2832 | 2793 | ) TransError!Node { |
| 2833 | | const is_shift = op == .assign_shl or op == .assign_shr; |
| 2834 | | const is_div = op == .assign_div; |
| 2835 | | const is_mod = op == .assign_mod; |
| 2794 | const is_shift = op == .shl_assign or op == .shr_assign; |
| 2795 | const is_div = op == .div_assign; |
| 2796 | const is_mod = op == .mod_assign; |
| 2836 | 2797 | const lhs = stmt.getLHS(); |
| 2837 | 2798 | const rhs = stmt.getRHS(); |
| 2838 | 2799 | const loc = stmt.getBeginLoc(); |
| ... | ... | @@ -2849,21 +2810,21 @@ fn transCreateCompoundAssign( |
| 2849 | 2810 | // c: lhs += rhs |
| 2850 | 2811 | // zig: lhs += rhs |
| 2851 | 2812 | if ((is_mod or is_div) and is_signed) { |
| 2852 | | const lhs_node = try transExpr(c, scope, lhs, .used, .l_value); |
| 2853 | | const rhs_node = try transExpr(c, scope, rhs, .used, .r_value); |
| 2813 | const lhs_node = try transExpr(c, scope, lhs, .used); |
| 2814 | const rhs_node = try transExpr(c, scope, rhs, .used); |
| 2854 | 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 | 2817 | 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 }); |
| 2858 | 2819 | |
| 2859 | 2820 | return transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used); |
| 2860 | 2821 | } |
| 2861 | 2822 | |
| 2862 | | const lhs_node = try transExpr(c, scope, lhs, .used, .l_value); |
| 2823 | const lhs_node = try transExpr(c, scope, lhs, .used); |
| 2863 | 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 | 2826 | else |
| 2866 | | try transExpr(c, scope, rhs, .used, .r_value); |
| 2827 | try transExpr(c, scope, rhs, .used); |
| 2867 | 2828 | |
| 2868 | 2829 | if (is_shift or requires_int_cast) { |
| 2869 | 2830 | // @intCast(rhs) |
| ... | ... | @@ -2871,11 +2832,11 @@ fn transCreateCompoundAssign( |
| 2871 | 2832 | try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc) |
| 2872 | 2833 | else |
| 2873 | 2834 | try transQualType(c, getExprQualType(c, lhs), loc); |
| 2874 | | |
| 2875 | | rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 2835 | |
| 2836 | rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 2876 | 2837 | } |
| 2877 | 2838 | |
| 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 | 2841 | // worst case |
| 2881 | 2842 | // c: lhs += rhs |
| ... | ... | @@ -2888,25 +2849,25 @@ fn transCreateCompoundAssign( |
| 2888 | 2849 | defer block_scope.deinit(); |
| 2889 | 2850 | const ref = try block_scope.makeMangledName(c, "ref"); |
| 2890 | 2851 | |
| 2891 | | const expr = try transExpr(c, scope, op_expr, .used, .r_value); |
| 2892 | | const addr_of = try Node.address_of.create(c.arena, expr); |
| 2893 | | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = ref, .init = addr_of}); |
| 2852 | const expr = try transExpr(c, scope, lhs, .used); |
| 2853 | const addr_of = try Tag.address_of.create(c.arena, expr); |
| 2854 | const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = ref, .init = addr_of }); |
| 2894 | 2855 | try block_scope.statements.append(ref_decl); |
| 2895 | 2856 | |
| 2896 | | const lhs_node = try Node.identifier.create(c.arena, ref); |
| 2897 | | const ref_node = try Node.deref.create(c.arena, lhs_node); |
| 2857 | const lhs_node = try Tag.identifier.create(c.arena, ref); |
| 2858 | const ref_node = try Tag.deref.create(c.arena, lhs_node); |
| 2898 | 2859 | |
| 2899 | 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 | 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 | 2864 | 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 }); |
| 2905 | 2866 | |
| 2906 | 2867 | const assign = try transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used); |
| 2907 | 2868 | try block_scope.statements.append(assign); |
| 2908 | 2869 | } else { |
| 2909 | | var rhs_node = try transExpr(c, scope, rhs, .used, .r_value); |
| 2870 | var rhs_node = try transExpr(c, scope, rhs, .used); |
| 2910 | 2871 | |
| 2911 | 2872 | if (is_shift or requires_int_cast) { |
| 2912 | 2873 | // @intCast(rhs) |
| ... | ... | @@ -2914,15 +2875,15 @@ fn transCreateCompoundAssign( |
| 2914 | 2875 | try qualTypeToLog2IntRef(c, getExprQualType(c, rhs), loc) |
| 2915 | 2876 | else |
| 2916 | 2877 | try transQualType(c, getExprQualType(c, lhs), loc); |
| 2917 | | |
| 2918 | | rhs_node = try Node.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 2878 | |
| 2879 | rhs_node = try Tag.int_cast.create(c.arena, .{ .lhs = cast_to_type, .rhs = rhs_node }); |
| 2919 | 2880 | } |
| 2920 | 2881 | |
| 2921 | 2882 | const assign = try transCreateNodeInfixOp(c, scope, op, ref_node, rhs_node, .used); |
| 2922 | 2883 | try block_scope.statements.append(assign); |
| 2923 | 2884 | } |
| 2924 | 2885 | |
| 2925 | | const break_node = try Node.break_val.create(c.arena, .{ |
| 2886 | const break_node = try Tag.break_val.create(c.arena, .{ |
| 2926 | 2887 | .label = block_scope.label, |
| 2927 | 2888 | .val = ref_node, |
| 2928 | 2889 | }); |
| ... | ... | @@ -2941,7 +2902,7 @@ fn transCPtrCast( |
| 2941 | 2902 | const child_type = ty.getPointeeType(); |
| 2942 | 2903 | const src_ty = src_type.getTypePtr(); |
| 2943 | 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); |
| 2945 | 2906 | |
| 2946 | 2907 | if ((src_child_type.isConstQualified() and |
| 2947 | 2908 | !child_type.isConstQualified()) or |
| ... | ... | @@ -2949,8 +2910,8 @@ fn transCPtrCast( |
| 2949 | 2910 | !child_type.isVolatileQualified())) |
| 2950 | 2911 | { |
| 2951 | 2912 | // Casting away const or volatile requires us to use @intToPtr |
| 2952 | | const ptr_to_int = try Node.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 }); |
| 2913 | const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr); |
| 2914 | const int_to_ptr = try Tag.int_to_ptr.create(c.arena, .{ .lhs = dst_type_node, .rhs = ptr_to_int }); |
| 2954 | 2915 | return int_to_ptr; |
| 2955 | 2916 | } else { |
| 2956 | 2917 | // Implicit downcasting from higher to lower alignment values is forbidden, |
| ... | ... | @@ -2963,17 +2924,17 @@ fn transCPtrCast( |
| 2963 | 2924 | expr |
| 2964 | 2925 | else blk: { |
| 2965 | 2926 | const child_type_node = try transQualType(c, child_type, loc); |
| 2966 | | const alignof = try Node.alignof.create(c.arena, child_type_node); |
| 2967 | | const align_cast = try Node.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr }); |
| 2927 | const alignof = try Tag.alignof.create(c.arena, child_type_node); |
| 2928 | const align_cast = try Tag.align_cast.create(c.arena, .{ .lhs = alignof, .rhs = expr }); |
| 2968 | 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 | } |
| 2973 | 2934 | |
| 2974 | 2935 | fn transBreak(c: *Context, scope: *Scope) TransError!Node { |
| 2975 | 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 | 2938 | const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope); |
| 2978 | 2939 | const block_scope = try scope.findBlockScope(c); |
| 2979 | 2940 | swtch.switch_label = try block_scope.makeMangledName(c, "switch"); |
| ... | ... | @@ -2981,20 +2942,20 @@ fn transBreak(c: *Context, scope: *Scope) TransError!Node { |
| 2981 | 2942 | } else |
| 2982 | 2943 | null; |
| 2983 | 2944 | |
| 2984 | | return Node.@"break".create(c.arena, label_text); |
| 2945 | return Tag.@"break".create(c.arena, label_text); |
| 2985 | 2946 | } |
| 2986 | 2947 | |
| 2987 | 2948 | fn transFloatingLiteral(c: *Context, scope: *Scope, stmt: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node { |
| 2988 | 2949 | // TODO use something more accurate |
| 2989 | 2950 | const dbl = stmt.getValueAsApproximateDouble(); |
| 2990 | 2951 | const node = try transCreateNodeNumber(c, dbl); |
| 2991 | | return maybeSuppressResult(c, scope, used, &node.base); |
| 2952 | return maybeSuppressResult(c, scope, used, node); |
| 2992 | 2953 | } |
| 2993 | 2954 | |
| 2994 | 2955 | fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node { |
| 2995 | 2956 | // GNU extension of the ternary operator where the middle expression is |
| 2996 | 2957 | // 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 | 2959 | const res_is_bool = qualTypeIsBoolean(qt); |
| 2999 | 2960 | const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt); |
| 3000 | 2961 | const cond_expr = casted_stmt.getCond(); |
| ... | ... | @@ -3010,26 +2971,33 @@ fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang |
| 3010 | 2971 | defer block_scope.deinit(); |
| 3011 | 2972 | |
| 3012 | 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); |
| 3014 | | const ref_decl = try Node.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node}); |
| 2974 | const init_node = try transExpr(c, &block_scope.base, cond_expr, .used); |
| 2975 | const ref_decl = try Tag.var_simple.create(c.arena, .{ .name = mangled_name, .init = init_node }); |
| 3015 | 2976 | try block_scope.statements.append(ref_decl); |
| 3016 | 2977 | |
| 2978 | var cond_scope = Scope.Condition{ |
| 2979 | .base = .{ |
| 2980 | .parent = &block_scope.base, |
| 2981 | .id = .condition, |
| 2982 | }, |
| 2983 | }; |
| 2984 | defer cond_scope.deinit(); |
| 3017 | 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 | 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 | } |
| 3022 | 2990 | |
| 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 | 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, .{ |
| 3028 | | .cond = cond, |
| 2995 | const if_node = try Tag.@"if".create(c.arena, .{ |
| 2996 | .cond = cond_node, |
| 3029 | 2997 | .then = then_body, |
| 3030 | 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 | 3001 | .label = block_scope.label, |
| 3034 | 3002 | .val = if_node, |
| 3035 | 3003 | }); |
| ... | ... | @@ -3042,31 +3010,31 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi |
| 3042 | 3010 | var cond_scope = Scope.Condition{ |
| 3043 | 3011 | .base = .{ |
| 3044 | 3012 | .parent = scope, |
| 3045 | | .id = .Condition, |
| 3013 | .id = .condition, |
| 3046 | 3014 | }, |
| 3047 | 3015 | }; |
| 3048 | 3016 | defer cond_scope.deinit(); |
| 3049 | 3017 | |
| 3050 | | const qt = @ptrCast(*const clang.Stmt, stmt).getType(); |
| 3018 | const qt = @ptrCast(*const clang.Expr, stmt).getType(); |
| 3051 | 3019 | const res_is_bool = qualTypeIsBoolean(qt); |
| 3052 | 3020 | const casted_stmt = @ptrCast(*const clang.AbstractConditionalOperator, stmt); |
| 3053 | 3021 | const cond_expr = casted_stmt.getCond(); |
| 3054 | 3022 | const true_expr = casted_stmt.getTrueExpr(); |
| 3055 | 3023 | const false_expr = casted_stmt.getFalseExpr(); |
| 3056 | 3024 | |
| 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); |
| 3058 | 3026 | |
| 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 | 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 | } |
| 3063 | 3031 | |
| 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 | 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 | } |
| 3068 | 3036 | |
| 3069 | | const if_node = try Node.@"if".create(c.arena, .{ |
| 3037 | const if_node = try Tag.@"if".create(c.arena, .{ |
| 3070 | 3038 | .cond = cond, |
| 3071 | 3039 | .then = then_body, |
| 3072 | 3040 | .@"else" = else_body, |
| ... | ... | @@ -3081,7 +3049,7 @@ fn maybeSuppressResult( |
| 3081 | 3049 | result: Node, |
| 3082 | 3050 | ) TransError!Node { |
| 3083 | 3051 | if (used == .used) return result; |
| 3084 | | return Node.ignore.create(c.arena, result); |
| 3052 | return Tag.ignore.create(c.arena, result); |
| 3085 | 3053 | } |
| 3086 | 3054 | |
| 3087 | 3055 | fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void { |
| ... | ... | @@ -3100,19 +3068,19 @@ fn transQualTypeInitialized( |
| 3100 | 3068 | const ty = qt.getTypePtr(); |
| 3101 | 3069 | if (ty.getTypeClass() == .IncompleteArray) { |
| 3102 | 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); |
| 3104 | 3072 | |
| 3105 | 3073 | switch (decl_init.getStmtClass()) { |
| 3106 | 3074 | .StringLiteralClass => { |
| 3107 | 3075 | const string_lit = @ptrCast(*const clang.StringLiteral, decl_init); |
| 3108 | 3076 | const string_lit_size = string_lit.getLength() + 1; // +1 for null terminator |
| 3109 | 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 | 3080 | .InitListExprClass => { |
| 3113 | 3081 | const init_expr = @ptrCast(*const clang.InitListExpr, decl_init); |
| 3114 | 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 | 3085 | else => {}, |
| 3118 | 3086 | } |
| ... | ... | @@ -3135,7 +3103,7 @@ fn transQualTypeIntWidthOf(c: *Context, ty: clang.QualType, is_signed: bool) Typ |
| 3135 | 3103 | fn transTypeIntWidthOf(c: *Context, ty: *const clang.Type, is_signed: bool) TypeError!Node { |
| 3136 | 3104 | assert(ty.getTypeClass() == .Builtin); |
| 3137 | 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 | 3107 | .Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8", |
| 3140 | 3108 | .UShort, .Short => if (is_signed) "c_short" else "c_ushort", |
| 3141 | 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 | 3182 | if (int_bit_width != 0) { |
| 3215 | 3183 | // we can perform the log2 now. |
| 3216 | 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 | } |
| 3219 | 3187 | |
| 3220 | 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 | } |
| 3223 | 3191 | |
| 3224 | 3192 | fn qualTypeChildIsFnProto(qt: clang.QualType) bool { |
| ... | ... | @@ -3392,10 +3360,10 @@ fn transCreateNodeAssign( |
| 3392 | 3360 | // c: lhs = rhs |
| 3393 | 3361 | // zig: lhs = rhs |
| 3394 | 3362 | if (result_used == .unused) { |
| 3395 | | const lhs_node = try transExpr(c, scope, lhs, .used, .l_value); |
| 3396 | | var rhs_node = try transExprCoercing(c, scope, rhs, .used, .r_value); |
| 3363 | const lhs_node = try transExpr(c, scope, lhs, .used); |
| 3364 | var rhs_node = try transExprCoercing(c, scope, rhs, .used); |
| 3397 | 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 | 3368 | return transCreateNodeInfixOp(c, scope, .assign, lhs_node, rhs_node, .used); |
| 3401 | 3369 | } |
| ... | ... | @@ -3411,17 +3379,16 @@ fn transCreateNodeAssign( |
| 3411 | 3379 | defer block_scope.deinit(); |
| 3412 | 3380 | |
| 3413 | 3381 | const tmp = try block_scope.makeMangledName(c, "tmp"); |
| 3414 | | const rhs = try transExpr(c, scope, op_expr, .used, .r_value); |
| 3415 | | const tmp_decl = try Node.var_simple.create(c.arena, .{ .name = tmp, .init = rhs}); |
| 3382 | const rhs_node = try transExpr(c, scope, rhs, .used); |
| 3383 | const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = rhs_node }); |
| 3416 | 3384 | try block_scope.statements.append(tmp_decl); |
| 3417 | 3385 | |
| 3418 | | |
| 3419 | | const lhs = try transExpr(c, &block_scope.base, lhs, .used, .l_value); |
| 3420 | | const tmp_ident = try Node.identifier.create(c.arena, tmp); |
| 3421 | | const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs, tmp_iden, .used); |
| 3386 | const lhs_node = try transExpr(c, &block_scope.base, lhs, .used); |
| 3387 | const tmp_ident = try Tag.identifier.create(c.arena, tmp); |
| 3388 | const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs_node, tmp_ident, .used); |
| 3422 | 3389 | try block_scope.statements.append(assign); |
| 3423 | 3390 | |
| 3424 | | const break_node = try Node.break_val.create(c.arena, .{ |
| 3391 | const break_node = try Tag.break_val.create(c.arena, .{ |
| 3425 | 3392 | .label = block_scope.label, |
| 3426 | 3393 | .val = tmp_ident, |
| 3427 | 3394 | }); |
| ... | ... | @@ -3432,7 +3399,7 @@ fn transCreateNodeAssign( |
| 3432 | 3399 | fn transCreateNodeInfixOp( |
| 3433 | 3400 | c: *Context, |
| 3434 | 3401 | scope: *Scope, |
| 3435 | | op: ast.Node.Tag, |
| 3402 | op: Tag, |
| 3436 | 3403 | lhs: Node, |
| 3437 | 3404 | rhs: Node, |
| 3438 | 3405 | used: ResultUsed, |
| ... | ... | @@ -3452,13 +3419,13 @@ fn transCreateNodeBoolInfixOp( |
| 3452 | 3419 | c: *Context, |
| 3453 | 3420 | scope: *Scope, |
| 3454 | 3421 | stmt: *const clang.BinaryOperator, |
| 3455 | | op: ast.Node.Tag, |
| 3422 | op: Tag, |
| 3456 | 3423 | used: ResultUsed, |
| 3457 | 3424 | ) !Node { |
| 3458 | | std.debug.assert(op == .bool_and or op == .bool_or); |
| 3425 | std.debug.assert(op == .@"and" or op == .@"or"); |
| 3459 | 3426 | |
| 3460 | | const lhs = try transBoolExpr(rp, scope, stmt.getLHS(), .used, .l_value); |
| 3461 | | const rhs = try transBoolExpr(rp, scope, stmt.getRHS(), .used, .r_value); |
| 3427 | const lhs = try transBoolExpr(c, scope, stmt.getLHS(), .used); |
| 3428 | const rhs = try transBoolExpr(c, scope, stmt.getRHS(), .used); |
| 3462 | 3429 | |
| 3463 | 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 | 3470 | const str = big.toStringAlloc(c.arena, 10, false) catch |err| switch (err) { |
| 3504 | 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 | } |
| 3508 | 3475 | |
| 3509 | 3476 | fn transCreateNodeNumber(c: *Context, int: anytype) !Node { |
| 3510 | 3477 | const fmt_s = if (comptime std.meta.trait.isNumber(@TypeOf(int))) "{d}" else "{s}"; |
| 3511 | 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 | } |
| 3514 | 3481 | |
| 3515 | 3482 | fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: *ast.Payload.Func) !Node { |
| 3516 | 3483 | const scope = &c.global_scope.base; |
| 3517 | 3484 | |
| 3518 | | var fn_params = std.ArrayList(Node).init(c.gpa); |
| 3485 | var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa); |
| 3519 | 3486 | defer fn_params.deinit(); |
| 3520 | 3487 | |
| 3521 | | for (proto_alias.params()) |param, i| { |
| 3488 | for (proto_alias.data.params) |param, i| { |
| 3522 | 3489 | const param_name = param.name orelse |
| 3523 | 3490 | try std.fmt.allocPrint(c.arena, "arg_{d}", .{c.getMangle()}); |
| 3524 | 3491 | |
| ... | ... | @@ -3529,29 +3496,29 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: Node, proto_alias: |
| 3529 | 3496 | }); |
| 3530 | 3497 | } |
| 3531 | 3498 | |
| 3532 | | const init = if (value.castTag(.var_decl)) |v| |
| 3533 | | v.data.init |
| 3534 | | else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v| |
| 3499 | const init = if (ref.castTag(.var_decl)) |v| |
| 3500 | v.data.init.? |
| 3501 | else if (ref.castTag(.var_simple) orelse ref.castTag(.pub_var_simple)) |v| |
| 3535 | 3502 | v.data.init |
| 3536 | 3503 | else |
| 3537 | 3504 | unreachable; |
| 3538 | 3505 | |
| 3539 | | const unwrap_expr = try Node.unwrap.create(c.arena, init); |
| 3540 | | const call_params = try c.arena.alloc(Node, fn_params.items.len); |
| 3506 | const unwrap_expr = try Tag.unwrap.create(c.arena, init); |
| 3507 | const args = try c.arena.alloc(Node, fn_params.items.len); |
| 3541 | 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 | 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); |
| 3549 | | const block = try Node.block_single.create(c.arean, return_expr); |
| 3515 | const return_expr = try Tag.@"return".create(c.arena, call_expr); |
| 3516 | const block = try Tag.block_single.create(c.arena, return_expr); |
| 3550 | 3517 | |
| 3551 | | return Node.pub_inline_fn.create(c.arena, .{ |
| 3518 | return Tag.pub_inline_fn.create(c.arena, .{ |
| 3552 | 3519 | .name = name, |
| 3553 | | .params = try c.arena.dupe(ast.Node.Param, fn_params.items), |
| 3554 | | .return_type = proto_alias.return_type, |
| 3520 | .params = try c.arena.dupe(ast.Payload.Param, fn_params.items), |
| 3521 | .return_type = proto_alias.data.return_type, |
| 3555 | 3522 | .body = block, |
| 3556 | 3523 | }); |
| 3557 | 3524 | } |
| ... | ... | @@ -3560,7 +3527,7 @@ fn transCreateNodeShiftOp( |
| 3560 | 3527 | c: *Context, |
| 3561 | 3528 | scope: *Scope, |
| 3562 | 3529 | stmt: *const clang.BinaryOperator, |
| 3563 | | op: Node.Tag, |
| 3530 | op: Tag, |
| 3564 | 3531 | used: ResultUsed, |
| 3565 | 3532 | ) !Node { |
| 3566 | 3533 | std.debug.assert(op == .shl or op == .shr); |
| ... | ... | @@ -3570,11 +3537,11 @@ fn transCreateNodeShiftOp( |
| 3570 | 3537 | const rhs_location = rhs_expr.getBeginLoc(); |
| 3571 | 3538 | // lhs >> @as(u5, rh) |
| 3572 | 3539 | |
| 3573 | | const lhs = try transExpr(c, scope, lhs_expr, .used, .l_value); |
| 3540 | const lhs = try transExpr(c, scope, lhs_expr, .used); |
| 3574 | 3541 | |
| 3575 | 3542 | const rhs_type = try qualTypeToLog2IntRef(c, stmt.getType(), rhs_location); |
| 3576 | | const rhs = try transExprCoercing(c, scope, rhs_expr, .used, .r_value); |
| 3577 | | const rhs_casted = try Node.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type }); |
| 3543 | const rhs = try transExprCoercing(c, scope, rhs_expr, .used); |
| 3544 | const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs_type }); |
| 3578 | 3545 | |
| 3579 | 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 | 3550 | switch (ty.getTypeClass()) { |
| 3584 | 3551 | .Builtin => { |
| 3585 | 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 | 3554 | .Void => "c_void", |
| 3588 | 3555 | .Bool => "bool", |
| 3589 | 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 | 3575 | }, |
| 3609 | 3576 | .FunctionProto => { |
| 3610 | 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 | 3581 | .FunctionNoProto => { |
| 3614 | 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 | 3586 | .Paren => { |
| 3618 | 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 | 3590 | .Pointer => { |
| 3622 | 3591 | const child_qt = ty.getPointeeType(); |
| 3623 | 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 | 3595 | const is_const = child_qt.isConstQualified(); |
| 3627 | 3596 | const is_volatile = child_qt.isVolatileQualified(); |
| 3628 | 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)) { |
| 3630 | | return Node.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type }); |
| 3598 | if (typeIsOpaque(c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(c, child_qt)) { |
| 3599 | return Tag.single_pointer.create(c.arena, .{ .is_const = is_const, .is_volatile = is_volatile, .elem_type = elem_type }); |
| 3631 | 3600 | } |
| 3632 | 3601 | |
| 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 | 3604 | .ConstantArray => { |
| 3636 | 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 | 3608 | const size = size_ap_int.getLimitedValue(math.maxInt(usize)); |
| 3640 | 3609 | const elem_type = try transType(c, const_arr_ty.getElementType().getTypePtr(), source_loc); |
| 3641 | 3610 | |
| 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 | 3613 | .IncompleteArray => { |
| 3645 | 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 | 3618 | const is_volatile = child_qt.isVolatileQualified(); |
| 3650 | 3619 | const elem_type = try transQualType(c, child_qt, source_loc); |
| 3651 | 3620 | |
| 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 | 3623 | .Typedef => { |
| 3655 | 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 | 3659 | }, |
| 3691 | 3660 | else => { |
| 3692 | 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 | 3739 | .AAPCS => return CallingConvention.AAPCS, |
| 3771 | 3740 | .AAPCS_VFP => return CallingConvention.AAPCSVFP, |
| 3772 | 3741 | else => return fail( |
| 3773 | | rp, |
| 3742 | c, |
| 3774 | 3743 | error.UnsupportedType, |
| 3775 | 3744 | source_loc, |
| 3776 | 3745 | "unsupported calling convention: {s}", |
| ... | ... | @@ -3786,7 +3755,7 @@ fn transFnProto( |
| 3786 | 3755 | source_loc: clang.SourceLocation, |
| 3787 | 3756 | fn_decl_context: ?FnDeclContext, |
| 3788 | 3757 | is_pub: bool, |
| 3789 | | ) !Node.FnProto { |
| 3758 | ) !*ast.Payload.Func { |
| 3790 | 3759 | const fn_ty = @ptrCast(*const clang.FunctionType, fn_proto_ty); |
| 3791 | 3760 | const cc = try transCC(c, fn_ty, source_loc); |
| 3792 | 3761 | const is_var_args = fn_proto_ty.isVariadic(); |
| ... | ... | @@ -3799,7 +3768,7 @@ fn transFnNoProto( |
| 3799 | 3768 | source_loc: clang.SourceLocation, |
| 3800 | 3769 | fn_decl_context: ?FnDeclContext, |
| 3801 | 3770 | is_pub: bool, |
| 3802 | | ) !Node.FnProto { |
| 3771 | ) !*ast.Payload.Func { |
| 3803 | 3772 | const cc = try transCC(c, fn_ty, source_loc); |
| 3804 | 3773 | const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static) else true; |
| 3805 | 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 | 3791 | // TODO check for always_inline attribute |
| 3823 | 3792 | // TODO check for align attribute |
| 3824 | 3793 | |
| 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 | 3795 | defer fn_params.deinit(); |
| 3827 | 3796 | const param_count: usize = if (fn_proto_ty != null) fn_proto_ty.?.getNumParams() else 0; |
| 3828 | 3797 | try fn_params.ensureCapacity(param_count); |
| ... | ... | @@ -3861,7 +3830,7 @@ fn finishTransFnProto( |
| 3861 | 3830 | break :blk null; |
| 3862 | 3831 | }; |
| 3863 | 3832 | |
| 3864 | | const alignment: c_uint = blk: { |
| 3833 | const alignment = blk: { |
| 3865 | 3834 | if (fn_decl) |decl| { |
| 3866 | 3835 | const alignment = decl.getAlignedAttribute(c.clang_context); |
| 3867 | 3836 | if (alignment != 0) { |
| ... | ... | @@ -3876,16 +3845,16 @@ fn finishTransFnProto( |
| 3876 | 3845 | |
| 3877 | 3846 | const return_type_node = blk: { |
| 3878 | 3847 | if (fn_ty.getNoReturnAttr()) { |
| 3879 | | break :blk Node.noreturn_type.init(); |
| 3848 | break :blk Tag.noreturn_type.init(); |
| 3880 | 3849 | } else { |
| 3881 | 3850 | const return_qt = fn_ty.getReturnType(); |
| 3882 | 3851 | if (isCVoid(return_qt)) { |
| 3883 | 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 | 3854 | } else { |
| 3886 | 3855 | break :blk transQualType(c, return_qt, source_loc) catch |err| switch (err) { |
| 3887 | 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 | 3858 | return err; |
| 3890 | 3859 | }, |
| 3891 | 3860 | error.OutOfMemory => |e| return e, |
| ... | ... | @@ -3893,26 +3862,31 @@ fn finishTransFnProto( |
| 3893 | 3862 | } |
| 3894 | 3863 | } |
| 3895 | 3864 | }; |
| 3896 | | |
| 3897 | | return Node.func.create(c.arena, .{ |
| 3898 | | .is_pub = is_pub, |
| 3899 | | .is_extern = is_extern, |
| 3900 | | .is_export = is_export, |
| 3901 | | .is_var_args = is_var_args, |
| 3902 | | .name = name, |
| 3903 | | .linksection_string = linksection_string, |
| 3904 | | .explicit_callconv = explicit_callconv, |
| 3905 | | .params = try c.arena.dupe(ast.Payload.Func.Param, fn_params.items), |
| 3906 | | .return_type = return_node, |
| 3907 | | .body = null, |
| 3908 | | .alignment = alignment, |
| 3909 | | }); |
| 3865 | const name: ?[]const u8 = if (fn_decl_context) |ctx| ctx.fn_name else null; |
| 3866 | const payload = try c.arena.create(ast.Payload.Func); |
| 3867 | payload.* = .{ |
| 3868 | .base = .{ .tag = .func }, |
| 3869 | .data = .{ |
| 3870 | .is_pub = is_pub, |
| 3871 | .is_extern = is_extern, |
| 3872 | .is_export = is_export, |
| 3873 | .is_var_args = is_var_args, |
| 3874 | .name = name, |
| 3875 | .linksection_string = linksection_string, |
| 3876 | .explicit_callconv = explicit_callconv, |
| 3877 | .params = try c.arena.dupe(ast.Payload.Param, fn_params.items), |
| 3878 | .return_type = return_type_node, |
| 3879 | .body = null, |
| 3880 | .alignment = alignment, |
| 3881 | }, |
| 3882 | }; |
| 3883 | return payload; |
| 3910 | 3884 | } |
| 3911 | 3885 | |
| 3912 | 3886 | fn warn(c: *Context, scope: *Scope, loc: clang.SourceLocation, comptime format: []const u8, args: anytype) !void { |
| 3913 | 3887 | const args_prefix = .{c.locStr(loc)}; |
| 3914 | | const value = std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args); |
| 3915 | | try scope.appendNode(c.gpa, try Node.warning.create(c.arena, value)); |
| 3888 | const value = try std.fmt.allocPrint(c.arena, "// {s}: warning: " ++ format, args_prefix ++ args); |
| 3889 | try scope.appendNode(try Tag.warning.create(c.arena, value)); |
| 3916 | 3890 | } |
| 3917 | 3891 | |
| 3918 | 3892 | fn fail( |
| ... | ... | @@ -3922,17 +3896,17 @@ fn fail( |
| 3922 | 3896 | comptime format: []const u8, |
| 3923 | 3897 | args: anytype, |
| 3924 | 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 | 3900 | return err; |
| 3927 | 3901 | } |
| 3928 | 3902 | |
| 3929 | | pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, comptime format: []const u8, args: anytype) !void { |
| 3903 | pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, comptime format: []const u8, args: anytype) Error!void { |
| 3930 | 3904 | // location |
| 3931 | 3905 | // pub const name = @compileError(msg); |
| 3932 | | const location_comment = std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)}); |
| 3933 | | try c.global_scope.nodes.append(try Node.warning.create(c.arena, location_comment)); |
| 3934 | | const fail_msg = std.fmt.allocPrint(c.arena, format, args); |
| 3935 | | try c.global_scope.nodes.append(try Node.fail_decl.create(c.arena, fail_msg)); |
| 3906 | const location_comment = try std.fmt.allocPrint(c.arena, "// {s}", .{c.locStr(loc)}); |
| 3907 | try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment)); |
| 3908 | const fail_msg = try std.fmt.allocPrint(c.arena, format, args); |
| 3909 | try c.global_scope.nodes.append(try Tag.fail_decl.create(c.arena, fail_msg)); |
| 3936 | 3910 | } |
| 3937 | 3911 | |
| 3938 | 3912 | pub fn freeErrors(errors: []ClangErrMsg) void { |
| ... | ... | @@ -4075,7 +4049,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4075 | 4049 | if (last != .Eof and last != .Nl) |
| 4076 | 4050 | return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)}); |
| 4077 | 4051 | |
| 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 | 4053 | _ = try c.global_scope.macro_table.put(m.name, var_decl); |
| 4080 | 4054 | } |
| 4081 | 4055 | |
| ... | ... | @@ -4099,7 +4073,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4099 | 4073 | try fn_params.append(.{ |
| 4100 | 4074 | .is_noalias = false, |
| 4101 | 4075 | .name = mangled_name, |
| 4102 | | .type = Node.@"anytype".init(), |
| 4076 | .type = Tag.@"anytype".init(), |
| 4103 | 4077 | }); |
| 4104 | 4078 | |
| 4105 | 4079 | if (m.peek().? != .Comma) break; |
| ... | ... | @@ -4119,19 +4093,19 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4119 | 4093 | const stmts = some.data.stmts; |
| 4120 | 4094 | const blk_last = stmts[stmts.len - 1]; |
| 4121 | 4095 | const br = blk_last.castTag(.break_val).?; |
| 4122 | | break :blk br.data; |
| 4096 | break :blk br.data.val; |
| 4123 | 4097 | } else expr; |
| 4124 | | const typeof = try Node.typeof.create(c.arean, typeof_arg); |
| 4125 | | const return_expr = try Node.@"return".create(c.arena, expr); |
| 4126 | | try block_scope.statements.append(&return_expr.base); |
| 4127 | | |
| 4128 | | const fn_decl = try Node.pub_inline_fn.create(c.arena, .{ |
| 4098 | const typeof = try Tag.typeof.create(c.arena, typeof_arg); |
| 4099 | const return_expr = try Tag.@"return".create(c.arena, expr); |
| 4100 | try block_scope.statements.append(return_expr); |
| 4101 | |
| 4102 | const fn_decl = try Tag.pub_inline_fn.create(c.arena, .{ |
| 4129 | 4103 | .name = m.name, |
| 4130 | 4104 | .params = try c.arena.dupe(ast.Payload.Param, fn_params.items), |
| 4131 | 4105 | .return_type = typeof, |
| 4132 | 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 | } |
| 4136 | 4110 | |
| 4137 | 4111 | const ParseError = Error || error{ParseError}; |
| ... | ... | @@ -4149,7 +4123,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4149 | 4123 | var last = node; |
| 4150 | 4124 | while (true) { |
| 4151 | 4125 | // suppress result |
| 4152 | | const ignore = try Node.ignore.create(c.arena, last); |
| 4126 | const ignore = try Tag.ignore.create(c.arena, last); |
| 4153 | 4127 | try block_scope.statements.append(ignore); |
| 4154 | 4128 | |
| 4155 | 4129 | last = try parseCCondExpr(c, m, scope); |
| ... | ... | @@ -4159,7 +4133,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4159 | 4133 | } |
| 4160 | 4134 | } |
| 4161 | 4135 | |
| 4162 | | const break_node = try Node.break_val.create(c.arena, .{ |
| 4136 | const break_node = try Tag.break_val.create(c.arena, .{ |
| 4163 | 4137 | .label = block_scope.label, |
| 4164 | 4138 | .val = last, |
| 4165 | 4139 | }); |
| ... | ... | @@ -4190,7 +4164,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { |
| 4190 | 4164 | return transCreateNodeNumber(c, lit_bytes); |
| 4191 | 4165 | } |
| 4192 | 4166 | |
| 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 | 4168 | .u => "c_uint", |
| 4195 | 4169 | .l => "c_long", |
| 4196 | 4170 | .lu => "c_ulong", |
| ... | ... | @@ -4205,7 +4179,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { |
| 4205 | 4179 | else => unreachable, |
| 4206 | 4180 | }]; |
| 4207 | 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 | 4184 | .FloatLiteral => |suffix| { |
| 4211 | 4185 | if (lit_bytes[0] == '.') |
| ... | ... | @@ -4213,13 +4187,13 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { |
| 4213 | 4187 | if (suffix == .none) { |
| 4214 | 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 | 4191 | .f => "f32", |
| 4218 | 4192 | .l => "c_longdouble", |
| 4219 | 4193 | else => unreachable, |
| 4220 | 4194 | }); |
| 4221 | 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 | 4198 | else => unreachable, |
| 4225 | 4199 | } |
| ... | ... | @@ -4391,56 +4365,56 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 4391 | 4365 | switch (tok) { |
| 4392 | 4366 | .CharLiteral => { |
| 4393 | 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 | 4369 | } else { |
| 4396 | 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 | 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 | 4377 | .IntegerLiteral, .FloatLiteral => { |
| 4404 | 4378 | return parseCNumLit(c, m); |
| 4405 | 4379 | }, |
| 4406 | 4380 | // 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"), |
| 4408 | | .Keyword_bool => return Node.type.create(c.arena, "bool"), |
| 4409 | | .Keyword_double => return Node.type.create(c.arena, "f64"), |
| 4410 | | .Keyword_long => return Node.type.create(c.arena, "c_long"), |
| 4411 | | .Keyword_int => return Node.type.create(c.arena, "c_int"), |
| 4412 | | .Keyword_float => return Node.type.create(c.arena, "f32"), |
| 4413 | | .Keyword_short => return Node.type.create(c.arena, "c_short"), |
| 4414 | | .Keyword_char => return Node.type.create(c.arena, "u8"), |
| 4381 | .Keyword_void => return Tag.type.create(c.arena, "c_void"), |
| 4382 | .Keyword_bool => return Tag.type.create(c.arena, "bool"), |
| 4383 | .Keyword_double => return Tag.type.create(c.arena, "f64"), |
| 4384 | .Keyword_long => return Tag.type.create(c.arena, "c_long"), |
| 4385 | .Keyword_int => return Tag.type.create(c.arena, "c_int"), |
| 4386 | .Keyword_float => return Tag.type.create(c.arena, "f32"), |
| 4387 | .Keyword_short => return Tag.type.create(c.arena, "c_short"), |
| 4388 | .Keyword_char => return Tag.type.create(c.arena, "u8"), |
| 4415 | 4389 | .Keyword_unsigned => if (m.next()) |t| switch (t) { |
| 4416 | | .Keyword_char => return Node.type.create(c.arena, "u8"), |
| 4417 | | .Keyword_short => return Node.type.create(c.arena, "c_ushort"), |
| 4418 | | .Keyword_int => return Node.type.create(c.arena, "c_uint"), |
| 4390 | .Keyword_char => return Tag.type.create(c.arena, "u8"), |
| 4391 | .Keyword_short => return Tag.type.create(c.arena, "c_ushort"), |
| 4392 | .Keyword_int => return Tag.type.create(c.arena, "c_uint"), |
| 4419 | 4393 | .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) { |
| 4420 | 4394 | _ = m.next(); |
| 4421 | | return Node.type.create(c.arena, "c_ulonglong"); |
| 4422 | | } else return Node.type.create(c.arena, "c_ulong"), |
| 4395 | return Tag.type.create(c.arena, "c_ulonglong"); |
| 4396 | } else return Tag.type.create(c.arena, "c_ulong"), |
| 4423 | 4397 | else => { |
| 4424 | 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 | 4401 | } else { |
| 4428 | | return Node.type.create(c.arena, "c_uint"); |
| 4402 | return Tag.type.create(c.arena, "c_uint"); |
| 4429 | 4403 | }, |
| 4430 | 4404 | .Keyword_signed => if (m.next()) |t| switch (t) { |
| 4431 | | .Keyword_char => return Node.type.create(c.arena, "i8"), |
| 4432 | | .Keyword_short => return Node.type.create(c.arena, "c_short"), |
| 4433 | | .Keyword_int => return Node.type.create(c.arena, "c_int"), |
| 4405 | .Keyword_char => return Tag.type.create(c.arena, "i8"), |
| 4406 | .Keyword_short => return Tag.type.create(c.arena, "c_short"), |
| 4407 | .Keyword_int => return Tag.type.create(c.arena, "c_int"), |
| 4434 | 4408 | .Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) { |
| 4435 | 4409 | _ = m.next(); |
| 4436 | | return Node.type.create(c.arena, "c_longlong"); |
| 4437 | | } else return Node.type.create(c.arena, "c_long"), |
| 4410 | return Tag.type.create(c.arena, "c_longlong"); |
| 4411 | } else return Tag.type.create(c.arena, "c_long"), |
| 4438 | 4412 | else => { |
| 4439 | 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 | 4416 | } else { |
| 4443 | | return Node.type.create(c.arena, "c_int"); |
| 4417 | return Tag.type.create(c.arena, "c_int"); |
| 4444 | 4418 | }, |
| 4445 | 4419 | .Keyword_enum, .Keyword_struct, .Keyword_union => { |
| 4446 | 4420 | // 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 | 4425 | } |
| 4452 | 4426 | |
| 4453 | 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 | 4430 | .Identifier => { |
| 4457 | 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 | 4434 | .LParen => { |
| 4461 | 4435 | const inner_node = try parseCExpr(c, m, scope); |
| ... | ... | @@ -4492,7 +4466,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N |
| 4492 | 4466 | return error.ParseError; |
| 4493 | 4467 | } |
| 4494 | 4468 | |
| 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 | 4471 | else => { |
| 4498 | 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 | 4485 | .StringLiteral, .Identifier => {}, |
| 4512 | 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 | 4490 | return node; |
| 4517 | 4491 | } |
| ... | ... | @@ -4521,7 +4495,7 @@ fn macroBoolToInt(c: *Context, node: Node) !Node { |
| 4521 | 4495 | return node; |
| 4522 | 4496 | } |
| 4523 | 4497 | |
| 4524 | | return Node.bool_to_int.create(c.arena, node); |
| 4498 | return Tag.bool_to_int.create(c.arena, node); |
| 4525 | 4499 | } |
| 4526 | 4500 | |
| 4527 | 4501 | fn macroIntToBool(c: *Context, node: Node) !Node { |
| ... | ... | @@ -4529,7 +4503,7 @@ fn macroIntToBool(c: *Context, node: Node) !Node { |
| 4529 | 4503 | return node; |
| 4530 | 4504 | } |
| 4531 | 4505 | |
| 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 | } |
| 4534 | 4508 | |
| 4535 | 4509 | 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 | 4519 | return error.ParseError; |
| 4546 | 4520 | } |
| 4547 | 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 | } |
| 4550 | 4524 | |
| 4551 | 4525 | 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 | 4527 | while (m.next().? == .PipePipe) { |
| 4554 | 4528 | const lhs = try macroIntToBool(c, node); |
| 4555 | 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 | 4532 | m.i -= 1; |
| 4559 | 4533 | return node; |
| ... | ... | @@ -4564,7 +4538,7 @@ fn parseCAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4564 | 4538 | while (m.next().? == .AmpersandAmpersand) { |
| 4565 | 4539 | const lhs = try macroIntToBool(c, node); |
| 4566 | 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 | 4543 | m.i -= 1; |
| 4570 | 4544 | return node; |
| ... | ... | @@ -4575,7 +4549,7 @@ fn parseCBitOrExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4575 | 4549 | while (m.next().? == .Pipe) { |
| 4576 | 4550 | const lhs = try macroBoolToInt(c, node); |
| 4577 | 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 | 4554 | m.i -= 1; |
| 4581 | 4555 | return node; |
| ... | ... | @@ -4586,7 +4560,7 @@ fn parseCBitXorExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4586 | 4560 | while (m.next().? == .Caret) { |
| 4587 | 4561 | const lhs = try macroBoolToInt(c, node); |
| 4588 | 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 | 4565 | m.i -= 1; |
| 4592 | 4566 | return node; |
| ... | ... | @@ -4597,7 +4571,7 @@ fn parseCBitAndExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4597 | 4571 | while (m.next().? == .Ampersand) { |
| 4598 | 4572 | const lhs = try macroBoolToInt(c, node); |
| 4599 | 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 | 4576 | m.i -= 1; |
| 4603 | 4577 | return node; |
| ... | ... | @@ -4611,13 +4585,13 @@ fn parseCEqExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4611 | 4585 | _ = m.next(); |
| 4612 | 4586 | const lhs = try macroBoolToInt(c, node); |
| 4613 | 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 | 4590 | .EqualEqual => { |
| 4617 | 4591 | _ = m.next(); |
| 4618 | 4592 | const lhs = try macroBoolToInt(c, node); |
| 4619 | 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 | 4596 | else => return node, |
| 4623 | 4597 | } |
| ... | ... | @@ -4632,25 +4606,25 @@ fn parseCRelExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4632 | 4606 | _ = m.next(); |
| 4633 | 4607 | const lhs = try macroBoolToInt(c, node); |
| 4634 | 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 | 4611 | .AngleBracketRightEqual => { |
| 4638 | 4612 | _ = m.next(); |
| 4639 | 4613 | const lhs = try macroBoolToInt(c, node); |
| 4640 | 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 | 4617 | .AngleBracketLeft => { |
| 4644 | 4618 | _ = m.next(); |
| 4645 | 4619 | const lhs = try macroBoolToInt(c, node); |
| 4646 | 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 | 4623 | .AngleBracketLeftEqual => { |
| 4650 | 4624 | _ = m.next(); |
| 4651 | 4625 | const lhs = try macroBoolToInt(c, node); |
| 4652 | 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 | 4629 | else => return node, |
| 4656 | 4630 | } |
| ... | ... | @@ -4665,13 +4639,13 @@ fn parseCShiftExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4665 | 4639 | _ = m.next(); |
| 4666 | 4640 | const lhs = try macroBoolToInt(c, node); |
| 4667 | 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 | 4644 | .AngleBracketAngleBracketRight => { |
| 4671 | 4645 | _ = m.next(); |
| 4672 | 4646 | const lhs = try macroBoolToInt(c, node); |
| 4673 | 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 | 4650 | else => return node, |
| 4677 | 4651 | } |
| ... | ... | @@ -4686,13 +4660,13 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4686 | 4660 | _ = m.next(); |
| 4687 | 4661 | const lhs = try macroBoolToInt(c, node); |
| 4688 | 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 | 4665 | .Minus => { |
| 4692 | 4666 | _ = m.next(); |
| 4693 | 4667 | const lhs = try macroBoolToInt(c, node); |
| 4694 | 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 | 4671 | else => return node, |
| 4698 | 4672 | } |
| ... | ... | @@ -4711,14 +4685,14 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4711 | 4685 | const prev_id = m.list[m.i - 1].id; |
| 4712 | 4686 | |
| 4713 | 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 | 4689 | .is_const = false, |
| 4716 | 4690 | .is_volatile = false, |
| 4717 | 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 | 4694 | } else { |
| 4721 | | return Node.c_pointer.create(c.arena, .{ |
| 4695 | return Tag.c_pointer.create(c.arena, .{ |
| 4722 | 4696 | .is_const = false, |
| 4723 | 4697 | .is_volatile = false, |
| 4724 | 4698 | .elem_type = node, |
| ... | ... | @@ -4728,18 +4702,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4728 | 4702 | // expr * expr |
| 4729 | 4703 | const lhs = try macroBoolToInt(c, node); |
| 4730 | 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 | 4708 | .Slash => { |
| 4735 | 4709 | const lhs = try macroBoolToInt(c, node); |
| 4736 | 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 | 4713 | .Percent => { |
| 4740 | 4714 | const lhs = try macroBoolToInt(c, node); |
| 4741 | 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 | 4718 | else => { |
| 4745 | 4719 | m.i -= 1; |
| ... | ... | @@ -4759,8 +4733,8 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4759 | 4733 | return error.ParseError; |
| 4760 | 4734 | } |
| 4761 | 4735 | |
| 4762 | | const ident = try Node.identifier.create(c.arena, m.slice()); |
| 4763 | | node = try Node.field_access.create(c.arena, .{ .lhs = node, .rhs = ident }); |
| 4736 | const ident = try Tag.identifier.create(c.arena, m.slice()); |
| 4737 | node = try Tag.field_access.create(c.arena, .{ .lhs = node, .rhs = ident }); |
| 4764 | 4738 | }, |
| 4765 | 4739 | .Arrow => { |
| 4766 | 4740 | if (m.next().? != .Identifier) { |
| ... | ... | @@ -4768,20 +4742,20 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4768 | 4742 | return error.ParseError; |
| 4769 | 4743 | } |
| 4770 | 4744 | |
| 4771 | | const deref = try Node.deref.create(c.arena, node); |
| 4772 | | const ident = try Node.identifier.create(c.arena, m.slice()); |
| 4773 | | node = try Node.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident }); |
| 4745 | const deref = try Tag.deref.create(c.arena, node); |
| 4746 | const ident = try Tag.identifier.create(c.arena, m.slice()); |
| 4747 | node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .rhs = ident }); |
| 4774 | 4748 | }, |
| 4775 | 4749 | .LBracket => { |
| 4776 | 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 | 4753 | .LParen => { |
| 4780 | | var call_params = std.ArrayList(Node).init(c.gpa); |
| 4781 | | defer call_params.deinit(); |
| 4754 | var args = std.ArrayList(Node).init(c.gpa); |
| 4755 | defer args.deinit(); |
| 4782 | 4756 | while (true) { |
| 4783 | 4757 | const arg = try parseCCondExpr(c, m, scope); |
| 4784 | | try call_params.append(arg); |
| 4758 | try args.append(arg); |
| 4785 | 4759 | switch (m.next().?) { |
| 4786 | 4760 | .Comma => {}, |
| 4787 | 4761 | .RParen => break, |
| ... | ... | @@ -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 | 4770 | .LBrace => { |
| 4797 | 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 | 4783 | }, |
| 4810 | 4784 | } |
| 4811 | 4785 | } |
| 4812 | | const tuple_node = try Node.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 }); |
| 4786 | const tuple_node = try Tag.tuple.create(c.arena, try c.arena.dupe(Node, init_vals.items)); |
| 4787 | node = try Tag.std_mem_zeroinit.create(c.arena, .{ .lhs = node, .rhs = tuple_node }); |
| 4814 | 4788 | }, |
| 4815 | 4789 | .PlusPlus, .MinusMinus => { |
| 4816 | 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 | 4802 | switch (m.next().?) { |
| 4829 | 4803 | .Bang => { |
| 4830 | 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 | 4807 | .Minus => { |
| 4834 | 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 | 4811 | .Plus => return try parseCUnaryExpr(c, m, scope), |
| 4838 | 4812 | .Tilde => { |
| 4839 | 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 | 4816 | .Asterisk => { |
| 4843 | 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 | 4820 | .Ampersand => { |
| 4847 | 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 | 4824 | .Keyword_sizeof => { |
| 4851 | 4825 | const operand = if (m.peek().? == .LParen) blk: { |
| ... | ... | @@ -4860,7 +4834,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 4860 | 4834 | break :blk inner; |
| 4861 | 4835 | } else try parseCUnaryExpr(c, m, scope); |
| 4862 | 4836 | |
| 4863 | | return Node.std_meta_sizeof.create(c.arena, operand); |
| 4837 | return Tag.std_meta_sizeof.create(c.arena, operand); |
| 4864 | 4838 | }, |
| 4865 | 4839 | .Keyword_alignof => { |
| 4866 | 4840 | // 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 | 4851 | return error.ParseError; |
| 4878 | 4852 | } |
| 4879 | 4853 | |
| 4880 | | return Node.alignof.create(c.arena, operand); |
| 4854 | return Tag.alignof.create(c.arena, operand); |
| 4881 | 4855 | }, |
| 4882 | 4856 | .PlusPlus, .MinusMinus => { |
| 4883 | 4857 | try m.fail(c, "TODO unary inc/dec expr", .{}); |
| ... | ... | @@ -4902,7 +4876,7 @@ fn getContainer(c: *Context, node: Node) ?Node { |
| 4902 | 4876 | .negate, |
| 4903 | 4877 | .negate_wrap, |
| 4904 | 4878 | .array_type, |
| 4905 | | .c_pointer, |
| 4879 | .c_pointer, |
| 4906 | 4880 | .single_pointer, |
| 4907 | 4881 | => return node, |
| 4908 | 4882 | |
| ... | ... | @@ -4910,7 +4884,7 @@ fn getContainer(c: *Context, node: Node) ?Node { |
| 4910 | 4884 | const ident = node.castTag(.identifier).?; |
| 4911 | 4885 | if (c.global_scope.sym_table.get(ident.data)) |value| { |
| 4912 | 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 | 4888 | if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |var_decl| |
| 4915 | 4889 | return getContainer(c, var_decl.data.init); |
| 4916 | 4890 | } |
| ... | ... | @@ -4923,8 +4897,8 @@ fn getContainer(c: *Context, node: Node) ?Node { |
| 4923 | 4897 | if (ty_node.castTag(.@"struct") orelse ty_node.castTag(.@"union")) |container| { |
| 4924 | 4898 | for (container.data.fields) |field| { |
| 4925 | 4899 | const ident = infix.data.rhs.castTag(.identifier).?; |
| 4926 | | if (mem.eql(u8, field.data.name, field.data)) { |
| 4927 | | return getContainer(c, field.type_expr.?); |
| 4900 | if (mem.eql(u8, field.name, ident.data)) { |
| 4901 | return getContainer(c, field.type); |
| 4928 | 4902 | } |
| 4929 | 4903 | } |
| 4930 | 4904 | } |
| ... | ... | @@ -4960,9 +4934,9 @@ fn getContainerTypeOf(c: *Context, ref: Node) ?Node { |
| 4960 | 4934 | } |
| 4961 | 4935 | |
| 4962 | 4936 | fn getFnProto(c: *Context, ref: Node) ?*ast.Payload.Func { |
| 4963 | | const init = if (value.castTag(.var_decl)) |v| |
| 4964 | | v.data.init |
| 4965 | | else if (value.castTag(.var_simple) orelse value.castTag(.pub_var_simple)) |v| |
| 4937 | const init = if (ref.castTag(.var_decl)) |v| |
| 4938 | v.data.init orelse return null |
| 4939 | else if (ref.castTag(.var_simple) orelse ref.castTag(.pub_var_simple)) |v| |
| 4966 | 4940 | v.data.init |
| 4967 | 4941 | else |
| 4968 | 4942 | return null; |