Source
pub fn printUnbuffered(
self: *Builder,
backing_writer: anytype,
) (@TypeOf(backing_writer).Error || Allocator.Error)!void {
const writer_with_errors = writerWithErrors(backing_writer, Allocator.Error);
const writer = writer_with_errors.writer();
var need_newline = false;
var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined };
defer metadata_formatter.map.deinit(self.gpa);
if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
if (self.source_filename != .none) try writer.print(
\\; ModuleID = '{s}'
\\source_filename = {"}
\\
, .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });
if (self.data_layout != .none) try writer.print(
\\target datalayout = {"}
\\
, .{self.data_layout.fmt(self)});
if (self.target_triple != .none) try writer.print(
\\target triple = {"}
\\
, .{self.target_triple.fmt(self)});
}
if (self.module_asm.items.len > 0) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
while (line_it.next()) |line| {
try writer.writeAll("module asm ");
try printEscapedString(line, .always_quote, writer);
try writer.writeByte('\n');
}
}
if (self.types.count() > 0) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
for (self.types.keys(), self.types.values()) |id, ty| try writer.print(
\\%{} = type {}
\\
, .{ id.fmt(self), ty.fmt(self) });
}
if (self.variables.items.len > 0) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
for (self.variables.items) |variable| {
if (variable.global.getReplacement(self) != .none) continue;
const global = variable.global.ptrConst(self);
metadata_formatter.need_comma = true;
defer metadata_formatter.need_comma = undefined;
try writer.print(
\\{} ={}{}{}{}{ }{}{ }{} {s} {%}{ }{, }{}
\\
, .{
variable.global.fmt(self),
Linkage.fmtOptional(if (global.linkage == .external and
variable.init != .no_init) null else global.linkage),
global.preemption,
global.visibility,
global.dll_storage_class,
variable.thread_local,
global.unnamed_addr,
global.addr_space,
global.externally_initialized,
@tagName(variable.mutability),
global.type.fmt(self),
variable.init.fmt(self),
variable.alignment,
try metadata_formatter.fmt("!dbg ", global.dbg),
});
}
}
if (self.aliases.items.len > 0) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
for (self.aliases.items) |alias| {
if (alias.global.getReplacement(self) != .none) continue;
const global = alias.global.ptrConst(self);
metadata_formatter.need_comma = true;
defer metadata_formatter.need_comma = undefined;
try writer.print(
\\{} ={}{}{}{}{ }{} alias {%}, {%}{}
\\
, .{
alias.global.fmt(self),
global.linkage,
global.preemption,
global.visibility,
global.dll_storage_class,
alias.thread_local,
global.unnamed_addr,
global.type.fmt(self),
alias.aliasee.fmt(self),
try metadata_formatter.fmt("!dbg ", global.dbg),
});
}
}
var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .empty;
defer attribute_groups.deinit(self.gpa);
for (0.., self.functions.items) |function_i, function| {
if (function.global.getReplacement(self) != .none) continue;
if (need_newline) try writer.writeByte('\n') else need_newline = true;
const function_index: Function.Index = @enumFromInt(function_i);
const global = function.global.ptrConst(self);
const params_len = global.type.functionParameters(self).len;
const function_attributes = function.attributes.func(self);
if (function_attributes != .none) try writer.print(
\\; Function Attrs:{}
\\
, .{function_attributes.fmt(self)});
try writer.print(
\\{s}{}{}{}{}{}{"} {%} {}(
, .{
if (function.instructions.len > 0) "define" else "declare",
global.linkage,
global.preemption,
global.visibility,
global.dll_storage_class,
function.call_conv,
function.attributes.ret(self).fmt(self),
global.type.functionReturn(self).fmt(self),
function.global.fmt(self),
});
for (0..params_len) |arg| {
if (arg > 0) try writer.writeAll(", ");
try writer.print(
\\{%}{"}
, .{
global.type.functionParameters(self)[arg].fmt(self),
function.attributes.param(arg, self).fmt(self),
});
if (function.instructions.len > 0)
try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
else
try writer.print(" %{d}", .{arg});
}
switch (global.type.functionKind(self)) {
.normal => {},
.vararg => {
if (params_len > 0) try writer.writeAll(", ");
try writer.writeAll("...");
},
}
try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });
if (function_attributes != .none) try writer.print(" #{d}", .{
(try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
});
{
metadata_formatter.need_comma = false;
defer metadata_formatter.need_comma = undefined;
try writer.print("{ }{}", .{
function.alignment,
try metadata_formatter.fmt(" !dbg ", global.dbg),
});
}
if (function.instructions.len > 0) {
var block_incoming_len: u32 = undefined;
try writer.writeAll(" {\n");
var maybe_dbg_index: ?u32 = null;
for (params_len..function.instructions.len) |instruction_i| {
const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
const instruction = function.instructions.get(@intFromEnum(instruction_index));
if (function.debug_locations.get(instruction_index)) |debug_location| switch (debug_location) {
.no_location => maybe_dbg_index = null,
.location => |location| {
const gop = try metadata_formatter.map.getOrPut(self.gpa, .{
.debug_location = location,
});
maybe_dbg_index = @intCast(gop.index);
},
};
switch (instruction.tag) {
.add,
.@"add nsw",
.@"add nuw",
.@"add nuw nsw",
.@"and",
.ashr,
.@"ashr exact",
.fadd,
.@"fadd fast",
.@"fcmp false",
.@"fcmp fast false",
.@"fcmp fast oeq",
.@"fcmp fast oge",
.@"fcmp fast ogt",
.@"fcmp fast ole",
.@"fcmp fast olt",
.@"fcmp fast one",
.@"fcmp fast ord",
.@"fcmp fast true",
.@"fcmp fast ueq",
.@"fcmp fast uge",
.@"fcmp fast ugt",
.@"fcmp fast ule",
.@"fcmp fast ult",
.@"fcmp fast une",
.@"fcmp fast uno",
.@"fcmp oeq",
.@"fcmp oge",
.@"fcmp ogt",
.@"fcmp ole",
.@"fcmp olt",
.@"fcmp one",
.@"fcmp ord",
.@"fcmp true",
.@"fcmp ueq",
.@"fcmp uge",
.@"fcmp ugt",
.@"fcmp ule",
.@"fcmp ult",
.@"fcmp une",
.@"fcmp uno",
.fdiv,
.@"fdiv fast",
.fmul,
.@"fmul fast",
.frem,
.@"frem fast",
.fsub,
.@"fsub fast",
.@"icmp eq",
.@"icmp ne",
.@"icmp sge",
.@"icmp sgt",
.@"icmp sle",
.@"icmp slt",
.@"icmp uge",
.@"icmp ugt",
.@"icmp ule",
.@"icmp ult",
.lshr,
.@"lshr exact",
.mul,
.@"mul nsw",
.@"mul nuw",
.@"mul nuw nsw",
.@"or",
.sdiv,
.@"sdiv exact",
.srem,
.shl,
.@"shl nsw",
.@"shl nuw",
.@"shl nuw nsw",
.sub,
.@"sub nsw",
.@"sub nuw",
.@"sub nuw nsw",
.udiv,
.@"udiv exact",
.urem,
.xor,
=> |tag| {
const extra = function.extraData(Function.Instruction.Binary, instruction.data);
try writer.print(" %{} = {s} {%}, {}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.lhs.fmt(function_index, self),
extra.rhs.fmt(function_index, self),
});
},
.addrspacecast,
.bitcast,
.fpext,
.fptosi,
.fptoui,
.fptrunc,
.inttoptr,
.ptrtoint,
.sext,
.sitofp,
.trunc,
.uitofp,
.zext,
=> |tag| {
const extra = function.extraData(Function.Instruction.Cast, instruction.data);
try writer.print(" %{} = {s} {%} to {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.val.fmt(function_index, self),
extra.type.fmt(self),
});
},
.alloca,
.@"alloca inalloca",
=> |tag| {
const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
try writer.print(" %{} = {s} {%}{,%}{, }{, }", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.type.fmt(self),
Value.fmt(switch (extra.len) {
.@"1" => .none,
else => extra.len,
}, function_index, self),
extra.info.alignment,
extra.info.addr_space,
});
},
.arg => unreachable,
.atomicrmw => |tag| {
const extra =
function.extraData(Function.Instruction.AtomicRmw, instruction.data);
try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.info.access_kind,
@tagName(extra.info.atomic_rmw_operation),
extra.ptr.fmt(function_index, self),
extra.val.fmt(function_index, self),
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.alignment,
});
},
.block => {
block_incoming_len = instruction.data;
const name = instruction_index.name(&function);
if (@intFromEnum(instruction_index) > params_len)
try writer.writeByte('\n');
try writer.print("{}:\n", .{name.fmt(self)});
continue;
},
.br => |tag| {
const target: Function.Block.Index = @enumFromInt(instruction.data);
try writer.print(" {s} {%}", .{
@tagName(tag), target.toInst(&function).fmt(function_index, self),
});
},
.br_cond => {
const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
try writer.print(" br {%}, {%}, {%}", .{
extra.cond.fmt(function_index, self),
extra.then.toInst(&function).fmt(function_index, self),
extra.@"else".toInst(&function).fmt(function_index, self),
});
metadata_formatter.need_comma = true;
defer metadata_formatter.need_comma = undefined;
switch (extra.weights) {
.none => {},
.unpredictable => try writer.writeAll("!unpredictable !{}"),
_ => try writer.print("{}", .{
try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.weights)))),
}),
}
},
.call,
.@"call fast",
.@"musttail call",
.@"musttail call fast",
.@"notail call",
.@"notail call fast",
.@"tail call",
.@"tail call fast",
=> |tag| {
var extra =
function.extraDataTrail(Function.Instruction.Call, instruction.data);
const args = extra.trail.next(extra.data.args_len, Value, &function);
try writer.writeAll(" ");
const ret_ty = extra.data.ty.functionReturn(self);
switch (ret_ty) {
.void => {},
else => try writer.print("%{} = ", .{
instruction_index.name(&function).fmt(self),
}),
.none => unreachable,
}
try writer.print("{s}{}{}{} {%} {}(", .{
@tagName(tag),
extra.data.info.call_conv,
extra.data.attributes.ret(self).fmt(self),
extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
switch (extra.data.ty.functionKind(self)) {
.normal => ret_ty,
.vararg => extra.data.ty,
}.fmt(self),
extra.data.callee.fmt(function_index, self),
});
for (0.., args) |arg_index, arg| {
if (arg_index > 0) try writer.writeAll(", ");
metadata_formatter.need_comma = false;
defer metadata_formatter.need_comma = undefined;
try writer.print("{%}{}{}", .{
arg.typeOf(function_index, self).fmt(self),
extra.data.attributes.param(arg_index, self).fmt(self),
try metadata_formatter.fmtLocal(" ", arg, function_index),
});
}
try writer.writeByte(')');
if (extra.data.info.has_op_bundle_cold) {
try writer.writeAll(" [ \"cold\"() ]");
}
const call_function_attributes = extra.data.attributes.func(self);
if (call_function_attributes != .none) try writer.print(" #{d}", .{
(try attribute_groups.getOrPutValue(
self.gpa,
call_function_attributes,
{},
)).index,
});
},
.cmpxchg,
.@"cmpxchg weak",
=> |tag| {
const extra =
function.extraData(Function.Instruction.CmpXchg, instruction.data);
try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.info.access_kind,
extra.ptr.fmt(function_index, self),
extra.cmp.fmt(function_index, self),
extra.new.fmt(function_index, self),
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.failure_ordering,
extra.info.alignment,
});
},
.extractelement => |tag| {
const extra =
function.extraData(Function.Instruction.ExtractElement, instruction.data);
try writer.print(" %{} = {s} {%}, {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.val.fmt(function_index, self),
extra.index.fmt(function_index, self),
});
},
.extractvalue => |tag| {
var extra = function.extraDataTrail(
Function.Instruction.ExtractValue,
instruction.data,
);
const indices = extra.trail.next(extra.data.indices_len, u32, &function);
try writer.print(" %{} = {s} {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.data.val.fmt(function_index, self),
});
for (indices) |index| try writer.print(", {d}", .{index});
},
.fence => |tag| {
const info: MemoryAccessInfo = @bitCast(instruction.data);
try writer.print(" {s}{ }{ }", .{
@tagName(tag),
info.sync_scope,
info.success_ordering,
});
},
.fneg,
.@"fneg fast",
=> |tag| {
const val: Value = @enumFromInt(instruction.data);
try writer.print(" %{} = {s} {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
val.fmt(function_index, self),
});
},
.getelementptr,
.@"getelementptr inbounds",
=> |tag| {
var extra = function.extraDataTrail(
Function.Instruction.GetElementPtr,
instruction.data,
);
const indices = extra.trail.next(extra.data.indices_len, Value, &function);
try writer.print(" %{} = {s} {%}, {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.data.type.fmt(self),
extra.data.base.fmt(function_index, self),
});
for (indices) |index| try writer.print(", {%}", .{
index.fmt(function_index, self),
});
},
.indirectbr => |tag| {
var extra =
function.extraDataTrail(Function.Instruction.IndirectBr, instruction.data);
const targets =
extra.trail.next(extra.data.targets_len, Function.Block.Index, &function);
try writer.print(" {s} {%}, [", .{
@tagName(tag),
extra.data.addr.fmt(function_index, self),
});
for (0.., targets) |target_index, target| {
if (target_index > 0) try writer.writeAll(", ");
try writer.print("{%}", .{
target.toInst(&function).fmt(function_index, self),
});
}
try writer.writeByte(']');
},
.insertelement => |tag| {
const extra =
function.extraData(Function.Instruction.InsertElement, instruction.data);
try writer.print(" %{} = {s} {%}, {%}, {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.val.fmt(function_index, self),
extra.elem.fmt(function_index, self),
extra.index.fmt(function_index, self),
});
},
.insertvalue => |tag| {
var extra =
function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
const indices = extra.trail.next(extra.data.indices_len, u32, &function);
try writer.print(" %{} = {s} {%}, {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.data.val.fmt(function_index, self),
extra.data.elem.fmt(function_index, self),
});
for (indices) |index| try writer.print(", {d}", .{index});
},
.load,
.@"load atomic",
=> |tag| {
const extra = function.extraData(Function.Instruction.Load, instruction.data);
try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.info.access_kind,
extra.type.fmt(self),
extra.ptr.fmt(function_index, self),
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.alignment,
});
},
.phi,
.@"phi fast",
=> |tag| {
var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data);
const vals = extra.trail.next(block_incoming_len, Value, &function);
const blocks =
extra.trail.next(block_incoming_len, Function.Block.Index, &function);
try writer.print(" %{} = {s} {%} ", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
vals[0].typeOf(function_index, self).fmt(self),
});
for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
if (incoming_index > 0) try writer.writeAll(", ");
try writer.print("[ {}, {} ]", .{
incoming_val.fmt(function_index, self),
incoming_block.toInst(&function).fmt(function_index, self),
});
}
},
.ret => |tag| {
const val: Value = @enumFromInt(instruction.data);
try writer.print(" {s} {%}", .{
@tagName(tag),
val.fmt(function_index, self),
});
},
.@"ret void",
.@"unreachable",
=> |tag| try writer.print(" {s}", .{@tagName(tag)}),
.select,
.@"select fast",
=> |tag| {
const extra = function.extraData(Function.Instruction.Select, instruction.data);
try writer.print(" %{} = {s} {%}, {%}, {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.cond.fmt(function_index, self),
extra.lhs.fmt(function_index, self),
extra.rhs.fmt(function_index, self),
});
},
.shufflevector => |tag| {
const extra =
function.extraData(Function.Instruction.ShuffleVector, instruction.data);
try writer.print(" %{} = {s} {%}, {%}, {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.lhs.fmt(function_index, self),
extra.rhs.fmt(function_index, self),
extra.mask.fmt(function_index, self),
});
},
.store,
.@"store atomic",
=> |tag| {
const extra = function.extraData(Function.Instruction.Store, instruction.data);
try writer.print(" {s}{ } {%}, {%}{ }{ }{, }", .{
@tagName(tag),
extra.info.access_kind,
extra.val.fmt(function_index, self),
extra.ptr.fmt(function_index, self),
extra.info.sync_scope,
extra.info.success_ordering,
extra.info.alignment,
});
},
.@"switch" => |tag| {
var extra =
function.extraDataTrail(Function.Instruction.Switch, instruction.data);
const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
const blocks =
extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
try writer.print(" {s} {%}, {%} [\n", .{
@tagName(tag),
extra.data.val.fmt(function_index, self),
extra.data.default.toInst(&function).fmt(function_index, self),
});
for (vals, blocks) |case_val, case_block| try writer.print(
" {%}, {%}\n",
.{
case_val.fmt(self),
case_block.toInst(&function).fmt(function_index, self),
},
);
try writer.writeAll(" ]");
metadata_formatter.need_comma = true;
defer metadata_formatter.need_comma = undefined;
switch (extra.data.weights) {
.none => {},
.unpredictable => try writer.writeAll("!unpredictable !{}"),
_ => try writer.print("{}", .{
try metadata_formatter.fmt("!prof ", @as(Metadata, @enumFromInt(@intFromEnum(extra.data.weights)))),
}),
}
},
.va_arg => |tag| {
const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
try writer.print(" %{} = {s} {%}, {%}", .{
instruction_index.name(&function).fmt(self),
@tagName(tag),
extra.list.fmt(function_index, self),
extra.type.fmt(self),
});
},
}
if (maybe_dbg_index) |dbg_index| {
try writer.print(", !dbg !{}", .{dbg_index});
}
try writer.writeByte('\n');
}
try writer.writeByte('}');
}
try writer.writeByte('\n');
}
if (attribute_groups.count() > 0) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
try writer.print(
\\attributes #{d} = {{{#"} }}
\\
, .{ attribute_group_index, attribute_group.fmt(self) });
}
if (self.metadata_named.count() > 0) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
for (self.metadata_named.keys(), self.metadata_named.values()) |name, data| {
const elements: []const Metadata =
@ptrCast(self.metadata_extra.items[data.index..][0..data.len]);
try writer.writeByte('!');
try printEscapedString(name.slice(self), .quote_unless_valid_identifier, writer);
try writer.writeAll(" = !{");
metadata_formatter.need_comma = false;
defer metadata_formatter.need_comma = undefined;
for (elements) |element| try writer.print("{}", .{try metadata_formatter.fmt("", element)});
try writer.writeAll("}\n");
}
}
if (metadata_formatter.map.count() > 0) {
if (need_newline) try writer.writeByte('\n') else need_newline = true;
var metadata_index: usize = 0;
while (metadata_index < metadata_formatter.map.count()) : (metadata_index += 1) {
@setEvalBranchQuota(10_000);
try writer.print("!{} = ", .{metadata_index});
metadata_formatter.need_comma = false;
defer metadata_formatter.need_comma = undefined;
const key = metadata_formatter.map.keys()[metadata_index];
const metadata_item = switch (key) {
.debug_location => |location| {
try metadata_formatter.specialized(.@"!", .DILocation, .{
.line = location.line,
.column = location.column,
.scope = location.scope,
.inlinedAt = location.inlined_at,
.isImplicitCode = false,
}, writer);
continue;
},
.metadata => |metadata| self.metadata_items.get(@intFromEnum(metadata)),
};
switch (metadata_item.tag) {
.none, .expression, .constant => unreachable,
.file => {
const extra = self.metadataExtraData(Metadata.File, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DIFile, .{
.filename = extra.filename,
.directory = extra.directory,
.checksumkind = null,
.checksum = null,
.source = null,
}, writer);
},
.compile_unit,
.@"compile_unit optimized",
=> |kind| {
const extra = self.metadataExtraData(Metadata.CompileUnit, metadata_item.data);
try metadata_formatter.specialized(.@"distinct !", .DICompileUnit, .{
.language = .DW_LANG_C99,
.file = extra.file,
.producer = extra.producer,
.isOptimized = switch (kind) {
.compile_unit => false,
.@"compile_unit optimized" => true,
else => unreachable,
},
.flags = null,
.runtimeVersion = 0,
.splitDebugFilename = null,
.emissionKind = .FullDebug,
.enums = extra.enums,
.retainedTypes = null,
.globals = extra.globals,
.imports = null,
.macros = null,
.dwoId = null,
.splitDebugInlining = false,
.debugInfoForProfiling = null,
.nameTableKind = null,
.rangesBaseAddress = null,
.sysroot = null,
.sdk = null,
}, writer);
},
.subprogram,
.@"subprogram local",
.@"subprogram definition",
.@"subprogram local definition",
.@"subprogram optimized",
.@"subprogram optimized local",
.@"subprogram optimized definition",
.@"subprogram optimized local definition",
=> |kind| {
const extra = self.metadataExtraData(Metadata.Subprogram, metadata_item.data);
try metadata_formatter.specialized(.@"distinct !", .DISubprogram, .{
.name = extra.name,
.linkageName = extra.linkage_name,
.scope = extra.file,
.file = extra.file,
.line = extra.line,
.type = extra.ty,
.scopeLine = extra.scope_line,
.containingType = null,
.virtualIndex = null,
.thisAdjustment = null,
.flags = extra.di_flags,
.spFlags = @as(Metadata.Subprogram.DISPFlags, @bitCast(@as(u32, @as(u3, @intCast(
@intFromEnum(kind) - @intFromEnum(Metadata.Tag.subprogram),
))) << 2)),
.unit = extra.compile_unit,
.templateParams = null,
.declaration = null,
.retainedNodes = null,
.thrownTypes = null,
.annotations = null,
.targetFuncName = null,
}, writer);
},
.lexical_block => {
const extra = self.metadataExtraData(Metadata.LexicalBlock, metadata_item.data);
try metadata_formatter.specialized(.@"distinct !", .DILexicalBlock, .{
.scope = extra.scope,
.file = extra.file,
.line = extra.line,
.column = extra.column,
}, writer);
},
.location => {
const extra = self.metadataExtraData(Metadata.Location, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DILocation, .{
.line = extra.line,
.column = extra.column,
.scope = extra.scope,
.inlinedAt = extra.inlined_at,
.isImplicitCode = false,
}, writer);
},
.basic_bool_type,
.basic_unsigned_type,
.basic_signed_type,
.basic_float_type,
=> |kind| {
const extra = self.metadataExtraData(Metadata.BasicType, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DIBasicType, .{
.tag = null,
.name = switch (extra.name) {
.none => null,
else => extra.name,
},
.size = extra.bitSize(),
.@"align" = null,
.encoding = @as(enum {
DW_ATE_boolean,
DW_ATE_unsigned,
DW_ATE_signed,
DW_ATE_float,
}, switch (kind) {
.basic_bool_type => .DW_ATE_boolean,
.basic_unsigned_type => .DW_ATE_unsigned,
.basic_signed_type => .DW_ATE_signed,
.basic_float_type => .DW_ATE_float,
else => unreachable,
}),
.flags = null,
}, writer);
},
.composite_struct_type,
.composite_union_type,
.composite_enumeration_type,
.composite_array_type,
.composite_vector_type,
=> |kind| {
const extra = self.metadataExtraData(Metadata.CompositeType, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DICompositeType, .{
.tag = @as(enum {
DW_TAG_structure_type,
DW_TAG_union_type,
DW_TAG_enumeration_type,
DW_TAG_array_type,
}, switch (kind) {
.composite_struct_type => .DW_TAG_structure_type,
.composite_union_type => .DW_TAG_union_type,
.composite_enumeration_type => .DW_TAG_enumeration_type,
.composite_array_type, .composite_vector_type => .DW_TAG_array_type,
else => unreachable,
}),
.name = switch (extra.name) {
.none => null,
else => extra.name,
},
.scope = extra.scope,
.file = null,
.line = null,
.baseType = extra.underlying_type,
.size = extra.bitSize(),
.@"align" = extra.bitAlign(),
.offset = null,
.flags = null,
.elements = extra.fields_tuple,
.runtimeLang = null,
.vtableHolder = null,
.templateParams = null,
.identifier = null,
.discriminator = null,
.dataLocation = null,
.associated = null,
.allocated = null,
.rank = null,
.annotations = null,
}, writer);
},
.derived_pointer_type,
.derived_member_type,
=> |kind| {
const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DIDerivedType, .{
.tag = @as(enum {
DW_TAG_pointer_type,
DW_TAG_member,
}, switch (kind) {
.derived_pointer_type => .DW_TAG_pointer_type,
.derived_member_type => .DW_TAG_member,
else => unreachable,
}),
.name = switch (extra.name) {
.none => null,
else => extra.name,
},
.scope = extra.scope,
.file = null,
.line = null,
.baseType = extra.underlying_type,
.size = extra.bitSize(),
.@"align" = extra.bitAlign(),
.offset = switch (extra.bitOffset()) {
0 => null,
else => |bit_offset| bit_offset,
},
.flags = null,
.extraData = null,
.dwarfAddressSpace = null,
.annotations = null,
}, writer);
},
.subroutine_type => {
const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DISubroutineType, .{
.flags = null,
.cc = null,
.types = extra.types_tuple,
}, writer);
},
.enumerator_unsigned,
.enumerator_signed_positive,
.enumerator_signed_negative,
=> |kind| {
const extra = self.metadataExtraData(Metadata.Enumerator, metadata_item.data);
const ExpectedContents = extern struct {
const expected_limbs = @divExact(512, @bitSizeOf(std.math.big.Limb));
string: [
(std.math.big.int.Const{
.limbs = &([1]std.math.big.Limb{
std.math.maxInt(std.math.big.Limb),
} ** expected_limbs),
.positive = false,
}).sizeInBaseUpperBound(10)
]u8,
limbs: [
std.math.big.int.calcToStringLimbsBufferLen(expected_limbs, 10)
]std.math.big.Limb,
};
var stack align(@alignOf(ExpectedContents)) =
std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
const allocator = stack.get();
const limbs = self.metadata_limbs.items[extra.limbs_index..][0..extra.limbs_len];
const bigint: std.math.big.int.Const = .{
.limbs = limbs,
.positive = switch (kind) {
.enumerator_unsigned,
.enumerator_signed_positive,
=> true,
.enumerator_signed_negative => false,
else => unreachable,
},
};
const str = try bigint.toStringAlloc(allocator, 10, undefined);
defer allocator.free(str);
try metadata_formatter.specialized(.@"!", .DIEnumerator, .{
.name = extra.name,
.value = str,
.isUnsigned = switch (kind) {
.enumerator_unsigned => true,
.enumerator_signed_positive,
.enumerator_signed_negative,
=> false,
else => unreachable,
},
}, writer);
},
.subrange => {
const extra = self.metadataExtraData(Metadata.Subrange, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DISubrange, .{
.count = extra.count,
.lowerBound = extra.lower_bound,
.upperBound = null,
.stride = null,
}, writer);
},
.tuple => {
var extra = self.metadataExtraDataTrail(Metadata.Tuple, metadata_item.data);
const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
try writer.writeAll("!{");
for (elements) |element| try writer.print("{[element]%}", .{
.element = try metadata_formatter.fmt("", element),
});
try writer.writeAll("}\n");
},
.str_tuple => {
var extra = self.metadataExtraDataTrail(Metadata.StrTuple, metadata_item.data);
const elements = extra.trail.next(extra.data.elements_len, Metadata, self);
try writer.print("!{{{[str]%}", .{
.str = try metadata_formatter.fmt("", extra.data.str),
});
for (elements) |element| try writer.print("{[element]%}", .{
.element = try metadata_formatter.fmt("", element),
});
try writer.writeAll("}\n");
},
.module_flag => {
const extra = self.metadataExtraData(Metadata.ModuleFlag, metadata_item.data);
try writer.print("!{{{[behavior]%}{[name]%}{[constant]%}}}\n", .{
.behavior = try metadata_formatter.fmt("", extra.behavior),
.name = try metadata_formatter.fmt("", extra.name),
.constant = try metadata_formatter.fmt("", extra.constant),
});
},
.local_var => {
const extra = self.metadataExtraData(Metadata.LocalVar, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DILocalVariable, .{
.name = extra.name,
.arg = null,
.scope = extra.scope,
.file = extra.file,
.line = extra.line,
.type = extra.ty,
.flags = null,
.@"align" = null,
.annotations = null,
}, writer);
},
.parameter => {
const extra = self.metadataExtraData(Metadata.Parameter, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DILocalVariable, .{
.name = extra.name,
.arg = extra.arg_no,
.scope = extra.scope,
.file = extra.file,
.line = extra.line,
.type = extra.ty,
.flags = null,
.@"align" = null,
.annotations = null,
}, writer);
},
.global_var,
.@"global_var local",
=> |kind| {
const extra = self.metadataExtraData(Metadata.GlobalVar, metadata_item.data);
try metadata_formatter.specialized(.@"distinct !", .DIGlobalVariable, .{
.name = extra.name,
.linkageName = extra.linkage_name,
.scope = extra.scope,
.file = extra.file,
.line = extra.line,
.type = extra.ty,
.isLocal = switch (kind) {
.global_var => false,
.@"global_var local" => true,
else => unreachable,
},
.isDefinition = true,
.declaration = null,
.templateParams = null,
.@"align" = null,
.annotations = null,
}, writer);
},
.global_var_expression => {
const extra =
self.metadataExtraData(Metadata.GlobalVarExpression, metadata_item.data);
try metadata_formatter.specialized(.@"!", .DIGlobalVariableExpression, .{
.@"var" = extra.variable,
.expr = extra.expression,
}, writer);
},
}
}
}
}