mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Air: replace .dbg_inline_* with .dbg_inline_block
This prevents the possibility of not emitting a `.dbg_inline_end` instruction and reduces the allocation requirements of the backends. Closes #19093
This commit is contained in:
parent
671c2acf47
commit
aa688567f5
25
src/Air.zig
25
src/Air.zig
@ -443,12 +443,9 @@ pub const Inst = struct {
|
||||
/// Result type is always void.
|
||||
/// Uses the `dbg_stmt` field.
|
||||
dbg_stmt,
|
||||
/// Marks the start of an inline call.
|
||||
/// Uses the `ty_fn` field.
|
||||
dbg_inline_begin,
|
||||
/// Marks the end of an inline call.
|
||||
/// Uses the `ty_fn` field.
|
||||
dbg_inline_end,
|
||||
/// A block that represents an inlined function call.
|
||||
/// Uses the `ty_pl` field. Payload is `DbgInlineBlock`.
|
||||
dbg_inline_block,
|
||||
/// Marks the beginning of a local variable. The operand is a pointer pointing
|
||||
/// to the storage for the variable. The local may be a const or a var.
|
||||
/// Result type is always void.
|
||||
@ -1051,10 +1048,6 @@ pub const Inst = struct {
|
||||
// Index into a different array.
|
||||
payload: u32,
|
||||
},
|
||||
ty_fn: struct {
|
||||
ty: Ref,
|
||||
func: InternPool.Index,
|
||||
},
|
||||
br: struct {
|
||||
block_inst: Index,
|
||||
operand: Ref,
|
||||
@ -1117,6 +1110,12 @@ pub const Block = struct {
|
||||
body_len: u32,
|
||||
};
|
||||
|
||||
/// Trailing is a list of instruction indexes for every `body_len`.
|
||||
pub const DbgInlineBlock = struct {
|
||||
func: InternPool.Index,
|
||||
body_len: u32,
|
||||
};
|
||||
|
||||
/// Trailing is a list of `Inst.Ref` for every `args_len`.
|
||||
pub const Call = struct {
|
||||
args_len: u32,
|
||||
@ -1371,6 +1370,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
|
||||
|
||||
.assembly,
|
||||
.block,
|
||||
.dbg_inline_block,
|
||||
.struct_field_ptr,
|
||||
.struct_field_val,
|
||||
.slice_elem_ptr,
|
||||
@ -1448,8 +1448,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
|
||||
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
.store,
|
||||
@ -1606,8 +1604,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
|
||||
.@"try",
|
||||
.try_ptr,
|
||||
.dbg_stmt,
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
.dbg_inline_block,
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
.ret,
|
||||
|
||||
@ -327,8 +327,6 @@ pub fn categorizeOperand(
|
||||
.trap,
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
.unreach,
|
||||
.ret_addr,
|
||||
.frame_addr,
|
||||
@ -604,9 +602,19 @@ pub fn categorizeOperand(
|
||||
.assembly => {
|
||||
return .complex;
|
||||
},
|
||||
.block => {
|
||||
const extra = air.extraData(Air.Block, air_datas[@intFromEnum(inst)].ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(air.extra[extra.end..][0..extra.data.body_len]);
|
||||
.block, .dbg_inline_block => |tag| {
|
||||
const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
|
||||
const body: []const Air.Inst.Index = @ptrCast(switch (tag) {
|
||||
inline .block, .dbg_inline_block => |comptime_tag| body: {
|
||||
const extra = air.extraData(switch (comptime_tag) {
|
||||
.block => Air.Block,
|
||||
.dbg_inline_block => Air.DbgInlineBlock,
|
||||
else => unreachable,
|
||||
}, ty_pl.payload);
|
||||
break :body air.extra[extra.end..][0..extra.data.body_len];
|
||||
},
|
||||
else => unreachable,
|
||||
});
|
||||
|
||||
if (body.len == 1 and air_tags[@intFromEnum(body[0])] == .cond_br) {
|
||||
// Peephole optimization for "panic-like" conditionals, which have
|
||||
@ -963,8 +971,6 @@ fn analyzeInst(
|
||||
.ret_ptr,
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
.fence,
|
||||
.ret_addr,
|
||||
.frame_addr,
|
||||
@ -1235,7 +1241,15 @@ fn analyzeInst(
|
||||
return big.finish();
|
||||
},
|
||||
|
||||
.block => return analyzeInstBlock(a, pass, data, inst),
|
||||
inline .block, .dbg_inline_block => |comptime_tag| {
|
||||
const ty_pl = inst_datas[@intFromEnum(inst)].ty_pl;
|
||||
const extra = a.air.extraData(switch (comptime_tag) {
|
||||
.block => Air.Block,
|
||||
.dbg_inline_block => Air.DbgInlineBlock,
|
||||
else => unreachable,
|
||||
}, ty_pl.payload);
|
||||
return analyzeInstBlock(a, pass, data, inst, ty_pl.ty, @ptrCast(a.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
},
|
||||
.loop => return analyzeInstLoop(a, pass, data, inst),
|
||||
|
||||
.@"try" => return analyzeInstCondBr(a, pass, data, inst, .@"try"),
|
||||
@ -1369,12 +1383,9 @@ fn analyzeInstBlock(
|
||||
comptime pass: LivenessPass,
|
||||
data: *LivenessPassData(pass),
|
||||
inst: Air.Inst.Index,
|
||||
ty: Air.Inst.Ref,
|
||||
body: []const Air.Inst.Index,
|
||||
) !void {
|
||||
const inst_datas = a.air.instructions.items(.data);
|
||||
const ty_pl = inst_datas[@intFromEnum(inst)].ty_pl;
|
||||
const extra = a.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(a.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
|
||||
const gpa = a.gpa;
|
||||
|
||||
// We actually want to do `analyzeOperands` *first*, since our result logically doesn't
|
||||
@ -1403,7 +1414,7 @@ fn analyzeInstBlock(
|
||||
|
||||
// If the block is noreturn, block deaths not only aren't useful, they're impossible to
|
||||
// find: there could be more stuff alive after the block than before it!
|
||||
if (!a.intern_pool.isNoReturn(ty_pl.ty.toType().ip_index)) {
|
||||
if (!a.intern_pool.isNoReturn(ty.toType().toIntern())) {
|
||||
// The block kills the difference in the live sets
|
||||
const block_scope = data.block_scopes.get(inst).?;
|
||||
const num_deaths = data.live_set.count() - block_scope.live_set.count();
|
||||
|
||||
@ -29,7 +29,7 @@ const LiveMap = std.AutoHashMapUnmanaged(Air.Inst.Index, void);
|
||||
|
||||
fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
|
||||
const ip = self.intern_pool;
|
||||
const tag = self.air.instructions.items(.tag);
|
||||
const tags = self.air.instructions.items(.tag);
|
||||
const data = self.air.instructions.items(.data);
|
||||
for (body) |inst| {
|
||||
if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip)) {
|
||||
@ -37,7 +37,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (tag[@intFromEnum(inst)]) {
|
||||
switch (tags[@intFromEnum(inst)]) {
|
||||
// no operands
|
||||
.arg,
|
||||
.alloc,
|
||||
@ -46,8 +46,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
|
||||
.ret_ptr,
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
.fence,
|
||||
.ret_addr,
|
||||
.frame_addr,
|
||||
@ -431,11 +429,20 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
|
||||
}
|
||||
try self.verifyInst(inst);
|
||||
},
|
||||
.block => {
|
||||
.block, .dbg_inline_block => |tag| {
|
||||
const ty_pl = data[@intFromEnum(inst)].ty_pl;
|
||||
const block_ty = ty_pl.ty.toType();
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
const block_body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
const block_body: []const Air.Inst.Index = @ptrCast(switch (tag) {
|
||||
inline .block, .dbg_inline_block => |comptime_tag| body: {
|
||||
const extra = self.air.extraData(switch (comptime_tag) {
|
||||
.block => Air.Block,
|
||||
.dbg_inline_block => Air.DbgInlineBlock,
|
||||
else => unreachable,
|
||||
}, ty_pl.payload);
|
||||
break :body self.air.extra[extra.end..][0..extra.data.body_len];
|
||||
},
|
||||
else => unreachable,
|
||||
});
|
||||
const block_liveness = self.liveness.getBlock(inst);
|
||||
|
||||
var orig_live = try self.live.clone(self.gpa);
|
||||
|
||||
153
src/Sema.zig
153
src/Sema.zig
@ -5939,6 +5939,7 @@ fn resolveBlockBody(
|
||||
if (child_block.is_comptime) {
|
||||
return sema.resolveInlineBody(child_block, body, body_inst);
|
||||
} else {
|
||||
assert(sema.air_instructions.items(.tag)[@intFromEnum(merges.block_inst)] == .block);
|
||||
var need_debug_scope = false;
|
||||
child_block.need_debug_scope = &need_debug_scope;
|
||||
if (sema.analyzeBodyInner(child_block, body)) |_| {
|
||||
@ -6002,18 +6003,44 @@ fn resolveAnalyzedBlock(
|
||||
assert(child_block.instructions.items.len != 0);
|
||||
assert(sema.typeOf(child_block.instructions.items[child_block.instructions.items.len - 1].toRef()).isNoReturn(mod));
|
||||
|
||||
const block_tag = sema.air_instructions.items(.tag)[@intFromEnum(merges.block_inst)];
|
||||
switch (block_tag) {
|
||||
.block => {},
|
||||
.dbg_inline_block => assert(need_debug_scope),
|
||||
else => unreachable,
|
||||
}
|
||||
if (merges.results.items.len == 0) {
|
||||
// No need for a block instruction. We can put the new instructions
|
||||
// directly into the parent block.
|
||||
if (need_debug_scope) {
|
||||
// The code following this block is unreachable, as the block has no
|
||||
// merges, so we don't necessarily need to emit this as an AIR block.
|
||||
// However, we need a block *somewhere* to make the scoping correct,
|
||||
// so forward this request to the parent block.
|
||||
if (parent_block.need_debug_scope) |ptr| ptr.* = true;
|
||||
switch (block_tag) {
|
||||
.block => {
|
||||
// No need for a block instruction. We can put the new instructions
|
||||
// directly into the parent block.
|
||||
if (need_debug_scope) {
|
||||
// The code following this block is unreachable, as the block has no
|
||||
// merges, so we don't necessarily need to emit this as an AIR block.
|
||||
// However, we need a block *somewhere* to make the scoping correct,
|
||||
// so forward this request to the parent block.
|
||||
if (parent_block.need_debug_scope) |ptr| ptr.* = true;
|
||||
}
|
||||
try parent_block.instructions.appendSlice(gpa, child_block.instructions.items);
|
||||
return child_block.instructions.items[child_block.instructions.items.len - 1].toRef();
|
||||
},
|
||||
.dbg_inline_block => {
|
||||
// Create a block containing all instruction from the body.
|
||||
try parent_block.instructions.append(gpa, merges.block_inst);
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.DbgInlineBlock).Struct.fields.len +
|
||||
child_block.instructions.items.len);
|
||||
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
|
||||
.ty = .noreturn_type,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.DbgInlineBlock{
|
||||
.func = child_block.inlining.?.func,
|
||||
.body_len = @intCast(child_block.instructions.items.len),
|
||||
}),
|
||||
} };
|
||||
sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
|
||||
return merges.block_inst.toRef();
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
try parent_block.instructions.appendSlice(gpa, child_block.instructions.items);
|
||||
return child_block.instructions.items[child_block.instructions.items.len - 1].toRef();
|
||||
}
|
||||
if (merges.results.items.len == 1) {
|
||||
// If the `break` is trailing, we may be able to elide the AIR block here
|
||||
@ -6036,14 +6063,30 @@ fn resolveAnalyzedBlock(
|
||||
if (try sema.resolveValue(merges.results.items[0])) |result_val| {
|
||||
// Create a block containing all instruction from the body.
|
||||
try parent_block.instructions.append(gpa, merges.block_inst);
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
|
||||
child_block.instructions.items.len);
|
||||
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
|
||||
.ty = .void_type,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.Block{
|
||||
.body_len = @intCast(child_block.instructions.items.len),
|
||||
}),
|
||||
} };
|
||||
switch (block_tag) {
|
||||
.block => {
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
|
||||
child_block.instructions.items.len);
|
||||
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
|
||||
.ty = .void_type,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.Block{
|
||||
.body_len = @intCast(child_block.instructions.items.len),
|
||||
}),
|
||||
} };
|
||||
},
|
||||
.dbg_inline_block => {
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.DbgInlineBlock).Struct.fields.len +
|
||||
child_block.instructions.items.len);
|
||||
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
|
||||
.ty = .void_type,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.DbgInlineBlock{
|
||||
.func = child_block.inlining.?.func,
|
||||
.body_len = @intCast(child_block.instructions.items.len),
|
||||
}),
|
||||
} };
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
|
||||
// Rewrite the break to just give value {}; the value is
|
||||
// comptime-known and will be returned directly.
|
||||
@ -6079,14 +6122,30 @@ fn resolveAnalyzedBlock(
|
||||
return sema.failWithOwnedErrorMsg(child_block, msg);
|
||||
}
|
||||
const ty_inst = Air.internedToRef(resolved_ty.toIntern());
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
|
||||
child_block.instructions.items.len);
|
||||
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
|
||||
.ty = ty_inst,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.Block{
|
||||
.body_len = @intCast(child_block.instructions.items.len),
|
||||
}),
|
||||
} };
|
||||
switch (block_tag) {
|
||||
.block => {
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
|
||||
child_block.instructions.items.len);
|
||||
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
|
||||
.ty = ty_inst,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.Block{
|
||||
.body_len = @intCast(child_block.instructions.items.len),
|
||||
}),
|
||||
} };
|
||||
},
|
||||
.dbg_inline_block => {
|
||||
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.DbgInlineBlock).Struct.fields.len +
|
||||
child_block.instructions.items.len);
|
||||
sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
|
||||
.ty = ty_inst,
|
||||
.payload = sema.addExtraAssumeCapacity(Air.DbgInlineBlock{
|
||||
.func = child_block.inlining.?.func,
|
||||
.body_len = @intCast(child_block.instructions.items.len),
|
||||
}),
|
||||
} };
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
|
||||
// Now that the block has its type resolved, we need to go back into all the break
|
||||
// instructions, and insert type coercion on the operands.
|
||||
@ -7379,7 +7438,6 @@ fn analyzeCall(
|
||||
.needed_comptime_reason = "function being called at comptime must be comptime-known",
|
||||
.block_comptime_reason = comptime_reason,
|
||||
});
|
||||
const prev_fn_index = sema.func_index;
|
||||
const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
|
||||
.extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
|
||||
@as([]const u8, if (is_comptime_call) "comptime" else "inline"),
|
||||
@ -7415,9 +7473,10 @@ fn analyzeCall(
|
||||
// set to in the `Block`.
|
||||
// This block instruction will be used to capture the return value from the
|
||||
// inlined function.
|
||||
const need_debug_scope = !is_comptime_call and !block.is_typeof and !block.ownerModule().strip;
|
||||
const block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
|
||||
try sema.air_instructions.append(gpa, .{
|
||||
.tag = .block,
|
||||
.tag = if (need_debug_scope) .dbg_inline_block else .block,
|
||||
.data = undefined,
|
||||
});
|
||||
// This one is shared among sub-blocks within the same callee, but not
|
||||
@ -7584,10 +7643,7 @@ fn analyzeCall(
|
||||
}
|
||||
|
||||
new_fn_info.return_type = sema.fn_ret_ty.toIntern();
|
||||
const new_func_resolved_ty = try mod.funcType(new_fn_info);
|
||||
if (!is_comptime_call and !block.is_typeof) {
|
||||
try emitDbgInline(block, prev_fn_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
|
||||
|
||||
const zir_tags = sema.code.instructions.items(.tag);
|
||||
for (fn_info.param_body) |param| switch (zir_tags[@intFromEnum(param)]) {
|
||||
.param, .param_comptime => {
|
||||
@ -7626,21 +7682,9 @@ fn analyzeCall(
|
||||
error.ComptimeReturn => break :result inlining.comptime_result,
|
||||
else => |e| return e,
|
||||
};
|
||||
break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, false);
|
||||
break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope);
|
||||
};
|
||||
|
||||
if (!is_comptime_call and !block.is_typeof and
|
||||
sema.typeOf(result).zigTypeTag(mod) != .NoReturn)
|
||||
{
|
||||
try emitDbgInline(
|
||||
block,
|
||||
module_fn_index,
|
||||
prev_fn_index,
|
||||
mod.funcOwnerDeclPtr(sema.func_index).ty,
|
||||
.dbg_inline_end,
|
||||
);
|
||||
}
|
||||
|
||||
if (should_memoize and is_comptime_call) {
|
||||
const result_val = try sema.resolveConstValue(block, .unneeded, result, undefined);
|
||||
const result_interned = try result_val.intern2(sema.fn_ret_ty, mod);
|
||||
@ -8207,27 +8251,6 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
|
||||
}
|
||||
}
|
||||
|
||||
fn emitDbgInline(
|
||||
block: *Block,
|
||||
old_func: InternPool.Index,
|
||||
new_func: InternPool.Index,
|
||||
new_func_ty: Type,
|
||||
tag: Air.Inst.Tag,
|
||||
) CompileError!void {
|
||||
if (block.ownerModule().strip) return;
|
||||
|
||||
// Recursive inline call; no dbg_inline needed.
|
||||
if (old_func == new_func) return;
|
||||
|
||||
_ = try block.addInst(.{
|
||||
.tag = tag,
|
||||
.data = .{ .ty_fn = .{
|
||||
.ty = Air.internedToRef(new_func_ty.toIntern()),
|
||||
.func = new_func,
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const int_type = sema.code.instructions.items(.data)[@intFromEnum(inst)].int_type;
|
||||
|
||||
@ -747,7 +747,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.frame_addr => try self.airFrameAddress(inst),
|
||||
.fence => try self.airFence(),
|
||||
.cond_br => try self.airCondBr(inst),
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.fptrunc => try self.airFptrunc(inst),
|
||||
.fpext => try self.airFpext(inst),
|
||||
.intcast => try self.airIntCast(inst),
|
||||
@ -805,14 +804,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.@"try" => try self.airTry(inst),
|
||||
.try_ptr => try self.airTryPtr(inst),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
=> try self.airDbgVar(inst),
|
||||
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
=> try self.airDbgInline(inst),
|
||||
|
||||
.call => try self.airCall(inst, .auto),
|
||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||
.call_never_tail => try self.airCall(inst, .never_tail),
|
||||
@ -4621,13 +4618,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAirBookkeeping();
|
||||
}
|
||||
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
const func = mod.funcInfo(extra.data.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||
@ -5042,6 +5040,12 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {
|
||||
try self.blocks.putNoClobber(self.gpa, inst, .{
|
||||
// A block is a setup to be able to jump to the end.
|
||||
.relocs = .{},
|
||||
@ -5054,9 +5058,6 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
});
|
||||
defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);
|
||||
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
// TODO emit debug info lexical block
|
||||
try self.genBody(body);
|
||||
|
||||
|
||||
@ -733,7 +733,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.frame_addr => try self.airFrameAddress(inst),
|
||||
.fence => try self.airFence(),
|
||||
.cond_br => try self.airCondBr(inst),
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.fptrunc => try self.airFptrunc(inst),
|
||||
.fpext => try self.airFpext(inst),
|
||||
.intcast => try self.airIntCast(inst),
|
||||
@ -791,14 +790,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.@"try" => try self.airTry(inst),
|
||||
.try_ptr => try self.airTryPtr(inst),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
=> try self.airDbgVar(inst),
|
||||
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
=> try self.airDbgInline(inst),
|
||||
|
||||
.call => try self.airCall(inst, .auto),
|
||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||
.call_never_tail => try self.airCall(inst, .never_tail),
|
||||
@ -4574,13 +4571,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAirBookkeeping();
|
||||
}
|
||||
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
const func = mod.funcInfo(extra.data.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||
@ -4973,6 +4971,12 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {
|
||||
try self.blocks.putNoClobber(self.gpa, inst, .{
|
||||
// A block is a setup to be able to jump to the end.
|
||||
.relocs = .{},
|
||||
@ -4985,9 +4989,6 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
});
|
||||
defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);
|
||||
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
// TODO emit debug info lexical block
|
||||
try self.genBody(body);
|
||||
|
||||
|
||||
@ -566,7 +566,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.frame_addr => try self.airFrameAddress(inst),
|
||||
.fence => try self.airFence(),
|
||||
.cond_br => try self.airCondBr(inst),
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.fptrunc => try self.airFptrunc(inst),
|
||||
.fpext => try self.airFpext(inst),
|
||||
.intcast => try self.airIntCast(inst),
|
||||
@ -624,14 +623,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.@"try" => @panic("TODO"),
|
||||
.try_ptr => @panic("TODO"),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
=> try self.airDbgVar(inst),
|
||||
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
=> try self.airDbgInline(inst),
|
||||
|
||||
.call => try self.airCall(inst, .auto),
|
||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||
.call_never_tail => try self.airCall(inst, .never_tail),
|
||||
@ -1881,13 +1878,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAirBookkeeping();
|
||||
}
|
||||
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
const func = mod.funcInfo(extra.data.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||
@ -2060,6 +2058,12 @@ fn jump(self: *Self, index: usize) !void {
|
||||
}
|
||||
|
||||
fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {
|
||||
try self.blocks.putNoClobber(self.gpa, inst, .{
|
||||
// A block is a setup to be able to jump to the end.
|
||||
.relocs = .{},
|
||||
@ -2071,10 +2075,6 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
.mcv = MCValue{ .none = {} },
|
||||
});
|
||||
defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);
|
||||
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
// TODO emit debug info lexical block
|
||||
try self.genBody(body);
|
||||
|
||||
|
||||
@ -579,7 +579,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.frame_addr => @panic("TODO try self.airFrameAddress(inst)"),
|
||||
.fence => try self.airFence(inst),
|
||||
.cond_br => try self.airCondBr(inst),
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.fptrunc => @panic("TODO try self.airFptrunc(inst)"),
|
||||
.fpext => @panic("TODO try self.airFpext(inst)"),
|
||||
.intcast => try self.airIntCast(inst),
|
||||
@ -637,14 +636,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.@"try" => try self.airTry(inst),
|
||||
.try_ptr => @panic("TODO try self.airTryPtr(inst)"),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
=> try self.airDbgVar(inst),
|
||||
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
=> try self.airDbgInline(inst),
|
||||
|
||||
.call => try self.airCall(inst, .auto),
|
||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||
.call_never_tail => try self.airCall(inst, .never_tail),
|
||||
@ -1127,6 +1124,12 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {
|
||||
try self.blocks.putNoClobber(self.gpa, inst, .{
|
||||
// A block is a setup to be able to jump to the end.
|
||||
.relocs = .{},
|
||||
@ -1139,9 +1142,6 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
});
|
||||
defer self.blocks.getPtr(inst).?.relocs.deinit(self.gpa);
|
||||
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
// TODO emit debug info lexical block
|
||||
try self.genBody(body);
|
||||
|
||||
@ -1652,13 +1652,14 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const mod = self.bin_file.comp.module.?;
|
||||
const func = mod.funcInfo(ty_fn.func);
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
const func = mod.funcInfo(extra.data.func);
|
||||
// TODO emit debug info for function change
|
||||
_ = func;
|
||||
return self.finishAir(inst, .dead, .{ .none, .none, .none });
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
|
||||
@ -1910,16 +1910,11 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
.@"try" => func.airTry(inst),
|
||||
.try_ptr => func.airTryPtr(inst),
|
||||
|
||||
// TODO
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
=> func.finishAir(inst, .none, &.{}),
|
||||
|
||||
.dbg_stmt => func.airDbgStmt(inst),
|
||||
.dbg_inline_block => func.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr => func.airDbgVar(inst, true),
|
||||
.dbg_var_val => func.airDbgVar(inst, false),
|
||||
|
||||
.dbg_stmt => func.airDbgStmt(inst),
|
||||
|
||||
.call => func.airCall(inst, .auto),
|
||||
.call_always_tail => func.airCall(inst, .always_tail),
|
||||
.call_never_tail => func.airCall(inst, .never_tail),
|
||||
@ -3476,12 +3471,14 @@ fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 {
|
||||
}
|
||||
|
||||
fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
const mod = func.bin_file.base.comp.module.?;
|
||||
const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const block_ty = ty_pl.ty.toType();
|
||||
const wasm_block_ty = genBlockType(block_ty, mod);
|
||||
const extra = func.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @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 lowerBlock(func: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const Air.Inst.Index) InnerError!void {
|
||||
const mod = func.bin_file.base.comp.module.?;
|
||||
const wasm_block_ty = genBlockType(block_ty, mod);
|
||||
|
||||
// if wasm_block_ty is non-empty, we create a register to store the temporary value
|
||||
const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: {
|
||||
@ -6472,7 +6469,27 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
func.finishAir(inst, result, &.{ty_op.operand});
|
||||
}
|
||||
|
||||
fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
|
||||
fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
|
||||
|
||||
const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
|
||||
try func.addInst(.{ .tag = .dbg_line, .data = .{
|
||||
.payload = try func.addExtra(Mir.DbgLineColumn{
|
||||
.line = dbg_stmt.line,
|
||||
.column = dbg_stmt.column,
|
||||
}),
|
||||
} });
|
||||
func.finishAir(inst, .none, &.{});
|
||||
}
|
||||
|
||||
fn airDbgInlineBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
const ty_pl = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = func.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
// TODO
|
||||
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 {
|
||||
if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
|
||||
|
||||
const mod = func.bin_file.base.comp.module.?;
|
||||
@ -6497,19 +6514,6 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
|
||||
func.finishAir(inst, .none, &.{});
|
||||
}
|
||||
|
||||
fn airDbgStmt(func: *CodeGen, inst: Air.Inst.Index) !void {
|
||||
if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
|
||||
|
||||
const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
|
||||
try func.addInst(.{ .tag = .dbg_line, .data = .{
|
||||
.payload = try func.addExtra(Mir.DbgLineColumn{
|
||||
.line = dbg_stmt.line,
|
||||
.column = dbg_stmt.column,
|
||||
}),
|
||||
} });
|
||||
func.finishAir(inst, .none, &.{});
|
||||
}
|
||||
|
||||
fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
const pl_op = func.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
|
||||
const err_union = try func.resolveInst(pl_op.operand);
|
||||
|
||||
@ -58,6 +58,7 @@ bin_file: *link.File,
|
||||
debug_output: DebugInfoOutput,
|
||||
target: *const std.Target,
|
||||
owner: Owner,
|
||||
inline_func: InternPool.Index,
|
||||
mod: *Package.Module,
|
||||
err_msg: ?*ErrorMsg,
|
||||
args: []MCValue,
|
||||
@ -820,6 +821,7 @@ pub fn generate(
|
||||
.bin_file = bin_file,
|
||||
.debug_output = debug_output,
|
||||
.owner = .{ .func_index = func_index },
|
||||
.inline_func = func_index,
|
||||
.err_msg = null,
|
||||
.args = undefined, // populated after `resolveCallingConventionValues`
|
||||
.va_info = undefined, // populated after `resolveCallingConventionValues`
|
||||
@ -987,6 +989,7 @@ pub fn generateLazy(
|
||||
.bin_file = bin_file,
|
||||
.debug_output = debug_output,
|
||||
.owner = .{ .lazy_sym = lazy_sym },
|
||||
.inline_func = undefined,
|
||||
.err_msg = null,
|
||||
.args = undefined,
|
||||
.va_info = undefined,
|
||||
@ -2042,7 +2045,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.frame_addr => try self.airFrameAddress(inst),
|
||||
.fence => try self.airFence(inst),
|
||||
.cond_br => try self.airCondBr(inst),
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.fptrunc => try self.airFptrunc(inst),
|
||||
.fpext => try self.airFpext(inst),
|
||||
.intcast => try self.airIntCast(inst),
|
||||
@ -2098,14 +2100,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.@"try" => try self.airTry(inst),
|
||||
.try_ptr => try self.airTryPtr(inst),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
=> try self.airDbgVar(inst),
|
||||
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
=> try self.airDbgInline(inst),
|
||||
|
||||
.call => try self.airCall(inst, .auto),
|
||||
.call_always_tail => try self.airCall(inst, .always_tail),
|
||||
.call_never_tail => try self.airCall(inst, .never_tail),
|
||||
@ -12962,14 +12962,23 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
self.finishAirBookkeeping();
|
||||
}
|
||||
|
||||
fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
const old_inline_func = self.inline_func;
|
||||
defer self.inline_func = old_inline_func;
|
||||
self.inline_func = extra.data.func;
|
||||
_ = try self.addInst(.{
|
||||
.tag = .pseudo,
|
||||
.ops = .pseudo_dbg_inline_func,
|
||||
.data = .{ .func = ty_fn.func },
|
||||
.data = .{ .func = extra.data.func },
|
||||
});
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
_ = try self.addInst(.{
|
||||
.tag = .pseudo,
|
||||
.ops = .pseudo_dbg_inline_func,
|
||||
.data = .{ .func = old_inline_func },
|
||||
});
|
||||
self.finishAirBookkeeping();
|
||||
}
|
||||
|
||||
fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
|
||||
@ -13407,6 +13416,12 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
try self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void {
|
||||
// A block is a setup to be able to jump to the end.
|
||||
const inst_tracking_i = self.inst_tracking.count();
|
||||
self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(.unreach));
|
||||
@ -13415,9 +13430,6 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
try self.blocks.putNoClobber(self.gpa, inst, .{ .state = self.initRetroactiveState() });
|
||||
const liveness = self.liveness.getBlock(inst);
|
||||
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
// TODO emit debug info lexical block
|
||||
try self.genBody(body);
|
||||
|
||||
|
||||
@ -2554,9 +2554,9 @@ pub fn genTypeDecl(
|
||||
.suffix,
|
||||
.{},
|
||||
);
|
||||
try writer.writeAll("; // ");
|
||||
try writer.writeAll("; /* ");
|
||||
try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer);
|
||||
try writer.writeByte('\n');
|
||||
try writer.writeAll(" */\n");
|
||||
},
|
||||
|
||||
.anon_struct,
|
||||
@ -3215,7 +3215,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
|
||||
.assembly => try airAsm(f, inst),
|
||||
.block => try airBlock(f, inst),
|
||||
.bitcast => try airBitcast(f, inst),
|
||||
.dbg_stmt => try airDbgStmt(f, inst),
|
||||
.intcast => try airIntCast(f, inst),
|
||||
.trunc => try airTrunc(f, inst),
|
||||
.int_from_bool => try airIntFromBool(f, inst),
|
||||
@ -3259,13 +3258,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
|
||||
.@"try" => try airTry(f, inst),
|
||||
.try_ptr => try airTryPtr(f, inst),
|
||||
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
=> try airDbgVar(f, inst),
|
||||
|
||||
.dbg_inline_begin,
|
||||
.dbg_inline_end,
|
||||
=> try airDbgInline(f, inst),
|
||||
.dbg_stmt => try airDbgStmt(f, inst),
|
||||
.dbg_inline_block => try airDbgInlineBlock(f, inst),
|
||||
.dbg_var_ptr, .dbg_var_val => try airDbgVar(f, inst),
|
||||
|
||||
.call => try airCall(f, inst, .auto),
|
||||
.call_always_tail => .none,
|
||||
@ -4497,15 +4492,16 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const ty_fn = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const mod = f.object.dg.module;
|
||||
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
const owner_decl = mod.funcOwnerDeclPtr(extra.data.func);
|
||||
const writer = f.object.writer();
|
||||
const owner_decl = mod.funcOwnerDeclPtr(ty_fn.func);
|
||||
try writer.print("/* dbg func:{s} */\n", .{
|
||||
mod.intern_pool.stringToSlice(owner_decl.name),
|
||||
});
|
||||
return .none;
|
||||
try writer.writeAll("/* ");
|
||||
try owner_decl.renderFullyQualifiedName(mod, writer);
|
||||
try writer.writeAll(" */ ");
|
||||
return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
@ -4522,10 +4518,13 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
}
|
||||
|
||||
fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const mod = f.object.dg.module;
|
||||
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = f.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue {
|
||||
const mod = f.object.dg.module;
|
||||
const liveness_block = f.liveness.getBlock(inst);
|
||||
|
||||
const block_id: usize = f.next_block_index;
|
||||
|
||||
@ -4762,11 +4762,7 @@ pub const FuncGen = struct {
|
||||
file: Builder.Metadata,
|
||||
scope: Builder.Metadata,
|
||||
|
||||
inlined: std.ArrayListUnmanaged(struct {
|
||||
base_line: u32,
|
||||
location: Builder.DebugLocation,
|
||||
scope: Builder.Metadata,
|
||||
}) = .{},
|
||||
inlined: Builder.DebugLocation = .no_location,
|
||||
|
||||
base_line: u32,
|
||||
prev_dbg_line: c_uint,
|
||||
@ -4811,7 +4807,6 @@ pub const FuncGen = struct {
|
||||
|
||||
fn deinit(self: *FuncGen) void {
|
||||
self.wip.deinit();
|
||||
self.inlined.deinit(self.gpa);
|
||||
self.func_inst_table.deinit(self.gpa);
|
||||
self.blocks.deinit(self.gpa);
|
||||
}
|
||||
@ -5107,8 +5102,7 @@ pub const FuncGen = struct {
|
||||
|
||||
.unreach => try self.airUnreach(inst),
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_inline_begin => try self.airDbgInlineBegin(inst),
|
||||
.dbg_inline_end => try self.airDbgInlineEnd(inst),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr => try self.airDbgVarPtr(inst),
|
||||
.dbg_var_val => try self.airDbgVarVal(inst),
|
||||
|
||||
@ -5126,17 +5120,81 @@ pub const FuncGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn genBodyDebugScope(self: *FuncGen, body: []const Air.Inst.Index) Error!void {
|
||||
fn genBodyDebugScope(self: *FuncGen, maybe_inline_func: ?InternPool.Index, body: []const Air.Inst.Index) Error!void {
|
||||
if (self.wip.strip) return self.genBody(body);
|
||||
|
||||
const old_file = self.file;
|
||||
const old_inlined = self.inlined;
|
||||
const old_base_line = self.base_line;
|
||||
const old_scope = self.scope;
|
||||
defer if (maybe_inline_func) |_| {
|
||||
self.wip.debug_location = self.inlined;
|
||||
self.file = old_file;
|
||||
self.inlined = old_inlined;
|
||||
self.base_line = old_base_line;
|
||||
};
|
||||
defer self.scope = old_scope;
|
||||
|
||||
if (maybe_inline_func) |inline_func| {
|
||||
const o = self.dg.object;
|
||||
const zcu = o.module;
|
||||
|
||||
const func = zcu.funcInfo(inline_func);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
const namespace = zcu.namespacePtr(decl.src_namespace);
|
||||
const owner_mod = namespace.file_scope.mod;
|
||||
|
||||
self.file = try o.getDebugFile(namespace.file_scope);
|
||||
|
||||
const line_number = decl.src_line + 1;
|
||||
self.inlined = self.wip.debug_location;
|
||||
|
||||
const fqn = try decl.fullyQualifiedName(zcu);
|
||||
|
||||
const is_internal_linkage = !zcu.decl_exports.contains(decl_index);
|
||||
const fn_ty = try zcu.funcType(.{
|
||||
.param_types = &.{},
|
||||
.return_type = .void_type,
|
||||
});
|
||||
|
||||
self.scope = try o.builder.debugSubprogram(
|
||||
self.file,
|
||||
try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)),
|
||||
try o.builder.metadataString(zcu.intern_pool.stringToSlice(fqn)),
|
||||
line_number,
|
||||
line_number + func.lbrace_line,
|
||||
try o.lowerDebugType(fn_ty),
|
||||
.{
|
||||
.di_flags = .{ .StaticMember = true },
|
||||
.sp_flags = .{
|
||||
.Optimized = owner_mod.optimize_mode != .Debug,
|
||||
.Definition = true,
|
||||
.LocalToUnit = is_internal_linkage,
|
||||
},
|
||||
},
|
||||
o.debug_compile_unit,
|
||||
);
|
||||
|
||||
self.base_line = decl.src_line;
|
||||
const inlined_at_location = try self.wip.debug_location.toMetadata(&o.builder);
|
||||
self.wip.debug_location = .{
|
||||
.location = .{
|
||||
.line = line_number,
|
||||
.column = 0,
|
||||
.scope = self.scope,
|
||||
.inlined_at = inlined_at_location,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
self.scope = try self.dg.object.builder.debugLexicalBlock(
|
||||
old_scope,
|
||||
self.scope,
|
||||
self.file,
|
||||
self.prev_dbg_line,
|
||||
self.prev_dbg_column,
|
||||
);
|
||||
try self.genBody(body);
|
||||
self.scope = old_scope;
|
||||
}
|
||||
|
||||
pub const CallAttr = enum {
|
||||
@ -5820,15 +5878,23 @@ pub const FuncGen = struct {
|
||||
}
|
||||
|
||||
fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||
const o = self.dg.object;
|
||||
const mod = o.module;
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
return self.lowerBlock(inst, null, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(
|
||||
self: *FuncGen,
|
||||
inst: Air.Inst.Index,
|
||||
maybe_inline_func: ?InternPool.Index,
|
||||
body: []const Air.Inst.Index,
|
||||
) !Builder.Value {
|
||||
const o = self.dg.object;
|
||||
const mod = o.module;
|
||||
const inst_ty = self.typeOfIndex(inst);
|
||||
|
||||
if (inst_ty.isNoReturn(mod)) {
|
||||
try self.genBodyDebugScope(body);
|
||||
try self.genBodyDebugScope(maybe_inline_func, body);
|
||||
return .none;
|
||||
}
|
||||
|
||||
@ -5844,7 +5910,7 @@ pub const FuncGen = struct {
|
||||
});
|
||||
defer assert(self.blocks.remove(inst));
|
||||
|
||||
try self.genBodyDebugScope(body);
|
||||
try self.genBodyDebugScope(maybe_inline_func, body);
|
||||
|
||||
self.wip.cursor = .{ .block = parent_bb };
|
||||
|
||||
@ -5903,10 +5969,10 @@ pub const FuncGen = struct {
|
||||
_ = try self.wip.brCond(cond, then_block, else_block);
|
||||
|
||||
self.wip.cursor = .{ .block = then_block };
|
||||
try self.genBodyDebugScope(then_body);
|
||||
try self.genBodyDebugScope(null, then_body);
|
||||
|
||||
self.wip.cursor = .{ .block = else_block };
|
||||
try self.genBodyDebugScope(else_body);
|
||||
try self.genBodyDebugScope(null, else_body);
|
||||
|
||||
// No need to reset the insert cursor since this instruction is noreturn.
|
||||
return .none;
|
||||
@ -5987,7 +6053,7 @@ pub const FuncGen = struct {
|
||||
_ = try fg.wip.brCond(is_err, return_block, continue_block);
|
||||
|
||||
fg.wip.cursor = .{ .block = return_block };
|
||||
try fg.genBodyDebugScope(body);
|
||||
try fg.genBodyDebugScope(null, body);
|
||||
|
||||
fg.wip.cursor = .{ .block = continue_block };
|
||||
}
|
||||
@ -6060,13 +6126,13 @@ pub const FuncGen = struct {
|
||||
}
|
||||
|
||||
self.wip.cursor = .{ .block = case_block };
|
||||
try self.genBodyDebugScope(case_body);
|
||||
try self.genBodyDebugScope(null, case_body);
|
||||
}
|
||||
|
||||
self.wip.cursor = .{ .block = else_block };
|
||||
const else_body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra_index..][0..switch_br.data.else_body_len]);
|
||||
if (else_body.len != 0) {
|
||||
try self.genBodyDebugScope(else_body);
|
||||
try self.genBodyDebugScope(null, else_body);
|
||||
} else {
|
||||
_ = try self.wip.@"unreachable"();
|
||||
}
|
||||
@ -6085,7 +6151,7 @@ pub const FuncGen = struct {
|
||||
_ = try self.wip.br(loop_block);
|
||||
|
||||
self.wip.cursor = .{ .block = loop_block };
|
||||
try self.genBodyDebugScope(body);
|
||||
try self.genBodyDebugScope(null, body);
|
||||
|
||||
// TODO instead of this logic, change AIR to have the property that
|
||||
// every block is guaranteed to end with a noreturn instruction.
|
||||
@ -6592,96 +6658,22 @@ pub const FuncGen = struct {
|
||||
self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1);
|
||||
self.prev_dbg_column = @intCast(dbg_stmt.column + 1);
|
||||
|
||||
const inlined_at_location = if (self.inlined.getLastOrNull()) |inlined|
|
||||
try inlined.location.toMetadata(self.wip.builder)
|
||||
else
|
||||
.none;
|
||||
|
||||
self.wip.debug_location = .{
|
||||
.location = .{
|
||||
.line = self.prev_dbg_line,
|
||||
.column = self.prev_dbg_column,
|
||||
.scope = self.scope,
|
||||
.inlined_at = inlined_at_location,
|
||||
.inlined_at = try self.inlined.toMetadata(self.wip.builder),
|
||||
},
|
||||
};
|
||||
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||
const o = self.dg.object;
|
||||
const zcu = o.module;
|
||||
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
const func = zcu.funcInfo(ty_fn.func);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
const namespace = zcu.namespacePtr(decl.src_namespace);
|
||||
const owner_mod = namespace.file_scope.mod;
|
||||
|
||||
self.file = try o.getDebugFile(namespace.file_scope);
|
||||
|
||||
const line_number = decl.src_line + 1;
|
||||
try self.inlined.append(self.gpa, .{
|
||||
.location = self.wip.debug_location,
|
||||
.scope = self.scope,
|
||||
.base_line = self.base_line,
|
||||
});
|
||||
|
||||
const fqn = try decl.fullyQualifiedName(zcu);
|
||||
|
||||
const is_internal_linkage = !zcu.decl_exports.contains(decl_index);
|
||||
const fn_ty = try zcu.funcType(.{
|
||||
.param_types = &.{},
|
||||
.return_type = .void_type,
|
||||
});
|
||||
|
||||
self.scope = try o.builder.debugSubprogram(
|
||||
self.file,
|
||||
try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)),
|
||||
try o.builder.metadataString(zcu.intern_pool.stringToSlice(fqn)),
|
||||
line_number,
|
||||
line_number + func.lbrace_line,
|
||||
try o.lowerDebugType(fn_ty),
|
||||
.{
|
||||
.di_flags = .{ .StaticMember = true },
|
||||
.sp_flags = .{
|
||||
.Optimized = owner_mod.optimize_mode != .Debug,
|
||||
.Definition = true,
|
||||
.LocalToUnit = is_internal_linkage,
|
||||
},
|
||||
},
|
||||
o.debug_compile_unit,
|
||||
);
|
||||
|
||||
self.base_line = decl.src_line;
|
||||
const inlined_at_location = try self.wip.debug_location.toMetadata(&o.builder);
|
||||
self.wip.debug_location = .{
|
||||
.location = .{
|
||||
.line = line_number,
|
||||
.column = 0,
|
||||
.scope = self.scope,
|
||||
.inlined_at = inlined_at_location,
|
||||
},
|
||||
};
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
|
||||
const o = self.dg.object;
|
||||
|
||||
const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
|
||||
const mod = o.module;
|
||||
const decl = mod.funcOwnerDeclPtr(ty_fn.func);
|
||||
self.file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope);
|
||||
|
||||
const old = self.inlined.pop();
|
||||
self.scope = old.scope;
|
||||
self.base_line = old.base_line;
|
||||
self.wip.debug_location = old.location;
|
||||
return .none;
|
||||
fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
return self.lowerBlock(inst, extra.data.func, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||
|
||||
@ -208,6 +208,7 @@ pub const Object = struct {
|
||||
false => .{ .unstructured = .{} },
|
||||
},
|
||||
.current_block_label = undefined,
|
||||
.base_line = decl.src_line,
|
||||
};
|
||||
defer decl_gen.deinit();
|
||||
|
||||
@ -321,9 +322,8 @@ const DeclGen = struct {
|
||||
/// The code (prologue and body) for the function we are currently generating code for.
|
||||
func: SpvModule.Fn = .{},
|
||||
|
||||
/// Stack of the base offsets of the current decl, which is what `dbg_stmt` is relative to.
|
||||
/// This is a stack to keep track of inline functions.
|
||||
base_line_stack: std.ArrayListUnmanaged(u32) = .{},
|
||||
/// The base offset of the current decl, which is what `dbg_stmt` is relative to.
|
||||
base_line: u32,
|
||||
|
||||
/// If `gen` returned `Error.CodegenFail`, this contains an explanatory message.
|
||||
/// Memory is owned by `module.gpa`.
|
||||
@ -401,7 +401,6 @@ const DeclGen = struct {
|
||||
self.wip_pointers.deinit(self.gpa);
|
||||
self.control_flow.deinit(self.gpa);
|
||||
self.func.deinit(self.gpa);
|
||||
self.base_line_stack.deinit(self.gpa);
|
||||
}
|
||||
|
||||
/// Return the target which we are currently compiling for.
|
||||
@ -1959,8 +1958,6 @@ const DeclGen = struct {
|
||||
|
||||
const decl_id = self.spv.declPtr(spv_decl_index).result_id;
|
||||
|
||||
try self.base_line_stack.append(self.gpa, decl.src_line);
|
||||
|
||||
if (decl.val.getFunction(mod)) |_| {
|
||||
assert(decl.ty.zigTypeTag(mod) == .Fn);
|
||||
const fn_info = mod.typeToFunc(decl.ty).?;
|
||||
@ -2317,8 +2314,7 @@ const DeclGen = struct {
|
||||
.unreach, .trap => return self.airUnreach(),
|
||||
|
||||
.dbg_stmt => return self.airDbgStmt(inst),
|
||||
.dbg_inline_begin => return self.airDbgInlineBegin(inst),
|
||||
.dbg_inline_end => return self.airDbgInlineEnd(inst),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr, .dbg_var_val => return self.airDbgVar(inst),
|
||||
|
||||
.unwrap_errunion_err => try self.airErrUnionErr(inst),
|
||||
@ -4311,6 +4307,12 @@ const DeclGen = struct {
|
||||
}
|
||||
|
||||
fn airBlock(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
|
||||
const inst_datas = self.air.instructions.items(.data);
|
||||
const extra = self.air.extraData(Air.Block, inst_datas[@intFromEnum(inst)].ty_pl.payload);
|
||||
return self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn lowerBlock(self: *DeclGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) !?IdRef {
|
||||
// In AIR, a block doesn't really define an entry point like a block, but
|
||||
// more like a scope that breaks can jump out of and "return" a value from.
|
||||
// This cannot be directly modelled in SPIR-V, so in a block instruction,
|
||||
@ -4320,10 +4322,6 @@ const DeclGen = struct {
|
||||
|
||||
const mod = self.module;
|
||||
const ty = self.typeOfIndex(inst);
|
||||
const inst_datas = self.air.instructions.items(.data);
|
||||
const extra = self.air.extraData(Air.Block, inst_datas[@intFromEnum(inst)].ty_pl.payload);
|
||||
const body: []const Air.Inst.Index =
|
||||
@ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
const have_block_result = ty.isFnOrHasRuntimeBitsIgnoreComptime(mod);
|
||||
|
||||
const cf = switch (self.control_flow) {
|
||||
@ -5157,25 +5155,22 @@ const DeclGen = struct {
|
||||
const decl = mod.declPtr(self.decl_index);
|
||||
const path = decl.getFileScope(mod).sub_file_path;
|
||||
const src_fname_id = try self.spv.resolveSourceFileName(path);
|
||||
const base_line = self.base_line_stack.getLast();
|
||||
try self.func.body.emit(self.spv.gpa, .OpLine, .{
|
||||
.file = src_fname_id,
|
||||
.line = base_line + dbg_stmt.line + 1,
|
||||
.line = self.base_line + dbg_stmt.line + 1,
|
||||
.column = dbg_stmt.column + 1,
|
||||
});
|
||||
}
|
||||
|
||||
fn airDbgInlineBegin(self: *DeclGen, inst: Air.Inst.Index) !void {
|
||||
fn airDbgInlineBlock(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
|
||||
const mod = self.module;
|
||||
const fn_ty = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
const decl_index = mod.funcInfo(fn_ty.func).owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
try self.base_line_stack.append(self.gpa, decl.src_line);
|
||||
}
|
||||
|
||||
fn airDbgInlineEnd(self: *DeclGen, inst: Air.Inst.Index) !void {
|
||||
_ = inst;
|
||||
_ = self.base_line_stack.pop();
|
||||
const inst_datas = self.air.instructions.items(.data);
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, inst_datas[@intFromEnum(inst)].ty_pl.payload);
|
||||
const decl = mod.funcOwnerDeclPtr(extra.data.func);
|
||||
const old_base_line = self.base_line;
|
||||
defer self.base_line = old_base_line;
|
||||
self.base_line = decl.src_line;
|
||||
return self.lowerBlock(inst, @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]));
|
||||
}
|
||||
|
||||
fn airDbgVar(self: *DeclGen, inst: Air.Inst.Index) !void {
|
||||
|
||||
@ -260,7 +260,7 @@ const Writer = struct {
|
||||
.c_va_copy,
|
||||
=> try w.writeTyOp(s, inst),
|
||||
|
||||
.block => try w.writeBlock(s, inst),
|
||||
.block, .dbg_inline_block => try w.writeBlock(s, tag, inst),
|
||||
|
||||
.loop => try w.writeLoop(s, inst),
|
||||
|
||||
@ -292,7 +292,6 @@ const Writer = struct {
|
||||
.assembly => try w.writeAssembly(s, inst),
|
||||
.dbg_stmt => try w.writeDbgStmt(s, inst),
|
||||
|
||||
.dbg_inline_begin, .dbg_inline_end => try w.writeDbgInline(s, inst),
|
||||
.aggregate_init => try w.writeAggregateInit(s, inst),
|
||||
.union_init => try w.writeUnionInit(s, inst),
|
||||
.br => try w.writeBr(s, inst),
|
||||
@ -367,17 +366,34 @@ const Writer = struct {
|
||||
try w.writeOperand(s, inst, 0, ty_op.operand);
|
||||
}
|
||||
|
||||
fn writeBlock(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
fn writeBlock(w: *Writer, s: anytype, tag: Air.Inst.Tag, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = w.air.extraData(Air.Block, ty_pl.payload);
|
||||
const body: []const Air.Inst.Index = @ptrCast(w.air.extra[extra.end..][0..extra.data.body_len]);
|
||||
try w.writeType(s, ty_pl.ty.toType());
|
||||
const body: []const Air.Inst.Index = @ptrCast(switch (tag) {
|
||||
inline .block, .dbg_inline_block => |comptime_tag| body: {
|
||||
const extra = w.air.extraData(switch (comptime_tag) {
|
||||
.block => Air.Block,
|
||||
.dbg_inline_block => Air.DbgInlineBlock,
|
||||
else => unreachable,
|
||||
}, ty_pl.payload);
|
||||
switch (comptime_tag) {
|
||||
.block => {},
|
||||
.dbg_inline_block => {
|
||||
try s.writeAll(", ");
|
||||
try w.writeInstRef(s, Air.internedToRef(extra.data.func), false);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
break :body w.air.extra[extra.end..][0..extra.data.body_len];
|
||||
},
|
||||
else => unreachable,
|
||||
});
|
||||
if (w.skip_body) return s.writeAll(", ...");
|
||||
const liveness_block = if (w.liveness) |liveness|
|
||||
liveness.getBlock(inst)
|
||||
else
|
||||
Liveness.BlockSlices{ .deaths = &.{} };
|
||||
|
||||
try w.writeType(s, ty_pl.ty.toType());
|
||||
if (w.skip_body) return s.writeAll(", ...");
|
||||
try s.writeAll(", {\n");
|
||||
const old_indent = w.indent;
|
||||
w.indent += 2;
|
||||
@ -661,13 +677,6 @@ const Writer = struct {
|
||||
try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
|
||||
}
|
||||
|
||||
fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const ty_fn = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
|
||||
const func_index = ty_fn.func;
|
||||
const owner_decl = w.module.funcOwnerDeclPtr(func_index);
|
||||
try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
|
||||
}
|
||||
|
||||
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;
|
||||
try w.writeOperand(s, inst, 0, pl_op.operand);
|
||||
|
||||
@ -913,3 +913,20 @@ test "switch prong captures range" {
|
||||
S.a(&arr, 5);
|
||||
try expect(arr[5] == 5);
|
||||
}
|
||||
|
||||
test "prong with inline call to unreachable" {
|
||||
const U = union(enum) {
|
||||
void: void,
|
||||
bool: bool,
|
||||
|
||||
inline fn unreach() noreturn {
|
||||
unreachable;
|
||||
}
|
||||
};
|
||||
var u: U = undefined;
|
||||
u = .{ .bool = true };
|
||||
switch (u) {
|
||||
.void => U.unreach(),
|
||||
.bool => |ok| try expect(ok),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user