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 {...@@ -1301,14 +1301,16 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1301 for (fn_proto.params()) |param, i| {1301 for (fn_proto.params()) |param, i| {
1302 const name_token = param.name_token.?;1302 const name_token = param.name_token.?;
1303 const src = tree.token_locs[name_token].start;1303 const src = tree.token_locs[name_token].start;
1304 const param_name = tree.tokenSlice(name_token);1304 const param_name = tree.tokenSlice(name_token); // TODO: call identifierTokenString
1305 const arg = try gen_scope_arena.allocator.create(zir.Inst.NoOp);1305 const arg = try gen_scope_arena.allocator.create(zir.Inst.Arg);
1306 arg.* = .{1306 arg.* = .{
1307 .base = .{1307 .base = .{
1308 .tag = .arg,1308 .tag = .arg,
1309 .src = src,1309 .src = src,
1310 },1310 },
1311 .positionals = .{},1311 .positionals = .{
1312 .name = param_name,
1313 },
1312 .kw_args = .{},1314 .kw_args = .{},
1313 };1315 };
1314 gen_scope.instructions.items[i] = &arg.base;1316 gen_scope.instructions.items[i] = &arg.base;
...@@ -1934,6 +1936,20 @@ pub fn addBinOp(...@@ -1934,6 +1936,20 @@ pub fn addBinOp(
1934 return &inst.base;1936 return &inst.base;
1935}1937}
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
1937pub fn addBr(1953pub fn addBr(
1938 self: *Module,1954 self: *Module,
1939 scope_block: *Scope.Block,1955 scope_block: *Scope.Block,
...@@ -2535,7 +2551,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst...@@ -2535,7 +2551,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
2535 }2551 }
2536 }2552 }
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 });
2539}2555}
25402556
2541pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst {2557pub 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(...@@ -51,6 +51,7 @@ pub fn generateSymbol(
51 code: *std.ArrayList(u8),51 code: *std.ArrayList(u8),
52 dbg_line: *std.ArrayList(u8),52 dbg_line: *std.ArrayList(u8),
53 dbg_info: *std.ArrayList(u8),53 dbg_info: *std.ArrayList(u8),
54 dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable,
54) GenerateSymbolError!Result {55) GenerateSymbolError!Result {
55 const tracy = trace(@src());56 const tracy = trace(@src());
56 defer tracy.end();57 defer tracy.end();
...@@ -58,57 +59,57 @@ pub fn generateSymbol(...@@ -58,57 +59,57 @@ pub fn generateSymbol(
58 switch (typed_value.ty.zigTypeTag()) {59 switch (typed_value.ty.zigTypeTag()) {
59 .Fn => {60 .Fn => {
60 switch (bin_file.base.options.target.cpu.arch) {61 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 //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
62 //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),63 //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
63 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),64 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
64 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),65 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
65 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),66 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
66 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),67 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
67 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),68 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
68 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),69 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
69 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),70 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
70 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),71 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
71 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),72 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
72 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),73 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
73 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),74 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
74 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),75 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
75 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),76 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
76 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),77 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
77 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),78 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
78 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),79 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
79 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),80 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
80 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),81 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
81 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),82 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
82 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),83 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
83 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),84 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
84 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),85 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
85 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),86 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
86 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),87 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
87 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),88 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
88 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),89 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
89 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),90 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
90 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),91 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
91 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),92 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
92 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),93 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
93 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),94 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
94 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),95 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
95 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),96 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
96 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),97 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
97 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),98 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
98 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),99 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
99 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),100 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
100 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),101 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
101 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),102 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
102 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),103 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
103 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),104 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
104 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),105 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
105 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),106 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
106 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),107 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
107 //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),108 //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
108 //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),109 //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
109 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),110 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
110 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),111 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
111 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info),112 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
112 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."),113 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."),
113 }114 }
114 },115 },
...@@ -122,7 +123,7 @@ pub fn generateSymbol(...@@ -122,7 +123,7 @@ pub fn generateSymbol(
122 switch (try generateSymbol(bin_file, src, .{123 switch (try generateSymbol(bin_file, src, .{
123 .ty = typed_value.ty.elemType(),124 .ty = typed_value.ty.elemType(),
124 .val = sentinel,125 .val = sentinel,
125 }, code, dbg_line, dbg_info)) {126 }, code, dbg_line, dbg_info, dbg_info_type_relocs)) {
126 .appended => return Result{ .appended = {} },127 .appended => return Result{ .appended = {} },
127 .externally_managed => |slice| {128 .externally_managed => |slice| {
128 code.appendSliceAssumeCapacity(slice);129 code.appendSliceAssumeCapacity(slice);
...@@ -225,6 +226,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -225,6 +226,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
225 code: *std.ArrayList(u8),226 code: *std.ArrayList(u8),
226 dbg_line: *std.ArrayList(u8),227 dbg_line: *std.ArrayList(u8),
227 dbg_info: *std.ArrayList(u8),228 dbg_info: *std.ArrayList(u8),
229 dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable,
228 err_msg: ?*ErrorMsg,230 err_msg: ?*ErrorMsg,
229 args: []MCValue,231 args: []MCValue,
230 ret_mcv: MCValue,232 ret_mcv: MCValue,
...@@ -395,6 +397,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -395,6 +397,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
395 code: *std.ArrayList(u8),397 code: *std.ArrayList(u8),
396 dbg_line: *std.ArrayList(u8),398 dbg_line: *std.ArrayList(u8),
397 dbg_info: *std.ArrayList(u8),399 dbg_info: *std.ArrayList(u8),
400 dbg_info_type_relocs: *link.File.Elf.DbgInfoTypeRelocsTable,
398 ) GenerateSymbolError!Result {401 ) GenerateSymbolError!Result {
399 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;402 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 {...@@ -433,6 +436,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
433 .code = code,436 .code = code,
434 .dbg_line = dbg_line,437 .dbg_line = dbg_line,
435 .dbg_info = dbg_info,438 .dbg_info = dbg_info,
439 .dbg_info_type_relocs = dbg_info_type_relocs,
436 .err_msg = null,440 .err_msg = null,
437 .args = undefined, // populated after `resolveCallingConventionValues`441 .args = undefined, // populated after `resolveCallingConventionValues`
438 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`442 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -610,6 +614,23 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -610,6 +614,23 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
610 }614 }
611 }615 }
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
613 fn genFuncInst(self: *Self, inst: *ir.Inst) !MCValue {634 fn genFuncInst(self: *Self, inst: *ir.Inst) !MCValue {
614 switch (inst.tag) {635 switch (inst.tag) {
615 .add => return self.genAdd(inst.castTag(.add).?),636 .add => return self.genAdd(inst.castTag(.add).?),
...@@ -1009,7 +1030,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1009,7 +1030,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1009 }1030 }
1010 }1031 }
10111032
1012 fn genArg(self: *Self, inst: *ir.Inst.NoOp) !MCValue {1033 fn genArg(self: *Self, inst: *ir.Inst.Arg) !MCValue {
1013 if (FreeRegInt == u0) {1034 if (FreeRegInt == u0) {
1014 return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});1035 return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});
1015 }1036 }
...@@ -1022,10 +1043,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1022,10 +1043,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1022 const result = self.args[self.arg_index];1043 const result = self.args[self.arg_index];
1023 self.arg_index += 1;1044 self.arg_index += 1;
10241045
1046 const name_with_null = inst.name[0..mem.lenZ(inst.name) + 1];
1025 switch (result) {1047 switch (result) {
1026 .register => |reg| {1048 .register => |reg| {
1027 branch.registers.putAssumeCapacityNoClobber(reg, .{ .inst = &inst.base });1049 branch.registers.putAssumeCapacityNoClobber(reg, .{ .inst = &inst.base });
1028 branch.markRegUsed(reg);1050 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
1029 },1060 },
1030 else => {},1061 else => {},
1031 }1062 }
src-self-hosted/codegen/riscv64.zig+9
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const DW = std.dwarf;
23
3pub const instructions = struct {4pub const instructions = struct {
4 pub const CallBreak = packed struct {5 pub const CallBreak = packed struct {
...@@ -48,6 +49,10 @@ pub const RawRegister = enum(u8) {...@@ -48,6 +49,10 @@ pub const RawRegister = enum(u8) {
48 x8, x9, x10, x11, x12, x13, x14, x15,49 x8, x9, x10, x11, x12, x13, x14, x15,
49 x16, x17, x18, x19, x20, x21, x22, x23,50 x16, x17, x18, x19, x20, x21, x22, x23,
50 x24, x25, x26, x27, x28, x29, x30, x31,51 x24, x25, x26, x27, x28, x29, x30, x31,
52
53 pub fn dwarfLocOp(reg: RawRegister) u8 {
54 return @enumToInt(reg) + DW.OP_reg0;
55 }
51};56};
5257
53pub const Register = enum(u8) {58pub const Register = enum(u8) {
...@@ -83,6 +88,10 @@ pub const Register = enum(u8) {...@@ -83,6 +88,10 @@ pub const Register = enum(u8) {
83 }88 }
84 return null;89 return null;
85 }90 }
91
92 pub fn dwarfLocOp(reg: Register) u8 {
93 return @enumToInt(reg) + DW.OP_reg0;
94 }
86};95};
8796
88// zig fmt: on97// zig fmt: on
src-self-hosted/codegen/x86.zig+79
...@@ -1,3 +1,6 @@...@@ -1,3 +1,6 @@
1const std = @import("std");
2const DW = std.dwarf;
3
1// zig fmt: off4// zig fmt: off
2pub const Register = enum(u8) {5pub const Register = enum(u8) {
3 // 0 through 7, 32-bit registers. id is int value6 // 0 through 7, 32-bit registers. id is int value
...@@ -37,8 +40,84 @@ pub const Register = enum(u8) {...@@ -37,8 +40,84 @@ pub const Register = enum(u8) {
37 else => null,40 else => null,
38 };41 };
39 }42 }
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 }
40};73};
4174
42// zig fmt: on75// zig fmt: on
4376
44pub const callee_preserved_regs = [_]Register{ .eax, .ecx, .edx, .esi, .edi };77pub 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 @@...@@ -1,4 +1,6 @@
1const std = @import("std");
1const Type = @import("../Type.zig");2const Type = @import("../Type.zig");
3const DW = std.dwarf;
24
3// zig fmt: off5// zig fmt: off
46
...@@ -101,6 +103,30 @@ pub const Register = enum(u8) {...@@ -101,6 +103,30 @@ pub const Register = enum(u8) {
101 pub fn to8(self: Register) Register {103 pub fn to8(self: Register) Register {
102 return @intToEnum(Register, @as(u8, self.id()) + 48);104 return @intToEnum(Register, @as(u8, self.id()) + 48);
103 }105 }
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 }
104};130};
105131
106// zig fmt: on132// zig fmt: on
...@@ -109,3 +135,86 @@ pub const Register = enum(u8) {...@@ -109,3 +135,86 @@ pub const Register = enum(u8) {
109pub const callee_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .rsi, .rdi, .r8, .r9, .r10, .r11 };135pub const callee_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .rsi, .rdi, .r8, .r9, .r10, .r11 };
110pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };136pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };
111pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx };137pub 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 {...@@ -87,7 +87,6 @@ pub const Inst = struct {
87 .alloc,87 .alloc,
88 .retvoid,88 .retvoid,
89 .unreach,89 .unreach,
90 .arg,
91 .breakpoint,90 .breakpoint,
92 .dbg_stmt,91 .dbg_stmt,
93 => NoOp,92 => NoOp,
...@@ -115,6 +114,7 @@ pub const Inst = struct {...@@ -115,6 +114,7 @@ pub const Inst = struct {
115 .store,114 .store,
116 => BinOp,115 => BinOp,
117116
117 .arg => Arg,
118 .assembly => Assembly,118 .assembly => Assembly,
119 .block => Block,119 .block => Block,
120 .br => Br,120 .br => Br,
...@@ -253,6 +253,20 @@ pub const Inst = struct {...@@ -253,6 +253,20 @@ pub const Inst = struct {
253 }253 }
254 };254 };
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
256 pub const Assembly = struct {270 pub const Assembly = struct {
257 pub const base_tag = Tag.assembly;271 pub const base_tag = Tag.assembly;
258272
src-self-hosted/link.zig+80-33
...@@ -391,6 +391,17 @@ pub const File = struct {...@@ -391,6 +391,17 @@ pub const File = struct {
391 const minimum_text_block_size = 64;391 const minimum_text_block_size = 64;
392 const min_text_capacity = minimum_text_block_size * alloc_num / alloc_den;392 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
394 pub const TextBlock = struct {405 pub const TextBlock = struct {
395 /// Each decl always gets a local symbol with the fully qualified name.406 /// Each decl always gets a local symbol with the fully qualified name.
396 /// The vaddr and size are found here directly.407 /// The vaddr and size are found here directly.
...@@ -991,6 +1002,7 @@ pub const File = struct {...@@ -991,6 +1002,7 @@ pub const File = struct {
991 pub const abbrev_subprogram_retvoid = 3;1002 pub const abbrev_subprogram_retvoid = 3;
992 pub const abbrev_base_type = 4;1003 pub const abbrev_base_type = 4;
993 pub const abbrev_pad1 = 5;1004 pub const abbrev_pad1 = 5;
1005 pub const abbrev_parameter = 6;
9941006
995 /// Commit pending changes and write headers.1007 /// Commit pending changes and write headers.
996 pub fn flush(self: *Elf) !void {1008 pub fn flush(self: *Elf) !void {
...@@ -1044,6 +1056,12 @@ pub const File = struct {...@@ -1044,6 +1056,12 @@ pub const File = struct {
1044 abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header1056 abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header
1045 0, 0, // table sentinel1057 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
1047 0, 0, 0, // section sentinel1065 0, 0, 0, // section sentinel
1048 };1066 };
10491067
...@@ -1088,7 +1106,8 @@ pub const File = struct {...@@ -1088,7 +1106,8 @@ pub const File = struct {
1088 // not including the initial length itself.1106 // not including the initial length itself.
1089 // We have to come back and write it later after we know the size.1107 // We have to come back and write it later after we know the size.
1090 const after_init_len = di_buf.items.len + init_len_size;1108 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;
1092 const init_len = dbg_info_end - after_init_len;1111 const init_len = dbg_info_end - after_init_len;
1093 switch (self.ptr_width) {1112 switch (self.ptr_width) {
1094 .p32 => {1113 .p32 => {
...@@ -1138,7 +1157,7 @@ pub const File = struct {...@@ -1138,7 +1157,7 @@ pub const File = struct {
1138 @panic("TODO: handle .debug_info header exceeding its padding");1157 @panic("TODO: handle .debug_info header exceeding its padding");
1139 }1158 }
1140 const jmp_amt = first_dbg_info_decl.dbg_info_off - di_buf.items.len;1159 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);
1142 self.debug_info_header_dirty = false;1161 self.debug_info_header_dirty = false;
1143 }1162 }
11441163
...@@ -1858,12 +1877,19 @@ pub const File = struct {...@@ -1858,12 +1877,19 @@ pub const File = struct {
1858 var dbg_info_buffer = std.ArrayList(u8).init(self.base.allocator);1877 var dbg_info_buffer = std.ArrayList(u8).init(self.base.allocator);
1859 defer dbg_info_buffer.deinit();1878 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
1861 const typed_value = decl.typed_value.most_recent.typed_value;1888 const typed_value = decl.typed_value.most_recent.typed_value;
1862 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {1889 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {
1863 .Fn => true,1890 .Fn => true,
1864 else => false,1891 else => false,
1865 };1892 };
1866 var fn_ret_has_bits: bool = undefined;
1867 if (is_fn) {1893 if (is_fn) {
1868 // For functions we need to add a prologue to the debug line program.1894 // For functions we need to add a prologue to the debug line program.
1869 try dbg_line_buffer.ensureCapacity(26);1895 try dbg_line_buffer.ensureCapacity(26);
...@@ -1919,7 +1945,8 @@ pub const File = struct {...@@ -1919,7 +1945,8 @@ pub const File = struct {
1919 const decl_name_with_null = decl.name[0..mem.lenZ(decl.name) + 1];1945 const decl_name_with_null = decl.name[0..mem.lenZ(decl.name) + 1];
1920 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 25 + decl_name_with_null.len);1946 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();
1923 if (fn_ret_has_bits) {1950 if (fn_ret_has_bits) {
1924 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);1951 dbg_info_buffer.appendAssumeCapacity(abbrev_subprogram);
1925 } else {1952 } else {
...@@ -1933,14 +1960,21 @@ pub const File = struct {...@@ -1933,14 +1960,21 @@ pub const File = struct {
1933 assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);1960 assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len);
1934 dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data41961 dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4
1935 if (fn_ret_has_bits) {1962 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));
1937 dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref41971 dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4
1938 }1972 }
1939 dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string1973 dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string
1940 } else {1974 } else {
1941 // TODO implement .debug_info for global variables1975 // TODO implement .debug_info for global variables
1942 }1976 }
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);
1944 const code = switch (res) {1978 const code = switch (res) {
1945 .externally_managed => |x| x,1979 .externally_managed => |x| x,
1946 .appended => code_buffer.items,1980 .appended => code_buffer.items,
...@@ -2011,7 +2045,6 @@ pub const File = struct {...@@ -2011,7 +2045,6 @@ pub const File = struct {
2011 const text_block = &decl.link.elf;2045 const text_block = &decl.link.elf;
20122046
2013 // If the Decl is a function, we need to update the .debug_line program.2047 // If the Decl is a function, we need to update the .debug_line program.
2014 var fn_ret_type_index: usize = undefined;
2015 if (is_fn) {2048 if (is_fn) {
2016 // Perform the relocations based on vaddr.2049 // Perform the relocations based on vaddr.
2017 switch (self.ptr_width) {2050 switch (self.ptr_width) {
...@@ -2117,28 +2150,30 @@ pub const File = struct {...@@ -2117,28 +2150,30 @@ pub const File = struct {
2117 const file_pos = debug_line_sect.sh_offset + src_fn.off;2150 const file_pos = debug_line_sect.sh_offset + src_fn.off;
2118 try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos);2151 try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos);
21192152
2120 // .debug_info2153 // .debug_info - End the TAG_subprogram children.
2121 try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 2);2154 try dbg_info_buffer.append(0);
2122 // End the TAG_subprogram children.2155 }
2123 dbg_info_buffer.appendAssumeCapacity(0);2156
2124 if (fn_ret_has_bits) {2157 // Now we emit the .debug_info types of the Decl. These will count towards the size of
2125 // Now we do the return type of the function. The relocation must be performed2158 // the buffer, so we have to do it before computing the offset, and we can't perform the actual
2126 // later after the offset for this subprogram is computed.2159 // relocations yet.
2127 fn_ret_type_index = dbg_info_buffer.items.len;2160 for (dbg_info_type_relocs.items()) |*entry| {
2128 try self.addDbgInfoType(typed_value.ty.fnReturnType(), &dbg_info_buffer);2161 entry.value.off = @intCast(u32, dbg_info_buffer.items.len);
2129 }2162 try self.addDbgInfoType(entry.key, &dbg_info_buffer);
2130 }2163 }
21312164
2132 try self.updateDeclDebugInfoAllocation(text_block, @intCast(u32, dbg_info_buffer.items.len));2165 try self.updateDeclDebugInfoAllocation(text_block, @intCast(u32, dbg_info_buffer.items.len));
21332166
2134 if (is_fn and fn_ret_has_bits) {2167 // Now that we have the offset assigned we can finally perform type relocations.
2135 // Perform function return type relocation.2168 for (dbg_info_type_relocs.items()) |entry| {
2136 mem.writeInt(2169 for (entry.value.relocs.items) |off| {
2137 u32,2170 mem.writeInt(
2138 dbg_info_buffer.items[self.getRelocDbgInfoSubprogramRetType()..][0..4],2171 u32,
2139 text_block.dbg_info_off + @intCast(u32, fn_ret_type_index),2172 dbg_info_buffer.items[off..][0..4],
2140 target_endian,2173 text_block.dbg_info_off + entry.value.off,
2141 );2174 target_endian,
2175 );
2176 }
2142 }2177 }
21432178
2144 try self.writeDeclDebugInfo(text_block, dbg_info_buffer.items);2179 try self.writeDeclDebugInfo(text_block, dbg_info_buffer.items);
...@@ -2151,7 +2186,8 @@ pub const File = struct {...@@ -2151,7 +2186,8 @@ pub const File = struct {
2151 /// Asserts the type has codegen bits.2186 /// Asserts the type has codegen bits.
2152 fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !void {2187 fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !void {
2153 switch (ty.zigTypeTag()) {2188 switch (ty.zigTypeTag()) {
2154 .Void, .NoReturn => unreachable,2189 .Void => unreachable,
2190 .NoReturn => unreachable,
2155 .Bool => {2191 .Bool => {
2156 try dbg_info_buffer.appendSlice(&[_]u8{2192 try dbg_info_buffer.appendSlice(&[_]u8{
2157 abbrev_base_type,2193 abbrev_base_type,
...@@ -2201,7 +2237,7 @@ pub const File = struct {...@@ -2201,7 +2237,7 @@ pub const File = struct {
2201 text_block.dbg_info_next = null;2237 text_block.dbg_info_next = null;
2202 // Populate where it used to be with NOPs.2238 // Populate where it used to be with NOPs.
2203 const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off;2239 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);
2205 // TODO Look at the free list before appending at the end.2241 // TODO Look at the free list before appending at the end.
2206 text_block.dbg_info_prev = last;2242 text_block.dbg_info_prev = last;
2207 last.dbg_info_next = text_block;2243 last.dbg_info_next = text_block;
...@@ -2238,7 +2274,8 @@ pub const File = struct {...@@ -2238,7 +2274,8 @@ pub const File = struct {
2238 const debug_info_sect = &self.sections.items[self.debug_info_section_index.?];2274 const debug_info_sect = &self.sections.items[self.debug_info_section_index.?];
22392275
2240 const last_decl = self.dbg_info_decl_last.?;2276 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;
2242 if (needed_size != debug_info_sect.sh_size) {2279 if (needed_size != debug_info_sect.sh_size) {
2243 if (needed_size > self.allocatedSize(debug_info_sect.sh_offset)) {2280 if (needed_size > self.allocatedSize(debug_info_sect.sh_offset)) {
2244 const new_offset = self.findFreeSpace(needed_size, 1);2281 const new_offset = self.findFreeSpace(needed_size, 1);
...@@ -2265,10 +2302,13 @@ pub const File = struct {...@@ -2265,10 +2302,13 @@ pub const File = struct {
2265 else2302 else
2266 0;2303 0;
22672304
2305 // To end the children of the decl tag.
2306 const trailing_zero = text_block.dbg_info_next == null;
2307
2268 // We only have support for one compilation unit so far, so the offsets are directly2308 // We only have support for one compilation unit so far, so the offsets are directly
2269 // from the .debug_info section.2309 // from the .debug_info section.
2270 const file_pos = debug_info_sect.sh_offset + text_block.dbg_info_off;2310 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);
2272 }2312 }
22732313
2274 /// Must be called only after a successful call to `updateDecl`.2314 /// Must be called only after a successful call to `updateDecl`.
...@@ -2598,10 +2638,6 @@ pub const File = struct {...@@ -2598,10 +2638,6 @@ pub const File = struct {
2598 return dbg_info_low_pc_reloc_index + self.ptrWidthBytes();2638 return dbg_info_low_pc_reloc_index + self.ptrWidthBytes();
2599 }2639 }
26002640
2601 fn getRelocDbgInfoSubprogramRetType(self: Elf) u32 {
2602 return self.getRelocDbgInfoSubprogramHighPC() + 4;
2603 }
2604
2605 fn dbgLineNeededHeaderBytes(self: Elf) u32 {2641 fn dbgLineNeededHeaderBytes(self: Elf) u32 {
2606 const directory_entry_format_count = 1;2642 const directory_entry_format_count = 1;
2607 const file_name_entry_format_count = 1;2643 const file_name_entry_format_count = 1;
...@@ -2710,6 +2746,7 @@ pub const File = struct {...@@ -2710,6 +2746,7 @@ pub const File = struct {
2710 prev_padding_size: usize,2746 prev_padding_size: usize,
2711 buf: []const u8,2747 buf: []const u8,
2712 next_padding_size: usize,2748 next_padding_size: usize,
2749 trailing_zero: bool,
2713 offset: usize,2750 offset: usize,
2714 ) !void {2751 ) !void {
2715 const tracy = trace(@src());2752 const tracy = trace(@src());
...@@ -2761,6 +2798,16 @@ pub const File = struct {...@@ -2761,6 +2798,16 @@ pub const File = struct {
2761 vec_index += 1;2798 vec_index += 1;
2762 }2799 }
2763 }2800 }
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
2764 try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);2811 try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
2765 }2812 }
27662813
src-self-hosted/type.zig+65-1
...@@ -103,7 +103,6 @@ pub const Type = extern union {...@@ -103,7 +103,6 @@ pub const Type = extern union {
103 }103 }
104104
105 pub fn eql(a: Type, b: Type) bool {105 pub fn eql(a: Type, b: Type) bool {
106 //std.debug.warn("test {} == {}\n", .{ a, b });
107 // As a shortcut, if the small tags / addresses match, we're done.106 // As a shortcut, if the small tags / addresses match, we're done.
108 if (a.tag_if_small_enough == b.tag_if_small_enough)107 if (a.tag_if_small_enough == b.tag_if_small_enough)
109 return true;108 return true;
...@@ -197,6 +196,71 @@ pub const Type = extern union {...@@ -197,6 +196,71 @@ pub const Type = extern union {
197 }196 }
198 }197 }
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
200 pub fn copy(self: Type, allocator: *Allocator) error{OutOfMemory}!Type {264 pub fn copy(self: Type, allocator: *Allocator) error{OutOfMemory}!Type {
201 if (self.tag_if_small_enough < Tag.no_payload_count) {265 if (self.tag_if_small_enough < Tag.no_payload_count) {
202 return Type{ .tag_if_small_enough = self.tag_if_small_enough };266 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 {...@@ -211,7 +211,6 @@ pub const Inst = struct {
211211
212 pub fn Type(tag: Tag) type {212 pub fn Type(tag: Tag) type {
213 return switch (tag) {213 return switch (tag) {
214 .arg,
215 .breakpoint,214 .breakpoint,
216 .dbg_stmt,215 .dbg_stmt,
217 .returnvoid,216 .returnvoid,
...@@ -268,6 +267,7 @@ pub const Inst = struct {...@@ -268,6 +267,7 @@ pub const Inst = struct {
268 .xor,267 .xor,
269 => BinOp,268 => BinOp,
270269
270 .arg => Arg,
271 .block => Block,271 .block => Block,
272 .@"break" => Break,272 .@"break" => Break,
273 .breakvoid => BreakVoid,273 .breakvoid => BreakVoid,
...@@ -431,6 +431,16 @@ pub const Inst = struct {...@@ -431,6 +431,16 @@ pub const Inst = struct {
431 kw_args: struct {},431 kw_args: struct {},
432 };432 };
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
434 pub const Block = struct {444 pub const Block = struct {
435 pub const base_tag = Tag.block;445 pub const base_tag = Tag.block;
436 base: Inst,446 base: Inst,
...@@ -1843,7 +1853,6 @@ const EmitZIR = struct {...@@ -1843,7 +1853,6 @@ const EmitZIR = struct {
1843 const new_inst = switch (inst.tag) {1853 const new_inst = switch (inst.tag) {
1844 .constant => unreachable, // excluded from function bodies1854 .constant => unreachable, // excluded from function bodies
18451855
1846 .arg => try self.emitNoOp(inst.src, .arg),
1847 .breakpoint => try self.emitNoOp(inst.src, .breakpoint),1856 .breakpoint => try self.emitNoOp(inst.src, .breakpoint),
1848 .unreach => try self.emitNoOp(inst.src, .@"unreachable"),1857 .unreach => try self.emitNoOp(inst.src, .@"unreachable"),
1849 .retvoid => try self.emitNoOp(inst.src, .returnvoid),1858 .retvoid => try self.emitNoOp(inst.src, .returnvoid),
...@@ -1886,6 +1895,22 @@ const EmitZIR = struct {...@@ -1886,6 +1895,22 @@ const EmitZIR = struct {
1886 break :blk &new_inst.base;1895 break :blk &new_inst.base;
1887 },1896 },
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
1889 .block => blk: {1914 .block => blk: {
1890 const old_inst = inst.castTag(.block).?;1915 const old_inst = inst.castTag(.block).?;
1891 const new_inst = try self.arena.allocator.create(Inst.Block);1916 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...@@ -408,7 +408,7 @@ fn analyzeInstCompileError(mod: *Module, scope: *Scope, inst: *zir.Inst.CompileE
408 return mod.fail(scope, inst.base.src, "{}", .{inst.positionals.msg});408 return mod.fail(scope, inst.base.src, "{}", .{inst.positionals.msg});
409}409}
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 {
412 const b = try mod.requireRuntimeBlock(scope, inst.base.src);412 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
413 const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty;413 const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
414 const param_index = b.instructions.items.len;414 const param_index = b.instructions.items.len;
...@@ -420,7 +420,8 @@ fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!...@@ -420,7 +420,8 @@ fn analyzeInstArg(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!
420 });420 });
421 }421 }
422 const param_type = fn_ty.fnParamType(param_index);422 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);
424}425}
425426
426fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {427fn analyzeInstBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {