Sets all extra data for a declaration instruction.
Unstacks type_gz, align_gz, linksection_gz, addrspace_gz, and value_gz.
fn setDeclaration(
decl_inst: Zir.Inst.Index,
args: struct
fn setDeclaration(
decl_inst: Zir.Inst.Index,
args: struct {
src_hash: std.zig.SrcHash,
src_line: u32,
src_column: u32,
kind: Zir.Inst.Declaration.Unwrapped.Kind,
name: Zir.NullTerminatedString,
is_pub: bool,
is_threadlocal: bool,
linkage: Zir.Inst.Declaration.Unwrapped.Linkage,
lib_name: Zir.NullTerminatedString = .empty,
type_gz: *GenZir,
/// Must be stacked on `type_gz`.
align_gz: *GenZir,
/// Must be stacked on `align_gz`.
linksection_gz: *GenZir,
/// Must be stacked on `linksection_gz`.
addrspace_gz: *GenZir,
/// Must be stacked on `addrspace_gz` and have nothing stacked on top of it.
value_gz: *GenZir,
},
) !void {
const astgen = args.value_gz.astgen;
const gpa = astgen.gpa;
const type_body = args.type_gz.instructionsSliceUpto(args.align_gz);
const align_body = args.align_gz.instructionsSliceUpto(args.linksection_gz);
const linksection_body = args.linksection_gz.instructionsSliceUpto(args.addrspace_gz);
const addrspace_body = args.addrspace_gz.instructionsSliceUpto(args.value_gz);
const value_body = args.value_gz.instructionsSlice();
const has_name = args.name != .empty;
const has_lib_name = args.lib_name != .empty;
const has_type_body = type_body.len != 0;
const has_special_body = align_body.len != 0 or linksection_body.len != 0 or addrspace_body.len != 0;
const has_value_body = value_body.len != 0;
const id: Zir.Inst.Declaration.Flags.Id = switch (args.kind) {
.unnamed_test => .unnamed_test,
.@"test" => .@"test",
.decltest => .decltest,
.@"comptime" => .@"comptime",
.@"const" => switch (args.linkage) {
.normal => if (args.is_pub) id: {
if (has_special_body) break :id .pub_const;
if (has_type_body) break :id .pub_const_typed;
break :id .pub_const_simple;
} else id: {
if (has_special_body) break :id .@"const";
if (has_type_body) break :id .const_typed;
break :id .const_simple;
},
.@"extern" => if (args.is_pub) id: {
if (has_lib_name) break :id .pub_extern_const;
if (has_special_body) break :id .pub_extern_const;
break :id .pub_extern_const_simple;
} else id: {
if (has_lib_name) break :id .extern_const;
if (has_special_body) break :id .extern_const;
break :id .extern_const_simple;
},
.@"export" => if (args.is_pub) .pub_export_const else .export_const,
},
.@"var" => switch (args.linkage) {
.normal => if (args.is_pub) id: {
if (args.is_threadlocal) break :id .pub_var_threadlocal;
if (has_special_body) break :id .pub_var;
if (has_type_body) break :id .pub_var;
break :id .pub_var_simple;
} else id: {
if (args.is_threadlocal) break :id .var_threadlocal;
if (has_special_body) break :id .@"var";
if (has_type_body) break :id .@"var";
break :id .var_simple;
},
.@"extern" => if (args.is_pub) id: {
if (args.is_threadlocal) break :id .pub_extern_var_threadlocal;
break :id .pub_extern_var;
} else id: {
if (args.is_threadlocal) break :id .extern_var_threadlocal;
break :id .extern_var;
},
.@"export" => if (args.is_pub) id: {
if (args.is_threadlocal) break :id .pub_export_var_threadlocal;
break :id .pub_export_var;
} else id: {
if (args.is_threadlocal) break :id .export_var_threadlocal;
break :id .export_var;
},
},
};
assert(id.hasTypeBody() or !has_type_body);
assert(id.hasSpecialBodies() or !has_special_body);
assert(id.hasValueBody() == has_value_body);
assert(id.linkage() == args.linkage);
assert(id.hasName() == has_name);
assert(id.hasLibName() or !has_lib_name);
assert(id.isPub() == args.is_pub);
assert(id.isThreadlocal() == args.is_threadlocal);
const type_len = astgen.countBodyLenAfterFixups(type_body);
const align_len = astgen.countBodyLenAfterFixups(align_body);
const linksection_len = astgen.countBodyLenAfterFixups(linksection_body);
const addrspace_len = astgen.countBodyLenAfterFixups(addrspace_body);
const value_len = astgen.countBodyLenAfterFixups(value_body);
const src_hash_arr: [4]u32 = @bitCast(args.src_hash);
const flags: Zir.Inst.Declaration.Flags = .{
.src_line = @intCast(args.src_line),
.src_column = @intCast(args.src_column),
.id = id,
};
const flags_arr: [2]u32 = @bitCast(flags);
const need_extra: usize =
@typeInfo(Zir.Inst.Declaration).@"struct".field_names.len +
@as(usize, @intFromBool(id.hasName())) +
@as(usize, @intFromBool(id.hasLibName())) +
@as(usize, @intFromBool(id.hasTypeBody())) +
3 * @as(usize, @intFromBool(id.hasSpecialBodies())) +
@as(usize, @intFromBool(id.hasValueBody())) +
type_len + align_len + linksection_len + addrspace_len + value_len;
try astgen.extra.ensureUnusedCapacity(gpa, need_extra);
const extra: Zir.Inst.Declaration = .{
.src_hash_0 = src_hash_arr[0],
.src_hash_1 = src_hash_arr[1],
.src_hash_2 = src_hash_arr[2],
.src_hash_3 = src_hash_arr[3],
.flags_0 = flags_arr[0],
.flags_1 = flags_arr[1],
};
astgen.instructions.items(.data)[@backingInt(decl_inst)].declaration.payload_index =
astgen.addExtraAssumeCapacity(extra);
if (id.hasName()) {
astgen.extra.appendAssumeCapacity(@backingInt(args.name));
}
if (id.hasLibName()) {
astgen.extra.appendAssumeCapacity(@backingInt(args.lib_name));
}
if (id.hasTypeBody()) {
astgen.extra.appendAssumeCapacity(type_len);
}
if (id.hasSpecialBodies()) {
astgen.extra.appendSliceAssumeCapacity(&.{
align_len,
linksection_len,
addrspace_len,
});
}
if (id.hasValueBody()) {
astgen.extra.appendAssumeCapacity(value_len);
}
astgen.appendBodyWithFixups(type_body);
astgen.appendBodyWithFixups(align_body);
astgen.appendBodyWithFixups(linksection_body);
astgen.appendBodyWithFixups(addrspace_body);
astgen.appendBodyWithFixups(value_body);
args.value_gz.unstack();
args.addrspace_gz.unstack();
args.linksection_gz.unstack();
args.align_gz.unstack();
args.type_gz.unstack();
}