mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 06:15:21 +00:00
incremental: new AnalUnit to group dependencies on std.builtin decls
This commit reworks how values like the panic handler function are
memoized during a compiler invocation. Previously, the value was
resolved by whichever analysis requested it first, and cached on `Zcu`.
This is problematic for incremental compilation, as after the initial
resolution, no dependencies are marked by users of this memoized state.
This is arguably acceptable for `std.builtin`, but it's definitely not
acceptable for the panic handler/messages, because those can be set by
the user (`std.builtin.Panic` checks `@import("root").Panic`).
So, here we introduce a new kind of `AnalUnit`, called `memoized_state`.
There are 3 such units:
* `.{ .memoized_state = .va_list }` resolves the type `std.builtin.VaList`
* `.{ .memoized_state = .panic }` resolves `std.Panic`
* `.{ .memoized_state = .main }` resolves everything else we want
These units essentially "bundle" the resolution of their corresponding
declarations, storing the results into fields on `Zcu`. This way, when,
for instance, a function wants to call the panic handler, it simply runs
`ensureMemoizedStateResolved`, registering one dependency, and pulls the
values from the `Zcu`. This "bundling" minimizes dependency edges. The 3
units are separated to allow them to act independently: for instance,
the panic handler can use `std.builtin.Type` without triggering a
dependency loop.
This commit is contained in:
parent
fd62912787
commit
f01029c4af
@ -3158,16 +3158,19 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
|
||||
if (!refs.contains(anal_unit)) continue;
|
||||
}
|
||||
|
||||
const file_index = switch (anal_unit.unwrap()) {
|
||||
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip),
|
||||
.nav_val, .nav_ty => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip),
|
||||
.type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip),
|
||||
.func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip),
|
||||
};
|
||||
report_ok: {
|
||||
const file_index = switch (anal_unit.unwrap()) {
|
||||
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index.resolveFile(ip),
|
||||
.nav_val, .nav_ty => |nav| ip.getNav(nav).analysis.?.zir_index.resolveFile(ip),
|
||||
.type => |ty| Type.fromInterned(ty).typeDeclInst(zcu).?.resolveFile(ip),
|
||||
.func => |ip_index| zcu.funcInfo(ip_index).zir_body_inst.resolveFile(ip),
|
||||
.memoized_state => break :report_ok, // always report std.builtin errors
|
||||
};
|
||||
|
||||
// Skip errors for AnalUnits within files that had a parse failure.
|
||||
// We'll try again once parsing succeeds.
|
||||
if (!zcu.fileByIndex(file_index).okToReportErrors()) continue;
|
||||
// Skip errors for AnalUnits within files that had a parse failure.
|
||||
// We'll try again once parsing succeeds.
|
||||
if (!zcu.fileByIndex(file_index).okToReportErrors()) continue;
|
||||
}
|
||||
|
||||
std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{
|
||||
error_msg.msg,
|
||||
@ -3391,7 +3394,7 @@ pub fn addModuleErrorMsg(
|
||||
const ref = maybe_ref orelse break;
|
||||
const gop = try seen.getOrPut(gpa, ref.referencer);
|
||||
if (gop.found_existing) break;
|
||||
if (ref_traces.items.len < max_references) {
|
||||
if (ref_traces.items.len < max_references) skip: {
|
||||
const src = ref.src.upgrade(zcu);
|
||||
const source = try src.file_scope.getSource(gpa);
|
||||
const span = try src.span(gpa);
|
||||
@ -3403,6 +3406,7 @@ pub fn addModuleErrorMsg(
|
||||
.nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
|
||||
.type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
|
||||
.func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
|
||||
.memoized_state => break :skip,
|
||||
};
|
||||
try ref_traces.append(gpa, .{
|
||||
.decl_name = try eb.addString(name),
|
||||
@ -3670,6 +3674,7 @@ fn performAllTheWorkInner(
|
||||
if (try zcu.findOutdatedToAnalyze()) |outdated| {
|
||||
try comp.queueJob(switch (outdated.unwrap()) {
|
||||
.func => |f| .{ .analyze_func = f },
|
||||
.memoized_state,
|
||||
.@"comptime",
|
||||
.nav_ty,
|
||||
.nav_val,
|
||||
@ -3737,6 +3742,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
|
||||
.nav_ty => |nav| pt.ensureNavTypeUpToDate(nav),
|
||||
.nav_val => |nav| pt.ensureNavValUpToDate(nav),
|
||||
.type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err,
|
||||
.memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage),
|
||||
.func => unreachable,
|
||||
};
|
||||
maybe_err catch |err| switch (err) {
|
||||
|
||||
@ -49,6 +49,11 @@ namespace_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index)
|
||||
/// Dependencies on the (non-)existence of some name in a namespace.
|
||||
/// Value is index into `dep_entries` of the first dependency on this name.
|
||||
namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.Index),
|
||||
// Dependencies on the value of fields memoized on `Zcu` (`panic_messages` etc).
|
||||
// If set, these are indices into `dep_entries` of the first dependency on this state.
|
||||
memoized_state_main_deps: DepEntry.Index.Optional,
|
||||
memoized_state_panic_deps: DepEntry.Index.Optional,
|
||||
memoized_state_va_list_deps: DepEntry.Index.Optional,
|
||||
|
||||
/// Given a `Depender`, points to an entry in `dep_entries` whose `depender`
|
||||
/// matches. The `next_dependee` field can be used to iterate all such entries
|
||||
@ -87,6 +92,9 @@ pub const empty: InternPool = .{
|
||||
.interned_deps = .empty,
|
||||
.namespace_deps = .empty,
|
||||
.namespace_name_deps = .empty,
|
||||
.memoized_state_main_deps = .none,
|
||||
.memoized_state_panic_deps = .none,
|
||||
.memoized_state_va_list_deps = .none,
|
||||
.first_dependency = .empty,
|
||||
.dep_entries = .empty,
|
||||
.free_dep_entries = .empty,
|
||||
@ -385,6 +393,7 @@ pub const AnalUnit = packed struct(u64) {
|
||||
nav_ty,
|
||||
type,
|
||||
func,
|
||||
memoized_state,
|
||||
};
|
||||
|
||||
pub const Unwrapped = union(Kind) {
|
||||
@ -399,6 +408,8 @@ pub const AnalUnit = packed struct(u64) {
|
||||
type: InternPool.Index,
|
||||
/// This `AnalUnit` analyzes the body of the given runtime function.
|
||||
func: InternPool.Index,
|
||||
/// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`.
|
||||
memoized_state: MemoizedStateStage,
|
||||
};
|
||||
|
||||
pub fn unwrap(au: AnalUnit) Unwrapped {
|
||||
@ -434,6 +445,16 @@ pub const AnalUnit = packed struct(u64) {
|
||||
};
|
||||
};
|
||||
|
||||
pub const MemoizedStateStage = enum(u32) {
|
||||
/// Everything other than panics and `VaList`.
|
||||
main,
|
||||
/// Everything within `std.builtin.Panic`.
|
||||
/// Since the panic handler is user-provided, this must be able to reference the other memoized state.
|
||||
panic,
|
||||
/// Specifically `std.builtin.VaList`. See `Zcu.BuiltinDecl.stage`.
|
||||
va_list,
|
||||
};
|
||||
|
||||
pub const ComptimeUnit = extern struct {
|
||||
zir_index: TrackedInst.Index,
|
||||
namespace: NamespaceIndex,
|
||||
@ -769,6 +790,7 @@ pub const Dependee = union(enum) {
|
||||
interned: Index,
|
||||
namespace: TrackedInst.Index,
|
||||
namespace_name: NamespaceNameKey,
|
||||
memoized_state: MemoizedStateStage,
|
||||
};
|
||||
|
||||
pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: AnalUnit) void {
|
||||
@ -819,6 +841,11 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI
|
||||
.interned => |x| ip.interned_deps.get(x),
|
||||
.namespace => |x| ip.namespace_deps.get(x),
|
||||
.namespace_name => |x| ip.namespace_name_deps.get(x),
|
||||
.memoized_state => |stage| switch (stage) {
|
||||
.main => ip.memoized_state_main_deps.unwrap(),
|
||||
.panic => ip.memoized_state_panic_deps.unwrap(),
|
||||
.va_list => ip.memoized_state_va_list_deps.unwrap(),
|
||||
},
|
||||
} orelse return .{
|
||||
.ip = ip,
|
||||
.next_entry = .none,
|
||||
@ -848,6 +875,33 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
|
||||
// This block should allocate an entry and prepend it to the relevant `*_deps` list.
|
||||
// The `next` field should be correctly initialized; all other fields may be undefined.
|
||||
const new_index: DepEntry.Index = switch (dependee) {
|
||||
.memoized_state => |stage| new_index: {
|
||||
const deps = switch (stage) {
|
||||
.main => &ip.memoized_state_main_deps,
|
||||
.panic => &ip.memoized_state_panic_deps,
|
||||
.va_list => &ip.memoized_state_va_list_deps,
|
||||
};
|
||||
|
||||
if (deps.unwrap()) |first| {
|
||||
if (ip.dep_entries.items[@intFromEnum(first)].depender == .none) {
|
||||
// Dummy entry, so we can reuse it rather than allocating a new one!
|
||||
break :new_index first;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepend a new dependency.
|
||||
const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.popOrNull()) |new_index| new: {
|
||||
break :new .{ new_index, &ip.dep_entries.items[@intFromEnum(new_index)] };
|
||||
} else .{ @enumFromInt(ip.dep_entries.items.len), ip.dep_entries.addOneAssumeCapacity() };
|
||||
if (deps.unwrap()) |old_first| {
|
||||
ptr.next = old_first.toOptional();
|
||||
ip.dep_entries.items[@intFromEnum(old_first)].prev = new_index.toOptional();
|
||||
} else {
|
||||
ptr.next = .none;
|
||||
}
|
||||
deps.* = new_index.toOptional();
|
||||
break :new_index new_index;
|
||||
},
|
||||
inline else => |dependee_payload, tag| new_index: {
|
||||
const gop = try switch (tag) {
|
||||
.file => ip.file_deps,
|
||||
@ -857,6 +911,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
|
||||
.interned => ip.interned_deps,
|
||||
.namespace => ip.namespace_deps,
|
||||
.namespace_name => ip.namespace_name_deps,
|
||||
.memoized_state => comptime unreachable,
|
||||
}.getOrPut(gpa, dependee_payload);
|
||||
|
||||
if (gop.found_existing and ip.dep_entries.items[@intFromEnum(gop.value_ptr.*)].depender == .none) {
|
||||
|
||||
423
src/Sema.zig
423
src/Sema.zig
@ -428,7 +428,7 @@ pub const Block = struct {
|
||||
} });
|
||||
}
|
||||
|
||||
fn nodeOffset(block: Block, node_offset: i32) LazySrcLoc {
|
||||
pub fn nodeOffset(block: Block, node_offset: i32) LazySrcLoc {
|
||||
return block.src(LazySrcLoc.Offset.nodeOffset(node_offset));
|
||||
}
|
||||
|
||||
@ -2149,7 +2149,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
|
||||
const addrs_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(addr_arr_ty));
|
||||
|
||||
// var st: StackTrace = undefined;
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));
|
||||
|
||||
@ -6600,6 +6600,7 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
|
||||
.nav_val,
|
||||
.nav_ty,
|
||||
.type,
|
||||
.memoized_state,
|
||||
=> return, // does nothing outside a function
|
||||
};
|
||||
ip.funcSetDisableInstrumentation(func);
|
||||
@ -6609,7 +6610,7 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
|
||||
fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
|
||||
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
|
||||
const src = block.builtinCallArgSrc(extra.node, 0);
|
||||
block.float_mode = try sema.resolveBuiltinEnum(block, src, extra.operand, "FloatMode", .{ .simple = .operand_setFloatMode });
|
||||
block.float_mode = try sema.resolveBuiltinEnum(block, src, extra.operand, .FloatMode, .{ .simple = .operand_setFloatMode });
|
||||
}
|
||||
|
||||
fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
|
||||
@ -6917,7 +6918,7 @@ fn lookupInNamespace(
|
||||
|
||||
ignore_self: {
|
||||
const skip_nav = switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .type, .func => break :ignore_self,
|
||||
.@"comptime", .type, .func, .memoized_state => break :ignore_self,
|
||||
.nav_ty, .nav_val => |nav| nav,
|
||||
};
|
||||
var i: usize = 0;
|
||||
@ -6990,7 +6991,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
|
||||
|
||||
if (!block.ownerModule().error_tracing) return .none;
|
||||
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
|
||||
const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
|
||||
@ -7032,7 +7033,7 @@ fn popErrorReturnTrace(
|
||||
// AstGen determined this result does not go to an error-handling expr (try/catch/return etc.), or
|
||||
// the result is comptime-known to be a non-error. Either way, pop unconditionally.
|
||||
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
|
||||
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
@ -7058,7 +7059,7 @@ fn popErrorReturnTrace(
|
||||
defer then_block.instructions.deinit(gpa);
|
||||
|
||||
// If non-error, then pop the error return trace by restoring the index.
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
|
||||
const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
@ -7178,7 +7179,7 @@ fn zirCall(
|
||||
const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call);
|
||||
|
||||
switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .type, .nav_ty, .nav_val => input_is_error = false,
|
||||
.@"comptime", .type, .memoized_state, .nav_ty, .nav_val => input_is_error = false,
|
||||
.func => |owner_func| if (!zcu.intern_pool.funcAnalysisUnordered(owner_func).calls_or_awaits_errorable_fn) {
|
||||
// No errorable fn actually called; we have no error return trace
|
||||
input_is_error = false;
|
||||
@ -7201,7 +7202,7 @@ fn zirCall(
|
||||
// If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
|
||||
// need to clean-up our own trace if we were passed to a non-error-handling expression.
|
||||
if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) {
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace);
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "index", .no_embedded_nulls);
|
||||
const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
|
||||
@ -8091,7 +8092,7 @@ fn analyzeCall(
|
||||
if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
|
||||
|
||||
switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .nav_ty, .nav_val, .type => {},
|
||||
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
|
||||
.func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
|
||||
ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
|
||||
},
|
||||
@ -8557,7 +8558,7 @@ fn instantiateGenericCall(
|
||||
if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
|
||||
|
||||
switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .nav_ty, .nav_val, .type => {},
|
||||
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
|
||||
.func => |owner_func| if (Type.fromInterned(func_ty_info.return_type).isError(zcu)) {
|
||||
ip.funcSetCallsOrAwaitsErrorableFn(owner_func);
|
||||
},
|
||||
@ -9537,6 +9538,7 @@ fn zirFunc(
|
||||
const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
|
||||
const target = zcu.getTarget();
|
||||
const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = inst_data.src_node });
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
|
||||
var extra_index = extra.end;
|
||||
|
||||
@ -9588,7 +9590,7 @@ fn zirFunc(
|
||||
// error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency,
|
||||
// let's eval that now and just get the transitive error. (It's guaranteed to error
|
||||
// because it does the exact `cCallingConvention` call we just did.)
|
||||
const cc_type = try sema.getBuiltinType("CallingConvention");
|
||||
const cc_type = try sema.getBuiltinType(src, .CallingConvention);
|
||||
_ = try sema.namespaceLookupVal(
|
||||
block,
|
||||
LazySrcLoc.unneeded,
|
||||
@ -10302,7 +10304,7 @@ fn finishFunc(
|
||||
if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
|
||||
// Make sure that StackTrace's fields are resolved so that the backend can
|
||||
// lower this fn type.
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
|
||||
try unresolved_stack_trace_ty.resolveFields(pt);
|
||||
}
|
||||
|
||||
@ -14283,7 +14285,7 @@ fn maybeErrorUnwrap(
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const msg_inst = try sema.resolveInst(inst_data.operand);
|
||||
|
||||
const panic_fn = try getPanicInnerFn(sema, block, operand_src, "call");
|
||||
const panic_fn = try getBuiltin(sema, operand_src, .@"Panic.call");
|
||||
const err_return_trace = try sema.getErrorReturnTrace(block);
|
||||
const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
|
||||
try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
|
||||
@ -17477,7 +17479,7 @@ fn analyzeArithmetic(
|
||||
if (block.wantSafety() and want_safety and scalar_tag == .int) {
|
||||
if (zcu.backendSupportsFeature(.safety_checked_instructions)) {
|
||||
if (air_tag != air_tag_safe) {
|
||||
_ = try sema.preparePanicId(block, src, .integer_overflow);
|
||||
_ = try sema.preparePanicId(src, .integer_overflow);
|
||||
}
|
||||
return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);
|
||||
} else {
|
||||
@ -18381,7 +18383,7 @@ fn zirBuiltinSrc(
|
||||
} });
|
||||
};
|
||||
|
||||
const src_loc_ty = try sema.getBuiltinType("SourceLocation");
|
||||
const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(0), .SourceLocation);
|
||||
const fields = .{
|
||||
// module: [:0]const u8,
|
||||
module_name_val,
|
||||
@ -18408,7 +18410,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
const ty = try sema.resolveType(block, src, inst_data.operand);
|
||||
const type_info_ty = try sema.getBuiltinType("Type");
|
||||
const type_info_ty = try sema.getBuiltinType(src, .Type);
|
||||
const type_info_tag_ty = type_info_ty.unionTagType(zcu).?;
|
||||
|
||||
if (ty.typeDeclInst(zcu)) |type_decl_inst| {
|
||||
@ -18428,8 +18430,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
=> |type_info_tag| return unionInitFromEnumTag(sema, block, src, type_info_ty, @intFromEnum(type_info_tag), .void_value),
|
||||
|
||||
.@"fn" => {
|
||||
const fn_info_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Fn");
|
||||
const param_info_ty = try getBuiltinInnerType(sema, block, src, fn_info_ty, "Type.Fn", "Param");
|
||||
const fn_info_ty = try sema.getBuiltinType(src, .@"Type.Fn");
|
||||
const param_info_ty = try sema.getBuiltinType(src, .@"Type.Fn.Param");
|
||||
|
||||
const func_ty_info = zcu.typeToFunc(ty).?;
|
||||
const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
|
||||
@ -18499,7 +18501,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
func_ty_info.return_type,
|
||||
} });
|
||||
|
||||
const callconv_ty = try sema.getBuiltinType("CallingConvention");
|
||||
const callconv_ty = try sema.getBuiltinType(src, .CallingConvention);
|
||||
const callconv_val = Value.uninterpret(func_ty_info.cc, callconv_ty, pt) catch |err| switch (err) {
|
||||
error.TypeMismatch => @panic("std.builtin is corrupt"),
|
||||
error.OutOfMemory => |e| return e,
|
||||
@ -18527,8 +18529,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.int => {
|
||||
const int_info_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Int");
|
||||
const signedness_ty = try sema.getBuiltinType("Signedness");
|
||||
const int_info_ty = try sema.getBuiltinType(src, .@"Type.Int");
|
||||
const signedness_ty = try sema.getBuiltinType(src, .Signedness);
|
||||
const info = ty.intInfo(zcu);
|
||||
const field_values = .{
|
||||
// signedness: Signedness,
|
||||
@ -18546,7 +18548,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.float => {
|
||||
const float_info_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Float");
|
||||
const float_info_ty = try sema.getBuiltinType(src, .@"Type.Float");
|
||||
|
||||
const field_vals = .{
|
||||
// bits: u16,
|
||||
@ -18568,9 +18570,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
else
|
||||
try Type.fromInterned(info.child).lazyAbiAlignment(pt);
|
||||
|
||||
const addrspace_ty = try sema.getBuiltinType("AddressSpace");
|
||||
const pointer_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Pointer");
|
||||
const ptr_size_ty = try getBuiltinInnerType(sema, block, src, pointer_ty, "Type.Pointer", "Size");
|
||||
const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace);
|
||||
const pointer_ty = try sema.getBuiltinType(src, .@"Type.Pointer");
|
||||
const ptr_size_ty = try sema.getBuiltinType(src, .@"Type.Pointer.Size");
|
||||
|
||||
const field_values = .{
|
||||
// size: Size,
|
||||
@ -18603,7 +18605,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.array => {
|
||||
const array_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Array");
|
||||
const array_field_ty = try sema.getBuiltinType(src, .@"Type.Array");
|
||||
|
||||
const info = ty.arrayInfo(zcu);
|
||||
const field_values = .{
|
||||
@ -18624,7 +18626,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.vector => {
|
||||
const vector_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Vector");
|
||||
const vector_field_ty = try sema.getBuiltinType(src, .@"Type.Vector");
|
||||
|
||||
const info = ty.arrayInfo(zcu);
|
||||
const field_values = .{
|
||||
@ -18643,7 +18645,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.optional => {
|
||||
const optional_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Optional");
|
||||
const optional_field_ty = try sema.getBuiltinType(src, .@"Type.Optional");
|
||||
|
||||
const field_values = .{
|
||||
// child: type,
|
||||
@ -18660,7 +18662,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
},
|
||||
.error_set => {
|
||||
// Get the Error type
|
||||
const error_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Error");
|
||||
const error_field_ty = try sema.getBuiltinType(src, .@"Type.Error");
|
||||
|
||||
// Build our list of Error values
|
||||
// Optional value is only null if anyerror
|
||||
@ -18756,7 +18758,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.error_union => {
|
||||
const error_union_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "ErrorUnion");
|
||||
const error_union_field_ty = try sema.getBuiltinType(src, .@"Type.ErrorUnion");
|
||||
|
||||
const field_values = .{
|
||||
// error_set: type,
|
||||
@ -18776,7 +18778,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
.@"enum" => {
|
||||
const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive);
|
||||
|
||||
const enum_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "EnumField");
|
||||
const enum_field_ty = try sema.getBuiltinType(src, .@"Type.EnumField");
|
||||
|
||||
const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len);
|
||||
for (enum_field_vals, 0..) |*field_val, tag_index| {
|
||||
@ -18861,9 +18863,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.loadEnumType(ty.toIntern()).namespace.toOptional());
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ip.loadEnumType(ty.toIntern()).namespace.toOptional());
|
||||
|
||||
const type_enum_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Enum");
|
||||
const type_enum_ty = try sema.getBuiltinType(src, .@"Type.Enum");
|
||||
|
||||
const field_values = .{
|
||||
// tag_type: type,
|
||||
@ -18885,8 +18887,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.@"union" => {
|
||||
const type_union_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Union");
|
||||
const union_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "UnionField");
|
||||
const type_union_ty = try sema.getBuiltinType(src, .@"Type.Union");
|
||||
const union_field_ty = try sema.getBuiltinType(src, .@"Type.UnionField");
|
||||
|
||||
try ty.resolveLayout(pt); // Getting alignment requires type layout
|
||||
const union_obj = zcu.typeToUnion(ty).?;
|
||||
@ -18974,14 +18976,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(zcu).toOptional());
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ty.getNamespaceIndex(zcu).toOptional());
|
||||
|
||||
const enum_tag_ty_val = try pt.intern(.{ .opt = .{
|
||||
.ty = (try pt.optionalType(.type_type)).toIntern(),
|
||||
.val = if (ty.unionTagType(zcu)) |tag_ty| tag_ty.toIntern() else .none,
|
||||
} });
|
||||
|
||||
const container_layout_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "ContainerLayout");
|
||||
const container_layout_ty = try sema.getBuiltinType(src, .@"Type.ContainerLayout");
|
||||
|
||||
const field_values = .{
|
||||
// layout: ContainerLayout,
|
||||
@ -19004,8 +19006,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.@"struct" => {
|
||||
const type_struct_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Struct");
|
||||
const struct_field_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "StructField");
|
||||
const type_struct_ty = try sema.getBuiltinType(src, .@"Type.Struct");
|
||||
const struct_field_ty = try sema.getBuiltinType(src, .@"Type.StructField");
|
||||
|
||||
try ty.resolveLayout(pt); // Getting alignment requires type layout
|
||||
|
||||
@ -19169,7 +19171,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} });
|
||||
};
|
||||
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace(zcu));
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ty.getNamespace(zcu));
|
||||
|
||||
const backing_integer_val = try pt.intern(.{ .opt = .{
|
||||
.ty = (try pt.optionalType(.type_type)).toIntern(),
|
||||
@ -19179,7 +19181,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
} else .none,
|
||||
} });
|
||||
|
||||
const container_layout_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "ContainerLayout");
|
||||
const container_layout_ty = try sema.getBuiltinType(src, .@"Type.ContainerLayout");
|
||||
|
||||
const layout = ty.containerLayout(zcu);
|
||||
|
||||
@ -19205,10 +19207,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
})));
|
||||
},
|
||||
.@"opaque" => {
|
||||
const type_opaque_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Opaque");
|
||||
const type_opaque_ty = try sema.getBuiltinType(src, .@"Type.Opaque");
|
||||
|
||||
try ty.resolveFields(pt);
|
||||
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace(zcu));
|
||||
const decls_val = try sema.typeInfoDecls(block, src, ty.getNamespace(zcu));
|
||||
|
||||
const field_values = .{
|
||||
// decls: []const Declaration,
|
||||
@ -19232,14 +19234,13 @@ fn typeInfoDecls(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
type_info_ty: Type,
|
||||
opt_namespace: InternPool.OptionalNamespaceIndex,
|
||||
) CompileError!InternPool.Index {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const gpa = sema.gpa;
|
||||
|
||||
const declaration_ty = try getBuiltinInnerType(sema, block, src, type_info_ty, "Type", "Declaration");
|
||||
const declaration_ty = try sema.getBuiltinType(src, .@"Type.Declaration");
|
||||
|
||||
var decl_vals = std.ArrayList(InternPool.Index).init(gpa);
|
||||
defer decl_vals.deinit();
|
||||
@ -20181,11 +20182,11 @@ fn retWithErrTracing(
|
||||
else => true,
|
||||
};
|
||||
const gpa = sema.gpa;
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
|
||||
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
const return_err_fn = try sema.getBuiltin("returnError");
|
||||
const return_err_fn = Air.internedToRef(try sema.getBuiltin(src, .returnError));
|
||||
const args: [1]Air.Inst.Ref = .{err_return_trace};
|
||||
|
||||
if (!need_check) {
|
||||
@ -21607,7 +21608,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
|
||||
const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
|
||||
@ -21616,7 +21617,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
|
||||
.func => |func| if (ip.funcAnalysisUnordered(func).calls_or_awaits_errorable_fn and block.ownerModule().error_tracing) {
|
||||
return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
|
||||
},
|
||||
.@"comptime", .nav_ty, .nav_val, .type => {},
|
||||
.@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
|
||||
}
|
||||
return Air.internedToRef(try pt.intern(.{ .opt = .{
|
||||
.ty = opt_ptr_stack_trace_ty.toIntern(),
|
||||
@ -21896,7 +21897,7 @@ fn zirReify(
|
||||
},
|
||||
},
|
||||
};
|
||||
const type_info_ty = try sema.getBuiltinType("Type");
|
||||
const type_info_ty = try sema.getBuiltinType(src, .Type);
|
||||
const uncasted_operand = try sema.resolveInst(extra.operand);
|
||||
const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
|
||||
const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Type });
|
||||
@ -23156,7 +23157,7 @@ fn reifyStruct(
|
||||
|
||||
fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
|
||||
const pt = sema.pt;
|
||||
const va_list_ty = try sema.getBuiltinType("VaList");
|
||||
const va_list_ty = try sema.getBuiltinType(src, .VaList);
|
||||
const va_list_ptr = try pt.singleMutPtrType(va_list_ty);
|
||||
|
||||
const inst = try sema.resolveInst(zir_ref);
|
||||
@ -23195,7 +23196,7 @@ fn zirCVaCopy(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
|
||||
const va_list_src = block.builtinCallArgSrc(extra.node, 0);
|
||||
|
||||
const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand);
|
||||
const va_list_ty = try sema.getBuiltinType("VaList");
|
||||
const va_list_ty = try sema.getBuiltinType(src, .VaList);
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, null);
|
||||
return block.addTyOp(.c_va_copy, va_list_ty, va_list_ref);
|
||||
@ -23215,7 +23216,7 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
|
||||
fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
|
||||
const src = block.nodeOffset(@bitCast(extended.operand));
|
||||
|
||||
const va_list_ty = try sema.getBuiltinType("VaList");
|
||||
const va_list_ty = try sema.getBuiltinType(src, .VaList);
|
||||
try sema.requireRuntimeBlock(block, src, null);
|
||||
return block.addInst(.{
|
||||
.tag = .c_va_start,
|
||||
@ -24821,7 +24822,7 @@ fn resolveExportOptions(
|
||||
const zcu = pt.zcu;
|
||||
const gpa = sema.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
const export_options_ty = try sema.getBuiltinType("ExportOptions");
|
||||
const export_options_ty = try sema.getBuiltinType(src, .ExportOptions);
|
||||
const air_ref = try sema.resolveInst(zir_ref);
|
||||
const options = try sema.coerce(block, export_options_ty, air_ref, src);
|
||||
|
||||
@ -24871,15 +24872,15 @@ fn resolveBuiltinEnum(
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
zir_ref: Zir.Inst.Ref,
|
||||
comptime name: []const u8,
|
||||
comptime name: Zcu.BuiltinDecl,
|
||||
reason: ComptimeReason,
|
||||
) CompileError!@field(std.builtin, name) {
|
||||
) CompileError!@field(std.builtin, @tagName(name)) {
|
||||
const pt = sema.pt;
|
||||
const ty = try sema.getBuiltinType(name);
|
||||
const ty = try sema.getBuiltinType(src, name);
|
||||
const air_ref = try sema.resolveInst(zir_ref);
|
||||
const coerced = try sema.coerce(block, ty, air_ref, src);
|
||||
const val = try sema.resolveConstDefinedValue(block, src, coerced, reason);
|
||||
return pt.zcu.toEnum(@field(std.builtin, name), val);
|
||||
return pt.zcu.toEnum(@field(std.builtin, @tagName(name)), val);
|
||||
}
|
||||
|
||||
fn resolveAtomicOrder(
|
||||
@ -24889,7 +24890,7 @@ fn resolveAtomicOrder(
|
||||
zir_ref: Zir.Inst.Ref,
|
||||
reason: ComptimeReason,
|
||||
) CompileError!std.builtin.AtomicOrder {
|
||||
return sema.resolveBuiltinEnum(block, src, zir_ref, "AtomicOrder", reason);
|
||||
return sema.resolveBuiltinEnum(block, src, zir_ref, .AtomicOrder, reason);
|
||||
}
|
||||
|
||||
fn resolveAtomicRmwOp(
|
||||
@ -24898,7 +24899,7 @@ fn resolveAtomicRmwOp(
|
||||
src: LazySrcLoc,
|
||||
zir_ref: Zir.Inst.Ref,
|
||||
) CompileError!std.builtin.AtomicRmwOp {
|
||||
return sema.resolveBuiltinEnum(block, src, zir_ref, "AtomicRmwOp", .{ .simple = .operand_atomicRmw_operation });
|
||||
return sema.resolveBuiltinEnum(block, src, zir_ref, .AtomicRmwOp, .{ .simple = .operand_atomicRmw_operation });
|
||||
}
|
||||
|
||||
fn zirCmpxchg(
|
||||
@ -25078,7 +25079,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const op_src = block.builtinCallArgSrc(inst_data.src_node, 0);
|
||||
const operand_src = block.builtinCallArgSrc(inst_data.src_node, 1);
|
||||
const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, "ReduceOp", .{ .simple = .operand_reduce_operation });
|
||||
const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, .ReduceOp, .{ .simple = .operand_reduce_operation });
|
||||
const operand = try sema.resolveInst(extra.rhs);
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
const pt = sema.pt;
|
||||
@ -25668,7 +25669,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
|
||||
const func = try sema.resolveInst(extra.callee);
|
||||
|
||||
const modifier_ty = try sema.getBuiltinType("CallModifier");
|
||||
const modifier_ty = try sema.getBuiltinType(call_src, .CallModifier);
|
||||
const air_ref = try sema.resolveInst(extra.modifier);
|
||||
const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src);
|
||||
const modifier_val = try sema.resolveConstDefinedValue(block, modifier_src, modifier_ref, .{ .simple = .call_modifier });
|
||||
@ -26630,13 +26631,13 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
const body = sema.code.bodySlice(extra_index, body_len);
|
||||
extra_index += body.len;
|
||||
|
||||
const cc_ty = try sema.getBuiltinType("CallingConvention");
|
||||
const cc_ty = try sema.getBuiltinType(cc_src, .CallingConvention);
|
||||
const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, .{ .simple = .@"callconv" });
|
||||
break :blk try sema.analyzeValueAsCallconv(block, cc_src, val);
|
||||
} else if (extra.data.bits.has_cc_ref) blk: {
|
||||
const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
const cc_ty = try sema.getBuiltinType("CallingConvention");
|
||||
const cc_ty = try sema.getBuiltinType(cc_src, .CallingConvention);
|
||||
const uncoerced_cc = try sema.resolveInst(cc_ref);
|
||||
const coerced_cc = try sema.coerce(block, cc_ty, uncoerced_cc, cc_src);
|
||||
const cc_val = try sema.resolveConstDefinedValue(block, cc_src, coerced_cc, .{ .simple = .@"callconv" });
|
||||
@ -26656,7 +26657,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
// error by trying to evaluate `std.builtin.CallingConvention.c`, so for consistency,
|
||||
// let's eval that now and just get the transitive error. (It's guaranteed to error
|
||||
// because it does the exact `cCallingConvention` call we just did.)
|
||||
const cc_type = try sema.getBuiltinType("CallingConvention");
|
||||
const cc_type = try sema.getBuiltinType(cc_src, .CallingConvention);
|
||||
_ = try sema.namespaceLookupVal(
|
||||
block,
|
||||
LazySrcLoc.unneeded,
|
||||
@ -26834,7 +26835,7 @@ fn resolvePrefetchOptions(
|
||||
const zcu = pt.zcu;
|
||||
const gpa = sema.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
const options_ty = try sema.getBuiltinType("PrefetchOptions");
|
||||
const options_ty = try sema.getBuiltinType(src, .PrefetchOptions);
|
||||
const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);
|
||||
|
||||
const rw_src = block.src(.{ .init_field_rw = src.offset.node_offset_builtin_call_arg.builtin_call_node });
|
||||
@ -26902,7 +26903,7 @@ fn resolveExternOptions(
|
||||
const gpa = sema.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
const options_inst = try sema.resolveInst(zir_ref);
|
||||
const extern_options_ty = try sema.getBuiltinType("ExternOptions");
|
||||
const extern_options_ty = try sema.getBuiltinType(src, .ExternOptions);
|
||||
const options = try sema.coerce(block, extern_options_ty, options_inst, src);
|
||||
|
||||
const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node });
|
||||
@ -27004,6 +27005,7 @@ fn zirBuiltinExtern(
|
||||
.zir_index = switch (sema.owner.unwrap()) {
|
||||
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index,
|
||||
.type => |owner_ty| Type.fromInterned(owner_ty).typeDeclInst(zcu).?,
|
||||
.memoized_state => unreachable,
|
||||
.nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index,
|
||||
.func => |func| zir_index: {
|
||||
const func_info = zcu.funcInfo(func);
|
||||
@ -27081,23 +27083,25 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
|
||||
const src = block.nodeOffset(@bitCast(extended.operand));
|
||||
const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
|
||||
|
||||
const type_name = switch (value) {
|
||||
.atomic_order => "AtomicOrder",
|
||||
.atomic_rmw_op => "AtomicRmwOp",
|
||||
.calling_convention => "CallingConvention",
|
||||
.address_space => "AddressSpace",
|
||||
.float_mode => "FloatMode",
|
||||
.reduce_op => "ReduceOp",
|
||||
.call_modifier => "CallModifier",
|
||||
.prefetch_options => "PrefetchOptions",
|
||||
.export_options => "ExportOptions",
|
||||
.extern_options => "ExternOptions",
|
||||
.type_info => "Type",
|
||||
.branch_hint => "BranchHint",
|
||||
const ty = switch (value) {
|
||||
// zig fmt: off
|
||||
.atomic_order => try sema.getBuiltinType(src, .AtomicOrder),
|
||||
.atomic_rmw_op => try sema.getBuiltinType(src, .AtomicRmwOp),
|
||||
.calling_convention => try sema.getBuiltinType(src, .CallingConvention),
|
||||
.address_space => try sema.getBuiltinType(src, .AddressSpace),
|
||||
.float_mode => try sema.getBuiltinType(src, .FloatMode),
|
||||
.reduce_op => try sema.getBuiltinType(src, .ReduceOp),
|
||||
.call_modifier => try sema.getBuiltinType(src, .CallModifier),
|
||||
.prefetch_options => try sema.getBuiltinType(src, .PrefetchOptions),
|
||||
.export_options => try sema.getBuiltinType(src, .ExportOptions),
|
||||
.extern_options => try sema.getBuiltinType(src, .ExternOptions),
|
||||
.type_info => try sema.getBuiltinType(src, .Type),
|
||||
.branch_hint => try sema.getBuiltinType(src, .BranchHint),
|
||||
// zig fmt: on
|
||||
|
||||
// Values are handled here.
|
||||
.calling_convention_c => {
|
||||
const callconv_ty = try sema.getBuiltinType("CallingConvention");
|
||||
const callconv_ty = try sema.getBuiltinType(src, .CallingConvention);
|
||||
return try sema.namespaceLookupVal(
|
||||
block,
|
||||
src,
|
||||
@ -27107,7 +27111,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
|
||||
},
|
||||
.calling_convention_inline => {
|
||||
comptime assert(@typeInfo(std.builtin.CallingConvention.Tag).@"enum".tag_type == u8);
|
||||
const callconv_ty = try sema.getBuiltinType("CallingConvention");
|
||||
const callconv_ty = try sema.getBuiltinType(src, .CallingConvention);
|
||||
const callconv_tag_ty = callconv_ty.unionTagType(zcu) orelse @panic("std.builtin is corrupt");
|
||||
const inline_tag_val = try pt.enumValue(
|
||||
callconv_tag_ty,
|
||||
@ -27119,7 +27123,6 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
|
||||
return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);
|
||||
},
|
||||
};
|
||||
const ty = try sema.getBuiltinType(type_name);
|
||||
return Air.internedToRef(ty.toIntern());
|
||||
}
|
||||
|
||||
@ -27158,7 +27161,7 @@ fn zirBranchHint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
|
||||
const uncoerced_hint = try sema.resolveInst(extra.operand);
|
||||
const operand_src = block.builtinCallArgSrc(extra.node, 0);
|
||||
|
||||
const hint_ty = try sema.getBuiltinType("BranchHint");
|
||||
const hint_ty = try sema.getBuiltinType(operand_src, .BranchHint);
|
||||
const coerced_hint = try sema.coerce(block, hint_ty, uncoerced_hint, operand_src);
|
||||
const hint_val = try sema.resolveConstDefinedValue(block, operand_src, coerced_hint, .{ .simple = .operand_branchHint });
|
||||
|
||||
@ -27603,61 +27606,19 @@ fn explainWhyTypeIsNotPacked(
|
||||
}
|
||||
}
|
||||
|
||||
fn prepareSimplePanic(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
|
||||
if (zcu.panic_func_index == .none) {
|
||||
zcu.panic_func_index = try sema.getPanicInnerFn(block, src, "call");
|
||||
// Here, function body analysis must be queued up so that backends can
|
||||
// make calls to this function.
|
||||
try zcu.ensureFuncBodyAnalysisQueued(zcu.panic_func_index);
|
||||
}
|
||||
|
||||
if (zcu.null_stack_trace == .none) {
|
||||
const stack_trace_ty = try sema.getBuiltinType("StackTrace");
|
||||
try stack_trace_ty.resolveFields(pt);
|
||||
const target = zcu.getTarget();
|
||||
const ptr_stack_trace_ty = try pt.ptrTypeSema(.{
|
||||
.child = stack_trace_ty.toIntern(),
|
||||
.flags = .{
|
||||
.address_space = target_util.defaultAddressSpace(target, .global_constant),
|
||||
},
|
||||
});
|
||||
const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
|
||||
zcu.null_stack_trace = try pt.intern(.{ .opt = .{
|
||||
.ty = opt_ptr_stack_trace_ty.toIntern(),
|
||||
.val = .none,
|
||||
} });
|
||||
}
|
||||
}
|
||||
|
||||
/// Backends depend on panic decls being available when lowering safety-checked
|
||||
/// instructions. This function ensures the panic function will be available to
|
||||
/// be called during that time.
|
||||
fn preparePanicId(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Nav.Index {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const gpa = sema.gpa;
|
||||
if (zcu.panic_messages[@intFromEnum(panic_id)].unwrap()) |x| return x;
|
||||
|
||||
try sema.prepareSimplePanic(block, src);
|
||||
|
||||
const panic_ty = try sema.getBuiltinType("Panic");
|
||||
const panic_messages_ty = try sema.getBuiltinInnerType(block, src, panic_ty, "Panic", "messages");
|
||||
const msg_nav_index = (sema.namespaceLookup(
|
||||
block,
|
||||
LazySrcLoc.unneeded,
|
||||
panic_messages_ty.getNamespaceIndex(zcu),
|
||||
try zcu.intern_pool.getOrPutString(gpa, pt.tid, @tagName(panic_id), .no_embedded_nulls),
|
||||
) catch |err| switch (err) {
|
||||
error.AnalysisFail => return error.AnalysisFail,
|
||||
error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
|
||||
error.OutOfMemory => |e| return e,
|
||||
}).?;
|
||||
try sema.ensureNavResolved(src, msg_nav_index, .fully);
|
||||
zcu.panic_messages[@intFromEnum(panic_id)] = msg_nav_index.toOptional();
|
||||
return msg_nav_index;
|
||||
fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Index {
|
||||
const zcu = sema.pt.zcu;
|
||||
try sema.ensureMemoizedStateResolved(src, .panic);
|
||||
try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.@"Panic.call");
|
||||
switch (panic_id) {
|
||||
inline else => |ct_panic_id| {
|
||||
const name = "Panic.messages." ++ @tagName(ct_panic_id);
|
||||
return @field(zcu.builtin_decl_values, name);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn addSafetyCheck(
|
||||
@ -27761,10 +27722,10 @@ fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.
|
||||
return;
|
||||
}
|
||||
|
||||
try sema.prepareSimplePanic(block, src);
|
||||
try sema.ensureMemoizedStateResolved(src, .panic);
|
||||
try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.@"Panic.call");
|
||||
|
||||
const panic_func = zcu.funcInfo(zcu.panic_func_index);
|
||||
const panic_fn = try sema.analyzeNavVal(block, src, panic_func.owner_nav);
|
||||
const panic_fn = Air.internedToRef(zcu.builtin_decl_values.@"Panic.call");
|
||||
const null_stack_trace = Air.internedToRef(zcu.null_stack_trace);
|
||||
|
||||
const opt_usize_ty = try pt.optionalType(.usize_type);
|
||||
@ -27812,7 +27773,7 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air.
|
||||
if (!zcu.backendSupportsFeature(.panic_fn)) {
|
||||
_ = try block.addNoOp(.trap);
|
||||
} else {
|
||||
const panic_fn = try getPanicInnerFn(sema, block, src, "unwrapError");
|
||||
const panic_fn = try getBuiltin(sema, src, .@"Panic.unwrapError");
|
||||
const err_return_trace = try sema.getErrorReturnTrace(block);
|
||||
const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
|
||||
try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
|
||||
@ -27829,7 +27790,7 @@ fn addSafetyCheckIndexOob(
|
||||
) !void {
|
||||
assert(!parent_block.isComptime());
|
||||
const ok = try parent_block.addBinOp(cmp_op, index, len);
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, "outOfBounds", &.{ index, len });
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.outOfBounds", &.{ index, len });
|
||||
}
|
||||
|
||||
fn addSafetyCheckInactiveUnionField(
|
||||
@ -27841,7 +27802,7 @@ fn addSafetyCheckInactiveUnionField(
|
||||
) !void {
|
||||
assert(!parent_block.isComptime());
|
||||
const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, "inactiveUnionField", &.{ active_tag, wanted_tag });
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.inactiveUnionField", &.{ active_tag, wanted_tag });
|
||||
}
|
||||
|
||||
fn addSafetyCheckSentinelMismatch(
|
||||
@ -27882,7 +27843,7 @@ fn addSafetyCheckSentinelMismatch(
|
||||
break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
|
||||
};
|
||||
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, "sentinelMismatch", &.{
|
||||
return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.sentinelMismatch", &.{
|
||||
expected_sentinel, actual_sentinel,
|
||||
});
|
||||
}
|
||||
@ -27892,7 +27853,7 @@ fn addSafetyCheckCall(
|
||||
parent_block: *Block,
|
||||
src: LazySrcLoc,
|
||||
ok: Air.Inst.Ref,
|
||||
func_name: []const u8,
|
||||
comptime func_decl: Zcu.BuiltinDecl,
|
||||
args: []const Air.Inst.Ref,
|
||||
) !void {
|
||||
assert(!parent_block.isComptime());
|
||||
@ -27916,7 +27877,7 @@ fn addSafetyCheckCall(
|
||||
if (!zcu.backendSupportsFeature(.panic_fn)) {
|
||||
_ = try fail_block.addNoOp(.trap);
|
||||
} else {
|
||||
const panic_fn = try getPanicInnerFn(sema, &fail_block, src, func_name);
|
||||
const panic_fn = try getBuiltin(sema, src, func_decl);
|
||||
try sema.callBuiltin(&fail_block, src, Air.internedToRef(panic_fn), .auto, args, .@"safety check");
|
||||
}
|
||||
|
||||
@ -27925,9 +27886,8 @@ fn addSafetyCheckCall(
|
||||
|
||||
/// This does not set `sema.branch_hint`.
|
||||
fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void {
|
||||
const msg_nav_index = try sema.preparePanicId(block, src, panic_id);
|
||||
const msg_inst = try sema.analyzeNavVal(block, src, msg_nav_index);
|
||||
try sema.panicWithMsg(block, src, msg_inst, .@"safety check");
|
||||
const msg_val = try sema.preparePanicId(src, panic_id);
|
||||
try sema.panicWithMsg(block, src, Air.internedToRef(msg_val), .@"safety check");
|
||||
}
|
||||
|
||||
fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
|
||||
@ -32524,6 +32484,19 @@ fn addTypeReferenceEntry(
|
||||
try zcu.addTypeReference(sema.owner, referenced_type, src);
|
||||
}
|
||||
|
||||
fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.MemoizedStateStage) SemaError!void {
|
||||
const pt = sema.pt;
|
||||
|
||||
const unit: AnalUnit = .wrap(.{ .memoized_state = stage });
|
||||
try sema.addReferenceEntry(src, unit);
|
||||
try sema.declareDependency(.{ .memoized_state = stage });
|
||||
|
||||
if (pt.zcu.analysis_in_progress.contains(unit)) {
|
||||
return sema.failWithOwnedErrorMsg(null, try sema.errMsg(src, "dependency loop detected", .{}));
|
||||
}
|
||||
try pt.ensureMemoizedStateUpToDate(stage);
|
||||
}
|
||||
|
||||
pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
@ -33373,7 +33346,7 @@ fn analyzeSlice(
|
||||
assert(!block.isComptime());
|
||||
try sema.requireRuntimeBlock(block, src, runtime_src.?);
|
||||
const ok = try block.addBinOp(.cmp_lte, start, end);
|
||||
try sema.addSafetyCheckCall(block, src, ok, "startGreaterThanEnd", &.{ start, end });
|
||||
try sema.addSafetyCheckCall(block, src, ok, .@"Panic.startGreaterThanEnd", &.{ start, end });
|
||||
}
|
||||
const new_len = if (by_length)
|
||||
try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
|
||||
@ -35493,7 +35466,7 @@ pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
|
||||
pub fn resolveFnTypes(sema: *Sema, fn_ty: Type, src: LazySrcLoc) CompileError!void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
@ -35505,7 +35478,7 @@ pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
|
||||
Type.fromInterned(fn_ty_info.return_type).isError(zcu))
|
||||
{
|
||||
// Ensure the type exists so that backends can assume that.
|
||||
_ = try sema.getBuiltinType("StackTrace");
|
||||
_ = try sema.getBuiltinType(src, .StackTrace);
|
||||
}
|
||||
|
||||
for (0..fn_ty_info.param_types.len) |i| {
|
||||
@ -37550,7 +37523,7 @@ pub fn analyzeAsAddressSpace(
|
||||
) !std.builtin.AddressSpace {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const addrspace_ty = try sema.getBuiltinType("AddressSpace");
|
||||
const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace);
|
||||
const coerced = try sema.coerce(block, addrspace_ty, air_ref, src);
|
||||
const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{ .simple = .@"addrspace" });
|
||||
const address_space = zcu.toEnum(std.builtin.AddressSpace, addrspace_val);
|
||||
@ -38747,69 +38720,15 @@ const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadR
|
||||
const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr;
|
||||
const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult;
|
||||
|
||||
fn getPanicInnerFn(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
inner_name: []const u8,
|
||||
) !InternPool.Index {
|
||||
const gpa = sema.gpa;
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const outer_ty = try sema.getBuiltinType("Panic");
|
||||
const inner_name_ip = try ip.getOrPutString(gpa, pt.tid, inner_name, .no_embedded_nulls);
|
||||
const opt_fn_ref = try namespaceLookupVal(sema, block, src, outer_ty.getNamespaceIndex(zcu), inner_name_ip);
|
||||
const fn_ref = opt_fn_ref orelse return sema.fail(block, src, "std.builtin.Panic missing {s}", .{inner_name});
|
||||
const fn_val = try sema.resolveConstValue(block, src, fn_ref, .{ .simple = .panic_handler });
|
||||
if (fn_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") {
|
||||
return sema.fail(block, src, "std.builtin.Panic.{s} is not a function", .{inner_name});
|
||||
}
|
||||
// Better not to queue up function body analysis because the function might be generic, and
|
||||
// the semantic analysis for the call will already queue if necessary.
|
||||
return fn_val.toIntern();
|
||||
pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, comptime decl: Zcu.BuiltinDecl) SemaError!Type {
|
||||
comptime assert(decl.kind() == .type);
|
||||
try sema.ensureMemoizedStateResolved(src, decl.stage());
|
||||
return .fromInterned(@field(sema.pt.zcu.builtin_decl_values, @tagName(decl)));
|
||||
}
|
||||
|
||||
fn getBuiltinType(sema: *Sema, name: []const u8) SemaError!Type {
|
||||
const pt = sema.pt;
|
||||
const ty_inst = try sema.getBuiltin(name);
|
||||
const ty = Type.fromInterned(ty_inst.toInterned() orelse @panic("std.builtin is corrupt"));
|
||||
try ty.resolveFully(pt);
|
||||
return ty;
|
||||
}
|
||||
|
||||
fn getBuiltinInnerType(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
outer_ty: Type,
|
||||
/// Relative to "std.builtin".
|
||||
compile_error_parent_name: []const u8,
|
||||
inner_name: []const u8,
|
||||
) !Type {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const gpa = sema.gpa;
|
||||
const inner_name_ip = try ip.getOrPutString(gpa, pt.tid, inner_name, .no_embedded_nulls);
|
||||
const opt_nav = try sema.namespaceLookup(block, src, outer_ty.getNamespaceIndex(zcu), inner_name_ip);
|
||||
const nav = opt_nav orelse return sema.fail(block, src, "std.builtin.{s} missing {s}", .{
|
||||
compile_error_parent_name, inner_name,
|
||||
});
|
||||
try sema.ensureNavResolved(src, nav, .fully);
|
||||
const val = Value.fromInterned(ip.getNav(nav).status.fully_resolved.val);
|
||||
const ty = val.toType();
|
||||
try ty.resolveFully(pt);
|
||||
return ty;
|
||||
}
|
||||
|
||||
fn getBuiltin(sema: *Sema, name: []const u8) SemaError!Air.Inst.Ref {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const nav = try pt.getBuiltinNav(name);
|
||||
try pt.ensureNavValUpToDate(nav);
|
||||
return Air.internedToRef(ip.getNav(nav).status.fully_resolved.val);
|
||||
pub fn getBuiltin(sema: *Sema, src: LazySrcLoc, comptime decl: Zcu.BuiltinDecl) SemaError!InternPool.Index {
|
||||
comptime assert(decl.kind() != .type);
|
||||
try sema.ensureMemoizedStateResolved(src, decl.stage());
|
||||
return @field(sema.pt.zcu.builtin_decl_values, @tagName(decl));
|
||||
}
|
||||
|
||||
pub const NavPtrModifiers = struct {
|
||||
@ -38877,3 +38796,77 @@ pub fn resolveNavPtrModifiers(
|
||||
.@"addrspace" = @"addrspace",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn analyzeMemoizedState(sema: *Sema, block: *Block, src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
var any_changed = false;
|
||||
|
||||
inline for (comptime std.enums.values(Zcu.BuiltinDecl)) |builtin_decl| {
|
||||
if (stage == comptime builtin_decl.stage()) {
|
||||
const parent_ns: Zcu.Namespace.Index, const parent_name: []const u8, const name: []const u8 = switch (comptime builtin_decl.access()) {
|
||||
.direct => |name| .{ builtin_namespace, "std.builtin", name },
|
||||
.nested => |nested| access: {
|
||||
const parent_ty: Type = .fromInterned(@field(zcu.builtin_decl_values, @tagName(nested[0])));
|
||||
const parent_ns = parent_ty.getNamespace(zcu).unwrap() orelse {
|
||||
return sema.fail(block, src, "std.builtin.{s} is not a container type", .{@tagName(nested[0])});
|
||||
};
|
||||
break :access .{ parent_ns, "std.builtin." ++ @tagName(nested[0]), nested[1] };
|
||||
},
|
||||
};
|
||||
|
||||
const name_nts = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
|
||||
const result = try sema.namespaceLookupVal(block, src, parent_ns, name_nts) orelse
|
||||
return sema.fail(block, src, "{s} missing {s}", .{ parent_name, name });
|
||||
|
||||
const val = try sema.resolveConstDefinedValue(block, src, result, null);
|
||||
|
||||
switch (builtin_decl.kind()) {
|
||||
.type => if (val.typeOf(zcu).zigTypeTag(zcu) != .type) {
|
||||
return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name });
|
||||
} else {
|
||||
try val.toType().resolveFully(pt);
|
||||
},
|
||||
.func => if (val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") {
|
||||
return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name });
|
||||
},
|
||||
.string => {
|
||||
const ty = val.typeOf(zcu);
|
||||
if (!ty.isSinglePointer(zcu) or
|
||||
!ty.isConstPtr(zcu) or
|
||||
ty.childType(zcu).zigTypeTag(zcu) != .array or
|
||||
ty.childType(zcu).childType(zcu).toIntern() != .u8_type)
|
||||
{
|
||||
return sema.fail(block, src, "{s}.{s} is not a valid string", .{ parent_name, name });
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const prev = @field(zcu.builtin_decl_values, @tagName(builtin_decl));
|
||||
if (val.toIntern() != prev) {
|
||||
@field(zcu.builtin_decl_values, @tagName(builtin_decl)) = val.toIntern();
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stage == .panic) {
|
||||
// We use `getBuiltinType` because this is from an earlier stage.
|
||||
const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
|
||||
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
|
||||
const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
|
||||
const null_stack_trace = try pt.intern(.{ .opt = .{
|
||||
.ty = opt_ptr_stack_trace_ty.toIntern(),
|
||||
.val = .none,
|
||||
} });
|
||||
if (null_stack_trace != zcu.null_stack_trace) {
|
||||
zcu.null_stack_trace = null_stack_trace;
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return any_changed;
|
||||
}
|
||||
|
||||
217
src/Zcu.zig
217
src/Zcu.zig
@ -217,15 +217,212 @@ all_type_references: std.ArrayListUnmanaged(TypeReference) = .empty,
|
||||
/// Freelist of indices in `all_type_references`.
|
||||
free_type_references: std.ArrayListUnmanaged(u32) = .empty,
|
||||
|
||||
panic_messages: [PanicId.len]InternPool.Nav.Index.Optional = .{.none} ** PanicId.len,
|
||||
/// The panic function body.
|
||||
panic_func_index: InternPool.Index = .none,
|
||||
/// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = s })`, where `s` depends on the field.
|
||||
builtin_decl_values: BuiltinDecl.Memoized = .{},
|
||||
/// Populated by analysis of `AnalUnit.wrap(.{ .memoized_state = .panic })`.
|
||||
null_stack_trace: InternPool.Index = .none,
|
||||
|
||||
generation: u32 = 0,
|
||||
|
||||
pub const PerThread = @import("Zcu/PerThread.zig");
|
||||
|
||||
/// Names of declarations in `std.builtin` whose values are memoized in a `BuiltinDecl.Memoized`.
|
||||
/// The name must exactly match the declaration name, as comptime logic is used to compute the namespace accesses.
|
||||
/// Parent namespaces must be before their children in this enum. For instance, `.Type` must be before `.@"Type.Fn"`.
|
||||
/// Additionally, parent namespaces must be resolved in the same stage as their children; see `BuiltinDecl.stage`.
|
||||
pub const BuiltinDecl = enum {
|
||||
Signedness,
|
||||
AddressSpace,
|
||||
CallingConvention,
|
||||
returnError,
|
||||
StackTrace,
|
||||
SourceLocation,
|
||||
CallModifier,
|
||||
AtomicOrder,
|
||||
AtomicRmwOp,
|
||||
ReduceOp,
|
||||
FloatMode,
|
||||
PrefetchOptions,
|
||||
ExportOptions,
|
||||
ExternOptions,
|
||||
BranchHint,
|
||||
|
||||
Type,
|
||||
@"Type.Fn",
|
||||
@"Type.Fn.Param",
|
||||
@"Type.Int",
|
||||
@"Type.Float",
|
||||
@"Type.Pointer",
|
||||
@"Type.Pointer.Size",
|
||||
@"Type.Array",
|
||||
@"Type.Vector",
|
||||
@"Type.Optional",
|
||||
@"Type.Error",
|
||||
@"Type.ErrorUnion",
|
||||
@"Type.EnumField",
|
||||
@"Type.Enum",
|
||||
@"Type.Union",
|
||||
@"Type.UnionField",
|
||||
@"Type.Struct",
|
||||
@"Type.StructField",
|
||||
@"Type.ContainerLayout",
|
||||
@"Type.Opaque",
|
||||
@"Type.Declaration",
|
||||
|
||||
Panic,
|
||||
@"Panic.call",
|
||||
@"Panic.sentinelMismatch",
|
||||
@"Panic.unwrapError",
|
||||
@"Panic.outOfBounds",
|
||||
@"Panic.startGreaterThanEnd",
|
||||
@"Panic.inactiveUnionField",
|
||||
@"Panic.messages",
|
||||
@"Panic.messages.reached_unreachable",
|
||||
@"Panic.messages.unwrap_null",
|
||||
@"Panic.messages.cast_to_null",
|
||||
@"Panic.messages.incorrect_alignment",
|
||||
@"Panic.messages.invalid_error_code",
|
||||
@"Panic.messages.cast_truncated_data",
|
||||
@"Panic.messages.negative_to_unsigned",
|
||||
@"Panic.messages.integer_overflow",
|
||||
@"Panic.messages.shl_overflow",
|
||||
@"Panic.messages.shr_overflow",
|
||||
@"Panic.messages.divide_by_zero",
|
||||
@"Panic.messages.exact_division_remainder",
|
||||
@"Panic.messages.integer_part_out_of_bounds",
|
||||
@"Panic.messages.corrupt_switch",
|
||||
@"Panic.messages.shift_rhs_too_big",
|
||||
@"Panic.messages.invalid_enum_value",
|
||||
@"Panic.messages.for_len_mismatch",
|
||||
@"Panic.messages.memcpy_len_mismatch",
|
||||
@"Panic.messages.memcpy_alias",
|
||||
@"Panic.messages.noreturn_returned",
|
||||
|
||||
VaList,
|
||||
|
||||
/// Determines what kind of validation will be done to the decl's value.
|
||||
pub fn kind(decl: BuiltinDecl) enum { type, func, string } {
|
||||
return switch (decl) {
|
||||
.returnError => .func,
|
||||
|
||||
.StackTrace,
|
||||
.CallingConvention,
|
||||
.SourceLocation,
|
||||
.Signedness,
|
||||
.AddressSpace,
|
||||
.VaList,
|
||||
.CallModifier,
|
||||
.AtomicOrder,
|
||||
.AtomicRmwOp,
|
||||
.ReduceOp,
|
||||
.FloatMode,
|
||||
.PrefetchOptions,
|
||||
.ExportOptions,
|
||||
.ExternOptions,
|
||||
.BranchHint,
|
||||
=> .type,
|
||||
|
||||
.Type,
|
||||
.@"Type.Fn",
|
||||
.@"Type.Fn.Param",
|
||||
.@"Type.Int",
|
||||
.@"Type.Float",
|
||||
.@"Type.Pointer",
|
||||
.@"Type.Pointer.Size",
|
||||
.@"Type.Array",
|
||||
.@"Type.Vector",
|
||||
.@"Type.Optional",
|
||||
.@"Type.Error",
|
||||
.@"Type.ErrorUnion",
|
||||
.@"Type.EnumField",
|
||||
.@"Type.Enum",
|
||||
.@"Type.Union",
|
||||
.@"Type.UnionField",
|
||||
.@"Type.Struct",
|
||||
.@"Type.StructField",
|
||||
.@"Type.ContainerLayout",
|
||||
.@"Type.Opaque",
|
||||
.@"Type.Declaration",
|
||||
=> .type,
|
||||
|
||||
.Panic => .type,
|
||||
|
||||
.@"Panic.call",
|
||||
.@"Panic.sentinelMismatch",
|
||||
.@"Panic.unwrapError",
|
||||
.@"Panic.outOfBounds",
|
||||
.@"Panic.startGreaterThanEnd",
|
||||
.@"Panic.inactiveUnionField",
|
||||
=> .func,
|
||||
|
||||
.@"Panic.messages" => .type,
|
||||
|
||||
.@"Panic.messages.reached_unreachable",
|
||||
.@"Panic.messages.unwrap_null",
|
||||
.@"Panic.messages.cast_to_null",
|
||||
.@"Panic.messages.incorrect_alignment",
|
||||
.@"Panic.messages.invalid_error_code",
|
||||
.@"Panic.messages.cast_truncated_data",
|
||||
.@"Panic.messages.negative_to_unsigned",
|
||||
.@"Panic.messages.integer_overflow",
|
||||
.@"Panic.messages.shl_overflow",
|
||||
.@"Panic.messages.shr_overflow",
|
||||
.@"Panic.messages.divide_by_zero",
|
||||
.@"Panic.messages.exact_division_remainder",
|
||||
.@"Panic.messages.integer_part_out_of_bounds",
|
||||
.@"Panic.messages.corrupt_switch",
|
||||
.@"Panic.messages.shift_rhs_too_big",
|
||||
.@"Panic.messages.invalid_enum_value",
|
||||
.@"Panic.messages.for_len_mismatch",
|
||||
.@"Panic.messages.memcpy_len_mismatch",
|
||||
.@"Panic.messages.memcpy_alias",
|
||||
.@"Panic.messages.noreturn_returned",
|
||||
=> .string,
|
||||
};
|
||||
}
|
||||
|
||||
/// Resolution of these values is done in three distinct stages:
|
||||
/// * Resolution of `std.builtin.Panic` and everything under it
|
||||
/// * Resolution of `VaList`
|
||||
/// * Everything else
|
||||
///
|
||||
/// Panics are separated because they are provided by the user, so must be able to use
|
||||
/// things like reification.
|
||||
///
|
||||
/// `VaList` is separate because its value depends on the target, so it needs some reflection
|
||||
/// machinery to work; additionally, it is `@compileError` on some targets, so must be referenced
|
||||
/// by itself.
|
||||
pub fn stage(decl: BuiltinDecl) InternPool.MemoizedStateStage {
|
||||
if (decl == .VaList) return .va_list;
|
||||
|
||||
if (@intFromEnum(decl) <= @intFromEnum(BuiltinDecl.@"Type.Declaration")) {
|
||||
return .main;
|
||||
} else {
|
||||
return .panic;
|
||||
}
|
||||
}
|
||||
|
||||
/// Based on the tag name, determines how to access this decl; either as a direct child of the
|
||||
/// `std.builtin` namespace, or as a child of some preceding `BuiltinDecl` value.
|
||||
pub fn access(decl: BuiltinDecl) union(enum) {
|
||||
direct: []const u8,
|
||||
nested: struct { BuiltinDecl, []const u8 },
|
||||
} {
|
||||
@setEvalBranchQuota(2000);
|
||||
return switch (decl) {
|
||||
inline else => |tag| {
|
||||
const name = @tagName(tag);
|
||||
const split = (comptime std.mem.lastIndexOfScalar(u8, name, '.')) orelse return .{ .direct = name };
|
||||
const parent = @field(BuiltinDecl, name[0..split]);
|
||||
comptime assert(@intFromEnum(parent) < @intFromEnum(tag)); // dependencies ordered correctly
|
||||
return .{ .nested = .{ parent, name[split + 1 ..] } };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const Memoized = std.enums.EnumFieldStruct(BuiltinDecl, InternPool.Index, .none);
|
||||
};
|
||||
|
||||
pub const PanicId = enum {
|
||||
reached_unreachable,
|
||||
unwrap_null,
|
||||
@ -247,8 +444,6 @@ pub const PanicId = enum {
|
||||
memcpy_len_mismatch,
|
||||
memcpy_alias,
|
||||
noreturn_returned,
|
||||
|
||||
pub const len = @typeInfo(PanicId).@"enum".fields.len;
|
||||
};
|
||||
|
||||
pub const GlobalErrorSet = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
|
||||
@ -2454,6 +2649,7 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
|
||||
.nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }),
|
||||
.type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),
|
||||
.func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }),
|
||||
.memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2468,6 +2664,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
|
||||
.nav_ty => |nav| .{ .nav_ty = nav },
|
||||
.type => |ty| .{ .interned = ty },
|
||||
.func => |func_index| .{ .interned = func_index }, // IES
|
||||
.memoized_state => |stage| .{ .memoized_state = stage },
|
||||
};
|
||||
log.debug("potentially outdated dependee: {}", .{zcu.fmtDependee(dependee)});
|
||||
var it = ip.dependencyIterator(dependee);
|
||||
@ -2553,6 +2750,12 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
|
||||
.type => |ty| .{ .interned = ty },
|
||||
.nav_val => |nav| .{ .nav_val = nav },
|
||||
.nav_ty => |nav| .{ .nav_ty = nav },
|
||||
.memoized_state => {
|
||||
// If we've hit a loop and some `.memoized_state` is outdated, we should make that choice eagerly.
|
||||
// In general, it's good to resolve this early on, since -- for instance -- almost every function
|
||||
// references the panic handler.
|
||||
return unit;
|
||||
},
|
||||
});
|
||||
while (it.next()) |_| n += 1;
|
||||
|
||||
@ -3462,7 +3665,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?Resolv
|
||||
const other: AnalUnit = .wrap(switch (unit.unwrap()) {
|
||||
.nav_val => |n| .{ .nav_ty = n },
|
||||
.nav_ty => |n| .{ .nav_val = n },
|
||||
.@"comptime", .type, .func => break :queue_paired,
|
||||
.@"comptime", .type, .func, .memoized_state => break :queue_paired,
|
||||
});
|
||||
if (result.contains(other)) break :queue_paired;
|
||||
try unit_queue.put(gpa, other, kv.value); // same reference location
|
||||
@ -3597,6 +3800,7 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co
|
||||
const nav = zcu.funcInfo(func).owner_nav;
|
||||
return writer.print("func('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) });
|
||||
},
|
||||
.memoized_state => return writer.writeAll("memoized_state"),
|
||||
}
|
||||
}
|
||||
fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
@ -3642,6 +3846,7 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com
|
||||
const file_path = zcu.fileByIndex(info.file).sub_file_path;
|
||||
return writer.print("namespace('{s}', %{d}, '{}')", .{ file_path, @intFromEnum(info.inst), k.name.fmt(ip) });
|
||||
},
|
||||
.memoized_state => return writer.writeAll("memoized_state"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -560,6 +560,147 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.Sem
|
||||
return pt.semaFile(file_index);
|
||||
}
|
||||
|
||||
/// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.
|
||||
/// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore
|
||||
/// this, since the error is already registered, but it must not use the value of memoized fields.
|
||||
pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.SemaError!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
const unit: AnalUnit = .wrap(.{ .memoized_state = stage });
|
||||
|
||||
log.debug("ensureMemoizedStateUpToDate", .{});
|
||||
|
||||
assert(!zcu.analysis_in_progress.contains(unit));
|
||||
|
||||
const was_outdated = zcu.outdated.swapRemove(unit) or zcu.potentially_outdated.swapRemove(unit);
|
||||
const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit);
|
||||
|
||||
if (was_outdated) {
|
||||
dev.check(.incremental);
|
||||
_ = zcu.outdated_ready.swapRemove(unit);
|
||||
// No need for `deleteUnitExports` because we never export anything.
|
||||
zcu.deleteUnitReferences(unit);
|
||||
if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| {
|
||||
kv.value.destroy(gpa);
|
||||
}
|
||||
_ = zcu.transitive_failed_analysis.swapRemove(unit);
|
||||
} else {
|
||||
if (prev_failed) return error.AnalysisFail;
|
||||
// We use an arbitrary field to check if the state has been resolved yet.
|
||||
const val = switch (stage) {
|
||||
.main => zcu.builtin_decl_values.Type,
|
||||
.panic => zcu.builtin_decl_values.Panic,
|
||||
.va_list => zcu.builtin_decl_values.VaList,
|
||||
};
|
||||
if (val != .none) return;
|
||||
}
|
||||
|
||||
const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage)) |any_changed|
|
||||
.{ any_changed or prev_failed, false }
|
||||
else |err| switch (err) {
|
||||
error.AnalysisFail => res: {
|
||||
if (!zcu.failed_analysis.contains(unit)) {
|
||||
// If this unit caused the error, it would have an entry in `failed_analysis`.
|
||||
// Since it does not, this must be a transitive failure.
|
||||
try zcu.transitive_failed_analysis.put(gpa, unit, {});
|
||||
log.debug("mark transitive analysis failure for {}", .{zcu.fmtAnalUnit(unit)});
|
||||
}
|
||||
break :res .{ !prev_failed, true };
|
||||
},
|
||||
error.OutOfMemory => {
|
||||
// TODO: same as for `ensureComptimeUnitUpToDate` etc
|
||||
return error.OutOfMemory;
|
||||
},
|
||||
error.GenericPoison => unreachable,
|
||||
error.ComptimeReturn => unreachable,
|
||||
error.ComptimeBreak => unreachable,
|
||||
};
|
||||
|
||||
if (was_outdated) {
|
||||
const dependee: InternPool.Dependee = .{ .memoized_state = stage };
|
||||
if (any_changed) {
|
||||
try zcu.markDependeeOutdated(.marked_po, dependee);
|
||||
} else {
|
||||
try zcu.markPoDependeeUpToDate(dependee);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_failed) return error.AnalysisFail;
|
||||
}
|
||||
|
||||
fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool {
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
const unit: AnalUnit = .wrap(.{ .memoized_state = stage });
|
||||
|
||||
try zcu.analysis_in_progress.put(gpa, unit, {});
|
||||
defer assert(zcu.analysis_in_progress.swapRemove(unit));
|
||||
|
||||
// Before we begin, collect:
|
||||
// * The type `std`, and its namespace
|
||||
// * The type `std.builtin`, and its namespace
|
||||
// * A semi-reasonable source location
|
||||
const std_file_imported = pt.importPkg(zcu.std_mod) catch return error.AnalysisFail;
|
||||
try pt.ensureFileAnalyzed(std_file_imported.file_index);
|
||||
const std_type: Type = .fromInterned(zcu.fileRootType(std_file_imported.file_index));
|
||||
const std_namespace = std_type.getNamespaceIndex(zcu);
|
||||
try pt.ensureNamespaceUpToDate(std_namespace);
|
||||
const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
|
||||
const builtin_nav = zcu.namespacePtr(std_namespace).pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse
|
||||
@panic("lib/std.zig is corrupt and missing 'builtin'");
|
||||
try pt.ensureNavValUpToDate(builtin_nav);
|
||||
const builtin_type: Type = .fromInterned(ip.getNav(builtin_nav).status.fully_resolved.val);
|
||||
const builtin_namespace = builtin_type.getNamespaceIndex(zcu);
|
||||
try pt.ensureNamespaceUpToDate(builtin_namespace);
|
||||
const src: Zcu.LazySrcLoc = .{
|
||||
.base_node_inst = builtin_type.typeDeclInst(zcu).?,
|
||||
.offset = .entire_file,
|
||||
};
|
||||
|
||||
var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
|
||||
defer analysis_arena.deinit();
|
||||
|
||||
var comptime_err_ret_trace: std.ArrayList(Zcu.LazySrcLoc) = .init(gpa);
|
||||
defer comptime_err_ret_trace.deinit();
|
||||
|
||||
var sema: Sema = .{
|
||||
.pt = pt,
|
||||
.gpa = gpa,
|
||||
.arena = analysis_arena.allocator(),
|
||||
.code = .{ .instructions = .empty, .string_bytes = &.{}, .extra = &.{} },
|
||||
.owner = unit,
|
||||
.func_index = .none,
|
||||
.func_is_naked = false,
|
||||
.fn_ret_ty = .void,
|
||||
.fn_ret_ty_ies = null,
|
||||
.comptime_err_ret_trace = &comptime_err_ret_trace,
|
||||
};
|
||||
defer sema.deinit();
|
||||
|
||||
var block: Sema.Block = .{
|
||||
.parent = null,
|
||||
.sema = &sema,
|
||||
.namespace = std_namespace,
|
||||
.instructions = .{},
|
||||
.inlining = null,
|
||||
.comptime_reason = .{ .reason = .{
|
||||
.src = src,
|
||||
.r = .{ .simple = .type },
|
||||
} },
|
||||
.src_base_inst = src.base_node_inst,
|
||||
.type_name_ctx = .empty,
|
||||
};
|
||||
defer block.instructions.deinit(gpa);
|
||||
|
||||
return sema.analyzeMemoizedState(&block, src, builtin_namespace, stage);
|
||||
}
|
||||
|
||||
/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis
|
||||
/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
|
||||
/// free to ignore this, since the error is already registered.
|
||||
@ -2615,7 +2756,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
|
||||
// result in circular dependency errors.
|
||||
// TODO: this can go away once we fix backends having to resolve `StackTrace`.
|
||||
// The codegen timing guarantees that the parameter types will be populated.
|
||||
sema.resolveFnTypes(fn_ty) catch |err| switch (err) {
|
||||
sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(0)) catch |err| switch (err) {
|
||||
error.GenericPoison => unreachable,
|
||||
error.ComptimeReturn => unreachable,
|
||||
error.ComptimeBreak => unreachable,
|
||||
@ -3471,23 +3612,6 @@ pub fn structPackedFieldBitOffset(
|
||||
unreachable; // index out of bounds
|
||||
}
|
||||
|
||||
pub fn getBuiltinNav(pt: Zcu.PerThread, name: []const u8) Allocator.Error!InternPool.Nav.Index {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
const std_file_imported = pt.importPkg(zcu.std_mod) catch @panic("failed to import lib/std.zig");
|
||||
const std_type = Type.fromInterned(zcu.fileRootType(std_file_imported.file_index));
|
||||
const std_namespace = zcu.namespacePtr(std_type.getNamespace(zcu).unwrap().?);
|
||||
const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
|
||||
const builtin_nav = std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse
|
||||
@panic("lib/std.zig is corrupt and missing 'builtin'");
|
||||
pt.ensureNavValUpToDate(builtin_nav) catch @panic("std.builtin is corrupt");
|
||||
const builtin_type = Type.fromInterned(ip.getNav(builtin_nav).status.fully_resolved.val);
|
||||
const builtin_namespace = zcu.namespacePtr(builtin_type.getNamespace(zcu).unwrap() orelse @panic("std.builtin is corrupt"));
|
||||
const name_str = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
|
||||
return builtin_namespace.pub_decls.getKeyAdapted(name_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt");
|
||||
}
|
||||
|
||||
pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type {
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
@ -5754,10 +5754,12 @@ pub const FuncGen = struct {
|
||||
const o = fg.ng.object;
|
||||
const zcu = o.pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;
|
||||
const msg_nav = ip.getNav(msg_nav_index);
|
||||
const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);
|
||||
const msg_ptr = try o.lowerValue(msg_nav.status.fully_resolved.val);
|
||||
const panic_msg_val: InternPool.Index = switch (panic_id) {
|
||||
inline else => |ct_panic_id| @field(zcu.builtin_decl_values, "Panic.messages." ++ @tagName(ct_panic_id)),
|
||||
};
|
||||
assert(panic_msg_val != .none);
|
||||
const msg_len = Value.fromInterned(panic_msg_val).typeOf(zcu).childType(zcu).arrayLen(zcu);
|
||||
const msg_ptr = try o.lowerValue(panic_msg_val);
|
||||
const null_opt_addr_global = try fg.resolveNullOptUsize();
|
||||
const target = zcu.getTarget();
|
||||
const llvm_usize = try o.lowerType(Type.usize);
|
||||
@ -5768,7 +5770,7 @@ pub const FuncGen = struct {
|
||||
// ptr null, ; stack trace
|
||||
// ptr @2, ; addr (null ?usize)
|
||||
// )
|
||||
const panic_func = zcu.funcInfo(zcu.panic_func_index);
|
||||
const panic_func = zcu.funcInfo(zcu.builtin_decl_values.@"Panic.call");
|
||||
const panic_nav = ip.getNav(panic_func.owner_nav);
|
||||
const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
|
||||
const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user