| ... | @@ -822,6 +822,16 @@ pub const Module = struct { | ... | @@ -822,6 +822,16 @@ pub const Module = struct { |
| 822 | decls: []*Decl, | 822 | decls: []*Decl, |
| 823 | arena: std.heap.ArenaAllocator, | 823 | arena: std.heap.ArenaAllocator, |
| 824 | error_msg: ?ErrorMsg = null, | 824 | error_msg: ?ErrorMsg = null, |
| | 825 | metadata: std.AutoHashMap(*Inst, MetaData), |
| | 826 | body_metadata: std.AutoHashMap(*Body, BodyMetaData), |
| | 827 | |
| | 828 | pub const MetaData = struct { |
| | 829 | deaths: ir.Inst.DeathsInt, |
| | 830 | }; |
| | 831 | |
| | 832 | pub const BodyMetaData = struct { |
| | 833 | deaths: []*Inst, |
| | 834 | }; |
| 825 | | 835 | |
| 826 | pub const Body = struct { | 836 | pub const Body = struct { |
| 827 | instructions: []*Inst, | 837 | instructions: []*Inst, |
| ... | @@ -878,6 +888,7 @@ pub const Module = struct { | ... | @@ -878,6 +888,7 @@ pub const Module = struct { |
| 878 | .loop_table = std.AutoHashMap(*Inst.Loop, []const u8).init(allocator), | 888 | .loop_table = std.AutoHashMap(*Inst.Loop, []const u8).init(allocator), |
| 879 | .arena = std.heap.ArenaAllocator.init(allocator), | 889 | .arena = std.heap.ArenaAllocator.init(allocator), |
| 880 | .indent = 2, | 890 | .indent = 2, |
| | 891 | .next_instr_index = undefined, |
| 881 | }; | 892 | }; |
| 882 | defer write.arena.deinit(); | 893 | defer write.arena.deinit(); |
| 883 | defer write.inst_table.deinit(); | 894 | defer write.inst_table.deinit(); |
| ... | @@ -889,15 +900,10 @@ pub const Module = struct { | ... | @@ -889,15 +900,10 @@ pub const Module = struct { |
| 889 | | 900 | |
| 890 | for (self.decls) |decl, decl_i| { | 901 | for (self.decls) |decl, decl_i| { |
| 891 | try write.inst_table.putNoClobber(decl.inst, .{ .inst = decl.inst, .index = null, .name = decl.name }); | 902 | try write.inst_table.putNoClobber(decl.inst, .{ .inst = decl.inst, .index = null, .name = decl.name }); |
| 892 | | | |
| 893 | if (decl.inst.cast(Inst.Fn)) |fn_inst| { | | |
| 894 | for (fn_inst.positionals.body.instructions) |inst, inst_i| { | | |
| 895 | try write.inst_table.putNoClobber(inst, .{ .inst = inst, .index = inst_i, .name = undefined }); | | |
| 896 | } | | |
| 897 | } | | |
| 898 | } | 903 | } |
| 899 | | 904 | |
| 900 | for (self.decls) |decl, i| { | 905 | for (self.decls) |decl, i| { |
| | 906 | write.next_instr_index = 0; |
| 901 | try stream.print("@{} ", .{decl.name}); | 907 | try stream.print("@{} ", .{decl.name}); |
| 902 | try write.writeInstToStream(stream, decl.inst); | 908 | try write.writeInstToStream(stream, decl.inst); |
| 903 | try stream.writeByte('\n'); | 909 | try stream.writeByte('\n'); |
| ... | @@ -914,6 +920,7 @@ const Writer = struct { | ... | @@ -914,6 +920,7 @@ const Writer = struct { |
| 914 | loop_table: std.AutoHashMap(*Inst.Loop, []const u8), | 920 | loop_table: std.AutoHashMap(*Inst.Loop, []const u8), |
| 915 | arena: std.heap.ArenaAllocator, | 921 | arena: std.heap.ArenaAllocator, |
| 916 | indent: usize, | 922 | indent: usize, |
| | 923 | next_instr_index: usize, |
| 917 | | 924 | |
| 918 | fn writeInstToStream( | 925 | fn writeInstToStream( |
| 919 | self: *Writer, | 926 | self: *Writer, |
| ... | @@ -944,7 +951,7 @@ const Writer = struct { | ... | @@ -944,7 +951,7 @@ const Writer = struct { |
| 944 | if (i != 0) { | 951 | if (i != 0) { |
| 945 | try stream.writeAll(", "); | 952 | try stream.writeAll(", "); |
| 946 | } | 953 | } |
| 947 | try self.writeParamToStream(stream, @field(inst.positionals, arg_field.name)); | 954 | try self.writeParamToStream(stream, &@field(inst.positionals, arg_field.name)); |
| 948 | } | 955 | } |
| 949 | | 956 | |
| 950 | comptime var need_comma = pos_fields.len != 0; | 957 | comptime var need_comma = pos_fields.len != 0; |
| ... | @@ -954,13 +961,13 @@ const Writer = struct { | ... | @@ -954,13 +961,13 @@ const Writer = struct { |
| 954 | if (@field(inst.kw_args, arg_field.name)) |non_optional| { | 961 | if (@field(inst.kw_args, arg_field.name)) |non_optional| { |
| 955 | if (need_comma) try stream.writeAll(", "); | 962 | if (need_comma) try stream.writeAll(", "); |
| 956 | try stream.print("{}=", .{arg_field.name}); | 963 | try stream.print("{}=", .{arg_field.name}); |
| 957 | try self.writeParamToStream(stream, non_optional); | 964 | try self.writeParamToStream(stream, &non_optional); |
| 958 | need_comma = true; | 965 | need_comma = true; |
| 959 | } | 966 | } |
| 960 | } else { | 967 | } else { |
| 961 | if (need_comma) try stream.writeAll(", "); | 968 | if (need_comma) try stream.writeAll(", "); |
| 962 | try stream.print("{}=", .{arg_field.name}); | 969 | try stream.print("{}=", .{arg_field.name}); |
| 963 | try self.writeParamToStream(stream, @field(inst.kw_args, arg_field.name)); | 970 | try self.writeParamToStream(stream, &@field(inst.kw_args, arg_field.name)); |
| 964 | need_comma = true; | 971 | need_comma = true; |
| 965 | } | 972 | } |
| 966 | } | 973 | } |
| ... | @@ -968,7 +975,8 @@ const Writer = struct { | ... | @@ -968,7 +975,8 @@ const Writer = struct { |
| 968 | try stream.writeByte(')'); | 975 | try stream.writeByte(')'); |
| 969 | } | 976 | } |
| 970 | | 977 | |
| 971 | fn writeParamToStream(self: *Writer, stream: anytype, param: anytype) !void { | 978 | fn writeParamToStream(self: *Writer, stream: anytype, param_ptr: anytype) !void { |
| | 979 | const param = param_ptr.*; |
| 972 | if (@typeInfo(@TypeOf(param)) == .Enum) { | 980 | if (@typeInfo(@TypeOf(param)) == .Enum) { |
| 973 | return stream.writeAll(@tagName(param)); | 981 | return stream.writeAll(@tagName(param)); |
| 974 | } | 982 | } |
| ... | @@ -986,18 +994,36 @@ const Writer = struct { | ... | @@ -986,18 +994,36 @@ const Writer = struct { |
| 986 | }, | 994 | }, |
| 987 | Module.Body => { | 995 | Module.Body => { |
| 988 | try stream.writeAll("{\n"); | 996 | try stream.writeAll("{\n"); |
| 989 | for (param.instructions) |inst, i| { | 997 | if (self.module.body_metadata.get(param_ptr)) |metadata| { |
| | 998 | if (metadata.deaths.len > 0) { |
| | 999 | try stream.writeByteNTimes(' ', self.indent); |
| | 1000 | try stream.writeAll("; deaths={"); |
| | 1001 | for (metadata.deaths) |death, i| { |
| | 1002 | if (i != 0) try stream.writeAll(", "); |
| | 1003 | try self.writeInstParamToStream(stream, death); |
| | 1004 | } |
| | 1005 | try stream.writeAll("}\n"); |
| | 1006 | } |
| | 1007 | } |
| | 1008 | |
| | 1009 | for (param.instructions) |inst| { |
| | 1010 | const my_i = self.next_instr_index; |
| | 1011 | self.next_instr_index += 1; |
| | 1012 | try self.inst_table.putNoClobber(inst, .{ .inst = inst, .index = my_i, .name = undefined }); |
| 990 | try stream.writeByteNTimes(' ', self.indent); | 1013 | try stream.writeByteNTimes(' ', self.indent); |
| 991 | try stream.print("%{} ", .{i}); | 1014 | try stream.print("%{} ", .{my_i}); |
| 992 | if (inst.cast(Inst.Block)) |block| { | 1015 | if (inst.cast(Inst.Block)) |block| { |
| 993 | const name = try std.fmt.allocPrint(&self.arena.allocator, "label_{}", .{i}); | 1016 | const name = try std.fmt.allocPrint(&self.arena.allocator, "label_{}", .{my_i}); |
| 994 | try self.block_table.put(block, name); | 1017 | try self.block_table.put(block, name); |
| 995 | } else if (inst.cast(Inst.Loop)) |loop| { | 1018 | } else if (inst.cast(Inst.Loop)) |loop| { |
| 996 | const name = try std.fmt.allocPrint(&self.arena.allocator, "loop_{}", .{i}); | 1019 | const name = try std.fmt.allocPrint(&self.arena.allocator, "loop_{}", .{my_i}); |
| 997 | try self.loop_table.put(loop, name); | 1020 | try self.loop_table.put(loop, name); |
| 998 | } | 1021 | } |
| 999 | self.indent += 2; | 1022 | self.indent += 2; |
| 1000 | try self.writeInstToStream(stream, inst); | 1023 | try self.writeInstToStream(stream, inst); |
| | 1024 | if (self.module.metadata.get(inst)) |metadata| { |
| | 1025 | try stream.print(" ; deaths=0b{b}", .{metadata.deaths}); |
| | 1026 | } |
| 1001 | self.indent -= 2; | 1027 | self.indent -= 2; |
| 1002 | try stream.writeByte('\n'); | 1028 | try stream.writeByte('\n'); |
| 1003 | } | 1029 | } |
| ... | @@ -1070,6 +1096,8 @@ pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module | ... | @@ -1070,6 +1096,8 @@ pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module |
| 1070 | .decls = parser.decls.toOwnedSlice(allocator), | 1096 | .decls = parser.decls.toOwnedSlice(allocator), |
| 1071 | .arena = parser.arena, | 1097 | .arena = parser.arena, |
| 1072 | .error_msg = parser.error_msg, | 1098 | .error_msg = parser.error_msg, |
| | 1099 | .metadata = std.AutoHashMap(*Inst, Module.MetaData).init(allocator), |
| | 1100 | .body_metadata = std.AutoHashMap(*Module.Body, Module.BodyMetaData).init(allocator), |
| 1073 | }; | 1101 | }; |
| 1074 | } | 1102 | } |
| 1075 | | 1103 | |
| ... | @@ -1478,7 +1506,11 @@ pub fn emit(allocator: *Allocator, old_module: IrModule) !Module { | ... | @@ -1478,7 +1506,11 @@ pub fn emit(allocator: *Allocator, old_module: IrModule) !Module { |
| 1478 | .indent = 0, | 1506 | .indent = 0, |
| 1479 | .block_table = std.AutoHashMap(*ir.Inst.Block, *Inst.Block).init(allocator), | 1507 | .block_table = std.AutoHashMap(*ir.Inst.Block, *Inst.Block).init(allocator), |
| 1480 | .loop_table = std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop).init(allocator), | 1508 | .loop_table = std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop).init(allocator), |
| | 1509 | .metadata = std.AutoHashMap(*Inst, Module.MetaData).init(allocator), |
| | 1510 | .body_metadata = std.AutoHashMap(*Module.Body, Module.BodyMetaData).init(allocator), |
| 1481 | }; | 1511 | }; |
| | 1512 | defer ctx.metadata.deinit(); |
| | 1513 | defer ctx.body_metadata.deinit(); |
| 1482 | defer ctx.block_table.deinit(); | 1514 | defer ctx.block_table.deinit(); |
| 1483 | defer ctx.loop_table.deinit(); | 1515 | defer ctx.loop_table.deinit(); |
| 1484 | defer ctx.decls.deinit(allocator); | 1516 | defer ctx.decls.deinit(allocator); |
| ... | @@ -1491,7 +1523,50 @@ pub fn emit(allocator: *Allocator, old_module: IrModule) !Module { | ... | @@ -1491,7 +1523,50 @@ pub fn emit(allocator: *Allocator, old_module: IrModule) !Module { |
| 1491 | return Module{ | 1523 | return Module{ |
| 1492 | .decls = ctx.decls.toOwnedSlice(allocator), | 1524 | .decls = ctx.decls.toOwnedSlice(allocator), |
| 1493 | .arena = ctx.arena, | 1525 | .arena = ctx.arena, |
| | 1526 | .metadata = ctx.metadata, |
| | 1527 | .body_metadata = ctx.body_metadata, |
| | 1528 | }; |
| | 1529 | } |
| | 1530 | |
| | 1531 | /// For debugging purposes, prints a function representation to stderr. |
| | 1532 | pub fn dumpFn(old_module: IrModule, module_fn: *IrModule.Fn) void { |
| | 1533 | const allocator = old_module.gpa; |
| | 1534 | var ctx: EmitZIR = .{ |
| | 1535 | .allocator = allocator, |
| | 1536 | .decls = .{}, |
| | 1537 | .arena = std.heap.ArenaAllocator.init(allocator), |
| | 1538 | .old_module = &old_module, |
| | 1539 | .next_auto_name = 0, |
| | 1540 | .names = std.StringHashMap(void).init(allocator), |
| | 1541 | .primitive_table = std.AutoHashMap(Inst.Primitive.Builtin, *Decl).init(allocator), |
| | 1542 | .indent = 0, |
| | 1543 | .block_table = std.AutoHashMap(*ir.Inst.Block, *Inst.Block).init(allocator), |
| | 1544 | .loop_table = std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop).init(allocator), |
| | 1545 | .metadata = std.AutoHashMap(*Inst, Module.MetaData).init(allocator), |
| | 1546 | .body_metadata = std.AutoHashMap(*Module.Body, Module.BodyMetaData).init(allocator), |
| | 1547 | }; |
| | 1548 | defer ctx.metadata.deinit(); |
| | 1549 | defer ctx.body_metadata.deinit(); |
| | 1550 | defer ctx.block_table.deinit(); |
| | 1551 | defer ctx.loop_table.deinit(); |
| | 1552 | defer ctx.decls.deinit(allocator); |
| | 1553 | defer ctx.names.deinit(); |
| | 1554 | defer ctx.primitive_table.deinit(); |
| | 1555 | defer ctx.arena.deinit(); |
| | 1556 | |
| | 1557 | const fn_ty = module_fn.owner_decl.typed_value.most_recent.typed_value.ty; |
| | 1558 | _ = ctx.emitFn(module_fn, 0, fn_ty) catch |err| { |
| | 1559 | std.debug.print("unable to dump function: {}\n", .{err}); |
| | 1560 | return; |
| | 1561 | }; |
| | 1562 | var module = Module{ |
| | 1563 | .decls = ctx.decls.items, |
| | 1564 | .arena = ctx.arena, |
| | 1565 | .metadata = ctx.metadata, |
| | 1566 | .body_metadata = ctx.body_metadata, |
| 1494 | }; | 1567 | }; |
| | 1568 | |
| | 1569 | module.dump(); |
| 1495 | } | 1570 | } |
| 1496 | | 1571 | |
| 1497 | const EmitZIR = struct { | 1572 | const EmitZIR = struct { |
| ... | @@ -1505,6 +1580,8 @@ const EmitZIR = struct { | ... | @@ -1505,6 +1580,8 @@ const EmitZIR = struct { |
| 1505 | indent: usize, | 1580 | indent: usize, |
| 1506 | block_table: std.AutoHashMap(*ir.Inst.Block, *Inst.Block), | 1581 | block_table: std.AutoHashMap(*ir.Inst.Block, *Inst.Block), |
| 1507 | loop_table: std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop), | 1582 | loop_table: std.AutoHashMap(*ir.Inst.Loop, *Inst.Loop), |
| | 1583 | metadata: std.AutoHashMap(*Inst, Module.MetaData), |
| | 1584 | body_metadata: std.AutoHashMap(*Module.Body, Module.BodyMetaData), |
| 1508 | | 1585 | |
| 1509 | fn emit(self: *EmitZIR) !void { | 1586 | fn emit(self: *EmitZIR) !void { |
| 1510 | // Put all the Decls in a list and sort them by name to avoid nondeterminism introduced | 1587 | // Put all the Decls in a list and sort them by name to avoid nondeterminism introduced |
| ... | @@ -1604,7 +1681,7 @@ const EmitZIR = struct { | ... | @@ -1604,7 +1681,7 @@ const EmitZIR = struct { |
| 1604 | } else blk: { | 1681 | } else blk: { |
| 1605 | break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst; | 1682 | break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst; |
| 1606 | }; | 1683 | }; |
| 1607 | try new_body.inst_table.putNoClobber(inst, new_inst); | 1684 | _ = try new_body.inst_table.put(inst, new_inst); |
| 1608 | return new_inst; | 1685 | return new_inst; |
| 1609 | } else { | 1686 | } else { |
| 1610 | return new_body.inst_table.get(inst).?; | 1687 | return new_body.inst_table.get(inst).?; |
| ... | @@ -1655,6 +1732,70 @@ const EmitZIR = struct { | ... | @@ -1655,6 +1732,70 @@ const EmitZIR = struct { |
| 1655 | return &declref_inst.base; | 1732 | return &declref_inst.base; |
| 1656 | } | 1733 | } |
| 1657 | | 1734 | |
| | 1735 | fn emitFn(self: *EmitZIR, module_fn: *IrModule.Fn, src: usize, ty: Type) Allocator.Error!*Decl { |
| | 1736 | var inst_table = std.AutoHashMap(*ir.Inst, *Inst).init(self.allocator); |
| | 1737 | defer inst_table.deinit(); |
| | 1738 | |
| | 1739 | var instructions = std.ArrayList(*Inst).init(self.allocator); |
| | 1740 | defer instructions.deinit(); |
| | 1741 | |
| | 1742 | switch (module_fn.analysis) { |
| | 1743 | .queued => unreachable, |
| | 1744 | .in_progress => unreachable, |
| | 1745 | .success => |body| { |
| | 1746 | try self.emitBody(body, &inst_table, &instructions); |
| | 1747 | }, |
| | 1748 | .sema_failure => { |
| | 1749 | const err_msg = self.old_module.failed_decls.get(module_fn.owner_decl).?; |
| | 1750 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); |
| | 1751 | fail_inst.* = .{ |
| | 1752 | .base = .{ |
| | 1753 | .src = src, |
| | 1754 | .tag = Inst.CompileError.base_tag, |
| | 1755 | }, |
| | 1756 | .positionals = .{ |
| | 1757 | .msg = try self.arena.allocator.dupe(u8, err_msg.msg), |
| | 1758 | }, |
| | 1759 | .kw_args = .{}, |
| | 1760 | }; |
| | 1761 | try instructions.append(&fail_inst.base); |
| | 1762 | }, |
| | 1763 | .dependency_failure => { |
| | 1764 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); |
| | 1765 | fail_inst.* = .{ |
| | 1766 | .base = .{ |
| | 1767 | .src = src, |
| | 1768 | .tag = Inst.CompileError.base_tag, |
| | 1769 | }, |
| | 1770 | .positionals = .{ |
| | 1771 | .msg = try self.arena.allocator.dupe(u8, "depends on another failed Decl"), |
| | 1772 | }, |
| | 1773 | .kw_args = .{}, |
| | 1774 | }; |
| | 1775 | try instructions.append(&fail_inst.base); |
| | 1776 | }, |
| | 1777 | } |
| | 1778 | |
| | 1779 | const fn_type = try self.emitType(src, ty); |
| | 1780 | |
| | 1781 | const arena_instrs = try self.arena.allocator.alloc(*Inst, instructions.items.len); |
| | 1782 | mem.copy(*Inst, arena_instrs, instructions.items); |
| | 1783 | |
| | 1784 | const fn_inst = try self.arena.allocator.create(Inst.Fn); |
| | 1785 | fn_inst.* = .{ |
| | 1786 | .base = .{ |
| | 1787 | .src = src, |
| | 1788 | .tag = Inst.Fn.base_tag, |
| | 1789 | }, |
| | 1790 | .positionals = .{ |
| | 1791 | .fn_type = fn_type.inst, |
| | 1792 | .body = .{ .instructions = arena_instrs }, |
| | 1793 | }, |
| | 1794 | .kw_args = .{}, |
| | 1795 | }; |
| | 1796 | return self.emitUnnamedDecl(&fn_inst.base); |
| | 1797 | } |
| | 1798 | |
| 1658 | fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: TypedValue) Allocator.Error!*Decl { | 1799 | fn emitTypedValue(self: *EmitZIR, src: usize, typed_value: TypedValue) Allocator.Error!*Decl { |
| 1659 | const allocator = &self.arena.allocator; | 1800 | const allocator = &self.arena.allocator; |
| 1660 | if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| { | 1801 | if (typed_value.val.cast(Value.Payload.DeclRef)) |decl_ref| { |
| ... | @@ -1718,68 +1859,7 @@ const EmitZIR = struct { | ... | @@ -1718,68 +1859,7 @@ const EmitZIR = struct { |
| 1718 | }, | 1859 | }, |
| 1719 | .Fn => { | 1860 | .Fn => { |
| 1720 | const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; | 1861 | const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; |
| 1721 | | 1862 | return self.emitFn(module_fn, src, typed_value.ty); |
| 1722 | var inst_table = std.AutoHashMap(*ir.Inst, *Inst).init(self.allocator); | | |
| 1723 | defer inst_table.deinit(); | | |
| 1724 | | | |
| 1725 | var instructions = std.ArrayList(*Inst).init(self.allocator); | | |
| 1726 | defer instructions.deinit(); | | |
| 1727 | | | |
| 1728 | switch (module_fn.analysis) { | | |
| 1729 | .queued => unreachable, | | |
| 1730 | .in_progress => unreachable, | | |
| 1731 | .success => |body| { | | |
| 1732 | try self.emitBody(body, &inst_table, &instructions); | | |
| 1733 | }, | | |
| 1734 | .sema_failure => { | | |
| 1735 | const err_msg = self.old_module.failed_decls.get(module_fn.owner_decl).?; | | |
| 1736 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); | | |
| 1737 | fail_inst.* = .{ | | |
| 1738 | .base = .{ | | |
| 1739 | .src = src, | | |
| 1740 | .tag = Inst.CompileError.base_tag, | | |
| 1741 | }, | | |
| 1742 | .positionals = .{ | | |
| 1743 | .msg = try self.arena.allocator.dupe(u8, err_msg.msg), | | |
| 1744 | }, | | |
| 1745 | .kw_args = .{}, | | |
| 1746 | }; | | |
| 1747 | try instructions.append(&fail_inst.base); | | |
| 1748 | }, | | |
| 1749 | .dependency_failure => { | | |
| 1750 | const fail_inst = try self.arena.allocator.create(Inst.CompileError); | | |
| 1751 | fail_inst.* = .{ | | |
| 1752 | .base = .{ | | |
| 1753 | .src = src, | | |
| 1754 | .tag = Inst.CompileError.base_tag, | | |
| 1755 | }, | | |
| 1756 | .positionals = .{ | | |
| 1757 | .msg = try self.arena.allocator.dupe(u8, "depends on another failed Decl"), | | |
| 1758 | }, | | |
| 1759 | .kw_args = .{}, | | |
| 1760 | }; | | |
| 1761 | try instructions.append(&fail_inst.base); | | |
| 1762 | }, | | |
| 1763 | } | | |
| 1764 | | | |
| 1765 | const fn_type = try self.emitType(src, typed_value.ty); | | |
| 1766 | | | |
| 1767 | const arena_instrs = try self.arena.allocator.alloc(*Inst, instructions.items.len); | | |
| 1768 | mem.copy(*Inst, arena_instrs, instructions.items); | | |
| 1769 | | | |
| 1770 | const fn_inst = try self.arena.allocator.create(Inst.Fn); | | |
| 1771 | fn_inst.* = .{ | | |
| 1772 | .base = .{ | | |
| 1773 | .src = src, | | |
| 1774 | .tag = Inst.Fn.base_tag, | | |
| 1775 | }, | | |
| 1776 | .positionals = .{ | | |
| 1777 | .fn_type = fn_type.inst, | | |
| 1778 | .body = .{ .instructions = arena_instrs }, | | |
| 1779 | }, | | |
| 1780 | .kw_args = .{}, | | |
| 1781 | }; | | |
| 1782 | return self.emitUnnamedDecl(&fn_inst.base); | | |
| 1783 | }, | 1863 | }, |
| 1784 | .Array => { | 1864 | .Array => { |
| 1785 | // TODO more checks to make sure this can be emitted as a string literal | 1865 | // TODO more checks to make sure this can be emitted as a string literal |
| ... | @@ -1810,7 +1890,7 @@ const EmitZIR = struct { | ... | @@ -1810,7 +1890,7 @@ const EmitZIR = struct { |
| 1810 | } | 1890 | } |
| 1811 | } | 1891 | } |
| 1812 | | 1892 | |
| 1813 | fn emitNoOp(self: *EmitZIR, src: usize, tag: Inst.Tag) Allocator.Error!*Inst { | 1893 | fn emitNoOp(self: *EmitZIR, src: usize, old_inst: *ir.Inst.NoOp, tag: Inst.Tag) Allocator.Error!*Inst { |
| 1814 | const new_inst = try self.arena.allocator.create(Inst.NoOp); | 1894 | const new_inst = try self.arena.allocator.create(Inst.NoOp); |
| 1815 | new_inst.* = .{ | 1895 | new_inst.* = .{ |
| 1816 | .base = .{ | 1896 | .base = .{ |
| ... | @@ -1902,10 +1982,10 @@ const EmitZIR = struct { | ... | @@ -1902,10 +1982,10 @@ const EmitZIR = struct { |
| 1902 | const new_inst = switch (inst.tag) { | 1982 | const new_inst = switch (inst.tag) { |
| 1903 | .constant => unreachable, // excluded from function bodies | 1983 | .constant => unreachable, // excluded from function bodies |
| 1904 | | 1984 | |
| 1905 | .breakpoint => try self.emitNoOp(inst.src, .breakpoint), | 1985 | .breakpoint => try self.emitNoOp(inst.src, inst.castTag(.breakpoint).?, .breakpoint), |
| 1906 | .unreach => try self.emitNoOp(inst.src, .@"unreachable"), | 1986 | .unreach => try self.emitNoOp(inst.src, inst.castTag(.unreach).?, .unreach_nocheck), |
| 1907 | .retvoid => try self.emitNoOp(inst.src, .returnvoid), | 1987 | .retvoid => try self.emitNoOp(inst.src, inst.castTag(.retvoid).?, .returnvoid), |
| 1908 | .dbg_stmt => try self.emitNoOp(inst.src, .dbg_stmt), | 1988 | .dbg_stmt => try self.emitNoOp(inst.src, inst.castTag(.dbg_stmt).?, .dbg_stmt), |
| 1909 | | 1989 | |
| 1910 | .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot), | 1990 | .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot), |
| 1911 | .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"), | 1991 | .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"), |
| ... | @@ -2119,10 +2199,24 @@ const EmitZIR = struct { | ... | @@ -2119,10 +2199,24 @@ const EmitZIR = struct { |
| 2119 | defer then_body.deinit(); | 2199 | defer then_body.deinit(); |
| 2120 | defer else_body.deinit(); | 2200 | defer else_body.deinit(); |
| 2121 | | 2201 | |
| | 2202 | const then_deaths = try self.arena.allocator.alloc(*Inst, old_inst.thenDeaths().len); |
| | 2203 | const else_deaths = try self.arena.allocator.alloc(*Inst, old_inst.elseDeaths().len); |
| | 2204 | |
| | 2205 | for (old_inst.thenDeaths()) |death, i| { |
| | 2206 | then_deaths[i] = try self.resolveInst(new_body, death); |
| | 2207 | } |
| | 2208 | for (old_inst.elseDeaths()) |death, i| { |
| | 2209 | else_deaths[i] = try self.resolveInst(new_body, death); |
| | 2210 | } |
| | 2211 | |
| 2122 | try self.emitBody(old_inst.then_body, inst_table, &then_body); | 2212 | try self.emitBody(old_inst.then_body, inst_table, &then_body); |
| 2123 | try self.emitBody(old_inst.else_body, inst_table, &else_body); | 2213 | try self.emitBody(old_inst.else_body, inst_table, &else_body); |
| 2124 | | 2214 | |
| 2125 | const new_inst = try self.arena.allocator.create(Inst.CondBr); | 2215 | const new_inst = try self.arena.allocator.create(Inst.CondBr); |
| | 2216 | |
| | 2217 | try self.body_metadata.put(&new_inst.positionals.then_body, .{ .deaths = then_deaths }); |
| | 2218 | try self.body_metadata.put(&new_inst.positionals.else_body, .{ .deaths = else_deaths }); |
| | 2219 | |
| 2126 | new_inst.* = .{ | 2220 | new_inst.* = .{ |
| 2127 | .base = .{ | 2221 | .base = .{ |
| 2128 | .src = inst.src, | 2222 | .src = inst.src, |
| ... | @@ -2138,6 +2232,7 @@ const EmitZIR = struct { | ... | @@ -2138,6 +2232,7 @@ const EmitZIR = struct { |
| 2138 | break :blk &new_inst.base; | 2232 | break :blk &new_inst.base; |
| 2139 | }, | 2233 | }, |
| 2140 | }; | 2234 | }; |
| | 2235 | try self.metadata.put(new_inst, .{ .deaths = inst.deaths }); |
| 2141 | try instructions.append(new_inst); | 2236 | try instructions.append(new_inst); |
| 2142 | try inst_table.put(inst, new_inst); | 2237 | try inst_table.put(inst, new_inst); |
| 2143 | } | 2238 | } |