| author | |
| committer | |
| log | 76654015009038a07f14b9eb8500bb84e9e28099 |
| tree | 1fb8848228473a8d9e85cf4fb30305f0671df94b |
| parent | 4e5495e443f8978f1e0fd8ccb6670a95f014f3b1 |
These were disabled during the MIR transition3 files changed, 140 insertions(+), 93 deletions(-)
src/arch/arm/CodeGen.zig+17-89| ... | ... | @@ -43,7 +43,7 @@ err_msg: ?*ErrorMsg, |
| 43 | 43 | args: []MCValue, |
| 44 | 44 | ret_mcv: MCValue, |
| 45 | 45 | fn_type: Type, |
| 46 | arg_index: usize, | |
| 46 | arg_index: u32, | |
| 47 | 47 | src_loc: Module.SrcLoc, |
| 48 | 48 | stack_align: u32, |
| 49 | 49 | |
| ... | ... | @@ -302,6 +302,7 @@ pub fn generate( |
| 302 | 302 | var emit = Emit{ |
| 303 | 303 | .mir = mir, |
| 304 | 304 | .bin_file = bin_file, |
| 305 | .function = &function, | |
| 305 | 306 | .debug_output = debug_output, |
| 306 | 307 | .target = &bin_file.options.target, |
| 307 | 308 | .src_loc = src_loc, |
| ... | ... | @@ -706,29 +707,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 706 | 707 | try table.ensureUnusedCapacity(self.gpa, additional_count); |
| 707 | 708 | } |
| 708 | 709 | |
| 709 | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, | |
| 710 | /// after codegen for this symbol is done. | |
| 711 | fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { | |
| 712 | switch (self.debug_output) { | |
| 713 | .dwarf => |dbg_out| { | |
| 714 | assert(ty.hasCodeGenBits()); | |
| 715 | const index = dbg_out.dbg_info.items.len; | |
| 716 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 717 | ||
| 718 | const gop = try dbg_out.dbg_info_type_relocs.getOrPut(self.gpa, ty); | |
| 719 | if (!gop.found_existing) { | |
| 720 | gop.value_ptr.* = .{ | |
| 721 | .off = undefined, | |
| 722 | .relocs = .{}, | |
| 723 | }; | |
| 724 | } | |
| 725 | try gop.value_ptr.relocs.append(self.gpa, @intCast(u32, index)); | |
| 726 | }, | |
| 727 | .plan9 => {}, | |
| 728 | .none => {}, | |
| 729 | } | |
| 730 | } | |
| 731 | ||
| 732 | 710 | fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 { |
| 733 | 711 | if (abi_align > self.stack_align) |
| 734 | 712 | self.stack_align = abi_align; |
| ... | ... | @@ -1171,6 +1149,9 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1171 | 1149 | switch (mcv) { |
| 1172 | 1150 | .dead, .unreach => unreachable, |
| 1173 | 1151 | .register => unreachable, // a slice doesn't fit in one register |
| 1152 | .stack_argument_offset => |off| { | |
| 1153 | break :result MCValue{ .stack_argument_offset = off }; | |
| 1154 | }, | |
| 1174 | 1155 | .stack_offset => |off| { |
| 1175 | 1156 | break :result MCValue{ .stack_offset = off }; |
| 1176 | 1157 | }, |
| ... | ... | @@ -1190,6 +1171,9 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1190 | 1171 | switch (mcv) { |
| 1191 | 1172 | .dead, .unreach => unreachable, |
| 1192 | 1173 | .register => unreachable, // a slice doesn't fit in one register |
| 1174 | .stack_argument_offset => |off| { | |
| 1175 | break :result MCValue{ .stack_argument_offset = off + 4 }; | |
| 1176 | }, | |
| 1193 | 1177 | .stack_offset => |off| { |
| 1194 | 1178 | break :result MCValue{ .stack_offset = off + 4 }; |
| 1195 | 1179 | }, |
| ... | ... | @@ -1208,7 +1192,6 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1208 | 1192 | const mcv = try self.resolveInst(ty_op.operand); |
| 1209 | 1193 | switch (mcv) { |
| 1210 | 1194 | .dead, .unreach => unreachable, |
| 1211 | .register => unreachable, // a slice doesn't fit in one register | |
| 1212 | 1195 | .ptr_stack_offset => |off| { |
| 1213 | 1196 | break :result MCValue{ .ptr_stack_offset = off + 4 }; |
| 1214 | 1197 | }, |
| ... | ... | @@ -1224,7 +1207,6 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1224 | 1207 | const mcv = try self.resolveInst(ty_op.operand); |
| 1225 | 1208 | switch (mcv) { |
| 1226 | 1209 | .dead, .unreach => unreachable, |
| 1227 | .register => unreachable, // a slice doesn't fit in one register | |
| 1228 | 1210 | .ptr_stack_offset => |off| { |
| 1229 | 1211 | break :result MCValue{ .ptr_stack_offset = off }; |
| 1230 | 1212 | }, |
| ... | ... | @@ -2135,66 +2117,6 @@ fn genArmInlineMemcpy( |
| 2135 | 2117 | // end: |
| 2136 | 2118 | } |
| 2137 | 2119 | |
| 2138 | fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void { | |
| 2139 | const ty_str = self.air.instructions.items(.data)[inst].ty_str; | |
| 2140 | const zir = &self.mod_fn.owner_decl.getFileScope().zir; | |
| 2141 | const name = zir.nullTerminatedString(ty_str.str); | |
| 2142 | const name_with_null = name.ptr[0 .. name.len + 1]; | |
| 2143 | const ty = self.air.getRefType(ty_str.ty); | |
| 2144 | ||
| 2145 | switch (mcv) { | |
| 2146 | .register => |reg| { | |
| 2147 | switch (self.debug_output) { | |
| 2148 | .dwarf => |dbg_out| { | |
| 2149 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | |
| 2150 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); | |
| 2151 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 2152 | 1, // ULEB128 dwarf expression length | |
| 2153 | reg.dwarfLocOp(), | |
| 2154 | }); | |
| 2155 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 2156 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 2157 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 2158 | }, | |
| 2159 | .plan9 => {}, | |
| 2160 | .none => {}, | |
| 2161 | } | |
| 2162 | }, | |
| 2163 | .stack_offset => |offset| { | |
| 2164 | switch (self.debug_output) { | |
| 2165 | .dwarf => |dbg_out| { | |
| 2166 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { | |
| 2167 | return self.fail("type '{}' too big to fit into stack frame", .{ty}); | |
| 2168 | }; | |
| 2169 | const adjusted_stack_offset = math.negateCast(offset + abi_size) catch { | |
| 2170 | return self.fail("Stack offset too large for arguments", .{}); | |
| 2171 | }; | |
| 2172 | ||
| 2173 | try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter); | |
| 2174 | ||
| 2175 | // Get length of the LEB128 stack offset | |
| 2176 | var counting_writer = std.io.countingWriter(std.io.null_writer); | |
| 2177 | leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable; | |
| 2178 | ||
| 2179 | // DW.AT.location, DW.FORM.exprloc | |
| 2180 | // ULEB128 dwarf expression length | |
| 2181 | try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); | |
| 2182 | try dbg_out.dbg_info.append(DW.OP.breg11); | |
| 2183 | try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); | |
| 2184 | ||
| 2185 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 2186 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 2187 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 2188 | }, | |
| 2189 | .plan9 => {}, | |
| 2190 | .none => {}, | |
| 2191 | } | |
| 2192 | }, | |
| 2193 | .stack_argument_offset => return self.fail("TODO genArgDbgInfo for stack_argument_offset", .{}), | |
| 2194 | else => {}, | |
| 2195 | } | |
| 2196 | } | |
| 2197 | ||
| 2198 | 2120 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 2199 | 2121 | const arg_index = self.arg_index; |
| 2200 | 2122 | self.arg_index += 1; |
| ... | ... | @@ -2216,8 +2138,15 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 2216 | 2138 | }, |
| 2217 | 2139 | else => result, |
| 2218 | 2140 | }; |
| 2219 | // TODO generate debug info | |
| 2220 | // try self.genArgDbgInfo(inst, mcv); | |
| 2141 | ||
| 2142 | _ = try self.addInst(.{ | |
| 2143 | .tag = .dbg_arg, | |
| 2144 | .cond = undefined, | |
| 2145 | .data = .{ .dbg_arg_info = .{ | |
| 2146 | .air_inst = inst, | |
| 2147 | .arg_index = arg_index, | |
| 2148 | } }, | |
| 2149 | }); | |
| 2221 | 2150 | |
| 2222 | 2151 | if (self.liveness.isUnused(inst)) |
| 2223 | 2152 | return self.finishAirBookkeeping(); |
| ... | ... | @@ -3496,7 +3425,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3496 | 3425 | } |
| 3497 | 3426 | }, |
| 3498 | 3427 | .stack_argument_offset => |unadjusted_off| { |
| 3499 | // TODO: maybe addressing from sp instead of fp | |
| 3500 | 3428 | const abi_size = ty.abiSize(self.target.*); |
| 3501 | 3429 | const adj_off = unadjusted_off + abi_size; |
| 3502 | 3430 |
src/arch/arm/Emit.zig+113-4| ... | ... | @@ -8,6 +8,8 @@ const Mir = @import("Mir.zig"); |
| 8 | 8 | const bits = @import("bits.zig"); |
| 9 | 9 | const link = @import("../../link.zig"); |
| 10 | 10 | const Module = @import("../../Module.zig"); |
| 11 | const Air = @import("../../Air.zig"); | |
| 12 | const Type = @import("../../type.zig").Type; | |
| 11 | 13 | const ErrorMsg = Module.ErrorMsg; |
| 12 | 14 | const assert = std.debug.assert; |
| 13 | 15 | const DW = std.dwarf; |
| ... | ... | @@ -16,9 +18,11 @@ const Instruction = bits.Instruction; |
| 16 | 18 | const Register = bits.Register; |
| 17 | 19 | const log = std.log.scoped(.aarch64_emit); |
| 18 | 20 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; |
| 21 | const CodeGen = @import("CodeGen.zig"); | |
| 19 | 22 | |
| 20 | 23 | mir: Mir, |
| 21 | 24 | bin_file: *link.File, |
| 25 | function: *const CodeGen, | |
| 22 | 26 | debug_output: DebugInfoOutput, |
| 23 | 27 | target: *const std.Target, |
| 24 | 28 | err_msg: ?*ErrorMsg = null, |
| ... | ... | @@ -95,6 +99,8 @@ pub fn emitMir( |
| 95 | 99 | .blx => try emit.mirBranchExchange(inst), |
| 96 | 100 | .bx => try emit.mirBranchExchange(inst), |
| 97 | 101 | |
| 102 | .dbg_arg => try emit.mirDbgArg(inst), | |
| 103 | ||
| 98 | 104 | .dbg_line => try emit.mirDbgLine(inst), |
| 99 | 105 | |
| 100 | 106 | .dbg_prologue_end => try emit.mirDebugPrologueEnd(), |
| ... | ... | @@ -106,9 +112,9 @@ pub fn emitMir( |
| 106 | 112 | .str => try emit.mirLoadStore(inst), |
| 107 | 113 | .strb => try emit.mirLoadStore(inst), |
| 108 | 114 | |
| 109 | .ldr_stack_argument => try emit.mirLoadStack(inst), | |
| 110 | .ldrb_stack_argument => try emit.mirLoadStack(inst), | |
| 111 | .ldrh_stack_argument => try emit.mirLoadStack(inst), | |
| 115 | .ldr_stack_argument => try emit.mirLoadStackArgument(inst), | |
| 116 | .ldrb_stack_argument => try emit.mirLoadStackArgument(inst), | |
| 117 | .ldrh_stack_argument => try emit.mirLoadStackArgument(inst), | |
| 112 | 118 | |
| 113 | 119 | .ldrh => try emit.mirLoadStoreExtra(inst), |
| 114 | 120 | .strh => try emit.mirLoadStoreExtra(inst), |
| ... | ... | @@ -168,6 +174,7 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { |
| 168 | 174 | .dbg_line, |
| 169 | 175 | .dbg_epilogue_begin, |
| 170 | 176 | .dbg_prologue_end, |
| 177 | .dbg_arg, | |
| 171 | 178 | => return 0, |
| 172 | 179 | else => return 4, |
| 173 | 180 | } |
| ... | ... | @@ -360,6 +367,98 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 360 | 367 | } |
| 361 | 368 | } |
| 362 | 369 | |
| 370 | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, | |
| 371 | /// after codegen for this symbol is done. | |
| 372 | fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void { | |
| 373 | switch (self.debug_output) { | |
| 374 | .dwarf => |dbg_out| { | |
| 375 | assert(ty.hasCodeGenBits()); | |
| 376 | const index = dbg_out.dbg_info.items.len; | |
| 377 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 378 | ||
| 379 | const gop = try dbg_out.dbg_info_type_relocs.getOrPut(self.bin_file.allocator, ty); | |
| 380 | if (!gop.found_existing) { | |
| 381 | gop.value_ptr.* = .{ | |
| 382 | .off = undefined, | |
| 383 | .relocs = .{}, | |
| 384 | }; | |
| 385 | } | |
| 386 | try gop.value_ptr.relocs.append(self.bin_file.allocator, @intCast(u32, index)); | |
| 387 | }, | |
| 388 | .plan9 => {}, | |
| 389 | .none => {}, | |
| 390 | } | |
| 391 | } | |
| 392 | ||
| 393 | fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { | |
| 394 | const mcv = self.function.args[arg_index]; | |
| 395 | ||
| 396 | const ty_str = self.function.air.instructions.items(.data)[inst].ty_str; | |
| 397 | const zir = &self.function.mod_fn.owner_decl.getFileScope().zir; | |
| 398 | const name = zir.nullTerminatedString(ty_str.str); | |
| 399 | const name_with_null = name.ptr[0 .. name.len + 1]; | |
| 400 | const ty = self.function.air.getRefType(ty_str.ty); | |
| 401 | ||
| 402 | switch (mcv) { | |
| 403 | .register => |reg| { | |
| 404 | switch (self.debug_output) { | |
| 405 | .dwarf => |dbg_out| { | |
| 406 | try dbg_out.dbg_info.ensureUnusedCapacity(3); | |
| 407 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); | |
| 408 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 409 | 1, // ULEB128 dwarf expression length | |
| 410 | reg.dwarfLocOp(), | |
| 411 | }); | |
| 412 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 413 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 414 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 415 | }, | |
| 416 | .plan9 => {}, | |
| 417 | .none => {}, | |
| 418 | } | |
| 419 | }, | |
| 420 | .stack_offset, | |
| 421 | .stack_argument_offset, | |
| 422 | => { | |
| 423 | switch (self.debug_output) { | |
| 424 | .dwarf => |dbg_out| { | |
| 425 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { | |
| 426 | return self.fail("type '{}' too big to fit into stack frame", .{ty}); | |
| 427 | }; | |
| 428 | const adjusted_stack_offset = switch (mcv) { | |
| 429 | .stack_offset => |offset| math.negateCast(offset + abi_size) catch { | |
| 430 | return self.fail("Stack offset too large for arguments", .{}); | |
| 431 | }, | |
| 432 | .stack_argument_offset => |offset| math.cast(i32, self.prologue_stack_space - offset - abi_size) catch { | |
| 433 | return self.fail("Stack offset too large for arguments", .{}); | |
| 434 | }, | |
| 435 | else => unreachable, | |
| 436 | }; | |
| 437 | ||
| 438 | try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter); | |
| 439 | ||
| 440 | // Get length of the LEB128 stack offset | |
| 441 | var counting_writer = std.io.countingWriter(std.io.null_writer); | |
| 442 | leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable; | |
| 443 | ||
| 444 | // DW.AT.location, DW.FORM.exprloc | |
| 445 | // ULEB128 dwarf expression length | |
| 446 | try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); | |
| 447 | try dbg_out.dbg_info.append(DW.OP.breg11); | |
| 448 | try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); | |
| 449 | ||
| 450 | try dbg_out.dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 451 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 452 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 453 | }, | |
| 454 | .plan9 => {}, | |
| 455 | .none => {}, | |
| 456 | } | |
| 457 | }, | |
| 458 | else => unreachable, // not a possible argument | |
| 459 | } | |
| 460 | } | |
| 461 | ||
| 363 | 462 | fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 364 | 463 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 365 | 464 | const cond = emit.mir.instructions.items(.cond)[inst]; |
| ... | ... | @@ -430,6 +529,16 @@ fn mirBranchExchange(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 430 | 529 | } |
| 431 | 530 | } |
| 432 | 531 | |
| 532 | fn mirDbgArg(emit: *Emit, inst: Mir.Inst.Index) !void { | |
| 533 | const tag = emit.mir.instructions.items(.tag)[inst]; | |
| 534 | const dbg_arg_info = emit.mir.instructions.items(.data)[inst].dbg_arg_info; | |
| 535 | ||
| 536 | switch (tag) { | |
| 537 | .dbg_arg => try emit.genArgDbgInfo(dbg_arg_info.air_inst, dbg_arg_info.arg_index), | |
| 538 | else => unreachable, | |
| 539 | } | |
| 540 | } | |
| 541 | ||
| 433 | 542 | fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 434 | 543 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 435 | 544 | const dbg_line_column = emit.mir.instructions.items(.data)[inst].dbg_line_column; |
| ... | ... | @@ -476,7 +585,7 @@ fn mirLoadStore(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 476 | 585 | } |
| 477 | 586 | } |
| 478 | 587 | |
| 479 | fn mirLoadStack(emit: *Emit, inst: Mir.Inst.Index) !void { | |
| 588 | fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void { | |
| 480 | 589 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 481 | 590 | const cond = emit.mir.instructions.items(.cond)[inst]; |
| 482 | 591 | const r_stack_offset = emit.mir.instructions.items(.data)[inst].r_stack_offset; |
src/arch/arm/Mir.zig+10| ... | ... | @@ -12,6 +12,7 @@ const builtin = @import("builtin"); |
| 12 | 12 | const assert = std.debug.assert; |
| 13 | 13 | |
| 14 | 14 | const bits = @import("bits.zig"); |
| 15 | const Air = @import("../../Air.zig"); | |
| 15 | 16 | const Register = bits.Register; |
| 16 | 17 | |
| 17 | 18 | instructions: std.MultiArrayList(Inst).Slice, |
| ... | ... | @@ -41,6 +42,8 @@ pub const Inst = struct { |
| 41 | 42 | bx, |
| 42 | 43 | /// Compare |
| 43 | 44 | cmp, |
| 45 | /// Pseudo-instruction: Argument | |
| 46 | dbg_arg, | |
| 44 | 47 | /// Pseudo-instruction: End of prologue |
| 45 | 48 | dbg_prologue_end, |
| 46 | 49 | /// Pseudo-instruction: Beginning of epilogue |
| ... | ... | @@ -195,6 +198,13 @@ pub const Inst = struct { |
| 195 | 198 | line: u32, |
| 196 | 199 | column: u32, |
| 197 | 200 | }, |
| 201 | /// Debug info: argument | |
| 202 | /// | |
| 203 | /// Used by e.g. dbg_arg | |
| 204 | dbg_arg_info: struct { | |
| 205 | air_inst: Air.Inst.Index, | |
| 206 | arg_index: u32, | |
| 207 | }, | |
| 198 | 208 | }; |
| 199 | 209 | |
| 200 | 210 | // Make sure we don't accidentally make instructions bigger than expected. |