authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-06-29 17:53:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-06-29 17:53:52-07:00
logd9742acc232a2af4f98e0fbb9f749737a126e6d1
treee8e28732fab6a70ca261dbb13654be44a202881e
parent7999374b21795a7b8fac7af0b2e326d39bd1e839

Sema: detect one-possible-value types after function calls

produces better Air for backends

2 files changed, 28 insertions(+), 15 deletions(-)

src/Air.zig+15-7
...@@ -1141,6 +1141,20 @@ pub const Inst = struct {...@@ -1141,6 +1141,20 @@ pub const Inst = struct {
1141 pub fn toType(ref: Ref) Type {1141 pub fn toType(ref: Ref) Type {
1142 return .fromInterned(ref.toInterned().?);1142 return .fromInterned(ref.toInterned().?);
1143 }1143 }
1144
1145 pub fn fromIntern(ip_index: InternPool.Index) Ref {
1146 return switch (ip_index) {
1147 .none => .none,
1148 else => {
1149 assert(@intFromEnum(ip_index) >> 31 == 0);
1150 return @enumFromInt(@as(u31, @intCast(@intFromEnum(ip_index))));
1151 },
1152 };
1153 }
1154
1155 pub fn fromValue(v: Value) Ref {
1156 return .fromIntern(v.toIntern());
1157 }
1144 };1158 };
11451159
1146 /// All instructions have an 8-byte payload, which is contained within1160 /// All instructions have an 8-byte payload, which is contained within
...@@ -1754,13 +1768,7 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {...@@ -1754,13 +1768,7 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {
1754}1768}
17551769
1756pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {1770pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {
1757 return switch (ip_index) {1771 return .fromIntern(ip_index);
1758 .none => .none,
1759 else => {
1760 assert(@intFromEnum(ip_index) >> 31 == 0);
1761 return @enumFromInt(@as(u31, @intCast(@intFromEnum(ip_index))));
1762 },
1763 };
1764}1772}
17651773
1766/// Returns `null` if runtime-known.1774/// Returns `null` if runtime-known.
src/Sema.zig+13-8
...@@ -8060,7 +8060,7 @@ fn analyzeCall(...@@ -8060,7 +8060,7 @@ fn analyzeCall(
8060 };8060 };
80618061
8062 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).@"struct".fields.len + runtime_args.len);8062 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).@"struct".fields.len + runtime_args.len);
8063 const result = try block.addInst(.{8063 const maybe_opv = try block.addInst(.{
8064 .tag = call_tag,8064 .tag = call_tag,
8065 .data = .{ .pl_op = .{8065 .data = .{ .pl_op = .{
8066 .operand = runtime_func,8066 .operand = runtime_func,
...@@ -8072,7 +8072,7 @@ fn analyzeCall(...@@ -8072,7 +8072,7 @@ fn analyzeCall(
8072 sema.appendRefsAssumeCapacity(runtime_args);8072 sema.appendRefsAssumeCapacity(runtime_args);
80738073
8074 if (ensure_result_used) {8074 if (ensure_result_used) {
8075 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);8075 try sema.ensureResultUsed(block, sema.typeOf(maybe_opv), call_src);
8076 }8076 }
80778077
8078 if (call_tag == .call_always_tail) {8078 if (call_tag == .call_always_tail) {
...@@ -8082,10 +8082,10 @@ fn analyzeCall(...@@ -8082,10 +8082,10 @@ fn analyzeCall(
8082 .pointer => func_or_ptr_ty.childType(zcu),8082 .pointer => func_or_ptr_ty.childType(zcu),
8083 else => unreachable,8083 else => unreachable,
8084 };8084 };
8085 return sema.handleTailCall(block, call_src, runtime_func_ty, result);8085 return sema.handleTailCall(block, call_src, runtime_func_ty, maybe_opv);
8086 }8086 }
80878087
8088 if (resolved_ret_ty.toIntern() == .noreturn_type) {8088 if (ip.isNoReturn(resolved_ret_ty.toIntern())) {
8089 const want_check = c: {8089 const want_check = c: {
8090 if (!block.wantSafety()) break :c false;8090 if (!block.wantSafety()) break :c false;
8091 if (func_val != null) break :c false;8091 if (func_val != null) break :c false;
...@@ -8099,6 +8099,11 @@ fn analyzeCall(...@@ -8099,6 +8099,11 @@ fn analyzeCall(
8099 return .unreachable_value;8099 return .unreachable_value;
8100 }8100 }
81018101
8102 const result: Air.Inst.Ref = if (try sema.typeHasOnePossibleValue(sema.typeOf(maybe_opv))) |opv|
8103 .fromValue(opv)
8104 else
8105 maybe_opv;
8106
8102 return result;8107 return result;
8103 }8108 }
81048109
...@@ -8335,7 +8340,7 @@ fn analyzeCall(...@@ -8335,7 +8340,7 @@ fn analyzeCall(
8335 break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, &inlining.merges, need_debug_scope);8340 break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, &inlining.merges, need_debug_scope);
8336 };8341 };
83378342
8338 const result: Air.Inst.Ref = if (try sema.resolveValue(result_raw)) |result_val| r: {8343 const maybe_opv: Air.Inst.Ref = if (try sema.resolveValue(result_raw)) |result_val| r: {
8339 const val_resolved = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern());8344 const val_resolved = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern());
8340 break :r Air.internedToRef(val_resolved);8345 break :r Air.internedToRef(val_resolved);
8341 } else r: {8346 } else r: {
...@@ -8347,7 +8352,7 @@ fn analyzeCall(...@@ -8347,7 +8352,7 @@ fn analyzeCall(
8347 };8352 };
83488353
8349 if (block.isComptime()) {8354 if (block.isComptime()) {
8350 const result_val = (try sema.resolveValue(result)).?;8355 const result_val = (try sema.resolveValue(maybe_opv)).?;
8351 if (want_memoize and sema.allow_memoize and !result_val.canMutateComptimeVarState(zcu)) {8356 if (want_memoize and sema.allow_memoize and !result_val.canMutateComptimeVarState(zcu)) {
8352 _ = try pt.intern(.{ .memoized_call = .{8357 _ = try pt.intern(.{ .memoized_call = .{
8353 .func = func_val.?.toIntern(),8358 .func = func_val.?.toIntern(),
...@@ -8359,10 +8364,10 @@ fn analyzeCall(...@@ -8359,10 +8364,10 @@ fn analyzeCall(
8359 }8364 }
83608365
8361 if (ensure_result_used) {8366 if (ensure_result_used) {
8362 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);8367 try sema.ensureResultUsed(block, sema.typeOf(maybe_opv), call_src);
8363 }8368 }
83648369
8365 return result;8370 return maybe_opv;
8366}8371}
83678372
8368fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref {8373fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref {