| author | |
| committer | |
| log | 3bfb1616db0883e6145a1fe1844eee3038bd4ca1 |
| tree | 8242c4c816ef753747cb492131a57a6f7cebf795 |
| parent | 4c83b11f71564e0de80f496f471ca6dfb83a95e3 |
This removes the questionable Air -> Mir dependency that existed
before. The x86_64 backend also performed this change.3 files changed, 106 insertions(+), 124 deletions(-)
src/arch/arm/CodeGen.zig+106-8| ... | ... | @@ -49,6 +49,7 @@ gpa: Allocator, |
| 49 | 49 | air: Air, |
| 50 | 50 | liveness: Liveness, |
| 51 | 51 | bin_file: *link.File, |
| 52 | debug_output: DebugInfoOutput, | |
| 52 | 53 | target: *const std.Target, |
| 53 | 54 | mod_fn: *const Module.Fn, |
| 54 | 55 | err_msg: ?*ErrorMsg, |
| ... | ... | @@ -73,6 +74,12 @@ end_di_column: u32, |
| 73 | 74 | /// which is a relative jump, based on the address following the reloc. |
| 74 | 75 | exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{}, |
| 75 | 76 | |
| 77 | /// For every argument, we postpone the creation of debug info for | |
| 78 | /// later after all Mir instructions have been generated. Only then we | |
| 79 | /// will know saved_regs_stack_space which is necessary in order to | |
| 80 | /// address parameters passed on the stack. | |
| 81 | dbg_arg_relocs: std.ArrayListUnmanaged(DbgArgReloc) = .{}, | |
| 82 | ||
| 76 | 83 | /// Whenever there is a runtime branch, we push a Branch onto this stack, |
| 77 | 84 | /// and pop it off when the runtime branch joins. This provides an "overlay" |
| 78 | 85 | /// of the table of mappings from instructions to `MCValue` from within the branch. |
| ... | ... | @@ -244,6 +251,11 @@ const BigTomb = struct { |
| 244 | 251 | } |
| 245 | 252 | }; |
| 246 | 253 | |
| 254 | const DbgArgReloc = struct { | |
| 255 | inst: Air.Inst.Index, | |
| 256 | index: u32, | |
| 257 | }; | |
| 258 | ||
| 247 | 259 | const Self = @This(); |
| 248 | 260 | |
| 249 | 261 | pub fn generate( |
| ... | ... | @@ -276,6 +288,7 @@ pub fn generate( |
| 276 | 288 | .liveness = liveness, |
| 277 | 289 | .target = &bin_file.options.target, |
| 278 | 290 | .bin_file = bin_file, |
| 291 | .debug_output = debug_output, | |
| 279 | 292 | .mod_fn = module_fn, |
| 280 | 293 | .err_msg = null, |
| 281 | 294 | .args = undefined, // populated after `resolveCallingConventionValues` |
| ... | ... | @@ -291,6 +304,7 @@ pub fn generate( |
| 291 | 304 | defer function.stack.deinit(bin_file.allocator); |
| 292 | 305 | defer function.blocks.deinit(bin_file.allocator); |
| 293 | 306 | defer function.exitlude_jump_relocs.deinit(bin_file.allocator); |
| 307 | defer function.dbg_arg_relocs.deinit(bin_file.allocator); | |
| 294 | 308 | |
| 295 | 309 | var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) { |
| 296 | 310 | error.CodegenFail => return FnResult{ .fail = function.err_msg.? }, |
| ... | ... | @@ -314,6 +328,10 @@ pub fn generate( |
| 314 | 328 | else => |e| return e, |
| 315 | 329 | }; |
| 316 | 330 | |
| 331 | for (function.dbg_arg_relocs.items) |reloc| { | |
| 332 | try function.genArgDbgInfo(reloc.inst, reloc.index, call_info.stack_byte_count); | |
| 333 | } | |
| 334 | ||
| 317 | 335 | var mir = Mir{ |
| 318 | 336 | .instructions = function.mir_instructions.toOwnedSlice(), |
| 319 | 337 | .extra = function.mir_extra.toOwnedSlice(bin_file.allocator), |
| ... | ... | @@ -323,7 +341,6 @@ pub fn generate( |
| 323 | 341 | var emit = Emit{ |
| 324 | 342 | .mir = mir, |
| 325 | 343 | .bin_file = bin_file, |
| 326 | .function = &function, | |
| 327 | 344 | .debug_output = debug_output, |
| 328 | 345 | .target = &bin_file.options.target, |
| 329 | 346 | .src_loc = src_loc, |
| ... | ... | @@ -3074,6 +3091,91 @@ fn genInlineMemcpy( |
| 3074 | 3091 | // end: |
| 3075 | 3092 | } |
| 3076 | 3093 | |
| 3094 | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, | |
| 3095 | /// after codegen for this symbol is done. | |
| 3096 | fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void { | |
| 3097 | switch (self.debug_output) { | |
| 3098 | .dwarf => |dw| { | |
| 3099 | assert(ty.hasRuntimeBits()); | |
| 3100 | const dbg_info = &dw.dbg_info; | |
| 3101 | const index = dbg_info.items.len; | |
| 3102 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 3103 | const atom = switch (self.bin_file.tag) { | |
| 3104 | .elf => &self.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 3105 | .macho => unreachable, | |
| 3106 | else => unreachable, | |
| 3107 | }; | |
| 3108 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); | |
| 3109 | }, | |
| 3110 | .plan9 => {}, | |
| 3111 | .none => {}, | |
| 3112 | } | |
| 3113 | } | |
| 3114 | ||
| 3115 | fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_count: u32) error{OutOfMemory}!void { | |
| 3116 | const prologue_stack_space = stack_byte_count + self.saved_regs_stack_space; | |
| 3117 | ||
| 3118 | const mcv = self.args[arg_index]; | |
| 3119 | const ty = self.air.instructions.items(.data)[inst].ty; | |
| 3120 | const name = self.mod_fn.getParamName(arg_index); | |
| 3121 | const name_with_null = name.ptr[0 .. name.len + 1]; | |
| 3122 | ||
| 3123 | switch (mcv) { | |
| 3124 | .register => |reg| { | |
| 3125 | switch (self.debug_output) { | |
| 3126 | .dwarf => |dw| { | |
| 3127 | const dbg_info = &dw.dbg_info; | |
| 3128 | try dbg_info.ensureUnusedCapacity(3); | |
| 3129 | dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); | |
| 3130 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 3131 | 1, // ULEB128 dwarf expression length | |
| 3132 | reg.dwarfLocOp(), | |
| 3133 | }); | |
| 3134 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 3135 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 3136 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 3137 | }, | |
| 3138 | .plan9 => {}, | |
| 3139 | .none => {}, | |
| 3140 | } | |
| 3141 | }, | |
| 3142 | .stack_offset, | |
| 3143 | .stack_argument_offset, | |
| 3144 | => { | |
| 3145 | switch (self.debug_output) { | |
| 3146 | .dwarf => |dw| { | |
| 3147 | // const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | |
| 3148 | const adjusted_stack_offset = switch (mcv) { | |
| 3149 | .stack_offset => |offset| -@intCast(i32, offset), | |
| 3150 | .stack_argument_offset => |offset| @intCast(i32, prologue_stack_space - offset), | |
| 3151 | else => unreachable, | |
| 3152 | }; | |
| 3153 | ||
| 3154 | const dbg_info = &dw.dbg_info; | |
| 3155 | try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); | |
| 3156 | ||
| 3157 | // Get length of the LEB128 stack offset | |
| 3158 | var counting_writer = std.io.countingWriter(std.io.null_writer); | |
| 3159 | leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable; | |
| 3160 | ||
| 3161 | // DW.AT.location, DW.FORM.exprloc | |
| 3162 | // ULEB128 dwarf expression length | |
| 3163 | try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1); | |
| 3164 | try dbg_info.append(DW.OP.breg11); | |
| 3165 | try leb128.writeILEB128(dbg_info.writer(), adjusted_stack_offset); | |
| 3166 | ||
| 3167 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 3168 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 3169 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 3170 | }, | |
| 3171 | .plan9 => {}, | |
| 3172 | .none => {}, | |
| 3173 | } | |
| 3174 | }, | |
| 3175 | else => unreachable, // not a possible argument | |
| 3176 | } | |
| 3177 | } | |
| 3178 | ||
| 3077 | 3179 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3078 | 3180 | const arg_index = self.arg_index; |
| 3079 | 3181 | self.arg_index += 1; |
| ... | ... | @@ -3094,13 +3196,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3094 | 3196 | else => result, |
| 3095 | 3197 | }; |
| 3096 | 3198 | |
| 3097 | _ = try self.addInst(.{ | |
| 3098 | .tag = .dbg_arg, | |
| 3099 | .cond = undefined, | |
| 3100 | .data = .{ .dbg_arg_info = .{ | |
| 3101 | .air_inst = inst, | |
| 3102 | .arg_index = arg_index, | |
| 3103 | } }, | |
| 3199 | try self.dbg_arg_relocs.append(self.gpa, .{ | |
| 3200 | .inst = inst, | |
| 3201 | .index = arg_index, | |
| 3104 | 3202 | }); |
| 3105 | 3203 | |
| 3106 | 3204 | if (self.liveness.isUnused(inst)) |
src/arch/arm/Emit.zig-106| ... | ... | @@ -9,7 +9,6 @@ const Mir = @import("Mir.zig"); |
| 9 | 9 | const bits = @import("bits.zig"); |
| 10 | 10 | const link = @import("../../link.zig"); |
| 11 | 11 | const Module = @import("../../Module.zig"); |
| 12 | const Air = @import("../../Air.zig"); | |
| 13 | 12 | const Type = @import("../../type.zig").Type; |
| 14 | 13 | const ErrorMsg = Module.ErrorMsg; |
| 15 | 14 | const assert = std.debug.assert; |
| ... | ... | @@ -23,7 +22,6 @@ const CodeGen = @import("CodeGen.zig"); |
| 23 | 22 | |
| 24 | 23 | mir: Mir, |
| 25 | 24 | bin_file: *link.File, |
| 26 | function: *const CodeGen, | |
| 27 | 25 | debug_output: DebugInfoOutput, |
| 28 | 26 | target: *const std.Target, |
| 29 | 27 | err_msg: ?*ErrorMsg = null, |
| ... | ... | @@ -102,8 +100,6 @@ pub fn emitMir( |
| 102 | 100 | .blx => try emit.mirBranchExchange(inst), |
| 103 | 101 | .bx => try emit.mirBranchExchange(inst), |
| 104 | 102 | |
| 105 | .dbg_arg => try emit.mirDbgArg(inst), | |
| 106 | ||
| 107 | 103 | .dbg_line => try emit.mirDbgLine(inst), |
| 108 | 104 | |
| 109 | 105 | .dbg_prologue_end => try emit.mirDebugPrologueEnd(), |
| ... | ... | @@ -189,7 +185,6 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { |
| 189 | 185 | .dbg_line, |
| 190 | 186 | .dbg_epilogue_begin, |
| 191 | 187 | .dbg_prologue_end, |
| 192 | .dbg_arg, | |
| 193 | 188 | => return 0, |
| 194 | 189 | else => return 4, |
| 195 | 190 | } |
| ... | ... | @@ -383,97 +378,6 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void { |
| 383 | 378 | } |
| 384 | 379 | } |
| 385 | 380 | |
| 386 | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, | |
| 387 | /// after codegen for this symbol is done. | |
| 388 | fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void { | |
| 389 | switch (self.debug_output) { | |
| 390 | .dwarf => |dw| { | |
| 391 | assert(ty.hasRuntimeBits()); | |
| 392 | const dbg_info = &dw.dbg_info; | |
| 393 | const index = dbg_info.items.len; | |
| 394 | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 395 | const atom = switch (self.bin_file.tag) { | |
| 396 | .elf => &self.function.mod_fn.owner_decl.link.elf.dbg_info_atom, | |
| 397 | .macho => unreachable, | |
| 398 | else => unreachable, | |
| 399 | }; | |
| 400 | try dw.addTypeReloc(atom, ty, @intCast(u32, index), null); | |
| 401 | }, | |
| 402 | .plan9 => {}, | |
| 403 | .none => {}, | |
| 404 | } | |
| 405 | } | |
| 406 | ||
| 407 | fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void { | |
| 408 | const mcv = self.function.args[arg_index]; | |
| 409 | ||
| 410 | const ty = self.function.air.instructions.items(.data)[inst].ty; | |
| 411 | const name = self.function.mod_fn.getParamName(arg_index); | |
| 412 | const name_with_null = name.ptr[0 .. name.len + 1]; | |
| 413 | const target = self.target.*; | |
| 414 | ||
| 415 | switch (mcv) { | |
| 416 | .register => |reg| { | |
| 417 | switch (self.debug_output) { | |
| 418 | .dwarf => |dw| { | |
| 419 | const dbg_info = &dw.dbg_info; | |
| 420 | try dbg_info.ensureUnusedCapacity(3); | |
| 421 | dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); | |
| 422 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 423 | 1, // ULEB128 dwarf expression length | |
| 424 | reg.dwarfLocOp(), | |
| 425 | }); | |
| 426 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 427 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 428 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 429 | }, | |
| 430 | .plan9 => {}, | |
| 431 | .none => {}, | |
| 432 | } | |
| 433 | }, | |
| 434 | .stack_offset, | |
| 435 | .stack_argument_offset, | |
| 436 | => { | |
| 437 | switch (self.debug_output) { | |
| 438 | .dwarf => |dw| { | |
| 439 | const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch { | |
| 440 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(target)}); | |
| 441 | }; | |
| 442 | const adjusted_stack_offset = switch (mcv) { | |
| 443 | .stack_offset => |offset| math.negateCast(offset + abi_size) catch { | |
| 444 | return self.fail("Stack offset too large for arguments", .{}); | |
| 445 | }, | |
| 446 | .stack_argument_offset => |offset| math.cast(i32, self.prologue_stack_space - offset - abi_size) catch { | |
| 447 | return self.fail("Stack offset too large for arguments", .{}); | |
| 448 | }, | |
| 449 | else => unreachable, | |
| 450 | }; | |
| 451 | ||
| 452 | const dbg_info = &dw.dbg_info; | |
| 453 | try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.parameter)); | |
| 454 | ||
| 455 | // Get length of the LEB128 stack offset | |
| 456 | var counting_writer = std.io.countingWriter(std.io.null_writer); | |
| 457 | leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable; | |
| 458 | ||
| 459 | // DW.AT.location, DW.FORM.exprloc | |
| 460 | // ULEB128 dwarf expression length | |
| 461 | try leb128.writeULEB128(dbg_info.writer(), counting_writer.bytes_written + 1); | |
| 462 | try dbg_info.append(DW.OP.breg11); | |
| 463 | try leb128.writeILEB128(dbg_info.writer(), adjusted_stack_offset); | |
| 464 | ||
| 465 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 466 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 467 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 468 | }, | |
| 469 | .plan9 => {}, | |
| 470 | .none => {}, | |
| 471 | } | |
| 472 | }, | |
| 473 | else => unreachable, // not a possible argument | |
| 474 | } | |
| 475 | } | |
| 476 | ||
| 477 | 381 | fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 478 | 382 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 479 | 383 | const cond = emit.mir.instructions.items(.cond)[inst]; |
| ... | ... | @@ -546,16 +450,6 @@ fn mirBranchExchange(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 546 | 450 | } |
| 547 | 451 | } |
| 548 | 452 | |
| 549 | fn mirDbgArg(emit: *Emit, inst: Mir.Inst.Index) !void { | |
| 550 | const tag = emit.mir.instructions.items(.tag)[inst]; | |
| 551 | const dbg_arg_info = emit.mir.instructions.items(.data)[inst].dbg_arg_info; | |
| 552 | ||
| 553 | switch (tag) { | |
| 554 | .dbg_arg => try emit.genArgDbgInfo(dbg_arg_info.air_inst, dbg_arg_info.arg_index), | |
| 555 | else => unreachable, | |
| 556 | } | |
| 557 | } | |
| 558 | ||
| 559 | 453 | fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 560 | 454 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 561 | 455 | const dbg_line_column = emit.mir.instructions.items(.data)[inst].dbg_line_column; |
src/arch/arm/Mir.zig-10| ... | ... | @@ -12,7 +12,6 @@ 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"); | |
| 16 | 15 | const Register = bits.Register; |
| 17 | 16 | |
| 18 | 17 | instructions: std.MultiArrayList(Inst).Slice, |
| ... | ... | @@ -44,8 +43,6 @@ pub const Inst = struct { |
| 44 | 43 | bx, |
| 45 | 44 | /// Compare |
| 46 | 45 | cmp, |
| 47 | /// Pseudo-instruction: Argument | |
| 48 | dbg_arg, | |
| 49 | 46 | /// Pseudo-instruction: End of prologue |
| 50 | 47 | dbg_prologue_end, |
| 51 | 48 | /// Pseudo-instruction: Beginning of epilogue |
| ... | ... | @@ -239,13 +236,6 @@ pub const Inst = struct { |
| 239 | 236 | line: u32, |
| 240 | 237 | column: u32, |
| 241 | 238 | }, |
| 242 | /// Debug info: argument | |
| 243 | /// | |
| 244 | /// Used by e.g. dbg_arg | |
| 245 | dbg_arg_info: struct { | |
| 246 | air_inst: Air.Inst.Index, | |
| 247 | arg_index: u32, | |
| 248 | }, | |
| 249 | 239 | }; |
| 250 | 240 | |
| 251 | 241 | // Make sure we don't accidentally make instructions bigger than expected. |