mirror of
https://github.com/ziglang/zig.git
synced 2025-12-17 11:43:16 +00:00
Merge pull request #21140 from jacobly0/self-dwarf
Dwarf: inline calls progress
This commit is contained in:
commit
16d74809d4
25
src/Air.zig
25
src/Air.zig
@ -456,6 +456,8 @@ pub const Inst = struct {
|
|||||||
/// Same as `dbg_var_ptr` except the local is a const, not a var, and the
|
/// Same as `dbg_var_ptr` except the local is a const, not a var, and the
|
||||||
/// operand is the local's value.
|
/// operand is the local's value.
|
||||||
dbg_var_val,
|
dbg_var_val,
|
||||||
|
/// Same as `dbg_var_val` except the local is an inline function argument.
|
||||||
|
dbg_arg_inline,
|
||||||
/// ?T => bool
|
/// ?T => bool
|
||||||
/// Result type is always bool.
|
/// Result type is always bool.
|
||||||
/// Uses the `un_op` field.
|
/// Uses the `un_op` field.
|
||||||
@ -1022,10 +1024,7 @@ pub const Inst = struct {
|
|||||||
ty: Ref,
|
ty: Ref,
|
||||||
/// Index into `extra` of a null-terminated string representing the parameter name.
|
/// Index into `extra` of a null-terminated string representing the parameter name.
|
||||||
/// This is `.none` if debug info is stripped.
|
/// This is `.none` if debug info is stripped.
|
||||||
name: enum(u32) {
|
name: NullTerminatedString,
|
||||||
none = std.math.maxInt(u32),
|
|
||||||
_,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
ty_op: struct {
|
ty_op: struct {
|
||||||
ty: Ref,
|
ty: Ref,
|
||||||
@ -1440,6 +1439,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
|
|||||||
.dbg_stmt,
|
.dbg_stmt,
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
.store,
|
.store,
|
||||||
.store_safe,
|
.store_safe,
|
||||||
.fence,
|
.fence,
|
||||||
@ -1562,14 +1562,16 @@ pub fn value(air: Air, inst: Inst.Ref, pt: Zcu.PerThread) !?Value {
|
|||||||
return air.typeOfIndex(index, &pt.zcu.intern_pool).onePossibleValue(pt);
|
return air.typeOfIndex(index, &pt.zcu.intern_pool).onePossibleValue(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {
|
pub const NullTerminatedString = enum(u32) {
|
||||||
const bytes = std.mem.sliceAsBytes(air.extra[index..]);
|
none = std.math.maxInt(u32),
|
||||||
var end: usize = 0;
|
_,
|
||||||
while (bytes[end] != 0) {
|
|
||||||
end += 1;
|
pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 {
|
||||||
|
if (nts == .none) return "";
|
||||||
|
const bytes = std.mem.sliceAsBytes(air.extra[@intFromEnum(nts)..]);
|
||||||
|
return bytes[0..std.mem.indexOfScalar(u8, bytes, 0).? :0];
|
||||||
}
|
}
|
||||||
return bytes[0..end :0];
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns whether the given instruction must always be lowered, for instance
|
/// Returns whether the given instruction must always be lowered, for instance
|
||||||
/// because it can cause side effects. If an instruction does not need to be
|
/// because it can cause side effects. If an instruction does not need to be
|
||||||
@ -1596,6 +1598,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
|
|||||||
.dbg_inline_block,
|
.dbg_inline_block,
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
.ret,
|
.ret,
|
||||||
.ret_safe,
|
.ret_safe,
|
||||||
.ret_load,
|
.ret_load,
|
||||||
|
|||||||
@ -339,6 +339,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
|
|||||||
|
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> {
|
=> {
|
||||||
if (!checkRef(data.pl_op.operand, zcu)) return false;
|
if (!checkRef(data.pl_op.operand, zcu)) return false;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2997,14 +2997,26 @@ pub fn saveState(comp: *Compilation) !void {
|
|||||||
addBuf(&bufs, mem.sliceAsBytes(ip.free_dep_entries.items));
|
addBuf(&bufs, mem.sliceAsBytes(ip.free_dep_entries.items));
|
||||||
|
|
||||||
for (ip.locals, pt_headers.items) |*local, pt_header| {
|
for (ip.locals, pt_headers.items) |*local, pt_header| {
|
||||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));
|
if (pt_header.intern_pool.limbs_len > 0) {
|
||||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));
|
addBuf(&bufs, mem.sliceAsBytes(local.shared.limbs.view().items(.@"0")[0..pt_header.intern_pool.limbs_len]));
|
||||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));
|
}
|
||||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));
|
if (pt_header.intern_pool.extra_len > 0) {
|
||||||
addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]);
|
addBuf(&bufs, mem.sliceAsBytes(local.shared.extra.view().items(.@"0")[0..pt_header.intern_pool.extra_len]));
|
||||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));
|
}
|
||||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));
|
if (pt_header.intern_pool.items_len > 0) {
|
||||||
addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));
|
addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.data)[0..pt_header.intern_pool.items_len]));
|
||||||
|
addBuf(&bufs, mem.sliceAsBytes(local.shared.items.view().items(.tag)[0..pt_header.intern_pool.items_len]));
|
||||||
|
}
|
||||||
|
if (pt_header.intern_pool.string_bytes_len > 0) {
|
||||||
|
addBuf(&bufs, local.shared.strings.view().items(.@"0")[0..pt_header.intern_pool.string_bytes_len]);
|
||||||
|
}
|
||||||
|
if (pt_header.intern_pool.tracked_insts_len > 0) {
|
||||||
|
addBuf(&bufs, mem.sliceAsBytes(local.shared.tracked_insts.view().items(.@"0")[0..pt_header.intern_pool.tracked_insts_len]));
|
||||||
|
}
|
||||||
|
if (pt_header.intern_pool.files_len > 0) {
|
||||||
|
addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.bin_digest)[0..pt_header.intern_pool.files_len]));
|
||||||
|
addBuf(&bufs, mem.sliceAsBytes(local.shared.files.view().items(.root_type)[0..pt_header.intern_pool.files_len]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//// TODO: compilation errors
|
//// TODO: compilation errors
|
||||||
|
|||||||
@ -464,6 +464,7 @@ pub fn categorizeOperand(
|
|||||||
|
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> {
|
=> {
|
||||||
const o = air_datas[@intFromEnum(inst)].pl_op.operand;
|
const o = air_datas[@intFromEnum(inst)].pl_op.operand;
|
||||||
if (o == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
if (o == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none);
|
||||||
@ -1097,6 +1098,7 @@ fn analyzeInst(
|
|||||||
|
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> {
|
=> {
|
||||||
const operand = inst_datas[@intFromEnum(inst)].pl_op.operand;
|
const operand = inst_datas[@intFromEnum(inst)].pl_op.operand;
|
||||||
return analyzeOperands(a, pass, data, inst, .{ operand, .none, .none });
|
return analyzeOperands(a, pass, data, inst, .{ operand, .none, .none });
|
||||||
|
|||||||
@ -157,6 +157,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
|
|||||||
},
|
},
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
.wasm_memory_grow,
|
.wasm_memory_grow,
|
||||||
=> {
|
=> {
|
||||||
const pl_op = data[@intFromEnum(inst)].pl_op;
|
const pl_op = data[@intFromEnum(inst)].pl_op;
|
||||||
|
|||||||
21
src/Sema.zig
21
src/Sema.zig
@ -376,7 +376,7 @@ pub const Block = struct {
|
|||||||
|
|
||||||
c_import_buf: ?*std.ArrayList(u8) = null,
|
c_import_buf: ?*std.ArrayList(u8) = null,
|
||||||
|
|
||||||
/// If not `null`, this boolean is set when a `dbg_var_ptr` or `dbg_var_val`
|
/// If not `null`, this boolean is set when a `dbg_var_ptr`, `dbg_var_val`, or `dbg_arg_inline`.
|
||||||
/// instruction is emitted. It signals that the innermost lexically
|
/// instruction is emitted. It signals that the innermost lexically
|
||||||
/// enclosing `block`/`block_inline` should be translated into a real AIR
|
/// enclosing `block`/`block_inline` should be translated into a real AIR
|
||||||
/// `block` in order for codegen to match lexical scoping for debug vars.
|
/// `block` in order for codegen to match lexical scoping for debug vars.
|
||||||
@ -6567,7 +6567,7 @@ fn addDbgVar(
|
|||||||
const operand_ty = sema.typeOf(operand);
|
const operand_ty = sema.typeOf(operand);
|
||||||
const val_ty = switch (air_tag) {
|
const val_ty = switch (air_tag) {
|
||||||
.dbg_var_ptr => operand_ty.childType(mod),
|
.dbg_var_ptr => operand_ty.childType(mod),
|
||||||
.dbg_var_val => operand_ty,
|
.dbg_var_val, .dbg_arg_inline => operand_ty,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
if (try sema.typeRequiresComptime(val_ty)) return;
|
if (try sema.typeRequiresComptime(val_ty)) return;
|
||||||
@ -6586,25 +6586,26 @@ fn addDbgVar(
|
|||||||
if (block.need_debug_scope) |ptr| ptr.* = true;
|
if (block.need_debug_scope) |ptr| ptr.* = true;
|
||||||
|
|
||||||
// Add the name to the AIR.
|
// Add the name to the AIR.
|
||||||
const name_extra_index = try sema.appendAirString(name);
|
const name_nts = try sema.appendAirString(name);
|
||||||
|
|
||||||
_ = try block.addInst(.{
|
_ = try block.addInst(.{
|
||||||
.tag = air_tag,
|
.tag = air_tag,
|
||||||
.data = .{ .pl_op = .{
|
.data = .{ .pl_op = .{
|
||||||
.payload = name_extra_index,
|
.payload = @intFromEnum(name_nts),
|
||||||
.operand = operand,
|
.operand = operand,
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!u32 {
|
pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTerminatedString {
|
||||||
const str_extra_index: u32 = @intCast(sema.air_extra.items.len);
|
if (str.len == 0) return .none;
|
||||||
|
const nts: Air.NullTerminatedString = @enumFromInt(sema.air_extra.items.len);
|
||||||
const elements_used = str.len / 4 + 1;
|
const elements_used = str.len / 4 + 1;
|
||||||
const elements = try sema.air_extra.addManyAsSlice(sema.gpa, elements_used);
|
const elements = try sema.air_extra.addManyAsSlice(sema.gpa, elements_used);
|
||||||
const buffer = mem.sliceAsBytes(elements);
|
const buffer = mem.sliceAsBytes(elements);
|
||||||
@memcpy(buffer[0..str.len], str);
|
@memcpy(buffer[0..str.len], str);
|
||||||
buffer[str.len] = 0;
|
buffer[str.len] = 0;
|
||||||
return str_extra_index;
|
return nts;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||||
@ -7748,14 +7749,14 @@ fn analyzeCall(
|
|||||||
const param_name = sema.code.nullTerminatedString(extra.data.name);
|
const param_name = sema.code.nullTerminatedString(extra.data.name);
|
||||||
const inst = sema.inst_map.get(param).?;
|
const inst = sema.inst_map.get(param).?;
|
||||||
|
|
||||||
try sema.addDbgVar(&child_block, inst, .dbg_var_val, param_name);
|
try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
|
||||||
},
|
},
|
||||||
.param_anytype, .param_anytype_comptime => {
|
.param_anytype, .param_anytype_comptime => {
|
||||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok;
|
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(param)].str_tok;
|
||||||
const param_name = inst_data.get(sema.code);
|
const param_name = inst_data.get(sema.code);
|
||||||
const inst = sema.inst_map.get(param).?;
|
const inst = sema.inst_map.get(param).?;
|
||||||
|
|
||||||
try sema.addDbgVar(&child_block, inst, .dbg_var_val, param_name);
|
try sema.addDbgVar(&child_block, inst, .dbg_arg_inline, param_name);
|
||||||
},
|
},
|
||||||
else => continue,
|
else => continue,
|
||||||
};
|
};
|
||||||
@ -8266,7 +8267,7 @@ fn instantiateGenericCall(
|
|||||||
.name = if (child_block.ownerModule().strip)
|
.name = if (child_block.ownerModule().strip)
|
||||||
.none
|
.none
|
||||||
else
|
else
|
||||||
@enumFromInt(try sema.appendAirString(fn_zir.nullTerminatedString(param_name))),
|
try sema.appendAirString(fn_zir.nullTerminatedString(param_name)),
|
||||||
} },
|
} },
|
||||||
}));
|
}));
|
||||||
try child_block.params.append(sema.arena, .{
|
try child_block.params.append(sema.arena, .{
|
||||||
|
|||||||
@ -1240,11 +1240,11 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const nav_already_populated, const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) {
|
const nav_already_populated, const queue_linker_work, const resolve_type = switch (ip.indexToKey(decl_val.toIntern())) {
|
||||||
.func => |f| .{ f.owner_nav == nav_index, false },
|
.func => |f| .{ f.owner_nav == nav_index, true, false },
|
||||||
.variable => |v| .{ false, v.owner_nav == nav_index },
|
.variable => |v| .{ false, v.owner_nav == nav_index, true },
|
||||||
.@"extern" => .{ false, false },
|
.@"extern" => .{ false, false, false },
|
||||||
else => .{ false, true },
|
else => .{ false, true, true },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (nav_already_populated) {
|
if (nav_already_populated) {
|
||||||
@ -1317,14 +1317,16 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
|
|||||||
queue_codegen: {
|
queue_codegen: {
|
||||||
if (!queue_linker_work) break :queue_codegen;
|
if (!queue_linker_work) break :queue_codegen;
|
||||||
|
|
||||||
// Needed for codegen_nav which will call updateDecl and then the
|
if (resolve_type) {
|
||||||
// codegen backend wants full access to the Decl Type.
|
// Needed for codegen_nav which will call updateDecl and then the
|
||||||
// We also need this for the `isFnOrHasRuntimeBits` check below.
|
// codegen backend wants full access to the Decl Type.
|
||||||
// TODO: we could make the language more lenient by deferring this work
|
// We also need this for the `isFnOrHasRuntimeBits` check below.
|
||||||
// to the `codegen_nav` job.
|
// TODO: we could make the language more lenient by deferring this work
|
||||||
try decl_ty.resolveFully(pt);
|
// to the `codegen_nav` job.
|
||||||
|
try decl_ty.resolveFully(pt);
|
||||||
|
}
|
||||||
|
|
||||||
if (!decl_ty.isFnOrHasRuntimeBits(pt)) {
|
if (!resolve_type or !decl_ty.hasRuntimeBits(pt)) {
|
||||||
if (zcu.comp.config.use_llvm) break :queue_codegen;
|
if (zcu.comp.config.use_llvm) break :queue_codegen;
|
||||||
if (file.mod.strip) break :queue_codegen;
|
if (file.mod.strip) break :queue_codegen;
|
||||||
}
|
}
|
||||||
@ -2158,7 +2160,7 @@ fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!
|
|||||||
.name = if (inner_block.ownerModule().strip)
|
.name = if (inner_block.ownerModule().strip)
|
||||||
.none
|
.none
|
||||||
else
|
else
|
||||||
@enumFromInt(try sema.appendAirString(sema.code.nullTerminatedString(param_name))),
|
try sema.appendAirString(sema.code.nullTerminatedString(param_name)),
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -170,7 +170,9 @@ const DbgInfoReloc = struct {
|
|||||||
|
|
||||||
fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
|
fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
|
||||||
switch (reloc.tag) {
|
switch (reloc.tag) {
|
||||||
.arg => try reloc.genArgDbgInfo(function),
|
.arg,
|
||||||
|
.dbg_arg_inline,
|
||||||
|
=> try reloc.genArgDbgInfo(function),
|
||||||
|
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
@ -201,7 +203,7 @@ const DbgInfoReloc = struct {
|
|||||||
else => unreachable, // not a possible argument
|
else => unreachable, // not a possible argument
|
||||||
|
|
||||||
};
|
};
|
||||||
try dw.genVarDebugInfo(.local_arg, reloc.name, reloc.ty, loc);
|
try dw.genLocalDebugInfo(.local_arg, reloc.name, reloc.ty, loc);
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
@ -237,7 +239,7 @@ const DbgInfoReloc = struct {
|
|||||||
break :blk .empty;
|
break :blk .empty;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try dwarf.genVarDebugInfo(.local_var, reloc.name, reloc.ty, loc);
|
try dwarf.genLocalDebugInfo(.local_var, reloc.name, reloc.ty, loc);
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
@ -799,6 +801,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
|||||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> try self.airDbgVar(inst),
|
=> try self.airDbgVar(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
@ -4220,17 +4223,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
|
|
||||||
const ty = self.typeOfIndex(inst);
|
const ty = self.typeOfIndex(inst);
|
||||||
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
||||||
|
const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
||||||
const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
|
||||||
if (name_nts != .none) {
|
.tag = tag,
|
||||||
const name = self.air.nullTerminatedString(@intFromEnum(name_nts));
|
.ty = ty,
|
||||||
try self.dbg_info_relocs.append(self.gpa, .{
|
.name = name.toSlice(self.air),
|
||||||
.tag = tag,
|
.mcv = self.args[arg_index],
|
||||||
.ty = ty,
|
});
|
||||||
.name = name,
|
|
||||||
.mcv = self.args[arg_index],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
|
||||||
return self.finishAir(inst, result, .{ .none, .none, .none });
|
return self.finishAir(inst, result, .{ .none, .none, .none });
|
||||||
@ -4644,14 +4643,14 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
||||||
const ty = self.typeOf(operand);
|
const ty = self.typeOf(operand);
|
||||||
const mcv = try self.resolveInst(operand);
|
const mcv = try self.resolveInst(operand);
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
|
|
||||||
log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });
|
log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });
|
||||||
|
|
||||||
try self.dbg_info_relocs.append(self.gpa, .{
|
try self.dbg_info_relocs.append(self.gpa, .{
|
||||||
.tag = tag,
|
.tag = tag,
|
||||||
.ty = ty,
|
.ty = ty,
|
||||||
.name = name,
|
.name = name.toSlice(self.air),
|
||||||
.mcv = mcv,
|
.mcv = mcv,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -248,7 +248,9 @@ const DbgInfoReloc = struct {
|
|||||||
|
|
||||||
fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
|
fn genDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
|
||||||
switch (reloc.tag) {
|
switch (reloc.tag) {
|
||||||
.arg => try reloc.genArgDbgInfo(function),
|
.arg,
|
||||||
|
.dbg_arg_inline,
|
||||||
|
=> try reloc.genArgDbgInfo(function),
|
||||||
|
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
@ -279,7 +281,7 @@ const DbgInfoReloc = struct {
|
|||||||
else => unreachable, // not a possible argument
|
else => unreachable, // not a possible argument
|
||||||
};
|
};
|
||||||
|
|
||||||
try dw.genVarDebugInfo(.local_arg, reloc.name, reloc.ty, loc);
|
try dw.genLocalDebugInfo(.local_arg, reloc.name, reloc.ty, loc);
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
@ -315,7 +317,7 @@ const DbgInfoReloc = struct {
|
|||||||
break :blk .empty;
|
break :blk .empty;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try dw.genVarDebugInfo(.local_var, reloc.name, reloc.ty, loc);
|
try dw.genLocalDebugInfo(.local_var, reloc.name, reloc.ty, loc);
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
@ -786,6 +788,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
|||||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> try self.airDbgVar(inst),
|
=> try self.airDbgVar(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
@ -4199,16 +4202,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const ty = self.typeOfIndex(inst);
|
const ty = self.typeOfIndex(inst);
|
||||||
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
||||||
|
|
||||||
const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
||||||
if (name_nts != .none) {
|
if (name != .none) try self.dbg_info_relocs.append(self.gpa, .{
|
||||||
const name = self.air.nullTerminatedString(@intFromEnum(name_nts));
|
.tag = tag,
|
||||||
try self.dbg_info_relocs.append(self.gpa, .{
|
.ty = ty,
|
||||||
.tag = tag,
|
.name = name.toSlice(self.air),
|
||||||
.ty = ty,
|
.mcv = self.args[arg_index],
|
||||||
.name = name,
|
});
|
||||||
.mcv = self.args[arg_index],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
|
||||||
return self.finishAir(inst, result, .{ .none, .none, .none });
|
return self.finishAir(inst, result, .{ .none, .none, .none });
|
||||||
@ -4612,14 +4612,14 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
||||||
const ty = self.typeOf(operand);
|
const ty = self.typeOf(operand);
|
||||||
const mcv = try self.resolveInst(operand);
|
const mcv = try self.resolveInst(operand);
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
|
|
||||||
log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });
|
log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv });
|
||||||
|
|
||||||
try self.dbg_info_relocs.append(self.gpa, .{
|
try self.dbg_info_relocs.append(self.gpa, .{
|
||||||
.tag = tag,
|
.tag = tag,
|
||||||
.ty = ty,
|
.ty = ty,
|
||||||
.name = name,
|
.name = name.toSlice(self.air),
|
||||||
.mcv = mcv,
|
.mcv = mcv,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1644,6 +1644,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
|
|||||||
|
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> try func.airDbgVar(inst),
|
=> try func.airDbgVar(inst),
|
||||||
|
|
||||||
.dbg_inline_block => try func.airDbgInlineBlock(inst),
|
.dbg_inline_block => try func.airDbgInlineBlock(inst),
|
||||||
@ -4673,11 +4674,15 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
|
|||||||
const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
|
const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
|
||||||
const ty = arg.ty.toType();
|
const ty = arg.ty.toType();
|
||||||
if (arg.name == .none) return;
|
if (arg.name == .none) return;
|
||||||
const name = func.air.nullTerminatedString(@intFromEnum(arg.name));
|
|
||||||
|
|
||||||
switch (func.debug_output) {
|
switch (func.debug_output) {
|
||||||
.dwarf => |dw| switch (mcv) {
|
.dwarf => |dw| switch (mcv) {
|
||||||
.register => |reg| try dw.genVarDebugInfo(.local_arg, name, ty, .{ .reg = reg.dwarfNum() }),
|
.register => |reg| try dw.genLocalDebugInfo(
|
||||||
|
.local_arg,
|
||||||
|
arg.name.toSlice(func.air),
|
||||||
|
ty,
|
||||||
|
.{ .reg = reg.dwarfNum() },
|
||||||
|
),
|
||||||
.load_frame => {},
|
.load_frame => {},
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
@ -5179,16 +5184,17 @@ fn airDbgVar(func: *Func, inst: Air.Inst.Index) !void {
|
|||||||
const operand = pl_op.operand;
|
const operand = pl_op.operand;
|
||||||
const ty = func.typeOf(operand);
|
const ty = func.typeOf(operand);
|
||||||
const mcv = try func.resolveInst(operand);
|
const mcv = try func.resolveInst(operand);
|
||||||
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
|
|
||||||
const name = func.air.nullTerminatedString(pl_op.payload);
|
const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)];
|
||||||
|
try func.genVarDbgInfo(tag, ty, mcv, name.toSlice(func.air));
|
||||||
try func.genVarDbgInfo(ty, mcv, name);
|
|
||||||
|
|
||||||
return func.finishAir(inst, .unreach, .{ operand, .none, .none });
|
return func.finishAir(inst, .unreach, .{ operand, .none, .none });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genVarDbgInfo(
|
fn genVarDbgInfo(
|
||||||
func: Func,
|
func: Func,
|
||||||
|
tag: Air.Inst.Tag,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
mcv: MCValue,
|
mcv: MCValue,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
@ -5205,7 +5211,11 @@ fn genVarDbgInfo(
|
|||||||
break :blk .empty;
|
break :blk .empty;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try dwarf.genVarDebugInfo(.local_var, name, ty, loc);
|
try dwarf.genLocalDebugInfo(switch (tag) {
|
||||||
|
else => unreachable,
|
||||||
|
.dbg_var_ptr, .dbg_var_val => .local_var,
|
||||||
|
.dbg_arg_inline => .local_arg,
|
||||||
|
}, name, ty, loc);
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
|
|||||||
@ -643,6 +643,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
|||||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> try self.airDbgVar(inst),
|
=> try self.airDbgVar(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
@ -1662,7 +1663,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
|
|
||||||
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
const operand = pl_op.operand;
|
const operand = pl_op.operand;
|
||||||
// TODO emit debug info for this variable
|
// TODO emit debug info for this variable
|
||||||
_ = name;
|
_ = name;
|
||||||
@ -3582,13 +3583,15 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
|
|||||||
const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
|
const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
|
||||||
const ty = arg.ty.toType();
|
const ty = arg.ty.toType();
|
||||||
if (arg.name == .none) return;
|
if (arg.name == .none) return;
|
||||||
const name = self.air.nullTerminatedString(@intFromEnum(arg.name));
|
|
||||||
|
|
||||||
switch (self.debug_output) {
|
switch (self.debug_output) {
|
||||||
.dwarf => |dw| switch (mcv) {
|
.dwarf => |dw| switch (mcv) {
|
||||||
.register => |reg| try dw.genVarDebugInfo(.local_arg, name, ty, .{
|
.register => |reg| try dw.genLocalDebugInfo(
|
||||||
.reg = reg.dwarfNum(),
|
.local_arg,
|
||||||
}),
|
arg.name.toSlice(self.air),
|
||||||
|
ty,
|
||||||
|
.{ .reg = reg.dwarfNum() },
|
||||||
|
),
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
|
|||||||
@ -1917,8 +1917,9 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
|||||||
|
|
||||||
.dbg_stmt => func.airDbgStmt(inst),
|
.dbg_stmt => func.airDbgStmt(inst),
|
||||||
.dbg_inline_block => func.airDbgInlineBlock(inst),
|
.dbg_inline_block => func.airDbgInlineBlock(inst),
|
||||||
.dbg_var_ptr => func.airDbgVar(inst, true),
|
.dbg_var_ptr => func.airDbgVar(inst, .local_var, true),
|
||||||
.dbg_var_val => func.airDbgVar(inst, false),
|
.dbg_var_val => func.airDbgVar(inst, .local_var, false),
|
||||||
|
.dbg_arg_inline => func.airDbgVar(inst, .local_arg, false),
|
||||||
|
|
||||||
.call => func.airCall(inst, .auto),
|
.call => func.airCall(inst, .auto),
|
||||||
.call_always_tail => func.airCall(inst, .always_tail),
|
.call_always_tail => func.airCall(inst, .always_tail),
|
||||||
@ -2585,13 +2586,13 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
|||||||
|
|
||||||
switch (func.debug_output) {
|
switch (func.debug_output) {
|
||||||
.dwarf => |dwarf| {
|
.dwarf => |dwarf| {
|
||||||
const name_nts = func.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
const name = func.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
||||||
if (name_nts != .none) {
|
if (name != .none) try dwarf.genLocalDebugInfo(
|
||||||
const name = func.air.nullTerminatedString(@intFromEnum(name_nts));
|
.local_arg,
|
||||||
try dwarf.genVarDebugInfo(.local_arg, name, arg_ty, .{
|
name.toSlice(func.air),
|
||||||
.wasm_ext = .{ .local = arg.local.value },
|
arg_ty,
|
||||||
});
|
.{ .wasm_ext = .{ .local = arg.local.value } },
|
||||||
}
|
);
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
@ -6454,7 +6455,12 @@ fn airDbgInlineBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
|||||||
try func.lowerBlock(inst, ty_pl.ty.toType(), @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));
|
try func.lowerBlock(inst, ty_pl.ty.toType(), @ptrCast(func.air.extra[extra.end..][0..extra.data.body_len]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void {
|
fn airDbgVar(
|
||||||
|
func: *CodeGen,
|
||||||
|
inst: Air.Inst.Index,
|
||||||
|
local_tag: link.File.Dwarf.WipNav.LocalTag,
|
||||||
|
is_ptr: bool,
|
||||||
|
) InnerError!void {
|
||||||
_ = is_ptr;
|
_ = is_ptr;
|
||||||
if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
|
if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
|
||||||
|
|
||||||
@ -6464,8 +6470,8 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void
|
|||||||
|
|
||||||
log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand });
|
log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand });
|
||||||
|
|
||||||
const name = func.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
log.debug(" var name = ({s})", .{name});
|
log.debug(" var name = ({s})", .{name.toSlice(func.air)});
|
||||||
|
|
||||||
const loc: link.File.Dwarf.Loc = switch (operand) {
|
const loc: link.File.Dwarf.Loc = switch (operand) {
|
||||||
.local => |local| .{ .wasm_ext = .{ .local = local.value } },
|
.local => |local| .{ .wasm_ext = .{ .local = local.value } },
|
||||||
@ -6474,7 +6480,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) InnerError!void
|
|||||||
break :blk .empty;
|
break :blk .empty;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try func.debug_output.dwarf.genVarDebugInfo(.local_var, name, ty, loc);
|
try func.debug_output.dwarf.genLocalDebugInfo(local_tag, name.toSlice(func.air), ty, loc);
|
||||||
|
|
||||||
return func.finishAir(inst, .none, &.{});
|
return func.finishAir(inst, .none, &.{});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,8 +64,8 @@ va_info: union {
|
|||||||
sysv: struct {
|
sysv: struct {
|
||||||
gp_count: u32,
|
gp_count: u32,
|
||||||
fp_count: u32,
|
fp_count: u32,
|
||||||
overflow_arg_area: FrameAddr,
|
overflow_arg_area: bits.FrameAddr,
|
||||||
reg_save_area: FrameAddr,
|
reg_save_area: bits.FrameAddr,
|
||||||
},
|
},
|
||||||
win64: struct {},
|
win64: struct {},
|
||||||
},
|
},
|
||||||
@ -81,9 +81,6 @@ mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
|
|||||||
/// MIR extra data
|
/// MIR extra data
|
||||||
mir_extra: std.ArrayListUnmanaged(u32) = .{},
|
mir_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||||
|
|
||||||
stack_args: std.ArrayListUnmanaged(StackVar) = .{},
|
|
||||||
stack_vars: std.ArrayListUnmanaged(StackVar) = .{},
|
|
||||||
|
|
||||||
/// Byte offset within the source file of the ending curly.
|
/// Byte offset within the source file of the ending curly.
|
||||||
end_di_line: u32,
|
end_di_line: u32,
|
||||||
end_di_column: u32,
|
end_di_column: u32,
|
||||||
@ -113,10 +110,6 @@ air_bookkeeping: @TypeOf(air_bookkeeping_init) = air_bookkeeping_init,
|
|||||||
|
|
||||||
const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
|
const air_bookkeeping_init = if (std.debug.runtime_safety) @as(usize, 0) else {};
|
||||||
|
|
||||||
const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
|
|
||||||
const RegisterOffset = struct { reg: Register, off: i32 = 0 };
|
|
||||||
const SymbolOffset = struct { sym: u32, off: i32 = 0 };
|
|
||||||
|
|
||||||
const Owner = union(enum) {
|
const Owner = union(enum) {
|
||||||
nav_index: InternPool.Nav.Index,
|
nav_index: InternPool.Nav.Index,
|
||||||
lazy_sym: link.File.LazySymbol,
|
lazy_sym: link.File.LazySymbol,
|
||||||
@ -174,7 +167,7 @@ pub const MCValue = union(enum) {
|
|||||||
/// The value is split across two registers.
|
/// The value is split across two registers.
|
||||||
register_pair: [2]Register,
|
register_pair: [2]Register,
|
||||||
/// The value is a constant offset from the value in a register.
|
/// The value is a constant offset from the value in a register.
|
||||||
register_offset: RegisterOffset,
|
register_offset: bits.RegisterOffset,
|
||||||
/// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
|
/// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
|
||||||
register_overflow: struct { reg: Register, eflags: Condition },
|
register_overflow: struct { reg: Register, eflags: Condition },
|
||||||
/// The value is in memory at a hard-coded address.
|
/// The value is in memory at a hard-coded address.
|
||||||
@ -182,11 +175,11 @@ pub const MCValue = union(enum) {
|
|||||||
memory: u64,
|
memory: u64,
|
||||||
/// The value is in memory at an address not-yet-allocated by the linker.
|
/// The value is in memory at an address not-yet-allocated by the linker.
|
||||||
/// This traditionally corresponds to a relocation emitted in a relocatable object file.
|
/// This traditionally corresponds to a relocation emitted in a relocatable object file.
|
||||||
load_symbol: SymbolOffset,
|
load_symbol: bits.SymbolOffset,
|
||||||
/// The address of the memory location not-yet-allocated by the linker.
|
/// The address of the memory location not-yet-allocated by the linker.
|
||||||
lea_symbol: SymbolOffset,
|
lea_symbol: bits.SymbolOffset,
|
||||||
/// The value is in memory at a constant offset from the address in a register.
|
/// The value is in memory at a constant offset from the address in a register.
|
||||||
indirect: RegisterOffset,
|
indirect: bits.RegisterOffset,
|
||||||
/// The value is in memory.
|
/// The value is in memory.
|
||||||
/// Payload is a symbol index.
|
/// Payload is a symbol index.
|
||||||
load_direct: u32,
|
load_direct: u32,
|
||||||
@ -207,10 +200,10 @@ pub const MCValue = union(enum) {
|
|||||||
lea_tlv: u32,
|
lea_tlv: u32,
|
||||||
/// The value stored at an offset from a frame index
|
/// The value stored at an offset from a frame index
|
||||||
/// Payload is a frame address.
|
/// Payload is a frame address.
|
||||||
load_frame: FrameAddr,
|
load_frame: bits.FrameAddr,
|
||||||
/// The address of an offset from a frame index
|
/// The address of an offset from a frame index
|
||||||
/// Payload is a frame address.
|
/// Payload is a frame address.
|
||||||
lea_frame: FrameAddr,
|
lea_frame: bits.FrameAddr,
|
||||||
/// Supports integer_per_element abi
|
/// Supports integer_per_element abi
|
||||||
elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },
|
elementwise_regs_then_frame: packed struct { regs: u3 = 0, frame_off: i29 = 0, frame_index: FrameIndex },
|
||||||
/// This indicates that we have already allocated a frame index for this instruction,
|
/// This indicates that we have already allocated a frame index for this instruction,
|
||||||
@ -426,10 +419,7 @@ pub const MCValue = union(enum) {
|
|||||||
.load_symbol => |sym_off| {
|
.load_symbol => |sym_off| {
|
||||||
assert(sym_off.off == 0);
|
assert(sym_off.off == 0);
|
||||||
return .{
|
return .{
|
||||||
.base = .{ .reloc = .{
|
.base = .{ .reloc = sym_off.sym_index },
|
||||||
.atom_index = try function.owner.getSymbolIndex(function),
|
|
||||||
.sym_index = sym_off.sym,
|
|
||||||
} },
|
|
||||||
.mod = .{ .rm = .{
|
.mod = .{ .rm = .{
|
||||||
.size = size,
|
.size = size,
|
||||||
.disp = sym_off.off,
|
.disp = sym_off.off,
|
||||||
@ -456,8 +446,8 @@ pub const MCValue = union(enum) {
|
|||||||
.register_overflow => |pl| try writer.print("{s}:{s}", .{
|
.register_overflow => |pl| try writer.print("{s}:{s}", .{
|
||||||
@tagName(pl.eflags), @tagName(pl.reg),
|
@tagName(pl.eflags), @tagName(pl.reg),
|
||||||
}),
|
}),
|
||||||
.load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym, pl.off }),
|
.load_symbol => |pl| try writer.print("[{} + 0x{x}]", .{ pl.sym_index, pl.off }),
|
||||||
.lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym, pl.off }),
|
.lea_symbol => |pl| try writer.print("{} + 0x{x}", .{ pl.sym_index, pl.off }),
|
||||||
.indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
|
.indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }),
|
||||||
.load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
|
.load_direct => |pl| try writer.print("[direct:{d}]", .{pl}),
|
||||||
.lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
|
.lea_direct => |pl| try writer.print("direct:{d}", .{pl}),
|
||||||
@ -728,12 +718,6 @@ const InstTracking = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const StackVar = struct {
|
|
||||||
name: []const u8,
|
|
||||||
type: Type,
|
|
||||||
frame_addr: FrameAddr,
|
|
||||||
};
|
|
||||||
|
|
||||||
const FrameAlloc = struct {
|
const FrameAlloc = struct {
|
||||||
abi_size: u31,
|
abi_size: u31,
|
||||||
spill_pad: u3,
|
spill_pad: u3,
|
||||||
@ -839,8 +823,6 @@ pub fn generate(
|
|||||||
function.exitlude_jump_relocs.deinit(gpa);
|
function.exitlude_jump_relocs.deinit(gpa);
|
||||||
function.mir_instructions.deinit(gpa);
|
function.mir_instructions.deinit(gpa);
|
||||||
function.mir_extra.deinit(gpa);
|
function.mir_extra.deinit(gpa);
|
||||||
function.stack_args.deinit(gpa);
|
|
||||||
function.stack_vars.deinit(gpa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});
|
wip_mir_log.debug("{}:", .{fmtNav(func.owner_nav, ip)});
|
||||||
@ -913,9 +895,6 @@ pub fn generate(
|
|||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
|
|
||||||
try function.genStackVarDebugInfo(.local_arg, function.stack_args.items);
|
|
||||||
try function.genStackVarDebugInfo(.local_var, function.stack_vars.items);
|
|
||||||
|
|
||||||
var mir: Mir = .{
|
var mir: Mir = .{
|
||||||
.instructions = function.mir_instructions.toOwnedSlice(),
|
.instructions = function.mir_instructions.toOwnedSlice(),
|
||||||
.extra = try function.mir_extra.toOwnedSlice(gpa),
|
.extra = try function.mir_extra.toOwnedSlice(gpa),
|
||||||
@ -924,6 +903,7 @@ pub fn generate(
|
|||||||
defer mir.deinit(gpa);
|
defer mir.deinit(gpa);
|
||||||
|
|
||||||
var emit: Emit = .{
|
var emit: Emit = .{
|
||||||
|
.air = function.air,
|
||||||
.lower = .{
|
.lower = .{
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.allocator = gpa,
|
.allocator = gpa,
|
||||||
@ -934,6 +914,13 @@ pub fn generate(
|
|||||||
.link_mode = comp.config.link_mode,
|
.link_mode = comp.config.link_mode,
|
||||||
.pic = mod.pic,
|
.pic = mod.pic,
|
||||||
},
|
},
|
||||||
|
.atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
|
||||||
|
error.CodegenFail => return Result{ .fail = function.err_msg.? },
|
||||||
|
error.OutOfRegisters => return Result{
|
||||||
|
.fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
|
||||||
|
},
|
||||||
|
else => |e| return e,
|
||||||
|
},
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.code = code,
|
.code = code,
|
||||||
.prev_di_pc = 0,
|
.prev_di_pc = 0,
|
||||||
@ -1013,14 +1000,15 @@ pub fn generateLazy(
|
|||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
|
|
||||||
var mir = Mir{
|
var mir: Mir = .{
|
||||||
.instructions = function.mir_instructions.toOwnedSlice(),
|
.instructions = function.mir_instructions.toOwnedSlice(),
|
||||||
.extra = try function.mir_extra.toOwnedSlice(gpa),
|
.extra = try function.mir_extra.toOwnedSlice(gpa),
|
||||||
.frame_locs = function.frame_locs.toOwnedSlice(),
|
.frame_locs = function.frame_locs.toOwnedSlice(),
|
||||||
};
|
};
|
||||||
defer mir.deinit(gpa);
|
defer mir.deinit(gpa);
|
||||||
|
|
||||||
var emit = Emit{
|
var emit: Emit = .{
|
||||||
|
.air = function.air,
|
||||||
.lower = .{
|
.lower = .{
|
||||||
.bin_file = bin_file,
|
.bin_file = bin_file,
|
||||||
.allocator = gpa,
|
.allocator = gpa,
|
||||||
@ -1031,6 +1019,13 @@ pub fn generateLazy(
|
|||||||
.link_mode = comp.config.link_mode,
|
.link_mode = comp.config.link_mode,
|
||||||
.pic = mod.pic,
|
.pic = mod.pic,
|
||||||
},
|
},
|
||||||
|
.atom_index = function.owner.getSymbolIndex(&function) catch |err| switch (err) {
|
||||||
|
error.CodegenFail => return Result{ .fail = function.err_msg.? },
|
||||||
|
error.OutOfRegisters => return Result{
|
||||||
|
.fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
|
||||||
|
},
|
||||||
|
else => |e| return e,
|
||||||
|
},
|
||||||
.debug_output = debug_output,
|
.debug_output = debug_output,
|
||||||
.code = code,
|
.code = code,
|
||||||
.prev_di_pc = undefined, // no debug info yet
|
.prev_di_pc = undefined, // no debug info yet
|
||||||
@ -1116,7 +1111,7 @@ fn formatWipMir(
|
|||||||
) @TypeOf(writer).Error!void {
|
) @TypeOf(writer).Error!void {
|
||||||
const comp = data.self.bin_file.comp;
|
const comp = data.self.bin_file.comp;
|
||||||
const mod = comp.root_mod;
|
const mod = comp.root_mod;
|
||||||
var lower = Lower{
|
var lower: Lower = .{
|
||||||
.bin_file = data.self.bin_file,
|
.bin_file = data.self.bin_file,
|
||||||
.allocator = data.self.gpa,
|
.allocator = data.self.gpa,
|
||||||
.mir = .{
|
.mir = .{
|
||||||
@ -1204,6 +1199,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
|
|||||||
self.mir_extra.appendAssumeCapacity(switch (field.type) {
|
self.mir_extra.appendAssumeCapacity(switch (field.type) {
|
||||||
u32 => @field(extra, field.name),
|
u32 => @field(extra, field.name),
|
||||||
i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),
|
i32, Mir.Memory.Info => @bitCast(@field(extra, field.name)),
|
||||||
|
bits.FrameIndex => @intFromEnum(@field(extra, field.name)),
|
||||||
else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
|
else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1357,6 +1353,124 @@ fn asmPlaceholder(self: *Self) !Mir.Inst.Index {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MirTagAir = enum { dbg_local };
|
||||||
|
|
||||||
|
fn asmAir(self: *Self, tag: MirTagAir, inst: Air.Inst.Index) !void {
|
||||||
|
_ = try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_a,
|
||||||
|
},
|
||||||
|
.data = .{ .a = .{ .air_inst = inst } },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn asmAirImmediate(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, imm: Immediate) !void {
|
||||||
|
switch (imm) {
|
||||||
|
.signed => |s| _ = try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_ai_s,
|
||||||
|
},
|
||||||
|
.data = .{ .ai = .{
|
||||||
|
.air_inst = inst,
|
||||||
|
.i = @bitCast(s),
|
||||||
|
} },
|
||||||
|
}),
|
||||||
|
.unsigned => |u| _ = if (math.cast(u32, u)) |small| try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_ai_u,
|
||||||
|
},
|
||||||
|
.data = .{ .ai = .{
|
||||||
|
.air_inst = inst,
|
||||||
|
.i = small,
|
||||||
|
} },
|
||||||
|
}) else try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_ai_64,
|
||||||
|
},
|
||||||
|
.data = .{ .ai = .{
|
||||||
|
.air_inst = inst,
|
||||||
|
.i = try self.addExtra(Mir.Imm64.encode(u)),
|
||||||
|
} },
|
||||||
|
}),
|
||||||
|
.reloc => |sym_off| _ = if (sym_off.off == 0) try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_as,
|
||||||
|
},
|
||||||
|
.data = .{ .as = .{
|
||||||
|
.air_inst = inst,
|
||||||
|
.sym_index = sym_off.sym_index,
|
||||||
|
} },
|
||||||
|
}) else try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_aso,
|
||||||
|
},
|
||||||
|
.data = .{ .ax = .{
|
||||||
|
.air_inst = inst,
|
||||||
|
.payload = try self.addExtra(sym_off),
|
||||||
|
} },
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn asmAirRegisterImmediate(
|
||||||
|
self: *Self,
|
||||||
|
tag: MirTagAir,
|
||||||
|
inst: Air.Inst.Index,
|
||||||
|
reg: Register,
|
||||||
|
imm: Immediate,
|
||||||
|
) !void {
|
||||||
|
_ = try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_aro,
|
||||||
|
},
|
||||||
|
.data = .{ .rx = .{
|
||||||
|
.r1 = reg,
|
||||||
|
.payload = try self.addExtra(Mir.AirOffset{
|
||||||
|
.air_inst = inst,
|
||||||
|
.off = imm.signed,
|
||||||
|
}),
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn asmAirFrameAddress(
|
||||||
|
self: *Self,
|
||||||
|
tag: MirTagAir,
|
||||||
|
inst: Air.Inst.Index,
|
||||||
|
frame_addr: bits.FrameAddr,
|
||||||
|
) !void {
|
||||||
|
_ = try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_af,
|
||||||
|
},
|
||||||
|
.data = .{ .ax = .{
|
||||||
|
.air_inst = inst,
|
||||||
|
.payload = try self.addExtra(frame_addr),
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn asmAirMemory(self: *Self, tag: MirTagAir, inst: Air.Inst.Index, m: Memory) !void {
|
||||||
|
_ = try self.addInst(.{
|
||||||
|
.tag = .pseudo,
|
||||||
|
.ops = switch (tag) {
|
||||||
|
.dbg_local => .pseudo_dbg_local_am,
|
||||||
|
},
|
||||||
|
.data = .{ .ax = .{
|
||||||
|
.air_inst = inst,
|
||||||
|
.payload = try self.addExtra(Mir.Memory.encode(m)),
|
||||||
|
} },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn asmOpOnly(self: *Self, tag: Mir.Inst.FixedTag) !void {
|
fn asmOpOnly(self: *Self, tag: Mir.Inst.FixedTag) !void {
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = tag[1],
|
.tag = tag[1],
|
||||||
@ -1395,9 +1509,9 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
|
|||||||
.reloc => .rel,
|
.reloc => .rel,
|
||||||
},
|
},
|
||||||
.data = switch (imm) {
|
.data = switch (imm) {
|
||||||
.reloc => |x| reloc: {
|
.reloc => |sym_off| reloc: {
|
||||||
assert(tag[0] == ._);
|
assert(tag[0] == ._);
|
||||||
break :reloc .{ .reloc = x };
|
break :reloc .{ .reloc = sym_off };
|
||||||
},
|
},
|
||||||
.signed, .unsigned => .{ .i = .{
|
.signed, .unsigned => .{ .i = .{
|
||||||
.fixes = tag[0],
|
.fixes = tag[0],
|
||||||
@ -1424,31 +1538,22 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void {
|
fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void {
|
||||||
const ops: Mir.Inst.Ops = switch (imm) {
|
const ops: Mir.Inst.Ops, const i: u32 = switch (imm) {
|
||||||
.signed => .ri_s,
|
.signed => |s| .{ .ri_s, @bitCast(s) },
|
||||||
.unsigned => |u| if (math.cast(u32, u)) |_| .ri_u else .ri64,
|
.unsigned => |u| if (math.cast(u32, u)) |small|
|
||||||
|
.{ .ri_u, small }
|
||||||
|
else
|
||||||
|
.{ .ri_64, try self.addExtra(Mir.Imm64.encode(imm.unsigned)) },
|
||||||
.reloc => unreachable,
|
.reloc => unreachable,
|
||||||
};
|
};
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = tag[1],
|
.tag = tag[1],
|
||||||
.ops = ops,
|
.ops = ops,
|
||||||
.data = switch (ops) {
|
.data = .{ .ri = .{
|
||||||
.ri_s, .ri_u => .{ .ri = .{
|
.fixes = tag[0],
|
||||||
.fixes = tag[0],
|
.r1 = reg,
|
||||||
.r1 = reg,
|
.i = i,
|
||||||
.i = switch (imm) {
|
} },
|
||||||
.signed => |s| @bitCast(s),
|
|
||||||
.unsigned => |u| @intCast(u),
|
|
||||||
.reloc => unreachable,
|
|
||||||
},
|
|
||||||
} },
|
|
||||||
.ri64 => .{ .rx = .{
|
|
||||||
.fixes = tag[0],
|
|
||||||
.r1 = reg,
|
|
||||||
.payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)),
|
|
||||||
} },
|
|
||||||
else => unreachable,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2158,6 +2263,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
|||||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> try self.airDbgVar(inst),
|
=> try self.airDbgVar(inst),
|
||||||
|
|
||||||
.call => try self.airCall(inst, .auto),
|
.call => try self.airCall(inst, .auto),
|
||||||
@ -2485,12 +2591,12 @@ fn computeFrameLayout(self: *Self, cc: std.builtin.CallingConvention) !FrameLayo
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFrameAddrAlignment(self: *Self, frame_addr: FrameAddr) Alignment {
|
fn getFrameAddrAlignment(self: *Self, frame_addr: bits.FrameAddr) Alignment {
|
||||||
const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
|
const alloc_align = self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_align;
|
||||||
return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
|
return @enumFromInt(@min(@intFromEnum(alloc_align), @ctz(frame_addr.off)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFrameAddrSize(self: *Self, frame_addr: FrameAddr) u32 {
|
fn getFrameAddrSize(self: *Self, frame_addr: bits.FrameAddr) u32 {
|
||||||
return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));
|
return self.frame_allocs.get(@intFromEnum(frame_addr.index)).abi_size - @as(u31, @intCast(frame_addr.off));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11951,87 +12057,65 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void {
|
fn airDbgArg(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
defer self.finishAirBookkeeping();
|
defer self.finishAirBookkeeping();
|
||||||
if (self.debug_output == .none) return;
|
if (self.debug_output == .none) return;
|
||||||
const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
|
||||||
const name = self.air.nullTerminatedString(@intFromEnum(name_nts));
|
if (name != .none) try self.genLocalDebugInfo(inst, self.getResolvedInstValue(inst).short);
|
||||||
if (name.len > 0) {
|
|
||||||
const arg_ty = self.typeOfIndex(inst);
|
|
||||||
const arg_mcv = self.getResolvedInstValue(inst).short;
|
|
||||||
try self.genVarDebugInfo(.local_arg, .dbg_var_val, name, arg_ty, arg_mcv);
|
|
||||||
}
|
|
||||||
if (self.liveness.isUnused(inst)) try self.processDeath(inst);
|
if (self.liveness.isUnused(inst)) try self.processDeath(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genVarDebugInfo(
|
fn genLocalDebugInfo(
|
||||||
self: *Self,
|
self: *Self,
|
||||||
var_tag: link.File.Dwarf.WipNav.VarTag,
|
inst: Air.Inst.Index,
|
||||||
tag: Air.Inst.Tag,
|
|
||||||
name: []const u8,
|
|
||||||
ty: Type,
|
|
||||||
mcv: MCValue,
|
mcv: MCValue,
|
||||||
) !void {
|
) !void {
|
||||||
const stack_vars = switch (var_tag) {
|
if (self.debug_output == .none) return;
|
||||||
.local_arg => &self.stack_args,
|
switch (self.air.instructions.items(.tag)[@intFromEnum(inst)]) {
|
||||||
.local_var => &self.stack_vars,
|
else => unreachable,
|
||||||
};
|
.arg, .dbg_arg_inline, .dbg_var_val => |tag| {
|
||||||
switch (self.debug_output) {
|
switch (mcv) {
|
||||||
.dwarf => |dwarf| switch (tag) {
|
.none => try self.asmAir(.dbg_local, inst),
|
||||||
else => unreachable,
|
|
||||||
.dbg_var_ptr => {
|
|
||||||
const var_ty = ty.childType(self.pt.zcu);
|
|
||||||
switch (mcv) {
|
|
||||||
else => {
|
|
||||||
log.info("dbg_var_ptr({s}({}))", .{ @tagName(mcv), mcv });
|
|
||||||
unreachable;
|
|
||||||
},
|
|
||||||
.unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
|
|
||||||
.lea_frame => |frame_addr| try stack_vars.append(self.gpa, .{
|
|
||||||
.name = name,
|
|
||||||
.type = var_ty,
|
|
||||||
.frame_addr = frame_addr,
|
|
||||||
}),
|
|
||||||
.lea_symbol => |sym_off| try dwarf.genVarDebugInfo(var_tag, name, var_ty, .{ .plus = .{
|
|
||||||
&.{ .addr = .{ .sym = sym_off.sym } },
|
|
||||||
&.{ .consts = sym_off.off },
|
|
||||||
} }),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.dbg_var_val => switch (mcv) {
|
|
||||||
.none => try dwarf.genVarDebugInfo(var_tag, name, ty, .empty),
|
|
||||||
.unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
|
.unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
|
||||||
.immediate => |immediate| try dwarf.genVarDebugInfo(var_tag, name, ty, .{ .stack_value = &.{
|
.immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, Immediate.u(imm)),
|
||||||
.constu = immediate,
|
.lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr),
|
||||||
} }),
|
.lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, Immediate.rel(sym_off)),
|
||||||
else => {
|
else => {
|
||||||
|
const ty = switch (tag) {
|
||||||
|
else => unreachable,
|
||||||
|
.arg => self.typeOfIndex(inst),
|
||||||
|
.dbg_arg_inline, .dbg_var_val => self.typeOf(
|
||||||
|
self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op.operand,
|
||||||
|
),
|
||||||
|
};
|
||||||
const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ty, self.pt));
|
const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(ty, self.pt));
|
||||||
try self.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});
|
try self.genSetMem(.{ .frame = frame_index }, 0, ty, mcv, .{});
|
||||||
try stack_vars.append(self.gpa, .{
|
try self.asmAirMemory(.dbg_local, inst, .{
|
||||||
.name = name,
|
.base = .{ .frame = frame_index },
|
||||||
.type = ty,
|
.mod = .{ .rm = .{ .size = .qword } },
|
||||||
.frame_addr = .{ .index = frame_index },
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
.dbg_var_ptr => switch (mcv) {
|
||||||
.none => {},
|
else => unreachable,
|
||||||
}
|
.unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable,
|
||||||
}
|
.lea_frame => |frame_addr| try self.asmAirMemory(.dbg_local, inst, .{
|
||||||
|
.base = .{ .frame = frame_addr.index },
|
||||||
fn genStackVarDebugInfo(
|
.mod = .{ .rm = .{
|
||||||
self: Self,
|
.size = .qword,
|
||||||
var_tag: link.File.Dwarf.WipNav.VarTag,
|
.disp = frame_addr.off,
|
||||||
stack_vars: []const StackVar,
|
} },
|
||||||
) !void {
|
}),
|
||||||
switch (self.debug_output) {
|
.lea_symbol => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{
|
||||||
.dwarf => |dwarf| for (stack_vars) |stack_var| {
|
.base = .{ .reloc = sym_off.sym_index },
|
||||||
const frame_loc = self.frame_locs.get(@intFromEnum(stack_var.frame_addr.index));
|
.mod = .{ .rm = .{
|
||||||
try dwarf.genVarDebugInfo(var_tag, stack_var.name, stack_var.type, .{ .plus = .{
|
.size = .qword,
|
||||||
&.{ .breg = frame_loc.base.dwarfNum() },
|
.disp = sym_off.off,
|
||||||
&.{ .consts = @as(i33, frame_loc.disp) + stack_var.frame_addr.off },
|
} },
|
||||||
} });
|
}),
|
||||||
|
.lea_direct, .lea_got, .lea_tlv => |sym_index| try self.asmAirMemory(.dbg_local, inst, .{
|
||||||
|
.base = .{ .reloc = sym_index },
|
||||||
|
.mod = .{ .rm = .{ .size = .qword } },
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
|
||||||
.none => {},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12351,10 +12435,7 @@ fn genCall(self: *Self, info: union(enum) {
|
|||||||
if (self.bin_file.cast(.elf)) |elf_file| {
|
if (self.bin_file.cast(.elf)) |elf_file| {
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
|
const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
|
||||||
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
|
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index }));
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = sym_index,
|
|
||||||
}));
|
|
||||||
} else if (self.bin_file.cast(.coff)) |coff_file| {
|
} else if (self.bin_file.cast(.coff)) |coff_file| {
|
||||||
const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
|
const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
|
||||||
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
|
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
|
||||||
@ -12364,10 +12445,7 @@ fn genCall(self: *Self, info: union(enum) {
|
|||||||
const zo = macho_file.getZigObject().?;
|
const zo = macho_file.getZigObject().?;
|
||||||
const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
|
const sym_index = try zo.getOrCreateMetadataForNav(macho_file, func.owner_nav);
|
||||||
const sym = zo.symbols.items[sym_index];
|
const sym = zo.symbols.items[sym_index];
|
||||||
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
|
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym.nlist_idx }));
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = sym.nlist_idx,
|
|
||||||
}));
|
|
||||||
} else if (self.bin_file.cast(.plan9)) |p9| {
|
} else if (self.bin_file.cast(.plan9)) |p9| {
|
||||||
const atom_index = try p9.seeNav(pt, func.owner_nav);
|
const atom_index = try p9.seeNav(pt, func.owner_nav);
|
||||||
const atom = p9.getAtom(atom_index);
|
const atom = p9.getAtom(atom_index);
|
||||||
@ -12385,19 +12463,13 @@ fn genCall(self: *Self, info: union(enum) {
|
|||||||
@"extern".name.toSlice(ip),
|
@"extern".name.toSlice(ip),
|
||||||
@"extern".lib_name.toSlice(ip),
|
@"extern".lib_name.toSlice(ip),
|
||||||
);
|
);
|
||||||
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
|
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = target_sym_index,
|
|
||||||
}));
|
|
||||||
} else if (self.bin_file.cast(.macho)) |macho_file| {
|
} else if (self.bin_file.cast(.macho)) |macho_file| {
|
||||||
const target_sym_index = try macho_file.getGlobalSymbol(
|
const target_sym_index = try macho_file.getGlobalSymbol(
|
||||||
@"extern".name.toSlice(ip),
|
@"extern".name.toSlice(ip),
|
||||||
@"extern".lib_name.toSlice(ip),
|
@"extern".lib_name.toSlice(ip),
|
||||||
);
|
);
|
||||||
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
|
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = target_sym_index,
|
|
||||||
}));
|
|
||||||
} else try self.genExternSymbolRef(
|
} else try self.genExternSymbolRef(
|
||||||
.call,
|
.call,
|
||||||
@"extern".lib_name.toSlice(ip),
|
@"extern".lib_name.toSlice(ip),
|
||||||
@ -12412,16 +12484,10 @@ fn genCall(self: *Self, info: union(enum) {
|
|||||||
},
|
},
|
||||||
.lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
|
.lib => |lib| if (self.bin_file.cast(.elf)) |elf_file| {
|
||||||
const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
|
const target_sym_index = try elf_file.getGlobalSymbol(lib.callee, lib.lib);
|
||||||
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
|
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = target_sym_index,
|
|
||||||
}));
|
|
||||||
} else if (self.bin_file.cast(.macho)) |macho_file| {
|
} else if (self.bin_file.cast(.macho)) |macho_file| {
|
||||||
const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
|
const target_sym_index = try macho_file.getGlobalSymbol(lib.callee, lib.lib);
|
||||||
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{
|
try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = target_sym_index }));
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = target_sym_index,
|
|
||||||
}));
|
|
||||||
} else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
|
} else try self.genExternSymbolRef(.call, lib.lib, lib.callee),
|
||||||
}
|
}
|
||||||
return call_info.return_value.short;
|
return call_info.return_value.short;
|
||||||
@ -13060,29 +13126,21 @@ fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
self.inline_func = extra.data.func;
|
self.inline_func = extra.data.func;
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = .pseudo,
|
.tag = .pseudo,
|
||||||
.ops = .pseudo_dbg_inline_func,
|
.ops = .pseudo_dbg_enter_inline_func,
|
||||||
.data = .{ .func = extra.data.func },
|
.data = .{ .func = extra.data.func },
|
||||||
});
|
});
|
||||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = .pseudo,
|
.tag = .pseudo,
|
||||||
.ops = .pseudo_dbg_inline_func,
|
.ops = .pseudo_dbg_leave_inline_func,
|
||||||
.data = .{ .func = old_inline_func },
|
.data = .{ .func = old_inline_func },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||||
const operand = pl_op.operand;
|
try self.genLocalDebugInfo(inst, try self.resolveInst(pl_op.operand));
|
||||||
const ty = self.typeOf(operand);
|
return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
|
||||||
const mcv = try self.resolveInst(operand);
|
|
||||||
|
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
|
||||||
|
|
||||||
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
|
|
||||||
try self.genVarDebugInfo(.local_var, tag, name, ty, mcv);
|
|
||||||
|
|
||||||
return self.finishAir(inst, .unreach, .{ operand, .none, .none });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
|
fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
|
||||||
@ -14970,10 +15028,7 @@ fn genSetReg(
|
|||||||
.general_purpose => {
|
.general_purpose => {
|
||||||
assert(sym_off.off == 0);
|
assert(sym_off.off == 0);
|
||||||
try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
|
try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(dst_reg, abi_size), .{
|
||||||
.base = .{ .reloc = .{
|
.base = .{ .reloc = sym_off.sym_index },
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = sym_off.sym,
|
|
||||||
} },
|
|
||||||
.mod = .{ .rm = .{
|
.mod = .{ .rm = .{
|
||||||
.size = self.memSize(ty),
|
.size = self.memSize(ty),
|
||||||
.disp = sym_off.off,
|
.disp = sym_off.off,
|
||||||
@ -14991,10 +15046,7 @@ fn genSetReg(
|
|||||||
.ops = .direct_reloc,
|
.ops = .direct_reloc,
|
||||||
.data = .{ .rx = .{
|
.data = .{ .rx = .{
|
||||||
.r1 = registerAlias(dst_reg, abi_size),
|
.r1 = registerAlias(dst_reg, abi_size),
|
||||||
.payload = try self.addExtra(bits.Symbol{
|
.payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
|
||||||
.sym_index = sym_index,
|
|
||||||
}),
|
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -15019,52 +15071,38 @@ fn genSetReg(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
.lea_symbol => |sym_index| {
|
.lea_symbol => |sym_off| switch (self.bin_file.tag) {
|
||||||
const atom_index = try self.owner.getSymbolIndex(self);
|
.elf, .macho => try self.asmRegisterMemory(
|
||||||
switch (self.bin_file.tag) {
|
.{ ._, .lea },
|
||||||
.elf, .macho => {
|
dst_reg.to64(),
|
||||||
try self.asmRegisterMemory(
|
.{
|
||||||
.{ ._, .lea },
|
.base = .{ .reloc = sym_off.sym_index },
|
||||||
dst_reg.to64(),
|
.mod = .{ .rm = .{
|
||||||
.{
|
.size = .qword,
|
||||||
.base = .{ .reloc = .{
|
.disp = sym_off.off,
|
||||||
.atom_index = atom_index,
|
} },
|
||||||
.sym_index = sym_index.sym,
|
|
||||||
} },
|
|
||||||
.mod = .{ .rm = .{
|
|
||||||
.size = .qword,
|
|
||||||
.disp = sym_index.off,
|
|
||||||
} },
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
else => return self.fail("TODO emit symbol sequence on {s}", .{
|
),
|
||||||
@tagName(self.bin_file.tag),
|
else => return self.fail("TODO emit symbol sequence on {s}", .{
|
||||||
}),
|
@tagName(self.bin_file.tag),
|
||||||
}
|
}),
|
||||||
},
|
|
||||||
.lea_direct, .lea_got => |sym_index| {
|
|
||||||
const atom_index = try self.owner.getSymbolIndex(self);
|
|
||||||
_ = try self.addInst(.{
|
|
||||||
.tag = switch (src_mcv) {
|
|
||||||
.lea_direct => .lea,
|
|
||||||
.lea_got => .mov,
|
|
||||||
else => unreachable,
|
|
||||||
},
|
|
||||||
.ops = switch (src_mcv) {
|
|
||||||
.lea_direct => .direct_reloc,
|
|
||||||
.lea_got => .got_reloc,
|
|
||||||
else => unreachable,
|
|
||||||
},
|
|
||||||
.data = .{ .rx = .{
|
|
||||||
.r1 = dst_reg.to64(),
|
|
||||||
.payload = try self.addExtra(bits.Symbol{
|
|
||||||
.atom_index = atom_index,
|
|
||||||
.sym_index = sym_index,
|
|
||||||
}),
|
|
||||||
} },
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
.lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{
|
||||||
|
.tag = switch (src_mcv) {
|
||||||
|
.lea_direct => .lea,
|
||||||
|
.lea_got => .mov,
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
.ops = switch (src_mcv) {
|
||||||
|
.lea_direct => .direct_reloc,
|
||||||
|
.lea_got => .got_reloc,
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
.data = .{ .rx = .{
|
||||||
|
.r1 = dst_reg.to64(),
|
||||||
|
.payload = try self.addExtra(bits.SymbolOffset{ .sym_index = sym_index }),
|
||||||
|
} },
|
||||||
|
}),
|
||||||
.lea_tlv => unreachable, // TODO: remove this
|
.lea_tlv => unreachable, // TODO: remove this
|
||||||
.air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
|
.air_ref => |src_ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(src_ref), opts),
|
||||||
}
|
}
|
||||||
@ -15085,7 +15123,7 @@ fn genSetMem(
|
|||||||
.none => .{ .immediate = @bitCast(@as(i64, disp)) },
|
.none => .{ .immediate = @bitCast(@as(i64, disp)) },
|
||||||
.reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
|
.reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
|
||||||
.frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
|
.frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
|
||||||
.reloc => |base_symbol| .{ .lea_symbol = .{ .sym = base_symbol.sym_index, .off = disp } },
|
.reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
|
||||||
};
|
};
|
||||||
switch (src_mcv) {
|
switch (src_mcv) {
|
||||||
.none,
|
.none,
|
||||||
@ -15328,7 +15366,6 @@ fn genExternSymbolRef(
|
|||||||
lib: ?[]const u8,
|
lib: ?[]const u8,
|
||||||
callee: []const u8,
|
callee: []const u8,
|
||||||
) InnerError!void {
|
) InnerError!void {
|
||||||
const atom_index = try self.owner.getSymbolIndex(self);
|
|
||||||
if (self.bin_file.cast(.coff)) |coff_file| {
|
if (self.bin_file.cast(.coff)) |coff_file| {
|
||||||
const global_index = try coff_file.getGlobalSymbol(callee, lib);
|
const global_index = try coff_file.getGlobalSymbol(callee, lib);
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
@ -15336,8 +15373,7 @@ fn genExternSymbolRef(
|
|||||||
.ops = .import_reloc,
|
.ops = .import_reloc,
|
||||||
.data = .{ .rx = .{
|
.data = .{ .rx = .{
|
||||||
.r1 = .rax,
|
.r1 = .rax,
|
||||||
.payload = try self.addExtra(bits.Symbol{
|
.payload = try self.addExtra(bits.SymbolOffset{
|
||||||
.atom_index = atom_index,
|
|
||||||
.sym_index = link.File.Coff.global_symbol_bit | global_index,
|
.sym_index = link.File.Coff.global_symbol_bit | global_index,
|
||||||
}),
|
}),
|
||||||
} },
|
} },
|
||||||
@ -15364,10 +15400,10 @@ fn genLazySymbolRef(
|
|||||||
if (self.mod.pic) {
|
if (self.mod.pic) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
.lea, .call => try self.genSetReg(reg, Type.usize, .{
|
.lea, .call => try self.genSetReg(reg, Type.usize, .{
|
||||||
.lea_symbol = .{ .sym = sym_index },
|
.lea_symbol = .{ .sym_index = sym_index },
|
||||||
}, .{}),
|
}, .{}),
|
||||||
.mov => try self.genSetReg(reg, Type.usize, .{
|
.mov => try self.genSetReg(reg, Type.usize, .{
|
||||||
.load_symbol = .{ .sym = sym_index },
|
.load_symbol = .{ .sym_index = sym_index },
|
||||||
}, .{}),
|
}, .{}),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
@ -15376,19 +15412,13 @@ fn genLazySymbolRef(
|
|||||||
.call => try self.asmRegister(.{ ._, .call }, reg),
|
.call => try self.asmRegister(.{ ._, .call }, reg),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
} else {
|
} else switch (tag) {
|
||||||
const reloc = bits.Symbol{
|
.lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
|
||||||
.atom_index = try self.owner.getSymbolIndex(self),
|
.base = .{ .reloc = sym_index },
|
||||||
.sym_index = sym_index,
|
.mod = .{ .rm = .{ .size = .qword } },
|
||||||
};
|
}),
|
||||||
switch (tag) {
|
.call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(.{ .sym_index = sym_index })),
|
||||||
.lea, .mov => try self.asmRegisterMemory(.{ ._, tag }, reg.to64(), .{
|
else => unreachable,
|
||||||
.base = .{ .reloc = reloc },
|
|
||||||
.mod = .{ .rm = .{ .size = .qword } },
|
|
||||||
}),
|
|
||||||
.call => try self.asmImmediate(.{ ._, .call }, Immediate.rel(reloc)),
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (self.bin_file.cast(.plan9)) |p9_file| {
|
} else if (self.bin_file.cast(.plan9)) |p9_file| {
|
||||||
const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
|
const atom_index = p9_file.getOrCreateAtomForLazySymbol(pt, lazy_sym) catch |err|
|
||||||
@ -15438,10 +15468,10 @@ fn genLazySymbolRef(
|
|||||||
const sym = zo.symbols.items[sym_index];
|
const sym = zo.symbols.items[sym_index];
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
.lea, .call => try self.genSetReg(reg, Type.usize, .{
|
.lea, .call => try self.genSetReg(reg, Type.usize, .{
|
||||||
.lea_symbol = .{ .sym = sym.nlist_idx },
|
.lea_symbol = .{ .sym_index = sym.nlist_idx },
|
||||||
}, .{}),
|
}, .{}),
|
||||||
.mov => try self.genSetReg(reg, Type.usize, .{
|
.mov => try self.genSetReg(reg, Type.usize, .{
|
||||||
.load_symbol = .{ .sym = sym.nlist_idx },
|
.load_symbol = .{ .sym_index = sym.nlist_idx },
|
||||||
}, .{}),
|
}, .{}),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
@ -18786,7 +18816,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
|
|||||||
.{ .frame = frame_index },
|
.{ .frame = frame_index },
|
||||||
0,
|
0,
|
||||||
Type.usize,
|
Type.usize,
|
||||||
.{ .lea_symbol = .{ .sym = tlv_sym } },
|
.{ .lea_symbol = .{ .sym_index = tlv_sym } },
|
||||||
.{},
|
.{},
|
||||||
);
|
);
|
||||||
break :init .{ .load_frame = .{ .index = frame_index } };
|
break :init .{ .load_frame = .{ .index = frame_index } };
|
||||||
@ -18842,8 +18872,8 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
|
|||||||
.undef => .undef,
|
.undef => .undef,
|
||||||
.immediate => |imm| .{ .immediate = imm },
|
.immediate => |imm| .{ .immediate = imm },
|
||||||
.memory => |addr| .{ .memory = addr },
|
.memory => |addr| .{ .memory = addr },
|
||||||
.load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
|
.load_symbol => |sym_index| .{ .load_symbol = .{ .sym_index = sym_index } },
|
||||||
.lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
|
.lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index } },
|
||||||
.load_direct => |sym_index| .{ .load_direct = sym_index },
|
.load_direct => |sym_index| .{ .load_direct = sym_index },
|
||||||
.lea_direct => |sym_index| .{ .lea_direct = sym_index },
|
.lea_direct => |sym_index| .{ .lea_direct = sym_index },
|
||||||
.load_got => |sym_index| .{ .lea_got = sym_index },
|
.load_got => |sym_index| .{ .lea_got = sym_index },
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
//! This file contains the functionality for emitting x86_64 MIR as machine code
|
//! This file contains the functionality for emitting x86_64 MIR as machine code
|
||||||
|
|
||||||
|
air: Air,
|
||||||
lower: Lower,
|
lower: Lower,
|
||||||
|
atom_index: u32,
|
||||||
debug_output: DebugInfoOutput,
|
debug_output: DebugInfoOutput,
|
||||||
code: *std.ArrayList(u8),
|
code: *std.ArrayList(u8),
|
||||||
|
|
||||||
@ -36,83 +38,84 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
}) switch (lowered_relocs[0].target) {
|
}) switch (lowered_relocs[0].target) {
|
||||||
.inst => |target| try emit.relocs.append(emit.lower.allocator, .{
|
.inst => |target| try emit.relocs.append(emit.lower.allocator, .{
|
||||||
.source = start_offset,
|
.source = start_offset,
|
||||||
|
.source_offset = end_offset - 4,
|
||||||
.target = target,
|
.target = target,
|
||||||
.offset = end_offset - 4,
|
.target_offset = lowered_relocs[0].off,
|
||||||
.length = @intCast(end_offset - start_offset),
|
.length = @intCast(end_offset - start_offset),
|
||||||
}),
|
}),
|
||||||
.linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
|
.linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
|
||||||
// Add relocation to the decl.
|
// Add relocation to the decl.
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
|
const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
|
||||||
const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
|
const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
|
||||||
try atom_ptr.addReloc(elf_file, .{
|
try atom_ptr.addReloc(elf_file, .{
|
||||||
.r_offset = end_offset - 4,
|
.r_offset = end_offset - 4,
|
||||||
.r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
|
.r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
|
||||||
.r_addend = -4,
|
.r_addend = lowered_relocs[0].off - 4,
|
||||||
});
|
});
|
||||||
} else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
|
} else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
|
||||||
// Add relocation to the decl.
|
// Add relocation to the decl.
|
||||||
const zo = macho_file.getZigObject().?;
|
const zo = macho_file.getZigObject().?;
|
||||||
const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?;
|
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
|
||||||
try atom.addReloc(macho_file, .{
|
try atom.addReloc(macho_file, .{
|
||||||
.tag = .@"extern",
|
.tag = .@"extern",
|
||||||
.offset = end_offset - 4,
|
.offset = end_offset - 4,
|
||||||
.target = symbol.sym_index,
|
.target = sym_index,
|
||||||
.addend = 0,
|
.addend = lowered_relocs[0].off,
|
||||||
.type = .branch,
|
.type = .branch,
|
||||||
.meta = .{
|
.meta = .{
|
||||||
.pcrel = true,
|
.pcrel = true,
|
||||||
.has_subtractor = false,
|
.has_subtractor = false,
|
||||||
.length = 2,
|
.length = 2,
|
||||||
.symbolnum = @intCast(symbol.sym_index),
|
.symbolnum = @intCast(sym_index),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
|
} else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
|
||||||
// Add relocation to the decl.
|
// Add relocation to the decl.
|
||||||
const atom_index = coff_file.getAtomIndexForSymbol(
|
const atom_index = coff_file.getAtomIndexForSymbol(
|
||||||
.{ .sym_index = symbol.atom_index, .file = null },
|
.{ .sym_index = emit.atom_index, .file = null },
|
||||||
).?;
|
).?;
|
||||||
const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
|
const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
|
||||||
coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
|
coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
|
||||||
else
|
else
|
||||||
link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
|
link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
|
||||||
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
|
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
|
||||||
.type = .direct,
|
.type = .direct,
|
||||||
.target = target,
|
.target = target,
|
||||||
.offset = end_offset - 4,
|
.offset = end_offset - 4,
|
||||||
.addend = 0,
|
.addend = @intCast(lowered_relocs[0].off),
|
||||||
.pcrel = true,
|
.pcrel = true,
|
||||||
.length = 2,
|
.length = 2,
|
||||||
});
|
});
|
||||||
} else return emit.fail("TODO implement extern reloc for {s}", .{
|
} else return emit.fail("TODO implement extern reloc for {s}", .{
|
||||||
@tagName(emit.lower.bin_file.tag),
|
@tagName(emit.lower.bin_file.tag),
|
||||||
}),
|
}),
|
||||||
.linker_tlsld => |data| {
|
.linker_tlsld => |sym_index| {
|
||||||
const elf_file = emit.lower.bin_file.cast(.elf).?;
|
const elf_file = emit.lower.bin_file.cast(.elf).?;
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
const atom = zo.symbol(data.atom_index).atom(elf_file).?;
|
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
|
||||||
const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
|
const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
|
||||||
try atom.addReloc(elf_file, .{
|
try atom.addReloc(elf_file, .{
|
||||||
.r_offset = end_offset - 4,
|
.r_offset = end_offset - 4,
|
||||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
|
.r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
|
||||||
.r_addend = -4,
|
.r_addend = lowered_relocs[0].off - 4,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.linker_dtpoff => |data| {
|
.linker_dtpoff => |sym_index| {
|
||||||
const elf_file = emit.lower.bin_file.cast(.elf).?;
|
const elf_file = emit.lower.bin_file.cast(.elf).?;
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
const atom = zo.symbol(data.atom_index).atom(elf_file).?;
|
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
|
||||||
const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
|
const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
|
||||||
try atom.addReloc(elf_file, .{
|
try atom.addReloc(elf_file, .{
|
||||||
.r_offset = end_offset - 4,
|
.r_offset = end_offset - 4,
|
||||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
|
.r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
|
||||||
.r_addend = 0,
|
.r_addend = lowered_relocs[0].off,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.linker_reloc => |data| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
|
.linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
const atom = zo.symbol(data.atom_index).atom(elf_file).?;
|
const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
|
||||||
const sym = zo.symbol(data.sym_index);
|
const sym = zo.symbol(sym_index);
|
||||||
if (emit.lower.pic) {
|
if (emit.lower.pic) {
|
||||||
const r_type: u32 = if (sym.flags.is_extern_ptr)
|
const r_type: u32 = if (sym.flags.is_extern_ptr)
|
||||||
@intFromEnum(std.elf.R_X86_64.GOTPCREL)
|
@intFromEnum(std.elf.R_X86_64.GOTPCREL)
|
||||||
@ -120,8 +123,8 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
@intFromEnum(std.elf.R_X86_64.PC32);
|
@intFromEnum(std.elf.R_X86_64.PC32);
|
||||||
try atom.addReloc(elf_file, .{
|
try atom.addReloc(elf_file, .{
|
||||||
.r_offset = end_offset - 4,
|
.r_offset = end_offset - 4,
|
||||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
|
.r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
|
||||||
.r_addend = -4,
|
.r_addend = lowered_relocs[0].off - 4,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const r_type: u32 = if (sym.flags.is_tls)
|
const r_type: u32 = if (sym.flags.is_tls)
|
||||||
@ -130,14 +133,14 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
@intFromEnum(std.elf.R_X86_64.@"32");
|
@intFromEnum(std.elf.R_X86_64.@"32");
|
||||||
try atom.addReloc(elf_file, .{
|
try atom.addReloc(elf_file, .{
|
||||||
.r_offset = end_offset - 4,
|
.r_offset = end_offset - 4,
|
||||||
.r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
|
.r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
|
||||||
.r_addend = 0,
|
.r_addend = lowered_relocs[0].off,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
|
} else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
|
||||||
const zo = macho_file.getZigObject().?;
|
const zo = macho_file.getZigObject().?;
|
||||||
const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
|
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
|
||||||
const sym = &zo.symbols.items[data.sym_index];
|
const sym = &zo.symbols.items[sym_index];
|
||||||
const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)
|
const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr)
|
||||||
.got_load
|
.got_load
|
||||||
else if (sym.flags.tlv)
|
else if (sym.flags.tlv)
|
||||||
@ -147,33 +150,33 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
try atom.addReloc(macho_file, .{
|
try atom.addReloc(macho_file, .{
|
||||||
.tag = .@"extern",
|
.tag = .@"extern",
|
||||||
.offset = @intCast(end_offset - 4),
|
.offset = @intCast(end_offset - 4),
|
||||||
.target = data.sym_index,
|
.target = sym_index,
|
||||||
.addend = 0,
|
.addend = lowered_relocs[0].off,
|
||||||
.type = @"type",
|
.type = @"type",
|
||||||
.meta = .{
|
.meta = .{
|
||||||
.pcrel = true,
|
.pcrel = true,
|
||||||
.has_subtractor = false,
|
.has_subtractor = false,
|
||||||
.length = 2,
|
.length = 2,
|
||||||
.symbolnum = @intCast(data.sym_index),
|
.symbolnum = @intCast(sym_index),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else unreachable,
|
} else unreachable,
|
||||||
.linker_got,
|
.linker_got,
|
||||||
.linker_direct,
|
.linker_direct,
|
||||||
.linker_import,
|
.linker_import,
|
||||||
=> |symbol| if (emit.lower.bin_file.cast(.elf)) |_| {
|
=> |sym_index| if (emit.lower.bin_file.cast(.elf)) |_| {
|
||||||
unreachable;
|
unreachable;
|
||||||
} else if (emit.lower.bin_file.cast(.macho)) |_| {
|
} else if (emit.lower.bin_file.cast(.macho)) |_| {
|
||||||
unreachable;
|
unreachable;
|
||||||
} else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
|
} else if (emit.lower.bin_file.cast(.coff)) |coff_file| {
|
||||||
const atom_index = coff_file.getAtomIndexForSymbol(.{
|
const atom_index = coff_file.getAtomIndexForSymbol(.{
|
||||||
.sym_index = symbol.atom_index,
|
.sym_index = emit.atom_index,
|
||||||
.file = null,
|
.file = null,
|
||||||
}).?;
|
}).?;
|
||||||
const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
|
const target = if (link.File.Coff.global_symbol_bit & sym_index != 0)
|
||||||
coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
|
coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & sym_index)
|
||||||
else
|
else
|
||||||
link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
|
link.File.Coff.SymbolWithLoc{ .sym_index = sym_index, .file = null };
|
||||||
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
|
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
|
||||||
.type = switch (lowered_relocs[0].target) {
|
.type = switch (lowered_relocs[0].target) {
|
||||||
.linker_got => .got,
|
.linker_got => .got,
|
||||||
@ -183,16 +186,15 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
},
|
},
|
||||||
.target = target,
|
.target = target,
|
||||||
.offset = @intCast(end_offset - 4),
|
.offset = @intCast(end_offset - 4),
|
||||||
.addend = 0,
|
.addend = @intCast(lowered_relocs[0].off),
|
||||||
.pcrel = true,
|
.pcrel = true,
|
||||||
.length = 2,
|
.length = 2,
|
||||||
});
|
});
|
||||||
} else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
|
} else if (emit.lower.bin_file.cast(.plan9)) |p9_file| {
|
||||||
const atom_index = symbol.atom_index;
|
try p9_file.addReloc(emit.atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
|
||||||
try p9_file.addReloc(atom_index, .{ // TODO we may need to add a .type field to the relocs if they are .linker_got instead of just .linker_direct
|
.target = sym_index, // we set sym_index to just be the atom index
|
||||||
.target = symbol.sym_index, // we set sym_index to just be the atom index
|
|
||||||
.offset = @intCast(end_offset - 4),
|
.offset = @intCast(end_offset - 4),
|
||||||
.addend = 0,
|
.addend = @intCast(lowered_relocs[0].off),
|
||||||
.type = .pcrel,
|
.type = .pcrel,
|
||||||
});
|
});
|
||||||
} else return emit.fail("TODO implement linker reloc for {s}", .{
|
} else return emit.fail("TODO implement linker reloc for {s}", .{
|
||||||
@ -232,13 +234,151 @@ pub fn emitMir(emit: *Emit) Error!void {
|
|||||||
.none => {},
|
.none => {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.pseudo_dbg_inline_func => {
|
.pseudo_dbg_enter_inline_func => {
|
||||||
switch (emit.debug_output) {
|
switch (emit.debug_output) {
|
||||||
.dwarf => |dw| {
|
.dwarf => |dw| {
|
||||||
log.debug("mirDbgInline (line={d}, col={d})", .{
|
log.debug("mirDbgEnterInline (line={d}, col={d})", .{
|
||||||
emit.prev_di_line, emit.prev_di_column,
|
emit.prev_di_line, emit.prev_di_column,
|
||||||
});
|
});
|
||||||
try dw.setInlineFunc(mir_inst.data.func);
|
try dw.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_line, emit.prev_di_column);
|
||||||
|
},
|
||||||
|
.plan9 => {},
|
||||||
|
.none => {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.pseudo_dbg_leave_inline_func => {
|
||||||
|
switch (emit.debug_output) {
|
||||||
|
.dwarf => |dw| {
|
||||||
|
log.debug("mirDbgLeaveInline (line={d}, col={d})", .{
|
||||||
|
emit.prev_di_line, emit.prev_di_column,
|
||||||
|
});
|
||||||
|
try dw.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);
|
||||||
|
},
|
||||||
|
.plan9 => {},
|
||||||
|
.none => {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.pseudo_dbg_local_a,
|
||||||
|
.pseudo_dbg_local_ai_s,
|
||||||
|
.pseudo_dbg_local_ai_u,
|
||||||
|
.pseudo_dbg_local_ai_64,
|
||||||
|
.pseudo_dbg_local_as,
|
||||||
|
.pseudo_dbg_local_aso,
|
||||||
|
.pseudo_dbg_local_aro,
|
||||||
|
.pseudo_dbg_local_af,
|
||||||
|
.pseudo_dbg_local_am,
|
||||||
|
=> {
|
||||||
|
switch (emit.debug_output) {
|
||||||
|
.dwarf => |dw| {
|
||||||
|
var loc_buf: [2]link.File.Dwarf.Loc = undefined;
|
||||||
|
const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {
|
||||||
|
else => unreachable,
|
||||||
|
.pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },
|
||||||
|
.pseudo_dbg_local_ai_s,
|
||||||
|
.pseudo_dbg_local_ai_u,
|
||||||
|
.pseudo_dbg_local_ai_64,
|
||||||
|
=> .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {
|
||||||
|
loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
|
||||||
|
.signed => |s| .{ .consts = s },
|
||||||
|
.unsigned => |u| .{ .constu = u },
|
||||||
|
};
|
||||||
|
break :stack_value &loc_buf[0];
|
||||||
|
} } },
|
||||||
|
.pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
|
||||||
|
.sym = mir_inst.data.as.sym_index,
|
||||||
|
} } },
|
||||||
|
.pseudo_dbg_local_aso => loc: {
|
||||||
|
const sym_off = emit.lower.mir.extraData(
|
||||||
|
bits.SymbolOffset,
|
||||||
|
mir_inst.data.ax.payload,
|
||||||
|
).data;
|
||||||
|
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||||
|
sym: {
|
||||||
|
loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
|
||||||
|
break :sym &loc_buf[0];
|
||||||
|
},
|
||||||
|
off: {
|
||||||
|
loc_buf[1] = .{ .consts = sym_off.off };
|
||||||
|
break :off &loc_buf[1];
|
||||||
|
},
|
||||||
|
} } };
|
||||||
|
},
|
||||||
|
.pseudo_dbg_local_aro => loc: {
|
||||||
|
const air_off = emit.lower.mir.extraData(
|
||||||
|
Mir.AirOffset,
|
||||||
|
mir_inst.data.rx.payload,
|
||||||
|
).data;
|
||||||
|
break :loc .{ air_off.air_inst, .{ .plus = .{
|
||||||
|
reg: {
|
||||||
|
loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
|
||||||
|
break :reg &loc_buf[0];
|
||||||
|
},
|
||||||
|
off: {
|
||||||
|
loc_buf[1] = .{ .consts = air_off.off };
|
||||||
|
break :off &loc_buf[1];
|
||||||
|
},
|
||||||
|
} } };
|
||||||
|
},
|
||||||
|
.pseudo_dbg_local_af => loc: {
|
||||||
|
const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
|
||||||
|
bits.FrameAddr,
|
||||||
|
mir_inst.data.ax.payload,
|
||||||
|
).data);
|
||||||
|
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||||
|
reg: {
|
||||||
|
loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
|
||||||
|
break :reg &loc_buf[0];
|
||||||
|
},
|
||||||
|
off: {
|
||||||
|
loc_buf[1] = .{ .consts = reg_off.off };
|
||||||
|
break :off &loc_buf[1];
|
||||||
|
},
|
||||||
|
} } };
|
||||||
|
},
|
||||||
|
.pseudo_dbg_local_am => loc: {
|
||||||
|
const mem = emit.lower.mem(mir_inst.data.ax.payload);
|
||||||
|
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||||
|
base: {
|
||||||
|
loc_buf[0] = switch (mem.base()) {
|
||||||
|
.none => .{ .constu = 0 },
|
||||||
|
.reg => |reg| .{ .breg = reg.dwarfNum() },
|
||||||
|
.frame => unreachable,
|
||||||
|
.reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
|
||||||
|
};
|
||||||
|
break :base &loc_buf[0];
|
||||||
|
},
|
||||||
|
disp: {
|
||||||
|
loc_buf[1] = switch (mem.disp()) {
|
||||||
|
.signed => |s| .{ .consts = s },
|
||||||
|
.unsigned => |u| .{ .constu = u },
|
||||||
|
};
|
||||||
|
break :disp &loc_buf[1];
|
||||||
|
},
|
||||||
|
} } };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const ip = &emit.lower.bin_file.comp.module.?.intern_pool;
|
||||||
|
const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
|
||||||
|
const name: Air.NullTerminatedString = switch (air_inst.tag) {
|
||||||
|
else => unreachable,
|
||||||
|
.arg => air_inst.data.arg.name,
|
||||||
|
.dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),
|
||||||
|
};
|
||||||
|
try dw.genLocalDebugInfo(
|
||||||
|
switch (air_inst.tag) {
|
||||||
|
else => unreachable,
|
||||||
|
.arg, .dbg_arg_inline => .local_arg,
|
||||||
|
.dbg_var_ptr, .dbg_var_val => .local_var,
|
||||||
|
},
|
||||||
|
name.toSlice(emit.air),
|
||||||
|
switch (air_inst.tag) {
|
||||||
|
else => unreachable,
|
||||||
|
.arg => emit.air.typeOfIndex(air_inst_index, ip),
|
||||||
|
.dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
|
||||||
|
.dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
|
||||||
|
},
|
||||||
|
loc,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
.plan9 => {},
|
.plan9 => {},
|
||||||
.none => {},
|
.none => {},
|
||||||
@ -268,10 +408,12 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
|
|||||||
const Reloc = struct {
|
const Reloc = struct {
|
||||||
/// Offset of the instruction.
|
/// Offset of the instruction.
|
||||||
source: usize,
|
source: usize,
|
||||||
|
/// Offset of the relocation within the instruction.
|
||||||
|
source_offset: u32,
|
||||||
/// Target of the relocation.
|
/// Target of the relocation.
|
||||||
target: Mir.Inst.Index,
|
target: Mir.Inst.Index,
|
||||||
/// Offset of the relocation within the instruction.
|
/// Offset from the target instruction.
|
||||||
offset: u32,
|
target_offset: i32,
|
||||||
/// Length of the instruction.
|
/// Length of the instruction.
|
||||||
length: u5,
|
length: u5,
|
||||||
};
|
};
|
||||||
@ -284,8 +426,8 @@ fn fixupRelocs(emit: *Emit) Error!void {
|
|||||||
for (emit.relocs.items) |reloc| {
|
for (emit.relocs.items) |reloc| {
|
||||||
const target = emit.code_offset_mapping.get(reloc.target) orelse
|
const target = emit.code_offset_mapping.get(reloc.target) orelse
|
||||||
return emit.fail("JMP/CALL relocation target not found!", .{});
|
return emit.fail("JMP/CALL relocation target not found!", .{});
|
||||||
const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length));
|
const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
|
||||||
mem.writeInt(i32, emit.code.items[reloc.offset..][0..4], @intCast(disp), .little);
|
std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,11 +480,12 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bits = @import("bits.zig");
|
||||||
const link = @import("../../link.zig");
|
const link = @import("../../link.zig");
|
||||||
const log = std.log.scoped(.emit);
|
const log = std.log.scoped(.emit);
|
||||||
const mem = std.mem;
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Air = @import("../../Air.zig");
|
||||||
const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
|
const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
|
||||||
const Emit = @This();
|
const Emit = @This();
|
||||||
const Lower = @import("Lower.zig");
|
const Lower = @import("Lower.zig");
|
||||||
|
|||||||
@ -4,10 +4,10 @@ bin_file: *link.File,
|
|||||||
output_mode: std.builtin.OutputMode,
|
output_mode: std.builtin.OutputMode,
|
||||||
link_mode: std.builtin.LinkMode,
|
link_mode: std.builtin.LinkMode,
|
||||||
pic: bool,
|
pic: bool,
|
||||||
allocator: Allocator,
|
allocator: std.mem.Allocator,
|
||||||
mir: Mir,
|
mir: Mir,
|
||||||
cc: std.builtin.CallingConvention,
|
cc: std.builtin.CallingConvention,
|
||||||
err_msg: ?*ErrorMsg = null,
|
err_msg: ?*Zcu.ErrorMsg = null,
|
||||||
src_loc: Zcu.LazySrcLoc,
|
src_loc: Zcu.LazySrcLoc,
|
||||||
result_insts_len: u8 = undefined,
|
result_insts_len: u8 = undefined,
|
||||||
result_relocs_len: u8 = undefined,
|
result_relocs_len: u8 = undefined,
|
||||||
@ -52,16 +52,17 @@ pub const Error = error{
|
|||||||
pub const Reloc = struct {
|
pub const Reloc = struct {
|
||||||
lowered_inst_index: u8,
|
lowered_inst_index: u8,
|
||||||
target: Target,
|
target: Target,
|
||||||
|
off: i32,
|
||||||
|
|
||||||
const Target = union(enum) {
|
const Target = union(enum) {
|
||||||
inst: Mir.Inst.Index,
|
inst: Mir.Inst.Index,
|
||||||
linker_reloc: bits.Symbol,
|
linker_reloc: u32,
|
||||||
linker_tlsld: bits.Symbol,
|
linker_tlsld: u32,
|
||||||
linker_dtpoff: bits.Symbol,
|
linker_dtpoff: u32,
|
||||||
linker_extern_fn: bits.Symbol,
|
linker_extern_fn: u32,
|
||||||
linker_got: bits.Symbol,
|
linker_got: u32,
|
||||||
linker_direct: bits.Symbol,
|
linker_direct: u32,
|
||||||
linker_import: bits.Symbol,
|
linker_import: u32,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -173,19 +174,19 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
|||||||
.pseudo_j_z_and_np_inst => {
|
.pseudo_j_z_and_np_inst => {
|
||||||
assert(inst.data.inst.fixes == ._);
|
assert(inst.data.inst.fixes == ._);
|
||||||
try lower.emit(.none, .jnz, &.{
|
try lower.emit(.none, .jnz, &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = index + 1 }) },
|
.{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
|
||||||
});
|
});
|
||||||
try lower.emit(.none, .jnp, &.{
|
try lower.emit(.none, .jnp, &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
|
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.pseudo_j_nz_or_p_inst => {
|
.pseudo_j_nz_or_p_inst => {
|
||||||
assert(inst.data.inst.fixes == ._);
|
assert(inst.data.inst.fixes == ._);
|
||||||
try lower.emit(.none, .jnz, &.{
|
try lower.emit(.none, .jnz, &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
|
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
|
||||||
});
|
});
|
||||||
try lower.emit(.none, .jp, &.{
|
try lower.emit(.none, .jp, &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
|
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -195,7 +196,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
|||||||
.{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
|
.{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
|
||||||
});
|
});
|
||||||
try lower.emit(.none, .jz, &.{
|
try lower.emit(.none, .jz, &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = index + 1 }) },
|
.{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
|
||||||
});
|
});
|
||||||
try lower.emit(.none, .lea, &.{
|
try lower.emit(.none, .lea, &.{
|
||||||
.{ .reg = inst.data.ri.r1 },
|
.{ .reg = inst.data.ri.r1 },
|
||||||
@ -211,7 +212,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
|||||||
.{ .reg = inst.data.ri.r1.to32() },
|
.{ .reg = inst.data.ri.r1.to32() },
|
||||||
});
|
});
|
||||||
try lower.emit(.none, .jmp, &.{
|
try lower.emit(.none, .jmp, &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = index }) },
|
.{ .imm = lower.reloc(.{ .inst = index }, 0) },
|
||||||
});
|
});
|
||||||
assert(lower.result_insts_len == pseudo_probe_align_insts);
|
assert(lower.result_insts_len == pseudo_probe_align_insts);
|
||||||
},
|
},
|
||||||
@ -257,7 +258,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
|||||||
.{ .imm = Immediate.s(page_size) },
|
.{ .imm = Immediate.s(page_size) },
|
||||||
});
|
});
|
||||||
try lower.emit(.none, .jae, &.{
|
try lower.emit(.none, .jae, &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = index }) },
|
.{ .imm = lower.reloc(.{ .inst = index }, 0) },
|
||||||
});
|
});
|
||||||
assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
|
assert(lower.result_insts_len == pseudo_probe_adjust_loop_insts);
|
||||||
},
|
},
|
||||||
@ -267,7 +268,17 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
|||||||
.pseudo_dbg_prologue_end_none,
|
.pseudo_dbg_prologue_end_none,
|
||||||
.pseudo_dbg_line_line_column,
|
.pseudo_dbg_line_line_column,
|
||||||
.pseudo_dbg_epilogue_begin_none,
|
.pseudo_dbg_epilogue_begin_none,
|
||||||
.pseudo_dbg_inline_func,
|
.pseudo_dbg_enter_inline_func,
|
||||||
|
.pseudo_dbg_leave_inline_func,
|
||||||
|
.pseudo_dbg_local_a,
|
||||||
|
.pseudo_dbg_local_ai_s,
|
||||||
|
.pseudo_dbg_local_ai_u,
|
||||||
|
.pseudo_dbg_local_ai_64,
|
||||||
|
.pseudo_dbg_local_as,
|
||||||
|
.pseudo_dbg_local_aso,
|
||||||
|
.pseudo_dbg_local_aro,
|
||||||
|
.pseudo_dbg_local_af,
|
||||||
|
.pseudo_dbg_local_am,
|
||||||
.pseudo_dead_none,
|
.pseudo_dead_none,
|
||||||
=> {},
|
=> {},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -283,17 +294,18 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
|||||||
pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
|
pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
|
||||||
@setCold(true);
|
@setCold(true);
|
||||||
assert(lower.err_msg == null);
|
assert(lower.err_msg == null);
|
||||||
lower.err_msg = try ErrorMsg.create(lower.allocator, lower.src_loc, format, args);
|
lower.err_msg = try Zcu.ErrorMsg.create(lower.allocator, lower.src_loc, format, args);
|
||||||
return error.LowerFail;
|
return error.LowerFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
|
pub fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
|
||||||
return switch (ops) {
|
return switch (ops) {
|
||||||
.rri_s,
|
.rri_s,
|
||||||
.ri_s,
|
.ri_s,
|
||||||
.i_s,
|
.i_s,
|
||||||
.mi_s,
|
.mi_s,
|
||||||
.rmi_s,
|
.rmi_s,
|
||||||
|
.pseudo_dbg_local_ai_s,
|
||||||
=> Immediate.s(@bitCast(i)),
|
=> Immediate.s(@bitCast(i)),
|
||||||
|
|
||||||
.rrri,
|
.rrri,
|
||||||
@ -306,22 +318,26 @@ fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
|
|||||||
.mri,
|
.mri,
|
||||||
.rrm,
|
.rrm,
|
||||||
.rrmi,
|
.rrmi,
|
||||||
|
.pseudo_dbg_local_ai_u,
|
||||||
=> Immediate.u(i),
|
=> Immediate.u(i),
|
||||||
|
|
||||||
.ri64 => Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
|
.ri_64,
|
||||||
|
.pseudo_dbg_local_ai_64,
|
||||||
|
=> Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
|
||||||
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mem(lower: Lower, payload: u32) Memory {
|
pub fn mem(lower: Lower, payload: u32) Memory {
|
||||||
return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
|
return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc(lower: *Lower, target: Reloc.Target) Immediate {
|
fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
|
||||||
lower.result_relocs[lower.result_relocs_len] = .{
|
lower.result_relocs[lower.result_relocs_len] = .{
|
||||||
.lowered_inst_index = lower.result_insts_len,
|
.lowered_inst_index = lower.result_insts_len,
|
||||||
.target = target,
|
.target = target,
|
||||||
|
.off = off,
|
||||||
};
|
};
|
||||||
lower.result_relocs_len += 1;
|
lower.result_relocs_len += 1;
|
||||||
return Immediate.s(0);
|
return Immediate.s(0);
|
||||||
@ -337,37 +353,36 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
|||||||
else => op,
|
else => op,
|
||||||
.mem => |mem_op| switch (mem_op.base()) {
|
.mem => |mem_op| switch (mem_op.base()) {
|
||||||
else => op,
|
else => op,
|
||||||
.reloc => |sym| op: {
|
.reloc => |sym_index| op: {
|
||||||
assert(prefix == .none);
|
assert(prefix == .none);
|
||||||
assert(mem_op.sib.disp == 0);
|
assert(mem_op.sib.disp == 0);
|
||||||
assert(mem_op.sib.scale_index.scale == 0);
|
assert(mem_op.sib.scale_index.scale == 0);
|
||||||
|
|
||||||
if (lower.bin_file.cast(.elf)) |elf_file| {
|
if (lower.bin_file.cast(.elf)) |elf_file| {
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
const elf_sym = zo.symbol(sym.sym_index);
|
const elf_sym = zo.symbol(sym_index);
|
||||||
|
|
||||||
if (elf_sym.flags.is_tls) {
|
if (elf_sym.flags.is_tls) {
|
||||||
// TODO handle extern TLS vars, i.e., emit GD model
|
// TODO handle extern TLS vars, i.e., emit GD model
|
||||||
if (lower.pic) {
|
if (lower.pic) {
|
||||||
// Here, we currently assume local dynamic TLS vars, and so
|
// Here, we currently assume local dynamic TLS vars, and so
|
||||||
// we emit LD model.
|
// we emit LD model.
|
||||||
_ = lower.reloc(.{ .linker_tlsld = sym });
|
_ = lower.reloc(.{ .linker_tlsld = sym_index }, 0);
|
||||||
lower.result_insts[lower.result_insts_len] =
|
lower.result_insts[lower.result_insts_len] =
|
||||||
try Instruction.new(.none, .lea, &[_]Operand{
|
try Instruction.new(.none, .lea, &[_]Operand{
|
||||||
.{ .reg = .rdi },
|
.{ .reg = .rdi },
|
||||||
.{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
|
.{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) },
|
||||||
});
|
});
|
||||||
lower.result_insts_len += 1;
|
lower.result_insts_len += 1;
|
||||||
_ = lower.reloc(.{ .linker_extern_fn = .{
|
_ = lower.reloc(.{
|
||||||
.atom_index = sym.atom_index,
|
.linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
|
||||||
.sym_index = try elf_file.getGlobalSymbol("__tls_get_addr", null),
|
}, 0);
|
||||||
} });
|
|
||||||
lower.result_insts[lower.result_insts_len] =
|
lower.result_insts[lower.result_insts_len] =
|
||||||
try Instruction.new(.none, .call, &[_]Operand{
|
try Instruction.new(.none, .call, &[_]Operand{
|
||||||
.{ .imm = Immediate.s(0) },
|
.{ .imm = Immediate.s(0) },
|
||||||
});
|
});
|
||||||
lower.result_insts_len += 1;
|
lower.result_insts_len += 1;
|
||||||
_ = lower.reloc(.{ .linker_dtpoff = sym });
|
_ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
|
||||||
emit_mnemonic = .lea;
|
emit_mnemonic = .lea;
|
||||||
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
||||||
.base = .{ .reg = .rax },
|
.base = .{ .reg = .rax },
|
||||||
@ -381,7 +396,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
|||||||
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
|
.{ .mem = Memory.sib(.qword, .{ .base = .{ .reg = .fs } }) },
|
||||||
});
|
});
|
||||||
lower.result_insts_len += 1;
|
lower.result_insts_len += 1;
|
||||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
|
||||||
emit_mnemonic = .lea;
|
emit_mnemonic = .lea;
|
||||||
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
|
||||||
.base = .{ .reg = .rax },
|
.base = .{ .reg = .rax },
|
||||||
@ -390,7 +405,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
|
||||||
if (lower.pic) switch (mnemonic) {
|
if (lower.pic) switch (mnemonic) {
|
||||||
.lea => {
|
.lea => {
|
||||||
if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
|
if (elf_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
|
||||||
@ -427,10 +442,10 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
|||||||
}
|
}
|
||||||
} else if (lower.bin_file.cast(.macho)) |macho_file| {
|
} else if (lower.bin_file.cast(.macho)) |macho_file| {
|
||||||
const zo = macho_file.getZigObject().?;
|
const zo = macho_file.getZigObject().?;
|
||||||
const macho_sym = zo.symbols.items[sym.sym_index];
|
const macho_sym = zo.symbols.items[sym_index];
|
||||||
|
|
||||||
if (macho_sym.flags.tlv) {
|
if (macho_sym.flags.tlv) {
|
||||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
|
||||||
lower.result_insts[lower.result_insts_len] =
|
lower.result_insts[lower.result_insts_len] =
|
||||||
try Instruction.new(.none, .mov, &[_]Operand{
|
try Instruction.new(.none, .mov, &[_]Operand{
|
||||||
.{ .reg = .rdi },
|
.{ .reg = .rdi },
|
||||||
@ -446,7 +461,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
|||||||
break :op .{ .reg = .rax };
|
break :op .{ .reg = .rax };
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = lower.reloc(.{ .linker_reloc = sym });
|
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
|
||||||
break :op switch (mnemonic) {
|
break :op switch (mnemonic) {
|
||||||
.lea => {
|
.lea => {
|
||||||
if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
|
if (macho_sym.flags.is_extern_ptr) emit_mnemonic = .mov;
|
||||||
@ -490,8 +505,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
|
|||||||
.rrrr => inst.data.rrrr.fixes,
|
.rrrr => inst.data.rrrr.fixes,
|
||||||
.rrri => inst.data.rrri.fixes,
|
.rrri => inst.data.rrri.fixes,
|
||||||
.rri_s, .rri_u => inst.data.rri.fixes,
|
.rri_s, .rri_u => inst.data.rri.fixes,
|
||||||
.ri_s, .ri_u => inst.data.ri.fixes,
|
.ri_s, .ri_u, .ri_64 => inst.data.ri.fixes,
|
||||||
.ri64, .rm, .rmi_s, .mr => inst.data.rx.fixes,
|
.rm, .rmi_s, .mr => inst.data.rx.fixes,
|
||||||
.mrr, .rrm, .rmr => inst.data.rrx.fixes,
|
.mrr, .rrm, .rmr => inst.data.rrx.fixes,
|
||||||
.rmi, .mri => inst.data.rix.fixes,
|
.rmi, .mri => inst.data.rix.fixes,
|
||||||
.rrmr => inst.data.rrrx.fixes,
|
.rrmr => inst.data.rrrx.fixes,
|
||||||
@ -525,7 +540,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
|
|||||||
}, switch (inst.ops) {
|
}, switch (inst.ops) {
|
||||||
.none => &.{},
|
.none => &.{},
|
||||||
.inst => &.{
|
.inst => &.{
|
||||||
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }) },
|
.{ .imm = lower.reloc(.{ .inst = inst.data.inst.inst }, 0) },
|
||||||
},
|
},
|
||||||
.i_s, .i_u => &.{
|
.i_s, .i_u => &.{
|
||||||
.{ .imm = lower.imm(inst.ops, inst.data.i.i) },
|
.{ .imm = lower.imm(inst.ops, inst.data.i.i) },
|
||||||
@ -554,14 +569,10 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
|
|||||||
.{ .reg = inst.data.rrri.r3 },
|
.{ .reg = inst.data.rrri.r3 },
|
||||||
.{ .imm = lower.imm(inst.ops, inst.data.rrri.i) },
|
.{ .imm = lower.imm(inst.ops, inst.data.rrri.i) },
|
||||||
},
|
},
|
||||||
.ri_s, .ri_u => &.{
|
.ri_s, .ri_u, .ri_64 => &.{
|
||||||
.{ .reg = inst.data.ri.r1 },
|
.{ .reg = inst.data.ri.r1 },
|
||||||
.{ .imm = lower.imm(inst.ops, inst.data.ri.i) },
|
.{ .imm = lower.imm(inst.ops, inst.data.ri.i) },
|
||||||
},
|
},
|
||||||
.ri64 => &.{
|
|
||||||
.{ .reg = inst.data.rx.r1 },
|
|
||||||
.{ .imm = lower.imm(inst.ops, inst.data.rx.payload) },
|
|
||||||
},
|
|
||||||
.rri_s, .rri_u => &.{
|
.rri_s, .rri_u => &.{
|
||||||
.{ .reg = inst.data.rri.r1 },
|
.{ .reg = inst.data.rri.r1 },
|
||||||
.{ .reg = inst.data.rri.r2 },
|
.{ .reg = inst.data.rri.r2 },
|
||||||
@ -631,17 +642,17 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
|
|||||||
.{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
|
.{ .imm = lower.imm(inst.ops, inst.data.rrix.i) },
|
||||||
},
|
},
|
||||||
.extern_fn_reloc, .rel => &.{
|
.extern_fn_reloc, .rel => &.{
|
||||||
.{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc }) },
|
.{ .imm = lower.reloc(.{ .linker_extern_fn = inst.data.reloc.sym_index }, inst.data.reloc.off) },
|
||||||
},
|
},
|
||||||
.got_reloc, .direct_reloc, .import_reloc => ops: {
|
.got_reloc, .direct_reloc, .import_reloc => ops: {
|
||||||
const reg = inst.data.rx.r1;
|
const reg = inst.data.rx.r1;
|
||||||
const extra = lower.mir.extraData(bits.Symbol, inst.data.rx.payload).data;
|
const extra = lower.mir.extraData(bits.SymbolOffset, inst.data.rx.payload).data;
|
||||||
_ = lower.reloc(switch (inst.ops) {
|
_ = lower.reloc(switch (inst.ops) {
|
||||||
.got_reloc => .{ .linker_got = extra },
|
.got_reloc => .{ .linker_got = extra.sym_index },
|
||||||
.direct_reloc => .{ .linker_direct = extra },
|
.direct_reloc => .{ .linker_direct = extra.sym_index },
|
||||||
.import_reloc => .{ .linker_import = extra },
|
.import_reloc => .{ .linker_import = extra.sym_index },
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
});
|
}, extra.off);
|
||||||
break :ops &.{
|
break :ops &.{
|
||||||
.{ .reg = reg },
|
.{ .reg = reg },
|
||||||
.{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
|
.{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
|
||||||
@ -670,9 +681,6 @@ const encoder = @import("encoder.zig");
|
|||||||
const link = @import("../../link.zig");
|
const link = @import("../../link.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Air = @import("../../Air.zig");
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const ErrorMsg = Zcu.ErrorMsg;
|
|
||||||
const Immediate = Instruction.Immediate;
|
const Immediate = Instruction.Immediate;
|
||||||
const Instruction = encoder.Instruction;
|
const Instruction = encoder.Instruction;
|
||||||
const Lower = @This();
|
const Lower = @This();
|
||||||
|
|||||||
@ -760,8 +760,8 @@ pub const Inst = struct {
|
|||||||
/// Uses `ri` payload.
|
/// Uses `ri` payload.
|
||||||
ri_u,
|
ri_u,
|
||||||
/// Register, 64-bit unsigned immediate operands.
|
/// Register, 64-bit unsigned immediate operands.
|
||||||
/// Uses `rx` payload with payload type `Imm64`.
|
/// Uses `ri` payload with `i` index of extra data of type `Imm64`.
|
||||||
ri64,
|
ri_64,
|
||||||
/// Immediate (sign-extended) operand.
|
/// Immediate (sign-extended) operand.
|
||||||
/// Uses `imm` payload.
|
/// Uses `imm` payload.
|
||||||
i_s,
|
i_s,
|
||||||
@ -796,7 +796,7 @@ pub const Inst = struct {
|
|||||||
/// Uses `rrix` payload with extra data of type `Memory`.
|
/// Uses `rrix` payload with extra data of type `Memory`.
|
||||||
rrmi,
|
rrmi,
|
||||||
/// Single memory operand.
|
/// Single memory operand.
|
||||||
/// Uses `x` with extra data of type `Memory`.
|
/// Uses `x` payload with extra data of type `Memory`.
|
||||||
m,
|
m,
|
||||||
/// Memory, immediate (sign-extend) operands.
|
/// Memory, immediate (sign-extend) operands.
|
||||||
/// Uses `x` payload with extra data of type `Imm32` followed by `Memory`.
|
/// Uses `x` payload with extra data of type `Imm32` followed by `Memory`.
|
||||||
@ -820,16 +820,16 @@ pub const Inst = struct {
|
|||||||
/// Uses `reloc` payload.
|
/// Uses `reloc` payload.
|
||||||
extern_fn_reloc,
|
extern_fn_reloc,
|
||||||
/// Linker relocation - GOT indirection.
|
/// Linker relocation - GOT indirection.
|
||||||
/// Uses `rx` payload with extra data of type `bits.Symbol`.
|
/// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
|
||||||
got_reloc,
|
got_reloc,
|
||||||
/// Linker relocation - direct reference.
|
/// Linker relocation - direct reference.
|
||||||
/// Uses `rx` payload with extra data of type `bits.Symbol`.
|
/// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
|
||||||
direct_reloc,
|
direct_reloc,
|
||||||
/// Linker relocation - imports table indirection (binding).
|
/// Linker relocation - imports table indirection (binding).
|
||||||
/// Uses `rx` payload with extra data of type `bits.Symbol`.
|
/// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
|
||||||
import_reloc,
|
import_reloc,
|
||||||
/// Linker relocation - threadlocal variable via GOT indirection.
|
/// Linker relocation - threadlocal variable via GOT indirection.
|
||||||
/// Uses `rx` payload with extra data of type `bits.Symbol`.
|
/// Uses `rx` payload with extra data of type `bits.SymbolOffset`.
|
||||||
tlv_reloc,
|
tlv_reloc,
|
||||||
|
|
||||||
// Pseudo instructions:
|
// Pseudo instructions:
|
||||||
@ -868,16 +868,16 @@ pub const Inst = struct {
|
|||||||
pseudo_j_nz_or_p_inst,
|
pseudo_j_nz_or_p_inst,
|
||||||
|
|
||||||
/// Probe alignment
|
/// Probe alignment
|
||||||
/// Uses `ri` payload
|
/// Uses `ri` payload.
|
||||||
pseudo_probe_align_ri_s,
|
pseudo_probe_align_ri_s,
|
||||||
/// Probe adjust unrolled
|
/// Probe adjust unrolled
|
||||||
/// Uses `ri` payload
|
/// Uses `ri` payload.
|
||||||
pseudo_probe_adjust_unrolled_ri_s,
|
pseudo_probe_adjust_unrolled_ri_s,
|
||||||
/// Probe adjust setup
|
/// Probe adjust setup
|
||||||
/// Uses `rri` payload
|
/// Uses `rri` payload.
|
||||||
pseudo_probe_adjust_setup_rri_s,
|
pseudo_probe_adjust_setup_rri_s,
|
||||||
/// Probe adjust loop
|
/// Probe adjust loop
|
||||||
/// Uses `rr` payload
|
/// Uses `rr` payload.
|
||||||
pseudo_probe_adjust_loop_rr,
|
pseudo_probe_adjust_loop_rr,
|
||||||
/// Push registers
|
/// Push registers
|
||||||
/// Uses `reg_list` payload.
|
/// Uses `reg_list` payload.
|
||||||
@ -893,8 +893,37 @@ pub const Inst = struct {
|
|||||||
pseudo_dbg_line_line_column,
|
pseudo_dbg_line_line_column,
|
||||||
/// Start of epilogue
|
/// Start of epilogue
|
||||||
pseudo_dbg_epilogue_begin_none,
|
pseudo_dbg_epilogue_begin_none,
|
||||||
/// Start or end of inline function
|
/// Start of inline function
|
||||||
pseudo_dbg_inline_func,
|
pseudo_dbg_enter_inline_func,
|
||||||
|
/// End of inline function
|
||||||
|
pseudo_dbg_leave_inline_func,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `a` payload.
|
||||||
|
pseudo_dbg_local_a,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `ai` payload.
|
||||||
|
pseudo_dbg_local_ai_s,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `ai` payload.
|
||||||
|
pseudo_dbg_local_ai_u,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `ai` payload with extra data of type `Imm64`.
|
||||||
|
pseudo_dbg_local_ai_64,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `as` payload.
|
||||||
|
pseudo_dbg_local_as,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `ax` payload with extra data of type `bits.SymbolOffset`.
|
||||||
|
pseudo_dbg_local_aso,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `rx` payload with extra data of type `AirOffset`.
|
||||||
|
pseudo_dbg_local_aro,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `ax` payload with extra data of type `bits.FrameAddr`.
|
||||||
|
pseudo_dbg_local_af,
|
||||||
|
/// Local argument or variable.
|
||||||
|
/// Uses `ax` payload with extra data of type `Memory`.
|
||||||
|
pseudo_dbg_local_am,
|
||||||
|
|
||||||
/// Tombstone
|
/// Tombstone
|
||||||
/// Emitter should skip this instruction.
|
/// Emitter should skip this instruction.
|
||||||
@ -997,10 +1026,28 @@ pub const Inst = struct {
|
|||||||
fixes: Fixes = ._,
|
fixes: Fixes = ._,
|
||||||
payload: u32,
|
payload: u32,
|
||||||
},
|
},
|
||||||
|
ix: struct {
|
||||||
|
payload: u32,
|
||||||
|
},
|
||||||
|
a: struct {
|
||||||
|
air_inst: Air.Inst.Index,
|
||||||
|
},
|
||||||
|
ai: struct {
|
||||||
|
air_inst: Air.Inst.Index,
|
||||||
|
i: u32,
|
||||||
|
},
|
||||||
|
as: struct {
|
||||||
|
air_inst: Air.Inst.Index,
|
||||||
|
sym_index: u32,
|
||||||
|
},
|
||||||
|
ax: struct {
|
||||||
|
air_inst: Air.Inst.Index,
|
||||||
|
payload: u32,
|
||||||
|
},
|
||||||
/// Relocation for the linker where:
|
/// Relocation for the linker where:
|
||||||
/// * `atom_index` is the index of the source
|
|
||||||
/// * `sym_index` is the index of the target
|
/// * `sym_index` is the index of the target
|
||||||
reloc: bits.Symbol,
|
/// * `off` is the offset from the target
|
||||||
|
reloc: bits.SymbolOffset,
|
||||||
/// Debug line and column position
|
/// Debug line and column position
|
||||||
line_column: struct {
|
line_column: struct {
|
||||||
line: u32,
|
line: u32,
|
||||||
@ -1020,6 +1067,8 @@ pub const Inst = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const AirOffset = struct { air_inst: Air.Inst.Index, off: i32 };
|
||||||
|
|
||||||
/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
|
/// Used in conjunction with payload to transfer a list of used registers in a compact manner.
|
||||||
pub const RegisterList = struct {
|
pub const RegisterList = struct {
|
||||||
bitset: BitSet = BitSet.initEmpty(),
|
bitset: BitSet = BitSet.initEmpty(),
|
||||||
@ -1118,15 +1167,13 @@ pub const Memory = struct {
|
|||||||
.none => undefined,
|
.none => undefined,
|
||||||
.reg => |reg| @intFromEnum(reg),
|
.reg => |reg| @intFromEnum(reg),
|
||||||
.frame => |frame_index| @intFromEnum(frame_index),
|
.frame => |frame_index| @intFromEnum(frame_index),
|
||||||
.reloc => |symbol| symbol.sym_index,
|
.reloc => |sym_index| sym_index,
|
||||||
},
|
},
|
||||||
.off = switch (mem.mod) {
|
.off = switch (mem.mod) {
|
||||||
.rm => |rm| @bitCast(rm.disp),
|
.rm => |rm| @bitCast(rm.disp),
|
||||||
.off => |off| @truncate(off),
|
.off => |off| @truncate(off),
|
||||||
},
|
},
|
||||||
.extra = if (mem.base == .reloc)
|
.extra = if (mem.mod == .off)
|
||||||
mem.base.reloc.atom_index
|
|
||||||
else if (mem.mod == .off)
|
|
||||||
@intCast(mem.mod.off >> 32)
|
@intCast(mem.mod.off >> 32)
|
||||||
else
|
else
|
||||||
undefined,
|
undefined,
|
||||||
@ -1146,7 +1193,7 @@ pub const Memory = struct {
|
|||||||
.none => .none,
|
.none => .none,
|
||||||
.reg => .{ .reg = @enumFromInt(mem.base) },
|
.reg => .{ .reg = @enumFromInt(mem.base) },
|
||||||
.frame => .{ .frame = @enumFromInt(mem.base) },
|
.frame => .{ .frame = @enumFromInt(mem.base) },
|
||||||
.reloc => .{ .reloc = .{ .atom_index = mem.extra, .sym_index = mem.base } },
|
.reloc => .{ .reloc = mem.base },
|
||||||
},
|
},
|
||||||
.scale_index = switch (mem.info.index) {
|
.scale_index = switch (mem.info.index) {
|
||||||
.none => null,
|
.none => null,
|
||||||
@ -1186,6 +1233,7 @@ pub fn extraData(mir: Mir, comptime T: type, index: u32) struct { data: T, end:
|
|||||||
@field(result, field.name) = switch (field.type) {
|
@field(result, field.name) = switch (field.type) {
|
||||||
u32 => mir.extra[i],
|
u32 => mir.extra[i],
|
||||||
i32, Memory.Info => @bitCast(mir.extra[i]),
|
i32, Memory.Info => @bitCast(mir.extra[i]),
|
||||||
|
bits.FrameIndex, Air.Inst.Index => @enumFromInt(mir.extra[i]),
|
||||||
else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
|
else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)),
|
||||||
};
|
};
|
||||||
i += 1;
|
i += 1;
|
||||||
@ -1201,6 +1249,11 @@ pub const FrameLoc = struct {
|
|||||||
disp: i32,
|
disp: i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffset {
|
||||||
|
const frame_loc = mir.frame_locs.get(@intFromEnum(frame_addr.index));
|
||||||
|
return .{ .reg = frame_loc.base, .off = frame_loc.disp + frame_addr.off };
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
|
pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
|
||||||
return switch (mem.info.base) {
|
return switch (mem.info.base) {
|
||||||
.none, .reg, .reloc => mem,
|
.none, .reg, .reloc => mem,
|
||||||
@ -1225,6 +1278,7 @@ const builtin = @import("builtin");
|
|||||||
const encoder = @import("encoder.zig");
|
const encoder = @import("encoder.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Air = @import("../../Air.zig");
|
||||||
const IntegerBitSet = std.bit_set.IntegerBitSet;
|
const IntegerBitSet = std.bit_set.IntegerBitSet;
|
||||||
const InternPool = @import("../../InternPool.zig");
|
const InternPool = @import("../../InternPool.zig");
|
||||||
const Mir = @This();
|
const Mir = @This();
|
||||||
|
|||||||
@ -447,26 +447,11 @@ pub const FrameIndex = enum(u32) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A linker symbol not yet allocated in VM.
|
pub const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
|
||||||
pub const Symbol = struct {
|
|
||||||
/// Index of the containing atom.
|
|
||||||
atom_index: u32,
|
|
||||||
/// Index into the linker's symbol table.
|
|
||||||
sym_index: u32,
|
|
||||||
|
|
||||||
pub fn format(
|
pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
|
||||||
sym: Symbol,
|
|
||||||
comptime fmt: []const u8,
|
pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
|
||||||
options: std.fmt.FormatOptions,
|
|
||||||
writer: anytype,
|
|
||||||
) @TypeOf(writer).Error!void {
|
|
||||||
try writer.writeAll("Symbol(");
|
|
||||||
try std.fmt.formatType(sym.atom_index, fmt, options, writer, 0);
|
|
||||||
try writer.writeAll(", ");
|
|
||||||
try std.fmt.formatType(sym.sym_index, fmt, options, writer, 0);
|
|
||||||
try writer.writeByte(')');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Memory = struct {
|
pub const Memory = struct {
|
||||||
base: Base,
|
base: Base,
|
||||||
@ -476,7 +461,7 @@ pub const Memory = struct {
|
|||||||
none,
|
none,
|
||||||
reg: Register,
|
reg: Register,
|
||||||
frame: FrameIndex,
|
frame: FrameIndex,
|
||||||
reloc: Symbol,
|
reloc: u32,
|
||||||
|
|
||||||
pub const Tag = @typeInfo(Base).Union.tag_type.?;
|
pub const Tag = @typeInfo(Base).Union.tag_type.?;
|
||||||
|
|
||||||
@ -568,7 +553,7 @@ pub const Memory = struct {
|
|||||||
pub const Immediate = union(enum) {
|
pub const Immediate = union(enum) {
|
||||||
signed: i32,
|
signed: i32,
|
||||||
unsigned: u64,
|
unsigned: u64,
|
||||||
reloc: Symbol,
|
reloc: SymbolOffset,
|
||||||
|
|
||||||
pub fn u(x: u64) Immediate {
|
pub fn u(x: u64) Immediate {
|
||||||
return .{ .unsigned = x };
|
return .{ .unsigned = x };
|
||||||
@ -578,19 +563,19 @@ pub const Immediate = union(enum) {
|
|||||||
return .{ .signed = x };
|
return .{ .signed = x };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rel(symbol: Symbol) Immediate {
|
pub fn rel(sym_off: SymbolOffset) Immediate {
|
||||||
return .{ .reloc = symbol };
|
return .{ .reloc = sym_off };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(
|
||||||
imm: Immediate,
|
imm: Immediate,
|
||||||
comptime fmt: []const u8,
|
comptime _: []const u8,
|
||||||
options: std.fmt.FormatOptions,
|
_: std.fmt.FormatOptions,
|
||||||
writer: anytype,
|
writer: anytype,
|
||||||
) @TypeOf(writer).Error!void {
|
) @TypeOf(writer).Error!void {
|
||||||
switch (imm) {
|
switch (imm) {
|
||||||
.reloc => |x| try std.fmt.formatType(x, fmt, options, writer, 0),
|
inline else => |int| try writer.print("{d}", .{int}),
|
||||||
inline else => |x| try writer.print("{d}", .{x}),
|
.reloc => |sym_off| try writer.print("Symbol({[sym_index]d}) + {[off]d}", sym_off),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -128,8 +128,8 @@ pub const Instruction = struct {
|
|||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rip(ptr_size: PtrSize, disp: i32) Memory {
|
pub fn rip(ptr_size: PtrSize, displacement: i32) Memory {
|
||||||
return .{ .rip = .{ .ptr_size = ptr_size, .disp = disp } };
|
return .{ .rip = .{ .ptr_size = ptr_size, .disp = displacement } };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isSegmentRegister(mem: Memory) bool {
|
pub fn isSegmentRegister(mem: Memory) bool {
|
||||||
@ -158,6 +158,14 @@ pub const Instruction = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn disp(mem: Memory) Immediate {
|
||||||
|
return switch (mem) {
|
||||||
|
.sib => |s| Immediate.s(s.disp),
|
||||||
|
.rip => |r| Immediate.s(r.disp),
|
||||||
|
.moffs => |m| Immediate.u(m.offset),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bitSize(mem: Memory) u64 {
|
pub fn bitSize(mem: Memory) u64 {
|
||||||
return switch (mem) {
|
return switch (mem) {
|
||||||
.rip => |r| r.ptr_size.bitSize(),
|
.rip => |r| r.ptr_size.bitSize(),
|
||||||
@ -258,17 +266,12 @@ pub const Instruction = struct {
|
|||||||
|
|
||||||
try writer.writeByte('[');
|
try writer.writeByte('[');
|
||||||
|
|
||||||
var any = false;
|
var any = true;
|
||||||
switch (sib.base) {
|
switch (sib.base) {
|
||||||
.none => {},
|
.none => any = false,
|
||||||
.reg => |reg| {
|
.reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
|
||||||
try writer.print("{s}", .{@tagName(reg)});
|
.frame => |frame_index| try writer.print("{}", .{frame_index}),
|
||||||
any = true;
|
.reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
|
||||||
},
|
|
||||||
inline .frame, .reloc => |payload| {
|
|
||||||
try writer.print("{}", .{payload});
|
|
||||||
any = true;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if (mem.scaleIndex()) |si| {
|
if (mem.scaleIndex()) |si| {
|
||||||
if (any) try writer.writeAll(" + ");
|
if (any) try writer.writeAll(" + ");
|
||||||
|
|||||||
@ -3293,7 +3293,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
|
|||||||
|
|
||||||
.dbg_stmt => try airDbgStmt(f, inst),
|
.dbg_stmt => try airDbgStmt(f, inst),
|
||||||
.dbg_inline_block => try airDbgInlineBlock(f, inst),
|
.dbg_inline_block => try airDbgInlineBlock(f, inst),
|
||||||
.dbg_var_ptr, .dbg_var_val => try airDbgVar(f, inst),
|
.dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => try airDbgVar(f, inst),
|
||||||
|
|
||||||
.call => try airCall(f, inst, .auto),
|
.call => try airCall(f, inst, .auto),
|
||||||
.call_always_tail => .none,
|
.call_always_tail => .none,
|
||||||
@ -4590,14 +4590,15 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
|
|||||||
fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
|
fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
const pt = f.object.dg.pt;
|
const pt = f.object.dg.pt;
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
|
const tag = f.air.instructions.items(.tag)[@intFromEnum(inst)];
|
||||||
const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||||
const name = f.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
const operand_is_undef = if (try f.air.value(pl_op.operand, pt)) |v| v.isUndefDeep(zcu) else false;
|
const operand_is_undef = if (try f.air.value(pl_op.operand, pt)) |v| v.isUndefDeep(zcu) else false;
|
||||||
if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
|
if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
|
||||||
|
|
||||||
try reap(f, inst, &.{pl_op.operand});
|
try reap(f, inst, &.{pl_op.operand});
|
||||||
const writer = f.object.writer();
|
const writer = f.object.writer();
|
||||||
try writer.print("/* var:{s} */\n", .{name});
|
try writer.print("/* {s}:{s} */\n", .{ @tagName(tag), name.toSlice(f.air) });
|
||||||
return .none;
|
return .none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1665,6 +1665,7 @@ pub const Object = struct {
|
|||||||
.ret_ptr = ret_ptr,
|
.ret_ptr = ret_ptr,
|
||||||
.args = args.items,
|
.args = args.items,
|
||||||
.arg_index = 0,
|
.arg_index = 0,
|
||||||
|
.arg_inline_index = 0,
|
||||||
.func_inst_table = .{},
|
.func_inst_table = .{},
|
||||||
.blocks = .{},
|
.blocks = .{},
|
||||||
.sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
|
.sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
|
||||||
@ -4769,7 +4770,8 @@ pub const FuncGen = struct {
|
|||||||
/// it omits 0-bit types. If the function uses sret as the first parameter,
|
/// it omits 0-bit types. If the function uses sret as the first parameter,
|
||||||
/// this slice does not include it.
|
/// this slice does not include it.
|
||||||
args: []const Builder.Value,
|
args: []const Builder.Value,
|
||||||
arg_index: usize,
|
arg_index: u32,
|
||||||
|
arg_inline_index: u32,
|
||||||
|
|
||||||
err_ret_trace: Builder.Value = .none,
|
err_ret_trace: Builder.Value = .none,
|
||||||
|
|
||||||
@ -5082,7 +5084,8 @@ pub const FuncGen = struct {
|
|||||||
.dbg_stmt => try self.airDbgStmt(inst),
|
.dbg_stmt => try self.airDbgStmt(inst),
|
||||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||||
.dbg_var_ptr => try self.airDbgVarPtr(inst),
|
.dbg_var_ptr => try self.airDbgVarPtr(inst),
|
||||||
.dbg_var_val => try self.airDbgVarVal(inst),
|
.dbg_var_val => try self.airDbgVarVal(inst, false),
|
||||||
|
.dbg_arg_inline => try self.airDbgVarVal(inst, true),
|
||||||
|
|
||||||
.c_va_arg => try self.airCVaArg(inst),
|
.c_va_arg => try self.airCVaArg(inst),
|
||||||
.c_va_copy => try self.airCVaCopy(inst),
|
.c_va_copy => try self.airCVaCopy(inst),
|
||||||
@ -6677,6 +6680,7 @@ pub const FuncGen = struct {
|
|||||||
fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||||
|
self.arg_inline_index = 0;
|
||||||
return self.lowerBlock(inst, extra.data.func, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
return self.lowerBlock(inst, extra.data.func, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6685,11 +6689,11 @@ pub const FuncGen = struct {
|
|||||||
const mod = o.pt.zcu;
|
const mod = o.pt.zcu;
|
||||||
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||||
const operand = try self.resolveInst(pl_op.operand);
|
const operand = try self.resolveInst(pl_op.operand);
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
const ptr_ty = self.typeOf(pl_op.operand);
|
const ptr_ty = self.typeOf(pl_op.operand);
|
||||||
|
|
||||||
const debug_local_var = try o.builder.debugLocalVar(
|
const debug_local_var = try o.builder.debugLocalVar(
|
||||||
try o.builder.metadataString(name),
|
try o.builder.metadataString(name.toSlice(self.air)),
|
||||||
self.file,
|
self.file,
|
||||||
self.scope,
|
self.scope,
|
||||||
self.prev_dbg_line,
|
self.prev_dbg_line,
|
||||||
@ -6712,15 +6716,25 @@ pub const FuncGen = struct {
|
|||||||
return .none;
|
return .none;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) !Builder.Value {
|
||||||
const o = self.ng.object;
|
const o = self.ng.object;
|
||||||
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||||
const operand = try self.resolveInst(pl_op.operand);
|
const operand = try self.resolveInst(pl_op.operand);
|
||||||
const operand_ty = self.typeOf(pl_op.operand);
|
const operand_ty = self.typeOf(pl_op.operand);
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
|
|
||||||
const debug_local_var = try o.builder.debugLocalVar(
|
const debug_local_var = if (is_arg) try o.builder.debugParameter(
|
||||||
try o.builder.metadataString(name),
|
try o.builder.metadataString(name.toSlice(self.air)),
|
||||||
|
self.file,
|
||||||
|
self.scope,
|
||||||
|
self.prev_dbg_line,
|
||||||
|
try o.lowerDebugType(operand_ty),
|
||||||
|
arg_no: {
|
||||||
|
self.arg_inline_index += 1;
|
||||||
|
break :arg_no self.arg_inline_index;
|
||||||
|
},
|
||||||
|
) else try o.builder.debugLocalVar(
|
||||||
|
try o.builder.metadataString(name.toSlice(self.air)),
|
||||||
self.file,
|
self.file,
|
||||||
self.scope,
|
self.scope,
|
||||||
self.prev_dbg_line,
|
self.prev_dbg_line,
|
||||||
@ -8835,12 +8849,12 @@ pub const FuncGen = struct {
|
|||||||
const lbrace_col = func.lbrace_column + 1;
|
const lbrace_col = func.lbrace_column + 1;
|
||||||
|
|
||||||
const debug_parameter = try o.builder.debugParameter(
|
const debug_parameter = try o.builder.debugParameter(
|
||||||
try o.builder.metadataString(self.air.nullTerminatedString(@intFromEnum(name))),
|
try o.builder.metadataString(name.toSlice(self.air)),
|
||||||
self.file,
|
self.file,
|
||||||
self.scope,
|
self.scope,
|
||||||
lbrace_line,
|
lbrace_line,
|
||||||
try o.lowerDebugType(inst_ty),
|
try o.lowerDebugType(inst_ty),
|
||||||
@intCast(self.arg_index),
|
self.arg_index,
|
||||||
);
|
);
|
||||||
|
|
||||||
const old_location = self.wip.debug_location;
|
const old_location = self.wip.debug_location;
|
||||||
|
|||||||
@ -6366,8 +6366,8 @@ const NavGen = struct {
|
|||||||
fn airDbgVar(self: *NavGen, inst: Air.Inst.Index) !void {
|
fn airDbgVar(self: *NavGen, inst: Air.Inst.Index) !void {
|
||||||
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||||
const target_id = try self.resolve(pl_op.operand);
|
const target_id = try self.resolve(pl_op.operand);
|
||||||
const name = self.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
try self.spv.debugName(target_id, name);
|
try self.spv.debugName(target_id, name.toSlice(self.air));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn airAssembly(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
|
fn airAssembly(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
|
||||||
|
|||||||
@ -317,8 +317,18 @@ pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !
|
|||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
const gpa = self.base.comp.gpa;
|
const gpa = self.base.comp.gpa;
|
||||||
|
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
|
const ip = &zcu.intern_pool;
|
||||||
|
|
||||||
|
const nav = ip.getNav(nav_index);
|
||||||
|
const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
|
||||||
|
.func => return,
|
||||||
|
.@"extern" => .none,
|
||||||
|
.variable => |variable| variable.init,
|
||||||
|
else => nav.status.resolved.val,
|
||||||
|
};
|
||||||
|
if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) return;
|
||||||
|
|
||||||
const gop = try self.navs.getOrPut(gpa, nav_index);
|
const gop = try self.navs.getOrPut(gpa, nav_index);
|
||||||
errdefer _ = self.navs.pop();
|
errdefer _ = self.navs.pop();
|
||||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||||
|
|||||||
@ -1207,6 +1207,7 @@ pub fn updateNav(
|
|||||||
|
|
||||||
const nav_val = zcu.navValue(nav_index);
|
const nav_val = zcu.navValue(nav_index);
|
||||||
const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
|
const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
|
||||||
|
.func => return,
|
||||||
.variable => |variable| Value.fromInterned(variable.init),
|
.variable => |variable| Value.fromInterned(variable.init),
|
||||||
.@"extern" => |@"extern"| {
|
.@"extern" => |@"extern"| {
|
||||||
if (ip.isFunctionType(@"extern".ty)) return;
|
if (ip.isFunctionType(@"extern".ty)) return;
|
||||||
@ -1220,7 +1221,7 @@ pub fn updateNav(
|
|||||||
else => nav_val,
|
else => nav_val,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
|
if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
|
||||||
const atom_index = try self.getOrCreateAtomForNav(nav_index);
|
const atom_index = try self.getOrCreateAtomForNav(nav_index);
|
||||||
Atom.freeRelocations(self, atom_index);
|
Atom.freeRelocations(self, atom_index);
|
||||||
const atom = self.getAtom(atom_index);
|
const atom = self.getAtom(atom_index);
|
||||||
|
|||||||
@ -21,8 +21,9 @@ pub const UpdateError =
|
|||||||
std.fs.File.OpenError ||
|
std.fs.File.OpenError ||
|
||||||
std.fs.File.SetEndPosError ||
|
std.fs.File.SetEndPosError ||
|
||||||
std.fs.File.CopyRangeError ||
|
std.fs.File.CopyRangeError ||
|
||||||
|
std.fs.File.PReadError ||
|
||||||
std.fs.File.PWriteError ||
|
std.fs.File.PWriteError ||
|
||||||
error{ Overflow, Underflow, UnexpectedEndOfFile };
|
error{ EndOfStream, Overflow, Underflow, UnexpectedEndOfFile };
|
||||||
|
|
||||||
pub const FlushError =
|
pub const FlushError =
|
||||||
UpdateError ||
|
UpdateError ||
|
||||||
@ -253,10 +254,8 @@ const Section = struct {
|
|||||||
.trailer_len = trailer_len,
|
.trailer_len = trailer_len,
|
||||||
.len = header_len + trailer_len,
|
.len = header_len + trailer_len,
|
||||||
.entries = .{},
|
.entries = .{},
|
||||||
.cross_entry_relocs = .{},
|
|
||||||
.cross_unit_relocs = .{},
|
.cross_unit_relocs = .{},
|
||||||
.cross_section_relocs = .{},
|
.cross_section_relocs = .{},
|
||||||
.external_relocs = .{},
|
|
||||||
};
|
};
|
||||||
if (sec.last.unwrap()) |last_unit| {
|
if (sec.last.unwrap()) |last_unit| {
|
||||||
const last_unit_ptr = sec.getUnit(last_unit);
|
const last_unit_ptr = sec.getUnit(last_unit);
|
||||||
@ -358,10 +357,8 @@ const Unit = struct {
|
|||||||
/// data length in bytes
|
/// data length in bytes
|
||||||
len: u32,
|
len: u32,
|
||||||
entries: std.ArrayListUnmanaged(Entry),
|
entries: std.ArrayListUnmanaged(Entry),
|
||||||
cross_entry_relocs: std.ArrayListUnmanaged(CrossEntryReloc),
|
|
||||||
cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),
|
cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),
|
||||||
cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),
|
cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),
|
||||||
external_relocs: std.ArrayListUnmanaged(ExternalReloc),
|
|
||||||
|
|
||||||
const Index = enum(u32) {
|
const Index = enum(u32) {
|
||||||
main,
|
main,
|
||||||
@ -381,12 +378,16 @@ const Unit = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn clear(unit: *Unit) void {
|
||||||
|
unit.cross_unit_relocs.clearRetainingCapacity();
|
||||||
|
unit.cross_section_relocs.clearRetainingCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
fn deinit(unit: *Unit, gpa: std.mem.Allocator) void {
|
fn deinit(unit: *Unit, gpa: std.mem.Allocator) void {
|
||||||
|
for (unit.entries.items) |*entry| entry.deinit(gpa);
|
||||||
unit.entries.deinit(gpa);
|
unit.entries.deinit(gpa);
|
||||||
unit.cross_entry_relocs.deinit(gpa);
|
|
||||||
unit.cross_unit_relocs.deinit(gpa);
|
unit.cross_unit_relocs.deinit(gpa);
|
||||||
unit.cross_section_relocs.deinit(gpa);
|
unit.cross_section_relocs.deinit(gpa);
|
||||||
unit.external_relocs.deinit(gpa);
|
|
||||||
unit.* = undefined;
|
unit.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,6 +399,10 @@ const Unit = struct {
|
|||||||
.next = .none,
|
.next = .none,
|
||||||
.off = 0,
|
.off = 0,
|
||||||
.len = 0,
|
.len = 0,
|
||||||
|
.cross_entry_relocs = .{},
|
||||||
|
.cross_unit_relocs = .{},
|
||||||
|
.cross_section_relocs = .{},
|
||||||
|
.external_relocs = .{},
|
||||||
};
|
};
|
||||||
if (unit.last.unwrap()) |last_entry| {
|
if (unit.last.unwrap()) |last_entry| {
|
||||||
const last_entry_ptr = unit.getEntry(last_entry);
|
const last_entry_ptr = unit.getEntry(last_entry);
|
||||||
@ -451,6 +456,14 @@ const Unit = struct {
|
|||||||
unit_ptr.len = len;
|
unit_ptr.len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn trim(unit: *Unit) void {
|
||||||
|
const len = unit.getEntry(unit.first.unwrap() orelse return).off;
|
||||||
|
if (len == 0) return;
|
||||||
|
for (unit.entries.items) |*entry| entry.off -= len;
|
||||||
|
unit.off += len;
|
||||||
|
unit.len -= len;
|
||||||
|
}
|
||||||
|
|
||||||
fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void {
|
fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void {
|
||||||
if (unit.off == new_off) return;
|
if (unit.off == new_off) return;
|
||||||
if (try dwarf.getFile().?.copyRangeAll(
|
if (try dwarf.getFile().?.copyRangeAll(
|
||||||
@ -463,6 +476,7 @@ const Unit = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resizeHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void {
|
fn resizeHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void {
|
||||||
|
unit.trim();
|
||||||
if (unit.header_len == len) return;
|
if (unit.header_len == len) return;
|
||||||
const available_len = if (unit.prev.unwrap()) |prev_unit| prev_excess: {
|
const available_len = if (unit.prev.unwrap()) |prev_unit| prev_excess: {
|
||||||
const prev_unit_ptr = sec.getUnit(prev_unit);
|
const prev_unit_ptr = sec.getUnit(prev_unit);
|
||||||
@ -535,23 +549,11 @@ const Unit = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
|
fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
|
||||||
for (unit.cross_entry_relocs.items) |reloc| {
|
const unit_off = sec.off + unit.off;
|
||||||
try dwarf.resolveReloc(
|
|
||||||
sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|
|
|
||||||
unit.header_len + unit.getEntry(source_entry).off
|
|
||||||
else
|
|
||||||
0) + reloc.source_off,
|
|
||||||
unit.off + unit.header_len + unit.getEntry(reloc.target_entry).assertNonEmpty(unit, sec, dwarf).off + reloc.target_off,
|
|
||||||
dwarf.sectionOffsetBytes(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (unit.cross_unit_relocs.items) |reloc| {
|
for (unit.cross_unit_relocs.items) |reloc| {
|
||||||
const target_unit = sec.getUnit(reloc.target_unit);
|
const target_unit = sec.getUnit(reloc.target_unit);
|
||||||
try dwarf.resolveReloc(
|
try dwarf.resolveReloc(
|
||||||
sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|
|
unit_off + reloc.source_off,
|
||||||
unit.header_len + unit.getEntry(source_entry).off
|
|
||||||
else
|
|
||||||
0) + reloc.source_off,
|
|
||||||
target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
|
target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
|
||||||
target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
|
target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
|
||||||
else
|
else
|
||||||
@ -565,10 +567,7 @@ const Unit = struct {
|
|||||||
};
|
};
|
||||||
const target_unit = target_sec.getUnit(reloc.target_unit);
|
const target_unit = target_sec.getUnit(reloc.target_unit);
|
||||||
try dwarf.resolveReloc(
|
try dwarf.resolveReloc(
|
||||||
sec.off + unit.off + (if (reloc.source_entry.unwrap()) |source_entry|
|
unit_off + reloc.source_off,
|
||||||
unit.header_len + unit.getEntry(source_entry).off
|
|
||||||
else
|
|
||||||
0) + reloc.source_off,
|
|
||||||
target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
|
target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
|
||||||
target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
|
target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
|
||||||
else
|
else
|
||||||
@ -576,57 +575,8 @@ const Unit = struct {
|
|||||||
dwarf.sectionOffsetBytes(),
|
dwarf.sectionOffsetBytes(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (dwarf.bin_file.cast(.elf)) |elf_file| {
|
for (unit.entries.items) |*entry| try entry.resolveRelocs(unit, sec, dwarf);
|
||||||
const zo = elf_file.zigObjectPtr().?;
|
|
||||||
for (unit.external_relocs.items) |reloc| {
|
|
||||||
const symbol = zo.symbol(reloc.target_sym);
|
|
||||||
try dwarf.resolveReloc(
|
|
||||||
sec.off + unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off,
|
|
||||||
@bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) -
|
|
||||||
if (symbol.flags.is_tls) elf_file.dtpAddress() else 0),
|
|
||||||
@intFromEnum(dwarf.address_size),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (dwarf.bin_file.cast(.macho)) |macho_file| {
|
|
||||||
const zo = macho_file.getZigObject().?;
|
|
||||||
for (unit.external_relocs.items) |reloc| {
|
|
||||||
const ref = zo.getSymbolRef(reloc.target_sym, macho_file);
|
|
||||||
try dwarf.resolveReloc(
|
|
||||||
sec.off + unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off,
|
|
||||||
ref.getSymbol(macho_file).?.getAddress(.{}, macho_file),
|
|
||||||
@intFromEnum(dwarf.address_size),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CrossEntryReloc = struct {
|
|
||||||
source_entry: Entry.Index.Optional = .none,
|
|
||||||
source_off: u32 = 0,
|
|
||||||
target_entry: Entry.Index,
|
|
||||||
target_off: u32 = 0,
|
|
||||||
};
|
|
||||||
const CrossUnitReloc = struct {
|
|
||||||
source_entry: Entry.Index.Optional = .none,
|
|
||||||
source_off: u32 = 0,
|
|
||||||
target_unit: Unit.Index,
|
|
||||||
target_entry: Entry.Index.Optional = .none,
|
|
||||||
target_off: u32 = 0,
|
|
||||||
};
|
|
||||||
const CrossSectionReloc = struct {
|
|
||||||
source_entry: Entry.Index.Optional = .none,
|
|
||||||
source_off: u32 = 0,
|
|
||||||
target_sec: Section.Index,
|
|
||||||
target_unit: Unit.Index,
|
|
||||||
target_entry: Entry.Index.Optional = .none,
|
|
||||||
target_off: u32 = 0,
|
|
||||||
};
|
|
||||||
const ExternalReloc = struct {
|
|
||||||
source_entry: Entry.Index,
|
|
||||||
source_off: u32 = 0,
|
|
||||||
target_sym: u32,
|
|
||||||
target_off: u64 = 0,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An indivisible entry within a `Unit` containing section-specific data.
|
/// An indivisible entry within a `Unit` containing section-specific data.
|
||||||
@ -637,6 +587,25 @@ const Entry = struct {
|
|||||||
off: u32,
|
off: u32,
|
||||||
/// data length in bytes
|
/// data length in bytes
|
||||||
len: u32,
|
len: u32,
|
||||||
|
cross_entry_relocs: std.ArrayListUnmanaged(CrossEntryReloc),
|
||||||
|
cross_unit_relocs: std.ArrayListUnmanaged(CrossUnitReloc),
|
||||||
|
cross_section_relocs: std.ArrayListUnmanaged(CrossSectionReloc),
|
||||||
|
external_relocs: std.ArrayListUnmanaged(ExternalReloc),
|
||||||
|
|
||||||
|
fn clear(entry: *Entry) void {
|
||||||
|
entry.cross_entry_relocs.clearRetainingCapacity();
|
||||||
|
entry.cross_unit_relocs.clearRetainingCapacity();
|
||||||
|
entry.cross_section_relocs.clearRetainingCapacity();
|
||||||
|
entry.external_relocs.clearRetainingCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(entry: *Entry, gpa: std.mem.Allocator) void {
|
||||||
|
entry.cross_entry_relocs.deinit(gpa);
|
||||||
|
entry.cross_unit_relocs.deinit(gpa);
|
||||||
|
entry.cross_section_relocs.deinit(gpa);
|
||||||
|
entry.external_relocs.deinit(gpa);
|
||||||
|
entry.* = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const Index = enum(u32) {
|
const Index = enum(u32) {
|
||||||
_,
|
_,
|
||||||
@ -803,6 +772,88 @@ const Entry = struct {
|
|||||||
}
|
}
|
||||||
@panic("missing dwarf relocation target");
|
@panic("missing dwarf relocation target");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolveRelocs(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void {
|
||||||
|
const entry_off = sec.off + unit.off + unit.header_len + entry.off;
|
||||||
|
for (entry.cross_entry_relocs.items) |reloc| {
|
||||||
|
try dwarf.resolveReloc(
|
||||||
|
entry_off + reloc.source_off,
|
||||||
|
unit.off + unit.header_len + unit.getEntry(reloc.target_entry).assertNonEmpty(unit, sec, dwarf).off + reloc.target_off,
|
||||||
|
dwarf.sectionOffsetBytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (entry.cross_unit_relocs.items) |reloc| {
|
||||||
|
const target_unit = sec.getUnit(reloc.target_unit);
|
||||||
|
try dwarf.resolveReloc(
|
||||||
|
entry_off + reloc.source_off,
|
||||||
|
target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
|
||||||
|
target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
|
||||||
|
else
|
||||||
|
0) + reloc.target_off,
|
||||||
|
dwarf.sectionOffsetBytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (entry.cross_section_relocs.items) |reloc| {
|
||||||
|
const target_sec = switch (reloc.target_sec) {
|
||||||
|
inline else => |target_sec| &@field(dwarf, @tagName(target_sec)).section,
|
||||||
|
};
|
||||||
|
const target_unit = target_sec.getUnit(reloc.target_unit);
|
||||||
|
try dwarf.resolveReloc(
|
||||||
|
entry_off + reloc.source_off,
|
||||||
|
target_unit.off + (if (reloc.target_entry.unwrap()) |target_entry|
|
||||||
|
target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sec, dwarf).off
|
||||||
|
else
|
||||||
|
0) + reloc.target_off,
|
||||||
|
dwarf.sectionOffsetBytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (dwarf.bin_file.cast(.elf)) |elf_file| {
|
||||||
|
const zo = elf_file.zigObjectPtr().?;
|
||||||
|
for (entry.external_relocs.items) |reloc| {
|
||||||
|
const symbol = zo.symbol(reloc.target_sym);
|
||||||
|
try dwarf.resolveReloc(
|
||||||
|
entry_off + reloc.source_off,
|
||||||
|
@bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) -
|
||||||
|
if (symbol.flags.is_tls) elf_file.dtpAddress() else 0),
|
||||||
|
@intFromEnum(dwarf.address_size),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (dwarf.bin_file.cast(.macho)) |macho_file| {
|
||||||
|
const zo = macho_file.getZigObject().?;
|
||||||
|
for (entry.external_relocs.items) |reloc| {
|
||||||
|
const ref = zo.getSymbolRef(reloc.target_sym, macho_file);
|
||||||
|
try dwarf.resolveReloc(
|
||||||
|
entry_off + reloc.source_off,
|
||||||
|
ref.getSymbol(macho_file).?.getAddress(.{}, macho_file),
|
||||||
|
@intFromEnum(dwarf.address_size),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const CrossEntryReloc = struct {
|
||||||
|
source_off: u32 = 0,
|
||||||
|
target_entry: Entry.Index,
|
||||||
|
target_off: u32 = 0,
|
||||||
|
};
|
||||||
|
const CrossUnitReloc = struct {
|
||||||
|
source_off: u32 = 0,
|
||||||
|
target_unit: Unit.Index,
|
||||||
|
target_entry: Entry.Index.Optional = .none,
|
||||||
|
target_off: u32 = 0,
|
||||||
|
};
|
||||||
|
const CrossSectionReloc = struct {
|
||||||
|
source_off: u32 = 0,
|
||||||
|
target_sec: Section.Index,
|
||||||
|
target_unit: Unit.Index,
|
||||||
|
target_entry: Entry.Index.Optional = .none,
|
||||||
|
target_off: u32 = 0,
|
||||||
|
};
|
||||||
|
const ExternalReloc = struct {
|
||||||
|
source_off: u32 = 0,
|
||||||
|
target_sym: u32,
|
||||||
|
target_off: u64 = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Loc = union(enum) {
|
pub const Loc = union(enum) {
|
||||||
@ -986,7 +1037,9 @@ pub const WipNav = struct {
|
|||||||
entry: Entry.Index,
|
entry: Entry.Index,
|
||||||
any_children: bool,
|
any_children: bool,
|
||||||
func: InternPool.Index,
|
func: InternPool.Index,
|
||||||
|
func_sym_index: u32,
|
||||||
func_high_reloc: u32,
|
func_high_reloc: u32,
|
||||||
|
inlined_funcs_high_reloc: std.ArrayListUnmanaged(u32),
|
||||||
debug_info: std.ArrayListUnmanaged(u8),
|
debug_info: std.ArrayListUnmanaged(u8),
|
||||||
debug_line: std.ArrayListUnmanaged(u8),
|
debug_line: std.ArrayListUnmanaged(u8),
|
||||||
debug_loclists: std.ArrayListUnmanaged(u8),
|
debug_loclists: std.ArrayListUnmanaged(u8),
|
||||||
@ -994,6 +1047,7 @@ pub const WipNav = struct {
|
|||||||
|
|
||||||
pub fn deinit(wip_nav: *WipNav) void {
|
pub fn deinit(wip_nav: *WipNav) void {
|
||||||
const gpa = wip_nav.dwarf.gpa;
|
const gpa = wip_nav.dwarf.gpa;
|
||||||
|
if (wip_nav.func != .none) wip_nav.inlined_funcs_high_reloc.deinit(gpa);
|
||||||
wip_nav.debug_info.deinit(gpa);
|
wip_nav.debug_info.deinit(gpa);
|
||||||
wip_nav.debug_line.deinit(gpa);
|
wip_nav.debug_line.deinit(gpa);
|
||||||
wip_nav.debug_loclists.deinit(gpa);
|
wip_nav.debug_loclists.deinit(gpa);
|
||||||
@ -1004,10 +1058,10 @@ pub const WipNav = struct {
|
|||||||
return wip_nav.debug_info.writer(wip_nav.dwarf.gpa);
|
return wip_nav.debug_info.writer(wip_nav.dwarf.gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const VarTag = enum { local_arg, local_var };
|
pub const LocalTag = enum { local_arg, local_var };
|
||||||
pub fn genVarDebugInfo(
|
pub fn genLocalDebugInfo(
|
||||||
wip_nav: *WipNav,
|
wip_nav: *WipNav,
|
||||||
tag: VarTag,
|
tag: LocalTag,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
loc: Loc,
|
loc: Loc,
|
||||||
@ -1078,7 +1132,43 @@ pub const WipNav = struct {
|
|||||||
try dlw.writeByte(DW.LNS.set_epilogue_begin);
|
try dlw.writeByte(DW.LNS.set_epilogue_begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enterInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64, line: u32, column: u32) UpdateError!void {
|
||||||
|
const dwarf = wip_nav.dwarf;
|
||||||
|
const zcu = wip_nav.pt.zcu;
|
||||||
|
const diw = wip_nav.debug_info.writer(dwarf.gpa);
|
||||||
|
try wip_nav.inlined_funcs_high_reloc.ensureUnusedCapacity(dwarf.gpa, 1);
|
||||||
|
|
||||||
|
try uleb128(diw, @intFromEnum(AbbrevCode.inlined_func));
|
||||||
|
try wip_nav.refNav(zcu.funcInfo(func).owner_nav);
|
||||||
|
try uleb128(diw, zcu.navSrcLine(zcu.funcInfo(wip_nav.func).owner_nav) + line + 1);
|
||||||
|
try uleb128(diw, column + 1);
|
||||||
|
const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
|
||||||
|
try external_relocs.ensureUnusedCapacity(dwarf.gpa, 2);
|
||||||
|
external_relocs.appendAssumeCapacity(.{
|
||||||
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
|
.target_sym = wip_nav.func_sym_index,
|
||||||
|
.target_off = code_off,
|
||||||
|
});
|
||||||
|
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
|
||||||
|
wip_nav.inlined_funcs_high_reloc.appendAssumeCapacity(@intCast(external_relocs.items.len));
|
||||||
|
external_relocs.appendAssumeCapacity(.{
|
||||||
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
|
.target_sym = wip_nav.func_sym_index,
|
||||||
|
.target_off = undefined,
|
||||||
|
});
|
||||||
|
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
|
||||||
|
try wip_nav.setInlineFunc(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn leaveInlineFunc(wip_nav: *WipNav, func: InternPool.Index, code_off: u64) UpdateError!void {
|
||||||
|
const external_relocs = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
|
||||||
|
external_relocs.items[wip_nav.inlined_funcs_high_reloc.pop()].target_off = code_off;
|
||||||
|
try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), @intFromEnum(AbbrevCode.null));
|
||||||
|
try wip_nav.setInlineFunc(func);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setInlineFunc(wip_nav: *WipNav, func: InternPool.Index) UpdateError!void {
|
pub fn setInlineFunc(wip_nav: *WipNav, func: InternPool.Index) UpdateError!void {
|
||||||
|
wip_nav.any_children = true;
|
||||||
const zcu = wip_nav.pt.zcu;
|
const zcu = wip_nav.pt.zcu;
|
||||||
const dwarf = wip_nav.dwarf;
|
const dwarf = wip_nav.dwarf;
|
||||||
if (wip_nav.func == func) return;
|
if (wip_nav.func == func) return;
|
||||||
@ -1096,8 +1186,7 @@ pub const WipNav = struct {
|
|||||||
try dlw.writeByte(DW.LNS.extended_op);
|
try dlw.writeByte(DW.LNS.extended_op);
|
||||||
try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
|
try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
|
||||||
try dlw.writeByte(DW.LNE.ZIG_set_decl);
|
try dlw.writeByte(DW.LNE.ZIG_set_decl);
|
||||||
try dwarf.debug_line.section.getUnit(wip_nav.unit).cross_section_relocs.append(dwarf.gpa, .{
|
try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
|
||||||
.source_entry = wip_nav.entry.toOptional(),
|
|
||||||
.source_off = @intCast(wip_nav.debug_line.items.len),
|
.source_off = @intCast(wip_nav.debug_line.items.len),
|
||||||
.target_sec = .debug_info,
|
.target_sec = .debug_info,
|
||||||
.target_unit = new_unit,
|
.target_unit = new_unit,
|
||||||
@ -1133,9 +1222,9 @@ pub const WipNav = struct {
|
|||||||
fn infoSectionOffset(wip_nav: *WipNav, sec: Section.Index, unit: Unit.Index, entry: Entry.Index, off: u32) UpdateError!void {
|
fn infoSectionOffset(wip_nav: *WipNav, sec: Section.Index, unit: Unit.Index, entry: Entry.Index, off: u32) UpdateError!void {
|
||||||
const dwarf = wip_nav.dwarf;
|
const dwarf = wip_nav.dwarf;
|
||||||
const gpa = dwarf.gpa;
|
const gpa = dwarf.gpa;
|
||||||
|
const entry_ptr = dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry);
|
||||||
if (sec != .debug_info) {
|
if (sec != .debug_info) {
|
||||||
try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_section_relocs.append(gpa, .{
|
try entry_ptr.cross_section_relocs.append(gpa, .{
|
||||||
.source_entry = wip_nav.entry.toOptional(),
|
|
||||||
.source_off = @intCast(wip_nav.debug_info.items.len),
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
.target_sec = sec,
|
.target_sec = sec,
|
||||||
.target_unit = unit,
|
.target_unit = unit,
|
||||||
@ -1143,16 +1232,14 @@ pub const WipNav = struct {
|
|||||||
.target_off = off,
|
.target_off = off,
|
||||||
});
|
});
|
||||||
} else if (unit != wip_nav.unit) {
|
} else if (unit != wip_nav.unit) {
|
||||||
try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_unit_relocs.append(gpa, .{
|
try entry_ptr.cross_unit_relocs.append(gpa, .{
|
||||||
.source_entry = wip_nav.entry.toOptional(),
|
|
||||||
.source_off = @intCast(wip_nav.debug_info.items.len),
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
.target_unit = unit,
|
.target_unit = unit,
|
||||||
.target_entry = entry.toOptional(),
|
.target_entry = entry.toOptional(),
|
||||||
.target_off = off,
|
.target_off = off,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
try dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs.append(gpa, .{
|
try entry_ptr.cross_entry_relocs.append(gpa, .{
|
||||||
.source_entry = wip_nav.entry.toOptional(),
|
|
||||||
.source_off = @intCast(wip_nav.debug_info.items.len),
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
.target_entry = entry,
|
.target_entry = entry,
|
||||||
.target_off = off,
|
.target_off = off,
|
||||||
@ -1167,8 +1254,7 @@ pub const WipNav = struct {
|
|||||||
|
|
||||||
fn addrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void {
|
fn addrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void {
|
||||||
const dwarf = wip_nav.dwarf;
|
const dwarf = wip_nav.dwarf;
|
||||||
try dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{
|
try dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
|
||||||
.source_entry = wip_nav.entry,
|
|
||||||
.source_off = @intCast(wip_nav.debug_info.items.len),
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
.target_sym = sym_index,
|
.target_sym = sym_index,
|
||||||
});
|
});
|
||||||
@ -1217,12 +1303,20 @@ pub const WipNav = struct {
|
|||||||
try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
|
try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn refNav(wip_nav: *WipNav, nav_index: InternPool.Nav.Index) UpdateError!void {
|
||||||
|
const zcu = wip_nav.pt.zcu;
|
||||||
|
const ip = &zcu.intern_pool;
|
||||||
|
const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(ip.getNav(nav_index).srcInst(ip).resolveFile(ip)).mod);
|
||||||
|
const nav_gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index);
|
||||||
|
if (!nav_gop.found_existing) nav_gop.value_ptr.* = try wip_nav.dwarf.addCommonEntry(unit);
|
||||||
|
try wip_nav.infoSectionOffset(.debug_info, unit, nav_gop.value_ptr.*, 0);
|
||||||
|
}
|
||||||
|
|
||||||
fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 {
|
fn refForward(wip_nav: *WipNav) std.mem.Allocator.Error!u32 {
|
||||||
const dwarf = wip_nav.dwarf;
|
const dwarf = wip_nav.dwarf;
|
||||||
const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs;
|
const cross_entry_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs;
|
||||||
const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);
|
const reloc_index: u32 = @intCast(cross_entry_relocs.items.len);
|
||||||
try cross_entry_relocs.append(dwarf.gpa, .{
|
try cross_entry_relocs.append(dwarf.gpa, .{
|
||||||
.source_entry = wip_nav.entry.toOptional(),
|
|
||||||
.source_off = @intCast(wip_nav.debug_info.items.len),
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
.target_entry = undefined,
|
.target_entry = undefined,
|
||||||
.target_off = undefined,
|
.target_off = undefined,
|
||||||
@ -1232,7 +1326,7 @@ pub const WipNav = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn finishForward(wip_nav: *WipNav, reloc_index: u32) void {
|
fn finishForward(wip_nav: *WipNav, reloc_index: u32) void {
|
||||||
const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).cross_entry_relocs.items[reloc_index];
|
const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index];
|
||||||
reloc.target_entry = wip_nav.entry;
|
reloc.target_entry = wip_nav.entry;
|
||||||
reloc.target_off = @intCast(wip_nav.debug_info.items.len);
|
reloc.target_off = @intCast(wip_nav.debug_info.items.len);
|
||||||
}
|
}
|
||||||
@ -1545,7 +1639,15 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
const unit = try dwarf.getUnit(file.mod);
|
const unit = try dwarf.getUnit(file.mod);
|
||||||
const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
|
const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
|
||||||
errdefer _ = dwarf.navs.pop();
|
errdefer _ = dwarf.navs.pop();
|
||||||
if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
|
if (nav_gop.found_existing) {
|
||||||
|
for ([_]*Section{
|
||||||
|
&dwarf.debug_aranges.section,
|
||||||
|
&dwarf.debug_info.section,
|
||||||
|
&dwarf.debug_line.section,
|
||||||
|
&dwarf.debug_loclists.section,
|
||||||
|
&dwarf.debug_rnglists.section,
|
||||||
|
}) |sec| sec.getUnit(unit).getEntry(nav_gop.value_ptr.*).clear();
|
||||||
|
} else nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
|
||||||
const nav_val = zcu.navValue(nav_index);
|
const nav_val = zcu.navValue(nav_index);
|
||||||
var wip_nav: WipNav = .{
|
var wip_nav: WipNav = .{
|
||||||
.dwarf = dwarf,
|
.dwarf = dwarf,
|
||||||
@ -1554,7 +1656,9 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
.entry = nav_gop.value_ptr.*,
|
.entry = nav_gop.value_ptr.*,
|
||||||
.any_children = false,
|
.any_children = false,
|
||||||
.func = .none,
|
.func = .none,
|
||||||
|
.func_sym_index = undefined,
|
||||||
.func_high_reloc = undefined,
|
.func_high_reloc = undefined,
|
||||||
|
.inlined_funcs_high_reloc = undefined,
|
||||||
.debug_info = .{},
|
.debug_info = .{},
|
||||||
.debug_line = .{},
|
.debug_line = .{},
|
||||||
.debug_loclists = .{},
|
.debug_loclists = .{},
|
||||||
@ -1608,16 +1712,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
try wip_nav.exprloc(.{ .addr = .{ .sym = sym_index } });
|
try wip_nav.exprloc(.{ .addr = .{ .sym = sym_index } });
|
||||||
try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
|
try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
|
||||||
ty.abiAlignment(pt).toByteUnits().?);
|
ty.abiAlignment(pt).toByteUnits().?);
|
||||||
const func_unit = InternPool.AnalUnit.wrap(.{ .func = nav_val.toIntern() });
|
try diw.writeByte(@intFromBool(false));
|
||||||
try diw.writeByte(@intFromBool(for (if (zcu.single_exports.get(func_unit)) |export_index|
|
|
||||||
zcu.all_exports.items[export_index..][0..1]
|
|
||||||
else if (zcu.multi_exports.get(func_unit)) |export_range|
|
|
||||||
zcu.all_exports.items[export_range.index..][0..export_range.len]
|
|
||||||
else
|
|
||||||
&.{}) |@"export"|
|
|
||||||
{
|
|
||||||
if (@"export".exported == .nav and @"export".exported.nav == nav_index) break true;
|
|
||||||
} else false));
|
|
||||||
wip_nav.finishForward(ty_reloc_index);
|
wip_nav.finishForward(ty_reloc_index);
|
||||||
try uleb128(diw, @intFromEnum(AbbrevCode.is_const));
|
try uleb128(diw, @intFromEnum(AbbrevCode.is_const));
|
||||||
try wip_nav.refType(ty);
|
try wip_nav.refType(ty);
|
||||||
@ -1668,16 +1763,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
try wip_nav.exprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr);
|
try wip_nav.exprloc(if (variable.is_threadlocal) .{ .form_tls_address = &addr } else addr);
|
||||||
try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
|
try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
|
||||||
ty.abiAlignment(pt).toByteUnits().?);
|
ty.abiAlignment(pt).toByteUnits().?);
|
||||||
const func_unit = InternPool.AnalUnit.wrap(.{ .func = nav_val.toIntern() });
|
try diw.writeByte(@intFromBool(false));
|
||||||
try diw.writeByte(@intFromBool(for (if (zcu.single_exports.get(func_unit)) |export_index|
|
|
||||||
zcu.all_exports.items[export_index..][0..1]
|
|
||||||
else if (zcu.multi_exports.get(func_unit)) |export_range|
|
|
||||||
zcu.all_exports.items[export_range.index..][0..export_range.len]
|
|
||||||
else
|
|
||||||
&.{}) |@"export"|
|
|
||||||
{
|
|
||||||
if (@"export".exported == .nav and @"export".exported.nav == nav_index) break true;
|
|
||||||
} else false));
|
|
||||||
},
|
},
|
||||||
.func => |func| {
|
.func => |func| {
|
||||||
assert(file.zir_loaded);
|
assert(file.zir_loaded);
|
||||||
@ -1712,6 +1798,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
|
|
||||||
const func_type = ip.indexToKey(func.ty).func_type;
|
const func_type = ip.indexToKey(func.ty).func_type;
|
||||||
wip_nav.func = nav_val.toIntern();
|
wip_nav.func = nav_val.toIntern();
|
||||||
|
wip_nav.func_sym_index = sym_index;
|
||||||
|
wip_nav.inlined_funcs_high_reloc = .{};
|
||||||
|
|
||||||
const diw = wip_nav.debug_info.writer(dwarf.gpa);
|
const diw = wip_nav.debug_info.writer(dwarf.gpa);
|
||||||
try uleb128(diw, @intFromEnum(AbbrevCode.decl_func));
|
try uleb128(diw, @intFromEnum(AbbrevCode.decl_func));
|
||||||
@ -1723,32 +1811,23 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
try wip_nav.strp(nav.name.toSlice(ip));
|
try wip_nav.strp(nav.name.toSlice(ip));
|
||||||
try wip_nav.strp(nav.fqn.toSlice(ip));
|
try wip_nav.strp(nav.fqn.toSlice(ip));
|
||||||
try wip_nav.refType(Type.fromInterned(func_type.return_type));
|
try wip_nav.refType(Type.fromInterned(func_type.return_type));
|
||||||
const external_relocs = &dwarf.debug_info.section.getUnit(unit).external_relocs;
|
const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
|
||||||
try external_relocs.append(dwarf.gpa, .{
|
try external_relocs.ensureUnusedCapacity(dwarf.gpa, 2);
|
||||||
.source_entry = wip_nav.entry,
|
external_relocs.appendAssumeCapacity(.{
|
||||||
.source_off = @intCast(wip_nav.debug_info.items.len),
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
.target_sym = sym_index,
|
.target_sym = sym_index,
|
||||||
});
|
});
|
||||||
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
|
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
|
||||||
wip_nav.func_high_reloc = @intCast(external_relocs.items.len);
|
wip_nav.func_high_reloc = @intCast(external_relocs.items.len);
|
||||||
try external_relocs.append(dwarf.gpa, .{
|
external_relocs.appendAssumeCapacity(.{
|
||||||
.source_entry = wip_nav.entry,
|
|
||||||
.source_off = @intCast(wip_nav.debug_info.items.len),
|
.source_off = @intCast(wip_nav.debug_info.items.len),
|
||||||
.target_sym = sym_index,
|
.target_sym = sym_index,
|
||||||
|
.target_off = undefined,
|
||||||
});
|
});
|
||||||
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
|
try diw.writeByteNTimes(0, @intFromEnum(dwarf.address_size));
|
||||||
try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
|
try uleb128(diw, nav.status.resolved.alignment.toByteUnits() orelse
|
||||||
target_info.defaultFunctionAlignment(file.mod.resolved_target.result).toByteUnits().?);
|
target_info.defaultFunctionAlignment(file.mod.resolved_target.result).toByteUnits().?);
|
||||||
const func_unit = InternPool.AnalUnit.wrap(.{ .func = nav_val.toIntern() });
|
try diw.writeByte(@intFromBool(false));
|
||||||
try diw.writeByte(@intFromBool(for (if (zcu.single_exports.get(func_unit)) |export_index|
|
|
||||||
zcu.all_exports.items[export_index..][0..1]
|
|
||||||
else if (zcu.multi_exports.get(func_unit)) |export_range|
|
|
||||||
zcu.all_exports.items[export_range.index..][0..export_range.len]
|
|
||||||
else
|
|
||||||
&.{}) |@"export"|
|
|
||||||
{
|
|
||||||
if (@"export".exported == .nav and @"export".exported.nav == nav_index) break true;
|
|
||||||
} else false));
|
|
||||||
try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));
|
try diw.writeByte(@intFromBool(func_type.return_type == .noreturn_type));
|
||||||
|
|
||||||
const dlw = wip_nav.debug_line.writer(dwarf.gpa);
|
const dlw = wip_nav.debug_line.writer(dwarf.gpa);
|
||||||
@ -1756,8 +1835,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
if (dwarf.incremental()) {
|
if (dwarf.incremental()) {
|
||||||
try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
|
try uleb128(dlw, 1 + dwarf.sectionOffsetBytes());
|
||||||
try dlw.writeByte(DW.LNE.ZIG_set_decl);
|
try dlw.writeByte(DW.LNE.ZIG_set_decl);
|
||||||
try dwarf.debug_line.section.getUnit(wip_nav.unit).cross_section_relocs.append(dwarf.gpa, .{
|
try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_section_relocs.append(dwarf.gpa, .{
|
||||||
.source_entry = wip_nav.entry.toOptional(),
|
|
||||||
.source_off = @intCast(wip_nav.debug_line.items.len),
|
.source_off = @intCast(wip_nav.debug_line.items.len),
|
||||||
.target_sec = .debug_info,
|
.target_sec = .debug_info,
|
||||||
.target_unit = wip_nav.unit,
|
.target_unit = wip_nav.unit,
|
||||||
@ -1772,8 +1850,7 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In
|
|||||||
} else {
|
} else {
|
||||||
try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size));
|
try uleb128(dlw, 1 + @intFromEnum(dwarf.address_size));
|
||||||
try dlw.writeByte(DW.LNE.set_address);
|
try dlw.writeByte(DW.LNE.set_address);
|
||||||
try dwarf.debug_line.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{
|
try dwarf.debug_line.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
|
||||||
.source_entry = wip_nav.entry,
|
|
||||||
.source_off = @intCast(wip_nav.debug_line.items.len),
|
.source_off = @intCast(wip_nav.debug_line.items.len),
|
||||||
.target_sym = sym_index,
|
.target_sym = sym_index,
|
||||||
});
|
});
|
||||||
@ -1806,7 +1883,8 @@ pub fn finishWipNav(
|
|||||||
log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)});
|
log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)});
|
||||||
|
|
||||||
if (wip_nav.func != .none) {
|
if (wip_nav.func != .none) {
|
||||||
dwarf.debug_info.section.getUnit(wip_nav.unit).external_relocs.items[wip_nav.func_high_reloc].target_off = sym.size;
|
const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs;
|
||||||
|
external_relocs.items[wip_nav.func_high_reloc].target_off = sym.size;
|
||||||
if (wip_nav.any_children) {
|
if (wip_nav.any_children) {
|
||||||
const diw = wip_nav.debug_info.writer(dwarf.gpa);
|
const diw = wip_nav.debug_info.writer(dwarf.gpa);
|
||||||
try uleb128(diw, @intFromEnum(AbbrevCode.null));
|
try uleb128(diw, @intFromEnum(AbbrevCode.null));
|
||||||
@ -1817,8 +1895,7 @@ pub fn finishWipNav(
|
|||||||
);
|
);
|
||||||
|
|
||||||
var aranges_entry = [1]u8{0} ** (8 + 8);
|
var aranges_entry = [1]u8{0} ** (8 + 8);
|
||||||
try dwarf.debug_aranges.section.getUnit(wip_nav.unit).external_relocs.append(dwarf.gpa, .{
|
try dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{
|
||||||
.source_entry = wip_nav.entry,
|
|
||||||
.target_sym = sym.index,
|
.target_sym = sym.index,
|
||||||
});
|
});
|
||||||
dwarf.writeInt(aranges_entry[0..@intFromEnum(dwarf.address_size)], 0);
|
dwarf.writeInt(aranges_entry[0..@intFromEnum(dwarf.address_size)], 0);
|
||||||
@ -1832,14 +1909,12 @@ pub fn finishWipNav(
|
|||||||
aranges_entry[0 .. @intFromEnum(dwarf.address_size) * 2],
|
aranges_entry[0 .. @intFromEnum(dwarf.address_size) * 2],
|
||||||
);
|
);
|
||||||
|
|
||||||
try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).external_relocs.appendSlice(dwarf.gpa, &.{
|
try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.appendSlice(dwarf.gpa, &.{
|
||||||
.{
|
.{
|
||||||
.source_entry = wip_nav.entry,
|
|
||||||
.source_off = 1,
|
.source_off = 1,
|
||||||
.target_sym = sym.index,
|
.target_sym = sym.index,
|
||||||
},
|
},
|
||||||
.{
|
.{
|
||||||
.source_entry = wip_nav.entry,
|
|
||||||
.source_off = 1 + @intFromEnum(dwarf.address_size),
|
.source_off = 1 + @intFromEnum(dwarf.address_size),
|
||||||
.target_sym = sym.index,
|
.target_sym = sym.index,
|
||||||
.target_off = sym.size,
|
.target_off = sym.size,
|
||||||
@ -1891,7 +1966,9 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
|
|||||||
.entry = undefined,
|
.entry = undefined,
|
||||||
.any_children = false,
|
.any_children = false,
|
||||||
.func = .none,
|
.func = .none,
|
||||||
|
.func_sym_index = undefined,
|
||||||
.func_high_reloc = undefined,
|
.func_high_reloc = undefined,
|
||||||
|
.inlined_funcs_high_reloc = undefined,
|
||||||
.debug_info = .{},
|
.debug_info = .{},
|
||||||
.debug_line = .{},
|
.debug_line = .{},
|
||||||
.debug_loclists = .{},
|
.debug_loclists = .{},
|
||||||
@ -1902,6 +1979,62 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
|
|||||||
const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
|
const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
|
||||||
errdefer _ = dwarf.navs.pop();
|
errdefer _ = dwarf.navs.pop();
|
||||||
switch (ip.indexToKey(nav_val.toIntern())) {
|
switch (ip.indexToKey(nav_val.toIntern())) {
|
||||||
|
.func => |func| {
|
||||||
|
if (nav_gop.found_existing) {
|
||||||
|
const unit_ptr = dwarf.debug_info.section.getUnit(unit);
|
||||||
|
const entry_ptr = unit_ptr.getEntry(nav_gop.value_ptr.*);
|
||||||
|
if (entry_ptr.len >= AbbrevCode.decl_bytes) {
|
||||||
|
var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined;
|
||||||
|
if (try dwarf.getFile().?.preadAll(
|
||||||
|
&abbrev_code_buf,
|
||||||
|
dwarf.debug_info.section.off + unit_ptr.off + unit_ptr.header_len + entry_ptr.off,
|
||||||
|
) != abbrev_code_buf.len) return error.InputOutput;
|
||||||
|
var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf);
|
||||||
|
const abbrev_code: AbbrevCode = @enumFromInt(
|
||||||
|
try std.leb.readUleb128(@typeInfo(AbbrevCode).Enum.tag_type, abbrev_code_fbs.reader()),
|
||||||
|
);
|
||||||
|
switch (abbrev_code) {
|
||||||
|
else => unreachable,
|
||||||
|
.decl_func, .decl_func_empty => return,
|
||||||
|
.decl_func_generic, .decl_func_generic_empty => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry_ptr.clear();
|
||||||
|
} else nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
|
||||||
|
wip_nav.entry = nav_gop.value_ptr.*;
|
||||||
|
|
||||||
|
const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
|
||||||
|
const parent_namespace_ptr = ip.namespacePtr(ip.getCau(cau).namespace);
|
||||||
|
break :parent .{
|
||||||
|
parent_namespace_ptr.owner_type,
|
||||||
|
if (parent_namespace_ptr.pub_decls.containsContext(nav_index, .{ .zcu = zcu }))
|
||||||
|
DW.ACCESS.public
|
||||||
|
else if (parent_namespace_ptr.priv_decls.containsContext(nav_index, .{ .zcu = zcu }))
|
||||||
|
DW.ACCESS.private
|
||||||
|
else
|
||||||
|
unreachable,
|
||||||
|
};
|
||||||
|
} else .{ zcu.fileRootType(inst_info.file), DW.ACCESS.private };
|
||||||
|
|
||||||
|
const func_type = ip.indexToKey(func.ty).func_type;
|
||||||
|
const diw = wip_nav.debug_info.writer(dwarf.gpa);
|
||||||
|
try uleb128(diw, @intFromEnum(@as(AbbrevCode, if (func_type.param_types.len > 0 or func_type.is_var_args) .decl_func_generic else .decl_func_generic_empty)));
|
||||||
|
try wip_nav.refType(Type.fromInterned(parent_type));
|
||||||
|
assert(wip_nav.debug_info.items.len == DebugInfo.declEntryLineOff(dwarf));
|
||||||
|
try diw.writeInt(u32, @intCast(loc.line + 1), dwarf.endian);
|
||||||
|
try uleb128(diw, loc.column + 1);
|
||||||
|
try diw.writeByte(accessibility);
|
||||||
|
try wip_nav.strp(nav.name.toSlice(ip));
|
||||||
|
try wip_nav.refType(Type.fromInterned(func_type.return_type));
|
||||||
|
if (func_type.param_types.len > 0 or func_type.is_var_args) {
|
||||||
|
for (0..func_type.param_types.len) |param_index| {
|
||||||
|
try uleb128(diw, @intFromEnum(AbbrevCode.func_type_param));
|
||||||
|
try wip_nav.refType(Type.fromInterned(func_type.param_types.get(ip)[param_index]));
|
||||||
|
}
|
||||||
|
if (func_type.is_var_args) try uleb128(diw, @intFromEnum(AbbrevCode.is_var_args));
|
||||||
|
try uleb128(diw, @intFromEnum(AbbrevCode.null));
|
||||||
|
}
|
||||||
|
},
|
||||||
.struct_type => done: {
|
.struct_type => done: {
|
||||||
const loaded_struct = ip.loadStructType(nav_val.toIntern());
|
const loaded_struct = ip.loadStructType(nav_val.toIntern());
|
||||||
|
|
||||||
@ -2304,7 +2437,9 @@ fn updateType(
|
|||||||
.entry = dwarf.types.get(type_index).?,
|
.entry = dwarf.types.get(type_index).?,
|
||||||
.any_children = false,
|
.any_children = false,
|
||||||
.func = .none,
|
.func = .none,
|
||||||
|
.func_sym_index = undefined,
|
||||||
.func_high_reloc = undefined,
|
.func_high_reloc = undefined,
|
||||||
|
.inlined_funcs_high_reloc = undefined,
|
||||||
.debug_info = .{},
|
.debug_info = .{},
|
||||||
.debug_line = .{},
|
.debug_line = .{},
|
||||||
.debug_loclists = .{},
|
.debug_loclists = .{},
|
||||||
@ -2467,13 +2602,25 @@ fn updateType(
|
|||||||
.error_union_type => |error_union_type| {
|
.error_union_type => |error_union_type| {
|
||||||
const error_union_error_set_type = Type.fromInterned(error_union_type.error_set_type);
|
const error_union_error_set_type = Type.fromInterned(error_union_type.error_set_type);
|
||||||
const error_union_payload_type = Type.fromInterned(error_union_type.payload_type);
|
const error_union_payload_type = Type.fromInterned(error_union_type.payload_type);
|
||||||
const error_union_error_set_offset = codegen.errUnionErrorOffset(error_union_payload_type, pt);
|
const error_union_error_set_offset, const error_union_payload_offset = switch (error_union_type.payload_type) {
|
||||||
const error_union_payload_offset = codegen.errUnionPayloadOffset(error_union_payload_type, pt);
|
.generic_poison_type => .{ 0, 0 },
|
||||||
|
else => .{
|
||||||
|
codegen.errUnionErrorOffset(error_union_payload_type, pt),
|
||||||
|
codegen.errUnionPayloadOffset(error_union_payload_type, pt),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
try uleb128(diw, @intFromEnum(AbbrevCode.union_type));
|
try uleb128(diw, @intFromEnum(AbbrevCode.union_type));
|
||||||
try wip_nav.strp(name);
|
try wip_nav.strp(name);
|
||||||
try uleb128(diw, ty.abiSize(pt));
|
if (error_union_type.error_set_type != .generic_poison_type and
|
||||||
try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
|
error_union_type.payload_type != .generic_poison_type)
|
||||||
|
{
|
||||||
|
try uleb128(diw, ty.abiSize(pt));
|
||||||
|
try uleb128(diw, ty.abiAlignment(pt).toByteUnits().?);
|
||||||
|
} else {
|
||||||
|
try uleb128(diw, 0);
|
||||||
|
try uleb128(diw, 1);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
|
try uleb128(diw, @intFromEnum(AbbrevCode.tagged_union));
|
||||||
try wip_nav.infoSectionOffset(
|
try wip_nav.infoSectionOffset(
|
||||||
@ -2655,10 +2802,16 @@ fn updateType(
|
|||||||
}
|
}
|
||||||
if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));
|
if (error_set_type.names.len > 0) try uleb128(diw, @intFromEnum(AbbrevCode.null));
|
||||||
},
|
},
|
||||||
.inferred_error_set_type => |func| {
|
.inferred_error_set_type => |func| switch (ip.funcIesResolvedUnordered(func)) {
|
||||||
try uleb128(diw, @intFromEnum(AbbrevCode.inferred_error_set_type));
|
.none => {
|
||||||
try wip_nav.strp(name);
|
try uleb128(diw, @intFromEnum(AbbrevCode.void_type));
|
||||||
try wip_nav.refType(Type.fromInterned(ip.funcIesResolvedUnordered(func)));
|
try wip_nav.strp(name);
|
||||||
|
},
|
||||||
|
else => |ies| {
|
||||||
|
try uleb128(diw, @intFromEnum(AbbrevCode.inferred_error_set_type));
|
||||||
|
try wip_nav.strp(name);
|
||||||
|
try wip_nav.refType(Type.fromInterned(ies));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// values, not types
|
// values, not types
|
||||||
@ -2705,7 +2858,9 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
|
|||||||
.entry = type_gop.value_ptr.*,
|
.entry = type_gop.value_ptr.*,
|
||||||
.any_children = false,
|
.any_children = false,
|
||||||
.func = .none,
|
.func = .none,
|
||||||
|
.func_sym_index = undefined,
|
||||||
.func_high_reloc = undefined,
|
.func_high_reloc = undefined,
|
||||||
|
.inlined_funcs_high_reloc = undefined,
|
||||||
.debug_info = .{},
|
.debug_info = .{},
|
||||||
.debug_line = .{},
|
.debug_line = .{},
|
||||||
.debug_loclists = .{},
|
.debug_loclists = .{},
|
||||||
@ -2766,7 +2921,9 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP
|
|||||||
.entry = type_gop.value_ptr.*,
|
.entry = type_gop.value_ptr.*,
|
||||||
.any_children = false,
|
.any_children = false,
|
||||||
.func = .none,
|
.func = .none,
|
||||||
|
.func_sym_index = undefined,
|
||||||
.func_high_reloc = undefined,
|
.func_high_reloc = undefined,
|
||||||
|
.inlined_funcs_high_reloc = undefined,
|
||||||
.debug_info = .{},
|
.debug_info = .{},
|
||||||
.debug_line = .{},
|
.debug_line = .{},
|
||||||
.debug_loclists = .{},
|
.debug_loclists = .{},
|
||||||
@ -2940,7 +3097,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
|
|||||||
.entry = entry,
|
.entry = entry,
|
||||||
.any_children = false,
|
.any_children = false,
|
||||||
.func = .none,
|
.func = .none,
|
||||||
|
.func_sym_index = undefined,
|
||||||
.func_high_reloc = undefined,
|
.func_high_reloc = undefined,
|
||||||
|
.inlined_funcs_high_reloc = undefined,
|
||||||
.debug_info = .{},
|
.debug_info = .{},
|
||||||
.debug_line = .{},
|
.debug_line = .{},
|
||||||
.debug_loclists = .{},
|
.debug_loclists = .{},
|
||||||
@ -2998,7 +3157,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
|
|||||||
if (dwarf.debug_aranges.section.dirty) {
|
if (dwarf.debug_aranges.section.dirty) {
|
||||||
for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
|
for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
|
||||||
const unit: Unit.Index = @enumFromInt(unit_index);
|
const unit: Unit.Index = @enumFromInt(unit_index);
|
||||||
try unit_ptr.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 1);
|
unit_ptr.clear();
|
||||||
|
try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 1);
|
||||||
header.clearRetainingCapacity();
|
header.clearRetainingCapacity();
|
||||||
try header.ensureTotalCapacity(unit_ptr.header_len);
|
try header.ensureTotalCapacity(unit_ptr.header_len);
|
||||||
const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
|
const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
|
||||||
@ -3029,8 +3189,9 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
|
|||||||
if (dwarf.debug_info.section.dirty) {
|
if (dwarf.debug_info.section.dirty) {
|
||||||
for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| {
|
for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| {
|
||||||
const unit: Unit.Index = @enumFromInt(unit_index);
|
const unit: Unit.Index = @enumFromInt(unit_index);
|
||||||
try unit_ptr.cross_unit_relocs.ensureUnusedCapacity(dwarf.gpa, 1);
|
unit_ptr.clear();
|
||||||
try unit_ptr.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 7);
|
try unit_ptr.cross_unit_relocs.ensureTotalCapacity(dwarf.gpa, 1);
|
||||||
|
try unit_ptr.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 7);
|
||||||
header.clearRetainingCapacity();
|
header.clearRetainingCapacity();
|
||||||
try header.ensureTotalCapacity(unit_ptr.header_len);
|
try header.ensureTotalCapacity(unit_ptr.header_len);
|
||||||
const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
|
const unit_len = (if (unit_ptr.next.unwrap()) |next_unit|
|
||||||
@ -3121,7 +3282,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
|
|||||||
for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit|
|
for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit|
|
||||||
try unit.resizeHeader(&dwarf.debug_line.section, dwarf, DebugLine.headerBytes(dwarf, @intCast(mod_info.dirs.count()), @intCast(mod_info.files.count())));
|
try unit.resizeHeader(&dwarf.debug_line.section, dwarf, DebugLine.headerBytes(dwarf, @intCast(mod_info.dirs.count()), @intCast(mod_info.files.count())));
|
||||||
for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {
|
for (dwarf.mods.values(), dwarf.debug_line.section.units.items) |mod_info, *unit| {
|
||||||
try unit.cross_section_relocs.ensureUnusedCapacity(dwarf.gpa, 2 * (1 + mod_info.files.count()));
|
unit.clear();
|
||||||
|
try unit.cross_section_relocs.ensureTotalCapacity(dwarf.gpa, 2 * (1 + mod_info.files.count()));
|
||||||
header.clearRetainingCapacity();
|
header.clearRetainingCapacity();
|
||||||
try header.ensureTotalCapacity(unit.header_len);
|
try header.ensureTotalCapacity(unit.header_len);
|
||||||
const unit_len = (if (unit.next.unwrap()) |next_unit|
|
const unit_len = (if (unit.next.unwrap()) |next_unit|
|
||||||
@ -3310,6 +3472,8 @@ const AbbrevCode = enum(u8) {
|
|||||||
decl_var,
|
decl_var,
|
||||||
decl_func,
|
decl_func,
|
||||||
decl_func_empty,
|
decl_func_empty,
|
||||||
|
decl_func_generic,
|
||||||
|
decl_func_generic_empty,
|
||||||
// the rest are unrestricted
|
// the rest are unrestricted
|
||||||
compile_unit,
|
compile_unit,
|
||||||
module,
|
module,
|
||||||
@ -3344,10 +3508,11 @@ const AbbrevCode = enum(u8) {
|
|||||||
struct_type,
|
struct_type,
|
||||||
packed_struct_type,
|
packed_struct_type,
|
||||||
union_type,
|
union_type,
|
||||||
|
inlined_func,
|
||||||
local_arg,
|
local_arg,
|
||||||
local_var,
|
local_var,
|
||||||
|
|
||||||
const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_func_empty));
|
const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_func_generic_empty));
|
||||||
|
|
||||||
const Attr = struct {
|
const Attr = struct {
|
||||||
DeclValEnum(DW.AT),
|
DeclValEnum(DW.AT),
|
||||||
@ -3451,6 +3616,19 @@ const AbbrevCode = enum(u8) {
|
|||||||
.{ .noreturn, .flag },
|
.{ .noreturn, .flag },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.decl_func_generic = .{
|
||||||
|
.tag = .subprogram,
|
||||||
|
.children = true,
|
||||||
|
.attrs = decl_abbrev_common_attrs ++ .{
|
||||||
|
.{ .type, .ref_addr },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.decl_func_generic_empty = .{
|
||||||
|
.tag = .subprogram,
|
||||||
|
.attrs = decl_abbrev_common_attrs ++ .{
|
||||||
|
.{ .type, .ref_addr },
|
||||||
|
},
|
||||||
|
},
|
||||||
.compile_unit = .{
|
.compile_unit = .{
|
||||||
.tag = .compile_unit,
|
.tag = .compile_unit,
|
||||||
.children = true,
|
.children = true,
|
||||||
@ -3706,6 +3884,17 @@ const AbbrevCode = enum(u8) {
|
|||||||
.{ .alignment, .udata },
|
.{ .alignment, .udata },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.inlined_func = .{
|
||||||
|
.tag = .inlined_subroutine,
|
||||||
|
.children = true,
|
||||||
|
.attrs = &.{
|
||||||
|
.{ .abstract_origin, .ref_addr },
|
||||||
|
.{ .call_line, .udata },
|
||||||
|
.{ .call_column, .udata },
|
||||||
|
.{ .low_pc, .addr },
|
||||||
|
.{ .high_pc, .addr },
|
||||||
|
},
|
||||||
|
},
|
||||||
.local_arg = .{
|
.local_arg = .{
|
||||||
.tag = .formal_parameter,
|
.tag = .formal_parameter,
|
||||||
.attrs = &.{
|
.attrs = &.{
|
||||||
|
|||||||
@ -1122,9 +1122,9 @@ pub fn updateNav(
|
|||||||
|
|
||||||
log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });
|
log.debug("updateNav {}({d})", .{ nav.fqn.fmt(ip), nav_index });
|
||||||
|
|
||||||
const nav_val = zcu.navValue(nav_index);
|
const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
|
||||||
const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
|
.func => .none,
|
||||||
.variable => |variable| Value.fromInterned(variable.init),
|
.variable => |variable| variable.init,
|
||||||
.@"extern" => |@"extern"| {
|
.@"extern" => |@"extern"| {
|
||||||
if (ip.isFunctionType(@"extern".ty)) return;
|
if (ip.isFunctionType(@"extern".ty)) return;
|
||||||
const sym_index = try self.getGlobalSymbol(
|
const sym_index = try self.getGlobalSymbol(
|
||||||
@ -1135,10 +1135,10 @@ pub fn updateNav(
|
|||||||
self.symbol(sym_index).flags.is_extern_ptr = true;
|
self.symbol(sym_index).flags.is_extern_ptr = true;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
else => nav_val,
|
else => nav.status.resolved.val,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
|
if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
|
||||||
const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index);
|
const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index);
|
||||||
self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
|
self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
|
||||||
|
|
||||||
@ -1153,7 +1153,7 @@ pub fn updateNav(
|
|||||||
&elf_file.base,
|
&elf_file.base,
|
||||||
pt,
|
pt,
|
||||||
zcu.navSrcLoc(nav_index),
|
zcu.navSrcLoc(nav_index),
|
||||||
nav_init,
|
Value.fromInterned(nav_init),
|
||||||
&code_buffer,
|
&code_buffer,
|
||||||
if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
|
if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
|
||||||
.{ .parent_atom_index = sym_index },
|
.{ .parent_atom_index = sym_index },
|
||||||
|
|||||||
@ -869,10 +869,11 @@ pub fn updateNav(
|
|||||||
|
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
const ip = &zcu.intern_pool;
|
const ip = &zcu.intern_pool;
|
||||||
|
const nav = ip.getNav(nav_index);
|
||||||
|
|
||||||
const nav_val = zcu.navValue(nav_index);
|
const nav_init = switch (ip.indexToKey(nav.status.resolved.val)) {
|
||||||
const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
|
.func => .none,
|
||||||
.variable => |variable| Value.fromInterned(variable.init),
|
.variable => |variable| variable.init,
|
||||||
.@"extern" => |@"extern"| {
|
.@"extern" => |@"extern"| {
|
||||||
if (ip.isFunctionType(@"extern".ty)) return;
|
if (ip.isFunctionType(@"extern".ty)) return;
|
||||||
// Extern variable gets a __got entry only
|
// Extern variable gets a __got entry only
|
||||||
@ -883,10 +884,10 @@ pub fn updateNav(
|
|||||||
sym.flags.is_extern_ptr = true;
|
sym.flags.is_extern_ptr = true;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
else => nav_val,
|
else => nav.status.resolved.val,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
|
if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
|
||||||
const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);
|
const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);
|
||||||
self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
|
self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
|
||||||
|
|
||||||
@ -900,7 +901,7 @@ pub fn updateNav(
|
|||||||
&macho_file.base,
|
&macho_file.base,
|
||||||
pt,
|
pt,
|
||||||
zcu.navSrcLoc(nav_index),
|
zcu.navSrcLoc(nav_index),
|
||||||
nav_init,
|
Value.fromInterned(nav_init),
|
||||||
&code_buffer,
|
&code_buffer,
|
||||||
if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
|
if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
|
||||||
.{ .parent_atom_index = sym_index },
|
.{ .parent_atom_index = sym_index },
|
||||||
|
|||||||
@ -448,6 +448,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
|
|||||||
const nav = ip.getNav(nav_index);
|
const nav = ip.getNav(nav_index);
|
||||||
const nav_val = zcu.navValue(nav_index);
|
const nav_val = zcu.navValue(nav_index);
|
||||||
const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
|
const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
|
||||||
|
.func => return,
|
||||||
.variable => |variable| Value.fromInterned(variable.init),
|
.variable => |variable| Value.fromInterned(variable.init),
|
||||||
.@"extern" => {
|
.@"extern" => {
|
||||||
log.debug("found extern decl: {}", .{nav.name.fmt(ip)});
|
log.debug("found extern decl: {}", .{nav.name.fmt(ip)});
|
||||||
@ -456,7 +457,7 @@ pub fn updateNav(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
|
|||||||
else => nav_val,
|
else => nav_val,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
|
if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
|
||||||
const atom_idx = try self.seeNav(pt, nav_index);
|
const atom_idx = try self.seeNav(pt, nav_index);
|
||||||
|
|
||||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||||
|
|||||||
@ -259,7 +259,7 @@ pub fn updateNav(
|
|||||||
else => .{ false, .none, nav_val },
|
else => .{ false, .none, nav_val },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (nav_init.typeOf(zcu).isFnOrHasRuntimeBits(pt)) {
|
if (nav_init.typeOf(zcu).hasRuntimeBits(pt)) {
|
||||||
const gpa = wasm_file.base.comp.gpa;
|
const gpa = wasm_file.base.comp.gpa;
|
||||||
const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index);
|
const atom_index = try zig_object.getOrCreateAtomForNav(wasm_file, pt, nav_index);
|
||||||
const atom = wasm_file.getAtomPtr(atom_index);
|
const atom = wasm_file.getAtomPtr(atom_index);
|
||||||
|
|||||||
@ -283,6 +283,7 @@ const Writer = struct {
|
|||||||
|
|
||||||
.dbg_var_ptr,
|
.dbg_var_ptr,
|
||||||
.dbg_var_val,
|
.dbg_var_val,
|
||||||
|
.dbg_arg_inline,
|
||||||
=> try w.writeDbgVar(s, inst),
|
=> try w.writeDbgVar(s, inst),
|
||||||
|
|
||||||
.struct_field_ptr => try w.writeStructField(s, inst),
|
.struct_field_ptr => try w.writeStructField(s, inst),
|
||||||
@ -358,10 +359,7 @@ const Writer = struct {
|
|||||||
try w.writeType(s, arg.ty.toType());
|
try w.writeType(s, arg.ty.toType());
|
||||||
switch (arg.name) {
|
switch (arg.name) {
|
||||||
.none => {},
|
.none => {},
|
||||||
_ => {
|
_ => try s.print(", \"{}\"", .{std.zig.fmtEscapes(arg.name.toSlice(w.air))}),
|
||||||
const name = w.air.nullTerminatedString(@intFromEnum(arg.name));
|
|
||||||
try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)});
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,8 +684,8 @@ const Writer = struct {
|
|||||||
fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||||
const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||||
try w.writeOperand(s, inst, 0, pl_op.operand);
|
try w.writeOperand(s, inst, 0, pl_op.operand);
|
||||||
const name = w.air.nullTerminatedString(pl_op.payload);
|
const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload);
|
||||||
try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)});
|
try s.print(", \"{}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||||
|
|||||||
@ -587,7 +587,7 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
db.addLldbTest(
|
db.addLldbTest(
|
||||||
"cross_module_call",
|
"inline_call",
|
||||||
target,
|
target,
|
||||||
&.{
|
&.{
|
||||||
.{
|
.{
|
||||||
@ -595,8 +595,18 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
|||||||
.source =
|
.source =
|
||||||
\\const module = @import("module");
|
\\const module = @import("module");
|
||||||
\\pub fn main() void {
|
\\pub fn main() void {
|
||||||
\\ module.foo(123);
|
\\ fa(12);
|
||||||
\\ module.bar(456);
|
\\ fb(34);
|
||||||
|
\\ module.fc(56);
|
||||||
|
\\ module.fd(78);
|
||||||
|
\\}
|
||||||
|
\\fn fa(pa: u32) void {
|
||||||
|
\\ const la = ~pa;
|
||||||
|
\\ _ = la;
|
||||||
|
\\}
|
||||||
|
\\inline fn fb(pb: u32) void {
|
||||||
|
\\ const lb = ~pb;
|
||||||
|
\\ _ = lb;
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
,
|
,
|
||||||
@ -605,34 +615,84 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
|||||||
.import = "module",
|
.import = "module",
|
||||||
.path = "module.zig",
|
.path = "module.zig",
|
||||||
.source =
|
.source =
|
||||||
\\pub fn foo(x: u32) void {
|
\\pub fn fc(pc: u32) void {
|
||||||
\\ _ = x;
|
\\ const lc = ~pc;
|
||||||
|
\\ _ = lc;
|
||||||
\\}
|
\\}
|
||||||
\\pub inline fn bar(y: u32) void {
|
\\pub inline fn fd(pd: u32) void {
|
||||||
\\ _ = y;
|
\\ const ld = ~pd;
|
||||||
|
\\ _ = ld;
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
,
|
,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
\\breakpoint set --file module.zig --source-pattern-regexp '_ = x;'
|
\\settings set frame-format 'frame #${frame.index}:{ ${module.file.basename}{\`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${line.file.basename}:${line.number}{:${line.column}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\n'
|
||||||
|
\\
|
||||||
|
\\breakpoint set --file main.zig --source-pattern-regexp '_ = la;'
|
||||||
\\process launch
|
\\process launch
|
||||||
\\source info
|
\\frame variable pa la
|
||||||
|
\\thread backtrace --count 2
|
||||||
\\breakpoint delete --force 1
|
\\breakpoint delete --force 1
|
||||||
\\
|
\\
|
||||||
\\breakpoint set --file module.zig --line 5
|
\\breakpoint set --file main.zig --source-pattern-regexp '_ = lb;'
|
||||||
\\process continue
|
\\process continue
|
||||||
\\source info
|
\\frame variable pb lb
|
||||||
|
\\thread backtrace --count 2
|
||||||
\\breakpoint delete --force 2
|
\\breakpoint delete --force 2
|
||||||
|
\\
|
||||||
|
\\breakpoint set --file module.zig --source-pattern-regexp '_ = lc;'
|
||||||
|
\\process continue
|
||||||
|
\\frame variable pc lc
|
||||||
|
\\thread backtrace --count 2
|
||||||
|
\\breakpoint delete --force 3
|
||||||
|
\\
|
||||||
|
\\breakpoint set --file module.zig --line 7
|
||||||
|
\\process continue
|
||||||
|
\\frame variable pd ld
|
||||||
|
\\thread backtrace --count 2
|
||||||
|
\\breakpoint delete --force 4
|
||||||
,
|
,
|
||||||
&.{
|
&.{
|
||||||
\\/module.zig:2:5
|
\\(lldb) frame variable pa la
|
||||||
|
\\(u32) pa = 12
|
||||||
|
\\(u32) la = 4294967283
|
||||||
|
\\(lldb) thread backtrace --count 2
|
||||||
|
\\* thread #1, name = 'inline_call', stop reason = breakpoint 1.1
|
||||||
|
\\ * frame #0: inline_call`main.fa(pa=12) at main.zig:10:5
|
||||||
|
\\ frame #1: inline_call`main.main at main.zig:3:7
|
||||||
\\(lldb) breakpoint delete --force 1
|
\\(lldb) breakpoint delete --force 1
|
||||||
\\1 breakpoints deleted; 0 breakpoint locations disabled.
|
\\1 breakpoints deleted; 0 breakpoint locations disabled.
|
||||||
,
|
,
|
||||||
\\/module.zig:5:5
|
\\(lldb) frame variable pb lb
|
||||||
|
\\(u32) pb = 34
|
||||||
|
\\(u32) lb = 4294967261
|
||||||
|
\\(lldb) thread backtrace --count 2
|
||||||
|
\\* thread #1, name = 'inline_call', stop reason = breakpoint 2.1
|
||||||
|
\\ * frame #0: inline_call`main.main [inlined] fb(pb=34) at main.zig:14:5
|
||||||
|
\\ frame #1: inline_call`main.main at main.zig:4:7
|
||||||
\\(lldb) breakpoint delete --force 2
|
\\(lldb) breakpoint delete --force 2
|
||||||
\\1 breakpoints deleted; 0 breakpoint locations disabled.
|
\\1 breakpoints deleted; 0 breakpoint locations disabled.
|
||||||
|
,
|
||||||
|
\\(lldb) frame variable pc lc
|
||||||
|
\\(u32) pc = 56
|
||||||
|
\\(u32) lc = 4294967239
|
||||||
|
\\(lldb) thread backtrace --count 2
|
||||||
|
\\* thread #1, name = 'inline_call', stop reason = breakpoint 3.1
|
||||||
|
\\ * frame #0: inline_call`module.fc(pc=56) at module.zig:3:5
|
||||||
|
\\ frame #1: inline_call`main.main at main.zig:5:14
|
||||||
|
\\(lldb) breakpoint delete --force 3
|
||||||
|
\\1 breakpoints deleted; 0 breakpoint locations disabled.
|
||||||
|
,
|
||||||
|
\\(lldb) frame variable pd ld
|
||||||
|
\\(u32) pd = 78
|
||||||
|
\\(u32) ld = 4294967217
|
||||||
|
\\(lldb) thread backtrace --count 2
|
||||||
|
\\* thread #1, name = 'inline_call', stop reason = breakpoint 4.1
|
||||||
|
\\ * frame #0: inline_call`main.main [inlined] fd(pd=78) at module.zig:7:5
|
||||||
|
\\ frame #1: inline_call`main.main at main.zig:6:14
|
||||||
|
\\(lldb) breakpoint delete --force 4
|
||||||
|
\\1 breakpoints deleted; 0 breakpoint locations disabled.
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user