mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
LLVM Builder: Emit debug info and metadata
This commit is contained in:
parent
d35080b792
commit
626c3f7959
@ -14466,19 +14466,449 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
|
||||
try constants_block.end();
|
||||
}
|
||||
|
||||
const MetadataAdapter = struct {
|
||||
builder: *const Builder,
|
||||
constant_adapter: ConstantAdapter,
|
||||
|
||||
pub fn init(
|
||||
builder: *const Builder,
|
||||
const_adapter: ConstantAdapter,
|
||||
) @This() {
|
||||
return .{
|
||||
.builder = builder,
|
||||
.constant_adapter = const_adapter,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(adapter: @This(), value: anytype, comptime field_name: []const u8) @TypeOf(value) {
|
||||
_ = field_name;
|
||||
const Ty = @TypeOf(value);
|
||||
return switch (Ty) {
|
||||
Metadata => @enumFromInt(adapter.getMetadataIndex(value)),
|
||||
MetadataString => @enumFromInt(adapter.getMetadataStringIndex(value)),
|
||||
Constant => @enumFromInt(adapter.constant_adapter.getConstantIndex(value)),
|
||||
else => value,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getMetadataIndex(adapter: @This(), metadata: Metadata) u32 {
|
||||
if (metadata == .none) return 0;
|
||||
return @intCast(adapter.builder.metadata_strings.count() +
|
||||
@intFromEnum(metadata.unwrap(adapter.builder)));
|
||||
}
|
||||
|
||||
pub fn getMetadataStringIndex(_: @This(), metadata_string: MetadataString) u32 {
|
||||
return @intFromEnum(metadata_string) + 1;
|
||||
}
|
||||
};
|
||||
|
||||
const metadata_adapter = MetadataAdapter.init(self, constant_adapter);
|
||||
|
||||
// METADATA_BLOCK
|
||||
if (!self.strip) {
|
||||
const MetadataBlock = IR.MetadataBlock;
|
||||
var metadata_block = try module_block.enterSubBlock(MetadataBlock);
|
||||
|
||||
const MetadataBlockWriter = @TypeOf(metadata_block);
|
||||
|
||||
// Emit all MetadataStrings
|
||||
{
|
||||
const strings_offset, const strings_size = blk: {
|
||||
var strings_offset: u32 = 0;
|
||||
var strings_size: u32 = 0;
|
||||
for (self.metadata_strings.keys()) |metadata_string| {
|
||||
if (metadata_string.slice(self)) |slice| {
|
||||
strings_offset += bitcode.bitsVBR(@as(u32, @intCast(slice.len)), 6);
|
||||
strings_size += @intCast(slice.len * 8);
|
||||
}
|
||||
}
|
||||
break :blk .{
|
||||
std.mem.alignForward(u32, strings_offset, 32) / 8,
|
||||
std.mem.alignForward(u32, strings_size, 32) / 8,
|
||||
};
|
||||
};
|
||||
|
||||
try bitcode.writeBits(
|
||||
comptime MetadataBlockWriter.abbrevId(MetadataBlock.Strings),
|
||||
MetadataBlockWriter.abbrev_len,
|
||||
);
|
||||
|
||||
try bitcode.writeVBR(@as(u32, @intCast(self.metadata_strings.count())), 6);
|
||||
try bitcode.writeVBR(strings_offset, 6);
|
||||
|
||||
try bitcode.writeVBR(strings_size + strings_offset, 6);
|
||||
|
||||
try bitcode.alignTo32();
|
||||
|
||||
for (self.metadata_strings.keys()) |metadata_string| {
|
||||
if (metadata_string.slice(self)) |slice|
|
||||
try bitcode.writeVBR(@as(u32, @intCast(slice.len)), 6);
|
||||
}
|
||||
|
||||
try bitcode.alignTo32();
|
||||
|
||||
for (self.metadata_strings.keys()) |metadata_string| {
|
||||
if (metadata_string.slice(self)) |slice| {
|
||||
for (slice) |c| {
|
||||
try bitcode.writeBits(c, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try bitcode.alignTo32();
|
||||
}
|
||||
|
||||
for (1..self.metadata_items.len) |metadata_index| {
|
||||
const tag = self.metadata_items.items(.tag)[metadata_index];
|
||||
const data = self.metadata_items.items(.data)[metadata_index];
|
||||
switch (tag) {
|
||||
.none => unreachable,
|
||||
.file => {
|
||||
const extra = self.metadataExtraData(Metadata.File, data);
|
||||
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.File{
|
||||
.name = extra.name,
|
||||
.path = extra.path,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.compile_unit, .@"compile_unit optimized" => |kind| {
|
||||
const is_optimized = kind == .@"compile_unit optimized";
|
||||
const extra = self.metadataExtraData(Metadata.CompileUnit, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.CompileUnit{
|
||||
.file = extra.file,
|
||||
.producer = extra.producer,
|
||||
.is_optimized = is_optimized,
|
||||
.enums = extra.enums,
|
||||
.globals = extra.globals,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.subprogram,
|
||||
.@"subprogram optimized",
|
||||
.@"subprogram local",
|
||||
.@"subprogram definition",
|
||||
.@"subprogram optimized local",
|
||||
.@"subprogram optimized definition",
|
||||
.@"subprogram optimized local definition",
|
||||
.@"subprogram local definition",
|
||||
=> |kind| {
|
||||
const sp_flags: u32 = switch (kind) {
|
||||
.subprogram => 0,
|
||||
.@"subprogram optimized" => 1 << 4,
|
||||
.@"subprogram local" => 1 << 2,
|
||||
.@"subprogram definition" => 1 << 3,
|
||||
.@"subprogram optimized local" => (1 << 4) | (1 << 2),
|
||||
.@"subprogram optimized definition" => (1 << 4) | (1 << 3),
|
||||
.@"subprogram optimized local definition" => (1 << 4) | (1 << 2) | (1 << 3),
|
||||
.@"subprogram local definition" => (1 << 2) | (1 << 3),
|
||||
else => unreachable,
|
||||
};
|
||||
const extra = self.metadataExtraData(Metadata.Subprogram, data);
|
||||
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.Subprogram{
|
||||
.scope = extra.file,
|
||||
.name = extra.name,
|
||||
.linkage_name = extra.linkage_name,
|
||||
.file = extra.file,
|
||||
.line = extra.line,
|
||||
.ty = Metadata.none, //extra.ty,
|
||||
.scope_line = extra.scope_line,
|
||||
.sp_flags = sp_flags,
|
||||
.flags = extra.debug_info_flags,
|
||||
.compile_unit = extra.compile_unit,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.lexical_block => {
|
||||
const extra = self.metadataExtraData(Metadata.LexicalBlock, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.LexicalBlock{
|
||||
.scope = extra.scope,
|
||||
.file = extra.file,
|
||||
.line = extra.line,
|
||||
.column = extra.column,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.location => {
|
||||
const extra = self.metadataExtraData(Metadata.Location, data);
|
||||
std.debug.assert(extra.scope != Metadata.none);
|
||||
try metadata_block.writeAbbrev(MetadataBlock.Location{
|
||||
.line = extra.line,
|
||||
.column = extra.column,
|
||||
.scope = metadata_adapter.getMetadataIndex(extra.scope) - 1,
|
||||
.inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(extra.inlined_at)),
|
||||
});
|
||||
},
|
||||
.basic_bool_type,
|
||||
.basic_unsigned_type,
|
||||
.basic_signed_type,
|
||||
.basic_float_type,
|
||||
=> |kind| {
|
||||
const extra = self.metadataExtraData(Metadata.BasicType, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.BasicType{
|
||||
.name = extra.name,
|
||||
.size_in_bits = @as(u64, extra.size_in_bits_lo) | @as(u64, extra.size_in_bits_hi) << 32,
|
||||
.encoding = switch (kind) {
|
||||
.basic_bool_type => std.dwarf.ATE.boolean,
|
||||
.basic_unsigned_type => std.dwarf.ATE.unsigned,
|
||||
.basic_signed_type => std.dwarf.ATE.signed,
|
||||
.basic_float_type => std.dwarf.ATE.float,
|
||||
else => unreachable,
|
||||
},
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.composite_struct_type,
|
||||
.composite_union_type,
|
||||
.composite_enumeration_type,
|
||||
.composite_array_type,
|
||||
=> |kind| {
|
||||
const extra = self.metadataExtraData(Metadata.CompositeType, data);
|
||||
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.CompositeType{
|
||||
.tag = switch (kind) {
|
||||
.composite_struct_type => std.dwarf.TAG.structure_type,
|
||||
.composite_union_type => std.dwarf.TAG.union_type,
|
||||
.composite_enumeration_type => std.dwarf.TAG.enumeration_type,
|
||||
.composite_array_type => std.dwarf.TAG.array_type,
|
||||
else => unreachable,
|
||||
},
|
||||
.name = extra.name,
|
||||
.file = extra.file,
|
||||
.line = extra.line,
|
||||
.scope = extra.scope,
|
||||
.underlying_type = extra.underlying_type,
|
||||
.size_in_bits = @as(u64, extra.size_in_bits_lo) | @as(u64, extra.size_in_bits_hi) << 32,
|
||||
.align_in_bits = @as(u64, extra.align_in_bits_lo) | @as(u64, extra.align_in_bits_hi) << 32,
|
||||
.elements = extra.fields_tuple,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.derived_pointer_type,
|
||||
.derived_member_type,
|
||||
=> |kind| {
|
||||
const extra = self.metadataExtraData(Metadata.DerivedType, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{
|
||||
.tag = switch (kind) {
|
||||
.derived_pointer_type => std.dwarf.TAG.pointer_type,
|
||||
.derived_member_type => std.dwarf.TAG.member,
|
||||
else => unreachable,
|
||||
},
|
||||
.name = extra.name,
|
||||
.file = extra.file,
|
||||
.line = extra.line,
|
||||
.scope = extra.scope,
|
||||
.underlying_type = extra.underlying_type,
|
||||
.size_in_bits = @as(u64, extra.size_in_bits_lo) | @as(u64, extra.size_in_bits_hi) << 32,
|
||||
.align_in_bits = @as(u64, extra.align_in_bits_lo) | @as(u64, extra.align_in_bits_hi) << 32,
|
||||
.offset_in_bits = @as(u64, extra.offset_in_bits_lo) | @as(u64, extra.offset_in_bits_hi) << 32,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.subroutine_type => {
|
||||
const extra = self.metadataExtraData(Metadata.SubroutineType, data);
|
||||
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.SubroutineType{
|
||||
.types = extra.types_tuple,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.enumerator_unsigned,
|
||||
.enumerator_signed_positive,
|
||||
.enumerator_signed_negative,
|
||||
=> |kind| {
|
||||
const positive = switch (kind) {
|
||||
.enumerator_unsigned,
|
||||
.enumerator_signed_positive,
|
||||
=> true,
|
||||
.enumerator_signed_negative => false,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const unsigned = switch (kind) {
|
||||
.enumerator_unsigned => true,
|
||||
.enumerator_signed_positive,
|
||||
.enumerator_signed_negative,
|
||||
=> false,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const extra = self.metadataExtraData(Metadata.Enumerator, data);
|
||||
|
||||
const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len];
|
||||
|
||||
const bigint = std.math.big.int.Const{
|
||||
.limbs = limbs,
|
||||
.positive = positive,
|
||||
};
|
||||
|
||||
if (extra.bit_width <= 64) {
|
||||
const val = bigint.to(i64) catch unreachable;
|
||||
const emit_val = if (positive)
|
||||
@shlWithOverflow(val, 1)[0]
|
||||
else
|
||||
(@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.Enumerator{
|
||||
.flags = .{
|
||||
.unsigned = unsigned,
|
||||
.bigint = false,
|
||||
},
|
||||
.bit_width = extra.bit_width,
|
||||
.name = extra.name,
|
||||
.value = @bitCast(emit_val),
|
||||
}, metadata_adapter);
|
||||
} else {
|
||||
const word_count = std.mem.alignForward(u32, extra.bit_width, 64) / 64;
|
||||
try record.ensureUnusedCapacity(self.gpa, 3 + word_count);
|
||||
|
||||
const flags = MetadataBlock.Enumerator.Flags{
|
||||
.unsigned = unsigned,
|
||||
.bigint = true,
|
||||
};
|
||||
|
||||
const FlagsInt = @typeInfo(MetadataBlock.Enumerator.Flags).Struct.backing_integer.?;
|
||||
|
||||
const flags_int: FlagsInt = @bitCast(flags);
|
||||
|
||||
record.appendAssumeCapacity(@intCast(flags_int));
|
||||
record.appendAssumeCapacity(@intCast(extra.bit_width));
|
||||
record.appendAssumeCapacity(metadata_adapter.getMetadataStringIndex(extra.name));
|
||||
|
||||
const buffer: [*]u8 = @ptrCast(record.items.ptr);
|
||||
bigint.writeTwosComplement(buffer[0..(word_count * 8)], .little);
|
||||
|
||||
const signed_buffer: [*]i64 = @ptrCast(record.items.ptr);
|
||||
for (signed_buffer[0..word_count], 0..) |val, i| {
|
||||
signed_buffer[i] = if (val >= 0)
|
||||
@shlWithOverflow(val, 1)[0]
|
||||
else
|
||||
(@shlWithOverflow(@addWithOverflow(~val, 1)[0], 1)[0] | 1);
|
||||
}
|
||||
|
||||
try metadata_block.writeUnabbrev(
|
||||
MetadataBlock.Enumerator.id,
|
||||
record.items.ptr[0..(3 + word_count)],
|
||||
);
|
||||
}
|
||||
},
|
||||
.subrange => {
|
||||
const extra = self.metadataExtraData(Metadata.Subrange, data);
|
||||
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.Subrange{
|
||||
.count = extra.count,
|
||||
.lower_bound = extra.lower_bound,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.expression => {
|
||||
var extra = self.metadataExtraDataTrail(Metadata.Expression, data);
|
||||
|
||||
const elements = extra.trail.next(extra.data.elements_len, u32, self);
|
||||
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.Expression{
|
||||
.elements = elements,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.tuple => {
|
||||
var extra = self.metadataExtraDataTrail(Metadata.Tuple, data);
|
||||
|
||||
const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
|
||||
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.Node{
|
||||
.elements = elements,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.module_flag => {
|
||||
const extra = self.metadataExtraData(Metadata.ModuleFlag, data);
|
||||
try metadata_block.writeAbbrev(MetadataBlock.Node{
|
||||
.elements = &.{
|
||||
@enumFromInt(metadata_adapter.getMetadataIndex(extra.behaviour)),
|
||||
@enumFromInt(metadata_adapter.getMetadataStringIndex(extra.name)),
|
||||
@enumFromInt(metadata_adapter.getMetadataIndex(extra.constant)),
|
||||
},
|
||||
});
|
||||
},
|
||||
.local_var => {
|
||||
const extra = self.metadataExtraData(Metadata.LocalVar, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.LocalVar{
|
||||
.scope = extra.scope,
|
||||
.name = extra.name,
|
||||
.file = extra.file,
|
||||
.line = extra.line,
|
||||
.ty = extra.ty,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.parameter => {
|
||||
const extra = self.metadataExtraData(Metadata.Parameter, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.Parameter{
|
||||
.scope = extra.scope,
|
||||
.name = extra.name,
|
||||
.file = extra.file,
|
||||
.line = extra.line,
|
||||
.ty = extra.ty,
|
||||
.arg = extra.arg_no,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.global_var,
|
||||
.@"global_var local",
|
||||
=> |kind| {
|
||||
const extra = self.metadataExtraData(Metadata.GlobalVar, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.GlobalVar{
|
||||
.scope = extra.scope,
|
||||
.name = extra.name,
|
||||
.linkage_name = extra.linkage_name,
|
||||
.file = extra.file,
|
||||
.line = extra.line,
|
||||
.ty = extra.ty,
|
||||
.local = kind == .@"global_var local",
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.global_var_expression => {
|
||||
const extra = self.metadataExtraData(Metadata.GlobalVarExpression, data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.GlobalVarExpression{
|
||||
.variable = extra.variable,
|
||||
.expression = extra.expression,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
.constant => {
|
||||
const constant: Constant = @enumFromInt(data);
|
||||
try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{
|
||||
.ty = constant.typeOf(self),
|
||||
.constant = constant,
|
||||
}, metadata_adapter);
|
||||
},
|
||||
}
|
||||
record.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
// Write named metadata
|
||||
for (self.metadata_named.keys(), self.metadata_named.values()) |name, operands| {
|
||||
const slice = name.slice(self).?;
|
||||
try metadata_block.writeAbbrev(MetadataBlock.Name{
|
||||
.name = slice,
|
||||
});
|
||||
|
||||
const elements = self.metadata_extra.items[operands.index..][0..operands.len];
|
||||
for (elements) |*e| {
|
||||
e.* = metadata_adapter.getMetadataIndex(@enumFromInt(e.*)) - 1;
|
||||
}
|
||||
|
||||
try metadata_block.writeAbbrev(MetadataBlock.NamedNode{
|
||||
.elements = @ptrCast(elements),
|
||||
});
|
||||
}
|
||||
|
||||
try metadata_block.end();
|
||||
}
|
||||
|
||||
// FUNCTION_BLOCKS
|
||||
{
|
||||
const FunctionAdapter = struct {
|
||||
constant_adapter: ConstantAdapter,
|
||||
metadata_adapter: MetadataAdapter,
|
||||
func: *const Function,
|
||||
instruction_index: u32 = 0,
|
||||
|
||||
pub fn init(
|
||||
const_adapter: ConstantAdapter,
|
||||
meta_adapter: MetadataAdapter,
|
||||
func: *const Function,
|
||||
) @This() {
|
||||
return .{
|
||||
.constant_adapter = const_adapter,
|
||||
.metadata_adapter = meta_adapter,
|
||||
.func = func,
|
||||
.instruction_index = 0,
|
||||
};
|
||||
@ -14499,12 +14929,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
|
||||
return @intCast(switch (value.unwrap()) {
|
||||
.instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(),
|
||||
.constant => |constant| adapter.constant_adapter.getConstantIndex(constant),
|
||||
.metadata => unreachable,
|
||||
.metadata => |metadata| if (!adapter.metadata_adapter.builder.strip) blk: {
|
||||
const real_metadata = metadata.unwrap(adapter.metadata_adapter.builder);
|
||||
if (@intFromEnum(real_metadata) < Metadata.first_local_metadata)
|
||||
break :blk adapter.metadata_adapter.getMetadataIndex(real_metadata) - 1;
|
||||
|
||||
return @intCast(@intFromEnum(metadata) -
|
||||
Metadata.first_local_metadata +
|
||||
adapter.metadata_adapter.builder.metadata_strings.count() +
|
||||
adapter.metadata_adapter.builder.metadata_map.count() - 1);
|
||||
} else unreachable,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn getOffsetValueIndex(adapter: @This(), value: Value) u32 {
|
||||
return adapter.offset() - adapter.getValueIndex(value);
|
||||
return @subWithOverflow(adapter.offset(), adapter.getValueIndex(value))[0];
|
||||
}
|
||||
|
||||
pub fn getOffsetValueSignedIndex(adapter: @This(), value: Value) i32 {
|
||||
@ -14543,11 +14982,28 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
|
||||
|
||||
try function_block.writeAbbrev(FunctionBlock.DeclareBlocks{ .num_blocks = func.blocks.len });
|
||||
|
||||
var adapter = FunctionAdapter.init(constant_adapter, &func);
|
||||
var adapter = FunctionAdapter.init(constant_adapter, metadata_adapter, &func);
|
||||
|
||||
// Emit function level metadata block
|
||||
if (!self.strip and func.debug_values.len != 0) {
|
||||
const MetadataBlock = IR.FunctionMetadataBlock;
|
||||
var metadata_block = try function_block.enterSubBlock(MetadataBlock);
|
||||
|
||||
for (func.debug_values) |value| {
|
||||
try metadata_block.writeAbbrev(MetadataBlock.Value{
|
||||
.ty = value.typeOf(@enumFromInt(func_index), self),
|
||||
.value = @enumFromInt(adapter.getValueIndex(value.toValue())),
|
||||
});
|
||||
}
|
||||
|
||||
try metadata_block.end();
|
||||
}
|
||||
|
||||
const tags = func.instructions.items(.tag);
|
||||
const datas = func.instructions.items(.data);
|
||||
|
||||
var has_location = false;
|
||||
|
||||
var block_incoming_len: u32 = undefined;
|
||||
for (0..func.instructions.len) |instr_index| {
|
||||
const tag = tags[instr_index];
|
||||
@ -14990,6 +15446,25 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
|
||||
},
|
||||
}
|
||||
|
||||
if (!self.strip) {
|
||||
if (func.debug_locations.get(@enumFromInt(instr_index))) |maybe_location| {
|
||||
if (maybe_location) |location| {
|
||||
try function_block.writeAbbrev(FunctionBlock.DebugLoc{
|
||||
.line = location.line,
|
||||
.column = location.column,
|
||||
.scope = @enumFromInt(metadata_adapter.getMetadataIndex(location.scope)),
|
||||
.inlined_at = @enumFromInt(metadata_adapter.getMetadataIndex(location.inlined_at)),
|
||||
.is_implicit = false,
|
||||
});
|
||||
has_location = true;
|
||||
} else {
|
||||
has_location = false;
|
||||
}
|
||||
} else if (has_location) {
|
||||
try function_block.writeAbbrev(FunctionBlock.DebugLocAgain{});
|
||||
}
|
||||
}
|
||||
|
||||
adapter.next();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user