authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-11 22:23:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-11 22:23:32-07:00
log8282f4271cf3a3e0d2159c698142b3cafe6b1603
tree7792bd59642c569519a301c46234eafe50e0f67e
parenta2a5cea286e87356b32a304853233e47a9fe70a7

stage2: basic support for parameters .debug_info

see #6014

10 files changed, 491 insertions(+), 96 deletions(-)

src-self-hosted/Module.zig+20-4
......@@ -1301,14 +1301,16 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
13011301 for (fn_proto.params()) |param, i| {
13021302 const name_token = param.name_token.?;
13031303 const src = tree.token_locs[name_token].start;
1304 const param_name = tree.tokenSlice(name_token);
1305 const arg = try gen_scope_arena.allocator.create(zir.Inst.NoOp);
1304 const param_name = tree.tokenSlice(name_token); // TODO: call identifierTokenString
1305 const arg = try gen_scope_arena.allocator.create(zir.Inst.Arg);
13061306 arg.* = .{
13071307 .base = .{
13081308 .tag = .arg,
13091309 .src = src,
13101310 },
1311 .positionals = .{},
1311 .positionals = .{
1312 .name = param_name,
1313 },
13121314 .kw_args = .{},
13131315 };
13141316 gen_scope.instructions.items[i] = &arg.base;
......@@ -1934,6 +1936,20 @@ pub fn addBinOp(
19341936 return &inst.base;
19351937}
19361938
1939pub fn addArg(self: *Module, block: *Scope.Block, src: usize, ty: Type, name: [*:0]const u8) !*Inst {
1940 const inst = try block.arena.create(Inst.Arg);
1941 inst.* = .{
1942 .base = .{
1943 .tag = .arg,
1944 .ty = ty,
1945 .src = src,
1946 },
1947 .name = name,
1948 };
1949 try block.instructions.append(self.gpa, &inst.base);
1950 return &inst.base;
1951}
1952
19371953pub fn addBr(
19381954 self: *Module,
19391955 scope_block: *Scope.Block,
......@@ -2535,7 +2551,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
25352551 }
25362552 }
25372553
2538 return self.fail(scope, inst.src, "expected {}, found {}", .{ dest_type, inst.ty });
2554 return self.fail(scope, inst.src, "expected {}, found {}", .{ dest_type, inst.ty });
25392555}
25402556
25412557pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst {
src-self-hosted/codegen.zig+84-53
......@@ -51,6 +51,7 @@ pub fn generateSymbol(
5151 code: *std.ArrayList(u8),
5252 dbg_line: *std.ArrayList(u8),
5353 dbg_info: *std.ArrayList(u8),
54 dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable,
5455) GenerateSymbolError!Result {
5556 const tracy = trace(@src());
5657 defer tracy.end();
......@@ -58,57 +59,57 @@ pub fn generateSymbol(
5859 switch (typed_value.ty.zigTypeTag()) {
5960 .Fn => {
6061 switch (bin_file.base.options.target.cpu.arch) {
61 //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
62 //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
63 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
64 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
65 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
66 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
67 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
68 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
69 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
70 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
71 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
72 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
73 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
74 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
75 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
76 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
77 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
78 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
79 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
80 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
81 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
82 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
83 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
84 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
85 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
86 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
87 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
88 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
89 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
90 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
91 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
92 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
93 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
94 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
95 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
96 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
97 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
98 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
99 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
100 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
101 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
102 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
103 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
104 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
105 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
106 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
107 //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
108 //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
109 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
110 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
111 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),
62 //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
63 //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
64 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
65 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
66 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
67 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
68 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
69 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
70 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
71 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
72 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
73 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
74 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
75 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
76 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
77 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
78 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
79 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
80 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
81 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
82 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
83 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
84 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
85 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
86 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
87 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
88 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
89 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
90 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
91 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
92 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
93 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
94 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
95 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
96 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
97 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
98 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
99 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
100 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
101 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
102 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
103 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
104 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
105 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
106 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
107 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
108 //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
109 //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
110 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
111 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
112 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
112113 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
113114 }
114115 },
......@@ -122,7 +123,7 @@ pub fn generateSymbol(
122123 switch (try generateSymbol(bin_file, src, .{
123124 .ty = typed_value.ty.elemType(),
124125 .val = sentinel,
125 }, code, dbg_line, dbg_info)) {
126 }, code, dbg_line, dbg_info, dbg_info_type_relocs)) {
126127 .appended => return Result{ .appended = {} },
127128 .externally_managed => |slice| {
128129 code.appendSliceAssumeCapacity(slice);
......@@ -225,6 +226,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
225226 code: *std.ArrayList(u8),
226227 dbg_line: *std.ArrayList(u8),
227228 dbg_info: *std.ArrayList(u8),
229 dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable,
228230 err_msg: ?*ErrorMsg,
229231 args: []MCValue,
230232 ret_mcv: MCValue,
......@@ -395,6 +397,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
395397 code: *std.ArrayList(u8),
396398 dbg_line: *std.ArrayList(u8),
397399 dbg_info: *std.ArrayList(u8),
400 dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable,
398401 ) GenerateSymbolError!Result {
399402 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
400403
......@@ -433,6 +436,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
433436 .code = code,
434437 .dbg_line = dbg_line,
435438 .dbg_info = dbg_info,
439 .dbg_info_type_relocs = dbg_info_type_relocs,
436440 .err_msg = null,
437441 .args = undefined, // populated after `resolveCallingConventionValues`
438442 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -610,6 +614,23 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
610614 }
611615 }
612616
617 /// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
618 /// after codegen for this symbol is done.
619 fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
620 assert(ty.hasCodeGenBits());
621 const index = self.dbg_info.items.len;
622 try self.dbg_info.resize(index + 4); // DW.AT_type, DW.FORM_ref4
623
624 const gop = try self.dbg_info_type_relocs.getOrPut(self.gpa, ty);
625 if (!gop.found_existing) {
626 gop.entry.value = .{
627 .off = undefined,
628 .relocs = .{},
629 };
630 }
631 try gop.entry.value.relocs.append(self.gpa, @intCast(u32, index));
632 }
633
613634 fn genFuncInst(self: *Self, inst: *ir.Inst) !MCValue {
614635 switch (inst.tag) {
615636 .add => return self.genAdd(inst.castTag(.add).?),
......@@ -1009,7 +1030,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
10091030 }
10101031 }
10111032
1012 fn genArg(self: *Self, inst: *ir.Inst.NoOp) !MCValue {
1033 fn genArg(self: *Self, inst: *ir.Inst.Arg) !MCValue {
10131034 if (FreeRegInt == u0) {
10141035 return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});
10151036 }
......@@ -1022,10 +1043,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
10221043 const result = self.args[self.arg_index];
10231044 self.arg_index += 1;
10241045
1046 const name_with_null = inst.name[0..mem.lenZ(inst.name) + 1];
10251047 switch (result) {
10261048 .register => |reg| {
10271049 branch.registers.putAssumeCapacityNoClobber(reg, .{ .inst = &inst.base });
10281050 branch.markRegUsed(reg);
1051
1052 try self.dbg_info.ensureCapacity(self.dbg_info.items.len + 8 + name_with_null.len);
1053 self.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
1054 self.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
1055 1, // ULEB128 dwarf expression length
1056 reg.dwarfLocOp(),
1057 });
1058 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
1059 self.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
10291060 },
10301061 else => {},
10311062 }
src-self-hosted/codegen/riscv64.zig+9
......@@ -1,4 +1,5 @@
11const std = @import("std");
2const DW = std.dwarf;
23
34pub const instructions = struct {
45 pub const CallBreak = packed struct {
......@@ -48,6 +49,10 @@ pub const RawRegister = enum(u8) {
4849 x8, x9, x10, x11, x12, x13, x14, x15,
4950 x16, x17, x18, x19, x20, x21, x22, x23,
5051 x24, x25, x26, x27, x28, x29, x30, x31,
52
53 pub fn dwarfLocOp(reg: RawRegister) u8 {
54 return @enumToInt(reg) + DW.OP_reg0;
55 }
5156};
5257
5358pub const Register = enum(u8) {
......@@ -83,6 +88,10 @@ pub const Register = enum(u8) {
8388 }
8489 return null;
8590 }
91
92 pub fn dwarfLocOp(reg: Register) u8 {
93 return @enumToInt(reg) + DW.OP_reg0;
94 }
8695};
8796
8897// zig fmt: on
src-self-hosted/codegen/x86.zig+79
......@@ -1,3 +1,6 @@
1const std = @import("std");
2const DW = std.dwarf;
3
14// zig fmt: off
25pub const Register = enum(u8) {
36 // 0 through 7, 32-bit registers. id is int value
......@@ -37,8 +40,84 @@ pub const Register = enum(u8) {
3740 else => null,
3841 };
3942 }
43
44 /// Convert from any register to its 32 bit alias.
45 pub fn to32(self: Register) Register {
46 return @intToEnum(Register, @as(u8, self.id()));
47 }
48
49 /// Convert from any register to its 16 bit alias.
50 pub fn to16(self: Register) Register {
51 return @intToEnum(Register, @as(u8, self.id()) + 8);
52 }
53
54 /// Convert from any register to its 8 bit alias.
55 pub fn to8(self: Register) Register {
56 return @intToEnum(Register, @as(u8, self.id()) + 16);
57 }
58
59
60 pub fn dwarfLocOp(reg: Register) u8 {
61 return switch (reg.to32()) {
62 .eax => DW.OP_reg0,
63 .ecx => DW.OP_reg1,
64 .edx => DW.OP_reg2,
65 .ebx => DW.OP_reg3,
66 .esp => DW.OP_reg4,
67 .ebp => DW.OP_reg5,
68 .esi => DW.OP_reg6,
69 .edi => DW.OP_reg7,
70 else => unreachable,
71 };
72 }
4073};
4174
4275// zig fmt: on
4376
4477pub const callee_preserved_regs = [_]Register{ .eax, .ecx, .edx, .esi, .edi };
78
79// TODO add these to Register enum and corresponding dwarfLocOp
80// // Return Address register. This is stored in `0(%esp, "")` and is not a physical register.
81// RA = (8, "RA"),
82//
83// ST0 = (11, "st0"),
84// ST1 = (12, "st1"),
85// ST2 = (13, "st2"),
86// ST3 = (14, "st3"),
87// ST4 = (15, "st4"),
88// ST5 = (16, "st5"),
89// ST6 = (17, "st6"),
90// ST7 = (18, "st7"),
91//
92// XMM0 = (21, "xmm0"),
93// XMM1 = (22, "xmm1"),
94// XMM2 = (23, "xmm2"),
95// XMM3 = (24, "xmm3"),
96// XMM4 = (25, "xmm4"),
97// XMM5 = (26, "xmm5"),
98// XMM6 = (27, "xmm6"),
99// XMM7 = (28, "xmm7"),
100//
101// MM0 = (29, "mm0"),
102// MM1 = (30, "mm1"),
103// MM2 = (31, "mm2"),
104// MM3 = (32, "mm3"),
105// MM4 = (33, "mm4"),
106// MM5 = (34, "mm5"),
107// MM6 = (35, "mm6"),
108// MM7 = (36, "mm7"),
109//
110// MXCSR = (39, "mxcsr"),
111//
112// ES = (40, "es"),
113// CS = (41, "cs"),
114// SS = (42, "ss"),
115// DS = (43, "ds"),
116// FS = (44, "fs"),
117// GS = (45, "gs"),
118//
119// TR = (48, "tr"),
120// LDTR = (49, "ldtr"),
121//
122// FS_BASE = (93, "fs.base"),
123// GS_BASE = (94, "gs.base"),
src-self-hosted/codegen/x86_64.zig+109
......@@ -1,4 +1,6 @@
1const std = @import("std");
12const Type = @import("../Type.zig");
3const DW = std.dwarf;
24
35// zig fmt: off
46
......@@ -101,6 +103,30 @@ pub const Register = enum(u8) {
101103 pub fn to8(self: Register) Register {
102104 return @intToEnum(Register, @as(u8, self.id()) + 48);
103105 }
106
107 pub fn dwarfLocOp(self: Register) u8 {
108 return switch (self.to64()) {
109 .rax => DW.OP_reg0,
110 .rdx => DW.OP_reg1,
111 .rcx => DW.OP_reg2,
112 .rbx => DW.OP_reg3,
113 .rsi => DW.OP_reg4,
114 .rdi => DW.OP_reg5,
115 .rbp => DW.OP_reg6,
116 .rsp => DW.OP_reg7,
117
118 .r8 => DW.OP_reg8,
119 .r9 => DW.OP_reg9,
120 .r10 => DW.OP_reg10,
121 .r11 => DW.OP_reg11,
122 .r12 => DW.OP_reg12,
123 .r13 => DW.OP_reg13,
124 .r14 => DW.OP_reg14,
125 .r15 => DW.OP_reg15,
126
127 else => unreachable,
128 };
129 }
104130};
105131
106132// zig fmt: on
......@@ -109,3 +135,86 @@ pub const Register = enum(u8) {
109135pub const callee_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .rsi, .rdi, .r8, .r9, .r10, .r11 };
110136pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };
111137pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx };
138
139// TODO add these registers to the enum and populate dwarfLocOp
140// // Return Address register. This is stored in `0(%rsp, "")` and is not a physical register.
141// RA = (16, "RA"),
142//
143// XMM0 = (17, "xmm0"),
144// XMM1 = (18, "xmm1"),
145// XMM2 = (19, "xmm2"),
146// XMM3 = (20, "xmm3"),
147// XMM4 = (21, "xmm4"),
148// XMM5 = (22, "xmm5"),
149// XMM6 = (23, "xmm6"),
150// XMM7 = (24, "xmm7"),
151//
152// XMM8 = (25, "xmm8"),
153// XMM9 = (26, "xmm9"),
154// XMM10 = (27, "xmm10"),
155// XMM11 = (28, "xmm11"),
156// XMM12 = (29, "xmm12"),
157// XMM13 = (30, "xmm13"),
158// XMM14 = (31, "xmm14"),
159// XMM15 = (32, "xmm15"),
160//
161// ST0 = (33, "st0"),
162// ST1 = (34, "st1"),
163// ST2 = (35, "st2"),
164// ST3 = (36, "st3"),
165// ST4 = (37, "st4"),
166// ST5 = (38, "st5"),
167// ST6 = (39, "st6"),
168// ST7 = (40, "st7"),
169//
170// MM0 = (41, "mm0"),
171// MM1 = (42, "mm1"),
172// MM2 = (43, "mm2"),
173// MM3 = (44, "mm3"),
174// MM4 = (45, "mm4"),
175// MM5 = (46, "mm5"),
176// MM6 = (47, "mm6"),
177// MM7 = (48, "mm7"),
178//
179// RFLAGS = (49, "rFLAGS"),
180// ES = (50, "es"),
181// CS = (51, "cs"),
182// SS = (52, "ss"),
183// DS = (53, "ds"),
184// FS = (54, "fs"),
185// GS = (55, "gs"),
186//
187// FS_BASE = (58, "fs.base"),
188// GS_BASE = (59, "gs.base"),
189//
190// TR = (62, "tr"),
191// LDTR = (63, "ldtr"),
192// MXCSR = (64, "mxcsr"),
193// FCW = (65, "fcw"),
194// FSW = (66, "fsw"),
195//
196// XMM16 = (67, "xmm16"),
197// XMM17 = (68, "xmm17"),
198// XMM18 = (69, "xmm18"),
199// XMM19 = (70, "xmm19"),
200// XMM20 = (71, "xmm20"),
201// XMM21 = (72, "xmm21"),
202// XMM22 = (73, "xmm22"),
203// XMM23 = (74, "xmm23"),
204// XMM24 = (75, "xmm24"),
205// XMM25 = (76, "xmm25"),
206// XMM26 = (77, "xmm26"),
207// XMM27 = (78, "xmm27"),
208// XMM28 = (79, "xmm28"),
209// XMM29 = (80, "xmm29"),
210// XMM30 = (81, "xmm30"),
211// XMM31 = (82, "xmm31"),
212//
213// K0 = (118, "k0"),
214// K1 = (119, "k1"),
215// K2 = (120, "k2"),
216// K3 = (121, "k3"),
217// K4 = (122, "k4"),
218// K5 = (123, "k5"),
219// K6 = (124, "k6"),
220// K7 = (125, "k7"),
src-self-hosted/ir.zig+15-1
......@@ -87,7 +87,6 @@ pub const Inst = struct {
8787 .alloc,
8888 .retvoid,
8989 .unreach,
90 .arg,
9190 .breakpoint,
9291 .dbg_stmt,
9392 => NoOp,
......@@ -115,6 +114,7 @@ pub const Inst = struct {
115114 .store,
116115 => BinOp,
117116
117 .arg => Arg,
118118 .assembly => Assembly,
119119 .block => Block,
120120 .br => Br,
......@@ -253,6 +253,20 @@ pub const Inst = struct {
253253 }
254254 };
255255
256 pub const Arg = struct {
257 pub const base_tag = Tag.arg;
258
259 base: Inst,
260 name: [*:0]const u8,
261
262 pub fn operandCount(self: *const Arg) usize {
263 return 0;
264 }
265 pub fn getOperand(self: *const Arg, index: usize) ?*Inst {
266 return null;
267 }
268 };
269
256270 pub const Assembly = struct {
257271 pub const base_tag = Tag.assembly;
258272
src-self-hosted/link.zig+80-33
......@@ -391,6 +391,17 @@ pub const File = struct {
391391 const minimum_text_block_size = 64;
392392 const min_text_capacity = minimum_text_block_size * alloc_num / alloc_den;
393393
394 pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.hash, Type.eql, true);
395
396 const DbgInfoTypeReloc = struct {
397 /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl).
398 /// This is where the .debug_info tag for the type is.
399 off: u32,
400 /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl).
401 /// List of DW.AT_type / DW.FORM_ref4 that points to the type.
402 relocs: std.ArrayListUnmanaged(u32),
403 };
404
394405 pub const TextBlock = struct {
395406 /// Each decl always gets a local symbol with the fully qualified name.
396407 /// The vaddr and size are found here directly.
......@@ -991,6 +1002,7 @@ pub const File = struct {
9911002 pub const abbrev_subprogram_retvoid = 3;
9921003 pub const abbrev_base_type = 4;
9931004 pub const abbrev_pad1 = 5;
1005 pub const abbrev_parameter = 6;
9941006
9951007 /// Commit pending changes and write headers.
9961008 pub fn flush(self: *Elf) !void {
......@@ -1044,6 +1056,12 @@ pub const File = struct {
10441056 abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header
10451057 0, 0, // table sentinel
10461058
1059 abbrev_parameter, DW.TAG_formal_parameter, DW.CHILDREN_no, // header
1060 DW.AT_location , DW.FORM_exprloc,
1061 DW.AT_type , DW.FORM_ref4,
1062 DW.AT_name , DW.FORM_string,
1063 0, 0, // table sentinel
1064
10471065 0, 0, 0, // section sentinel
10481066 };
10491067
......@@ -1088,7 +1106,8 @@ pub const File = struct {
10881106 // not including the initial length itself.
10891107 // We have to come back and write it later after we know the size.
10901108 const after_init_len = di_buf.items.len + init_len_size;
1091 const dbg_info_end = last_dbg_info_decl.dbg_info_off + last_dbg_info_decl.dbg_info_len;
1109 // +1 for the final 0 that ends the compilation unit children.
1110 const dbg_info_end = last_dbg_info_decl.dbg_info_off + last_dbg_info_decl.dbg_info_len + 1;
10921111 const init_len = dbg_info_end - after_init_len;
10931112 switch (self.ptr_width) {
10941113 .p32 => {
......@@ -1138,7 +1157,7 @@ pub const File = struct {
11381157 @panic("TODO: handle .debug_info header exceeding its padding");
11391158 }
11401159 const jmp_amt = first_dbg_info_decl.dbg_info_off - di_buf.items.len;
1141 try self.pwriteDbgInfoNops(0, di_buf.items, jmp_amt, debug_info_sect.sh_offset);
1160 try self.pwriteDbgInfoNops(0, di_buf.items, jmp_amt, false, debug_info_sect.sh_offset);
11421161 self.debug_info_header_dirty = false;
11431162 }
11441163
......@@ -1858,12 +1877,19 @@ pub const File = struct {
18581877 var dbg_info_buffer = std.ArrayList(u8).init(self.base.allocator);
18591878 defer dbg_info_buffer.deinit();
18601879
1880 var dbg_info_type_relocs: DbgInfoTypeRelocsTable = .{};
1881 defer {
1882 for (dbg_info_type_relocs.items()) |*entry| {
1883 entry.value.relocs.deinit(self.base.allocator);
1884 }
1885 dbg_info_type_relocs.deinit(self.base.allocator);
1886 }
1887
18611888 const typed_value = decl.typed_value.most_recent.typed_value;
18621889 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {
18631890 .Fn => true,
18641891 else => false,
18651892 };
1866 var fn_ret_has_bits: bool = undefined;
18671893 if (is_fn) {
18681894 // For functions we need to add a prologue to the debug line program.
18691895 try dbg_line_buffer.ensureCapacity(26);
......@@ -1919,7 +1945,8 @@ pub const File = struct {
19191945 const decl_name_with_null = decl.name[0..mem.lenZ(decl.name) + 1];
19201946 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len);
19211947
1922 fn_ret_has_bits = typed_value.ty.fnReturnType().hasCodeGenBits();
1948 const fn_ret_type = typed_value.ty.fnReturnType();
1949 const fn_ret_has_bits = fn_ret_type.hasCodeGenBits();
19231950 if (fn_ret_has_bits) {
19241951 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
19251952 } else {
......@@ -1933,14 +1960,21 @@ pub const File = struct {
19331960 assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);
19341961 dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4
19351962 if (fn_ret_has_bits) {
1936 assert(self.getRelocDbgInfoSubprogramRetType() == dbg_info_buffer.items.len);
1963 const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, fn_ret_type);
1964 if (!gop.found_existing) {
1965 gop.entry.value = .{
1966 .off = undefined,
1967 .relocs = .{},
1968 };
1969 }
1970 try gop.entry.value.relocs.append(self.base.allocator, @intCast(u32, dbg_info_buffer.items.len));
19371971 dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4
19381972 }
19391973 dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string
19401974 } else {
19411975 // TODO implement .debug_info for global variables
19421976 }
1943 const res = try codegen.generateSymbol(self, decl.src(), typed_value, &code_buffer, &dbg_line_buffer, &dbg_info_buffer);
1977 const res = try codegen.generateSymbol(self, decl.src(), typed_value, &code_buffer, &dbg_line_buffer, &dbg_info_buffer, &dbg_info_type_relocs);
19441978 const code = switch (res) {
19451979 .externally_managed => |x| x,
19461980 .appended => code_buffer.items,
......@@ -2011,7 +2045,6 @@ pub const File = struct {
20112045 const text_block = &decl.link.elf;
20122046
20132047 // If the Decl is a function, we need to update the .debug_line program.
2014 var fn_ret_type_index: usize = undefined;
20152048 if (is_fn) {
20162049 // Perform the relocations based on vaddr.
20172050 switch (self.ptr_width) {
......@@ -2117,28 +2150,30 @@ pub const File = struct {
21172150 const file_pos = debug_line_sect.sh_offset + src_fn.off;
21182151 try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos);
21192152
2120 // .debug_info
2121 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 2);
2122 // End the TAG_subprogram children.
2123 dbg_info_buffer.appendAssumeCapacity(0);
2124 if (fn_ret_has_bits) {
2125 // Now we do the return type of the function. The relocation must be performed
2126 // later after the offset for this subprogram is computed.
2127 fn_ret_type_index = dbg_info_buffer.items.len;
2128 try self.addDbgInfoType(typed_value.ty.fnReturnType(), &dbg_info_buffer);
2129 }
2153 // .debug_info - End the TAG_subprogram children.
2154 try dbg_info_buffer.append(0);
2155 }
2156
2157 // Now we emit the .debug_info types of the Decl. These will count towards the size of
2158 // the buffer, so we have to do it before computing the offset, and we can't perform the actual
2159 // relocations yet.
2160 for (dbg_info_type_relocs.items()) |*entry| {
2161 entry.value.off = @intCast(u32, dbg_info_buffer.items.len);
2162 try self.addDbgInfoType(entry.key, &dbg_info_buffer);
21302163 }
21312164
21322165 try self.updateDeclDebugInfoAllocation(text_block, @intCast(u32, dbg_info_buffer.items.len));
21332166
2134 if (is_fn and fn_ret_has_bits) {
2135 // Perform function return type relocation.
2136 mem.writeInt(
2137 u32,
2138 dbg_info_buffer.items[self.getRelocDbgInfoSubprogramRetType()..][0..4],
2139 text_block.dbg_info_off + @intCast(u32, fn_ret_type_index),
2140 target_endian,
2141 );
2167 // Now that we have the offset assigned we can finally perform type relocations.
2168 for (dbg_info_type_relocs.items()) |entry| {
2169 for (entry.value.relocs.items) |off| {
2170 mem.writeInt(
2171 u32,
2172 dbg_info_buffer.items[off..][0..4],
2173 text_block.dbg_info_off + entry.value.off,
2174 target_endian,
2175 );
2176 }
21422177 }
21432178
21442179 try self.writeDeclDebugInfo(text_block, dbg_info_buffer.items);
......@@ -2151,7 +2186,8 @@ pub const File = struct {
21512186 /// Asserts the type has codegen bits.
21522187 fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !void {
21532188 switch (ty.zigTypeTag()) {
2154 .Void, .NoReturn => unreachable,
2189 .Void => unreachable,
2190 .NoReturn => unreachable,
21552191 .Bool => {
21562192 try dbg_info_buffer.appendSlice(&[_]u8{
21572193 abbrev_base_type,
......@@ -2201,7 +2237,7 @@ pub const File = struct {
22012237 text_block.dbg_info_next = null;
22022238 // Populate where it used to be with NOPs.
22032239 const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off;
2204 try self.pwriteDbgInfoNops(0, &[0]u8{}, text_block.dbg_info_len, file_pos);
2240 try self.pwriteDbgInfoNops(0, &[0]u8{}, text_block.dbg_info_len, false, file_pos);
22052241 // TODO Look at the free list before appending at the end.
22062242 text_block.dbg_info_prev = last;
22072243 last.dbg_info_next = text_block;
......@@ -2238,7 +2274,8 @@ pub const File = struct {
22382274 const debug_info_sect = &self.sections.items[self.debug_info_section_index.?];
22392275
22402276 const last_decl = self.dbg_info_decl_last.?;
2241 const needed_size = last_decl.dbg_info_off + last_decl.dbg_info_len;
2277 // +1 for a trailing zero to end the children of the decl tag.
2278 const needed_size = last_decl.dbg_info_off + last_decl.dbg_info_len + 1;
22422279 if (needed_size != debug_info_sect.sh_size) {
22432280 if (needed_size > self.allocatedSize(debug_info_sect.sh_offset)) {
22442281 const new_offset = self.findFreeSpace(needed_size, 1);
......@@ -2265,10 +2302,13 @@ pub const File = struct {
22652302 else
22662303 0;
22672304
2305 // To end the children of the decl tag.
2306 const trailing_zero = text_block.dbg_info_next == null;
2307
22682308 // We only have support for one compilation unit so far, so the offsets are directly
22692309 // from the .debug_info section.
22702310 const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off;
2271 try self.pwriteDbgInfoNops(prev_padding_size, dbg_info_buf, next_padding_size, file_pos);
2311 try self.pwriteDbgInfoNops(prev_padding_size, dbg_info_buf, next_padding_size, trailing_zero, file_pos);
22722312 }
22732313
22742314 /// Must be called only after a successful call to `updateDecl`.
......@@ -2598,10 +2638,6 @@ pub const File = struct {
25982638 return dbg_info_low_pc_reloc_index + self.ptrWidthBytes();
25992639 }
26002640
2601 fn getRelocDbgInfoSubprogramRetType(self: Elf) u32 {
2602 return self.getRelocDbgInfoSubprogramHighPC() + 4;
2603 }
2604
26052641 fn dbgLineNeededHeaderBytes(self: Elf) u32 {
26062642 const directory_entry_format_count = 1;
26072643 const file_name_entry_format_count = 1;
......@@ -2710,6 +2746,7 @@ pub const File = struct {
27102746 prev_padding_size: usize,
27112747 buf: []const u8,
27122748 next_padding_size: usize,
2749 trailing_zero: bool,
27132750 offset: usize,
27142751 ) !void {
27152752 const tracy = trace(@src());
......@@ -2761,6 +2798,16 @@ pub const File = struct {
27612798 vec_index += 1;
27622799 }
27632800 }
2801
2802 if (trailing_zero) {
2803 var zbuf = [1]u8{0};
2804 vecs[vec_index] = .{
2805 .iov_base = &zbuf,
2806 .iov_len = zbuf.len,
2807 };
2808 vec_index += 1;
2809 }
2810
27642811 try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
27652812 }
27662813
src-self-hosted/type.zig+65-1
......@@ -103,7 +103,6 @@ pub const Type = extern union {
103103 }
104104
105105 pub fn eql(a: Type, b: Type) bool {
106 //std.debug.warn("test {} == {}\n", .{ a, b });
107106 // As a shortcut, if the small tags / addresses match, we're done.
108107 if (a.tag_if_small_enough == b.tag_if_small_enough)
109108 return true;
......@@ -197,6 +196,71 @@ pub const Type = extern union {
197196 }
198197 }
199198
199 pub fn hash(self: Type) u32 {
200 var hasher = std.hash.Wyhash.init(0);
201 const zig_type_tag = self.zigTypeTag();
202 std.hash.autoHash(&hasher, zig_type_tag);
203 switch (zig_type_tag) {
204 .Type,
205 .Void,
206 .Bool,
207 .NoReturn,
208 .ComptimeFloat,
209 .ComptimeInt,
210 .Undefined,
211 .Null,
212 => {}, // The zig type tag is all that is needed to distinguish.
213
214 .Pointer => {
215 // TODO implement more pointer type hashing
216 },
217 .Int => {
218 // Detect that e.g. u64 != usize, even if the bits match on a particular target.
219 if (self.isNamedInt()) {
220 std.hash.autoHash(&hasher, self.tag());
221 } else {
222 // Remaining cases are arbitrary sized integers.
223 // The target will not be branched upon, because we handled target-dependent cases above.
224 const info = self.intInfo(@as(Target, undefined));
225 std.hash.autoHash(&hasher, info.signed);
226 std.hash.autoHash(&hasher, info.bits);
227 }
228 },
229 .Array => {
230 std.hash.autoHash(&hasher, self.arrayLen());
231 std.hash.autoHash(&hasher, self.elemType().hash());
232 // TODO hash array sentinel
233 },
234 .Fn => {
235 std.hash.autoHash(&hasher, self.fnReturnType().hash());
236 std.hash.autoHash(&hasher, self.fnCallingConvention());
237 const params_len = self.fnParamLen();
238 std.hash.autoHash(&hasher, params_len);
239 var i: usize = 0;
240 while (i < params_len) : (i += 1) {
241 std.hash.autoHash(&hasher, self.fnParamType(i).hash());
242 }
243 },
244 .Float,
245 .Struct,
246 .Optional,
247 .ErrorUnion,
248 .ErrorSet,
249 .Enum,
250 .Union,
251 .BoundFn,
252 .Opaque,
253 .Frame,
254 .AnyFrame,
255 .Vector,
256 .EnumLiteral,
257 => {
258 // TODO implement more type hashing
259 },
260 }
261 return @truncate(u32, hasher.final());
262 }
263
200264 pub fn copy(self: Type, allocator: *Allocator) error{OutOfMemory}!Type {
201265 if (self.tag_if_small_enough < Tag.no_payload_count) {
202266 return Type{ .tag_if_small_enough = self.tag_if_small_enough };
src-self-hosted/zir.zig+27-2
......@@ -211,7 +211,6 @@ pub const Inst = struct {
211211
212212 pub fn Type(tag: Tag) type {
213213 return switch (tag) {
214 .arg,
215214 .breakpoint,
216215 .dbg_stmt,
217216 .returnvoid,
......@@ -268,6 +267,7 @@ pub const Inst = struct {
268267 .xor,
269268 => BinOp,
270269
270 .arg => Arg,
271271 .block => Block,
272272 .@"break" => Break,
273273 .breakvoid => BreakVoid,
......@@ -431,6 +431,16 @@ pub const Inst = struct {
431431 kw_args: struct {},
432432 };
433433
434 pub const Arg = struct {
435 pub const base_tag = Tag.arg;
436 base: Inst,
437
438 positionals: struct {
439 name: []const u8,
440 },
441 kw_args: struct {},
442 };
443
434444 pub const Block = struct {
435445 pub const base_tag = Tag.block;
436446 base: Inst,
......@@ -1843,7 +1853,6 @@ const EmitZIR = struct {
18431853 const new_inst = switch (inst.tag) {
18441854 .constant => unreachable, // excluded from function bodies
18451855
1846 .arg => try self.emitNoOp(inst.src, .arg),
18471856 .breakpoint => try self.emitNoOp(inst.src, .breakpoint),
18481857 .unreach => try self.emitNoOp(inst.src, .@"unreachable"),
18491858 .retvoid => try self.emitNoOp(inst.src, .returnvoid),
......@@ -1886,6 +1895,22 @@ const EmitZIR = struct {
18861895 break :blk &new_inst.base;
18871896 },
18881897
1898 .arg => blk: {
1899 const old_inst = inst.castTag(.arg).?;
1900 const new_inst = try self.arena.allocator.create(Inst.Arg);
1901 new_inst.* = .{
1902 .base = .{
1903 .src = inst.src,
1904 .tag = .arg,
1905 },
1906 .positionals = .{
1907 .name = try self.arena.allocator.dupe(u8, mem.spanZ(old_inst.name)),
1908 },
1909 .kw_args = .{},
1910 };
1911 break :blk &new_inst.base;
1912 },
1913
18891914 .block => blk: {
18901915 const old_inst = inst.castTag(.block).?;
18911916 const new_inst = try self.arena.allocator.create(Inst.Block);
src-self-hosted/zir_sema.zig+3-2
......@@ -408,7 +408,7 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileE
408408 return mod.fail(scope, inst.base.src, "{}", .{inst.positionals.msg});
409409}
410410
411fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
411fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {
412412 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
413413 const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
414414 const param_index = b.instructions.items.len;
......@@ -420,7 +420,8 @@ fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!
420420 });
421421 }
422422 const param_type = fn_ty.fnParamType(param_index);
423 return mod.addNoOp(b, inst.base.src, param_type, .arg);
423 const name = try scope.arena().dupeZ(u8, inst.positionals.name);
424 return mod.addArg(b, inst.base.src, param_type, name);
424425}
425426
426427fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {