authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-21 17:03:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-26 15:57:07-07:00
logf1b7c76ae9c015eeadeeff6ffcdf1523afce43f5
tree9f18b9d6edfaf3f550236f3503b6720736888fbd
parenta6eb83bd1b7739156ab01e3fc55588f67d924daa

LLVM: implement call_async_alloc

It's based on a runtime alloca based on the frame size. This allows us to lower async function calls before lowering the callee, and allows updating callees without updating the callers. Sema: add `std.debug.Trace` integration for `unneeded`. This helps us debug when `LazySrcLoc.unneeded` was incorrectly used.

8 files changed, 367 insertions(+), 209 deletions(-)

src/Module.zig+17-3
......@@ -2178,7 +2178,10 @@ pub const SrcLoc = struct {
21782178
21792179 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {
21802180 switch (src_loc.lazy) {
2181 .unneeded => unreachable,
2181 .unneeded => |t| {
2182 t.dump();
2183 unreachable;
2184 },
21822185 .entire_file => return Span{ .start = 0, .end = 1, .main = 0 },
21832186
21842187 .byte_abs => |byte_index| return Span{ .start = byte_index, .end = byte_index + 1, .main = byte_index },
......@@ -2905,7 +2908,7 @@ pub const LazySrcLoc = union(enum) {
29052908 /// unreachable. If you are debugging this tag incorrectly being this value,
29062909 /// look into using reverse-continue with a memory watchpoint to see where the
29072910 /// value is being set to this tag.
2908 unneeded,
2911 unneeded: std.debug.Trace,
29092912 /// Means the source location points to an entire file; not any particular
29102913 /// location within the file. `file_scope` union field will be active.
29112914 entire_file,
......@@ -3197,6 +3200,7 @@ pub const LazySrcLoc = union(enum) {
31973200 for_capture_from_input: i32,
31983201
31993202 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
3203 pub const un = if (TracedOffset.want_tracing) unneededDebug else unneededRelease;
32003204
32013205 noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc {
32023206 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };
......@@ -3204,10 +3208,20 @@ pub const LazySrcLoc = union(enum) {
32043208 return result;
32053209 }
32063210
3207 fn nodeOffsetRelease(node_offset: i32) LazySrcLoc {
3211 noinline fn unneededDebug() LazySrcLoc {
3212 var result: LazySrcLoc = .{ .unneeded = .{} };
3213 result.unneeded.addAddr(@returnAddress(), "init");
3214 return result;
3215 }
3216
3217 inline fn nodeOffsetRelease(node_offset: i32) LazySrcLoc {
32083218 return .{ .node_offset = .{ .x = node_offset } };
32093219 }
32103220
3221 inline fn unneededRelease() LazySrcLoc {
3222 return .{ .unneeded = .{} };
3223 }
3224
32113225 /// Upgrade to a `SrcLoc` based on the `Decl` provided.
32123226 pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl, mod: *Module) SrcLoc {
32133227 return switch (lazy) {
src/Sema.zig+73-73
......@@ -1887,7 +1887,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
18871887 var err_trace_block = block.makeSubBlock();
18881888 defer err_trace_block.instructions.deinit(gpa);
18891889
1890 const src: LazySrcLoc = .unneeded;
1890 const src = LazySrcLoc.un();
18911891
18921892 // var addrs: [err_return_trace_addr_count]usize = undefined;
18931893 const err_return_trace_addr_count = 32;
......@@ -2913,7 +2913,7 @@ fn createAnonymousDeclTypeNamed(
29132913 // If not then this is a struct type being returned from a non-generic
29142914 // function and the name doesn't matter since it will later
29152915 // result in a compile error.
2916 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg, "") catch
2916 const arg_val = sema.resolveConstMaybeUndefVal(block, LazySrcLoc.un(), arg, "") catch
29172917 return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null);
29182918
29192919 if (arg_i != 0) try writer.writeByte(',');
......@@ -3161,7 +3161,7 @@ fn zirEnumDecl(
31613161 const tag_val_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index]));
31623162 extra_index += 1;
31633163 const tag_inst = try sema.resolveInst(tag_val_ref);
3164 last_tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) {
3164 last_tag_val = sema.resolveConstValue(block, LazySrcLoc.un(), tag_inst, "") catch |err| switch (err) {
31653165 error.NeededSourceLocation => {
31663166 const value_src = mod.fieldSrcLoc(new_decl_index, .{
31673167 .index = field_i,
......@@ -5834,7 +5834,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
58345834 break :index_blk maybe_index orelse
58355835 return sema.failWithBadMemberAccess(block, container_ty, operand_src, decl_name);
58365836 } else try sema.lookupIdentifier(block, operand_src, decl_name);
5837 const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) {
5837 const options = sema.resolveExportOptions(block, LazySrcLoc.un(), extra.options) catch |err| switch (err) {
58385838 error.NeededSourceLocation => {
58395839 _ = try sema.resolveExportOptions(block, options_src, extra.options);
58405840 unreachable;
......@@ -5861,7 +5861,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
58615861 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
58625862 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
58635863 const operand = try sema.resolveInstConst(block, operand_src, extra.operand, "export target must be comptime-known");
5864 const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) {
5864 const options = sema.resolveExportOptions(block, LazySrcLoc.un(), extra.options) catch |err| switch (err) {
58655865 error.NeededSourceLocation => {
58665866 _ = try sema.resolveExportOptions(block, options_src, extra.options);
58675867 unreachable;
......@@ -6995,7 +6995,7 @@ fn analyzeCall(
69956995 sema.analyzeInlineCallArg(
69966996 block,
69976997 &child_block,
6998 .unneeded,
6998 LazySrcLoc.un(),
69996999 inst,
70007000 &new_fn_info,
70017001 &arg_i,
......@@ -7141,7 +7141,7 @@ fn analyzeCall(
71417141 }
71427142
71437143 if (should_memoize and is_comptime_call) {
7144 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
7144 const result_val = try sema.resolveConstMaybeUndefVal(block, LazySrcLoc.un(), result, "");
71457145
71467146 // TODO: check whether any external comptime memory was mutated by the
71477147 // comptime function call. If so, then do not memoize the call here.
......@@ -7171,7 +7171,7 @@ fn analyzeCall(
71717171 const param_ty = mod.typeToFunc(func_ty).?.param_types[i].toType();
71727172 args[i] = sema.analyzeCallArg(
71737173 block,
7174 .unneeded,
7174 LazySrcLoc.un(),
71757175 param_ty,
71767176 uncasted_arg,
71777177 opts,
......@@ -7190,7 +7190,7 @@ fn analyzeCall(
71907190 else => |e| return e,
71917191 };
71927192 } else {
7193 args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) {
7193 args[i] = sema.coerceVarArgParam(block, uncasted_arg, LazySrcLoc.un()) catch |err| switch (err) {
71947194 error.NeededSourceLocation => {
71957195 const decl = mod.declPtr(block.src_decl);
71967196 _ = try sema.coerceVarArgParam(
......@@ -7608,7 +7608,7 @@ fn instantiateGenericCall(
76087608 }
76097609
76107610 if (is_comptime) {
7611 const casted_arg = sema.analyzeGenericCallArgVal(block, .unneeded, arg_ty.toType(), uncasted_arg, "") catch |err| switch (err) {
7611 const casted_arg = sema.analyzeGenericCallArgVal(block, LazySrcLoc.un(), arg_ty.toType(), uncasted_arg, "") catch |err| switch (err) {
76127612 error.NeededSourceLocation => {
76137613 const decl = mod.declPtr(block.src_decl);
76147614 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
......@@ -7741,7 +7741,7 @@ fn instantiateGenericCall(
77417741 }
77427742 sema.analyzeGenericCallArg(
77437743 block,
7744 .unneeded,
7744 LazySrcLoc.un(),
77457745 uncasted_args[total_i],
77467746 comptime_args[total_i],
77477747 runtime_args,
......@@ -7893,7 +7893,7 @@ fn resolveGenericInstantiationType(
78937893 } else if (is_anytype) {
78947894 const arg_ty = sema.typeOf(arg);
78957895 if (try sema.typeRequiresComptime(arg_ty)) {
7896 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
7896 const arg_val = sema.resolveConstValue(block, LazySrcLoc.un(), arg, "") catch |err| switch (err) {
78977897 error.NeededSourceLocation => {
78987898 const decl = mod.declPtr(block.src_decl);
78997899 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
......@@ -7927,7 +7927,7 @@ fn resolveGenericInstantiationType(
79277927 child_block.error_return_trace_index = error_return_trace_index;
79287928
79297929 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
7930 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;
7930 const new_func_val = child_sema.resolveConstValue(&child_block, LazySrcLoc.un(), new_func_inst, undefined) catch unreachable;
79317931 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
79327932 assert(new_func == new_module_func);
79337933
......@@ -8091,7 +8091,7 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
80918091fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
80928092 const mod = sema.mod;
80938093 const bin = sema.code.instructions.items(.data)[inst].bin;
8094 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
8094 const indexable_ty = try sema.resolveType(block, LazySrcLoc.un(), bin.lhs);
80958095 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
80968096 if (indexable_ty.zigTypeTag(mod) == .Struct) {
80978097 const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod);
......@@ -8105,7 +8105,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
81058105fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
81068106 const mod = sema.mod;
81078107 const un_node = sema.code.instructions.items(.data)[inst].un_node;
8108 const ptr_ty = try sema.resolveType(block, .unneeded, un_node.operand);
8108 const ptr_ty = try sema.resolveType(block, LazySrcLoc.un(), un_node.operand);
81098109 assert(ptr_ty.zigTypeTag(mod) == .Pointer); // validated by a previous instruction
81108110 return sema.addType(ptr_ty.childType(mod));
81118111}
......@@ -9101,7 +9101,7 @@ fn funcCommon(
91019101 dest_param_ty.* = param.ty.toIntern();
91029102 sema.analyzeParameter(
91039103 block,
9104 .unneeded,
9104 LazySrcLoc.un(),
91059105 param,
91069106 &comptime_bits,
91079107 i,
......@@ -9500,7 +9500,7 @@ fn zirParam(
95009500 if (is_comptime and sema.preallocated_new_func != .none) {
95019501 // We have a comptime value for this parameter so it should be elided from the
95029502 // function type of the function instruction in this block.
9503 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
9503 const coerced_arg = sema.coerce(block, param_ty, arg, LazySrcLoc.un()) catch |err| switch (err) {
95049504 error.NeededSourceLocation => {
95059505 // We are instantiating a generic function and a comptime arg
95069506 // cannot be coerced to the param type, but since we don't
......@@ -10169,7 +10169,7 @@ fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1016910169 const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node };
1017010170 const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
1017110171
10172 return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, .unneeded, ptr_src, start_src, end_src, false);
10172 return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, LazySrcLoc.un(), ptr_src, start_src, end_src, false);
1017310173}
1017410174
1017510175fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -10186,7 +10186,7 @@ fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1018610186 const start_src: LazySrcLoc = .{ .node_offset_slice_start = inst_data.src_node };
1018710187 const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
1018810188
10189 return sema.analyzeSlice(block, src, array_ptr, start, end, .none, .unneeded, ptr_src, start_src, end_src, false);
10189 return sema.analyzeSlice(block, src, array_ptr, start, end, .none, LazySrcLoc.un(), ptr_src, start_src, end_src, false);
1019010190}
1019110191
1019210192fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -10223,7 +10223,7 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1022310223 const start_src: LazySrcLoc = .{ .node_offset_slice_start = extra.start_src_node_offset };
1022410224 const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
1022510225 const sentinel_src: LazySrcLoc = if (sentinel == .none)
10226 .unneeded
10226 LazySrcLoc.un()
1022710227 else
1022810228 .{ .node_offset_slice_sentinel = inst_data.src_node };
1022910229
......@@ -10418,7 +10418,7 @@ const SwitchProngAnalysis = struct {
1041810418 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = switch_node_offset };
1041910419
1042010420 if (inline_case_capture != .none) {
10421 const item_val = sema.resolveConstValue(block, .unneeded, inline_case_capture, "") catch unreachable;
10421 const item_val = sema.resolveConstValue(block, LazySrcLoc.un(), inline_case_capture, "") catch unreachable;
1042210422 if (operand_ty.zigTypeTag(mod) == .Union) {
1042310423 const field_index = @as(u32, @intCast(operand_ty.unionTagFieldIndex(item_val, mod).?));
1042410424 const union_obj = mod.typeToUnion(operand_ty).?;
......@@ -10477,15 +10477,15 @@ const SwitchProngAnalysis = struct {
1047710477 switch (operand_ty.zigTypeTag(mod)) {
1047810478 .Union => {
1047910479 const union_obj = mod.typeToUnion(operand_ty).?;
10480 const first_item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
10480 const first_item_val = sema.resolveConstValue(block, LazySrcLoc.un(), case_vals[0], "") catch unreachable;
1048110481
1048210482 const first_field_index = @as(u32, @intCast(operand_ty.unionTagFieldIndex(first_item_val, mod).?));
1048310483 const first_field = union_obj.fields.values()[first_field_index];
1048410484
1048510485 const field_tys = try sema.arena.alloc(Type, case_vals.len);
1048610486 for (case_vals, field_tys) |item, *field_ty| {
10487 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
10488 const field_idx = @as(u32, @intCast(operand_ty.unionTagFieldIndex(item_val, sema.mod).?));
10487 const item_val = sema.resolveConstValue(block, LazySrcLoc.un(), item, "") catch unreachable;
10488 const field_idx: u32 = @intCast(operand_ty.unionTagFieldIndex(item_val, sema.mod).?);
1048910489 field_ty.* = union_obj.fields.values()[field_idx].ty;
1049010490 }
1049110491
......@@ -10503,9 +10503,9 @@ const SwitchProngAnalysis = struct {
1050310503 }
1050410504
1050510505 const case_srcs = try sema.arena.alloc(?LazySrcLoc, case_vals.len);
10506 @memset(case_srcs, .unneeded);
10506 @memset(case_srcs, LazySrcLoc.un());
1050710507
10508 break :capture_ty sema.resolvePeerTypes(block, .unneeded, dummy_captures, .{ .override = case_srcs }) catch |err| switch (err) {
10508 break :capture_ty sema.resolvePeerTypes(block, LazySrcLoc.un(), dummy_captures, .{ .override = case_srcs }) catch |err| switch (err) {
1050910509 error.NeededSourceLocation => {
1051010510 // This must be a multi-prong so this must be a `multi_capture` src
1051110511 const multi_idx = raw_capture_src.multi_capture;
......@@ -10555,7 +10555,7 @@ const SwitchProngAnalysis = struct {
1055510555 .address_space = operand_ptr_info.flags.address_space,
1055610556 },
1055710557 });
10558 if (.ok != try sema.coerceInMemoryAllowed(block, capture_ptr_ty, field_ptr_ty, false, sema.mod.getTarget(), .unneeded, .unneeded)) {
10558 if (.ok != try sema.coerceInMemoryAllowed(block, capture_ptr_ty, field_ptr_ty, false, sema.mod.getTarget(), LazySrcLoc.un(), LazySrcLoc.un())) {
1055910559 const multi_idx = raw_capture_src.multi_capture;
1056010560 const src_decl_ptr = sema.mod.declPtr(block.src_decl);
1056110561 const capture_src = raw_capture_src.resolve(mod, src_decl_ptr, switch_node_offset, .none);
......@@ -10611,7 +10611,7 @@ const SwitchProngAnalysis = struct {
1061110611 // If we can, try to avoid that using in-memory coercions.
1061210612 const first_non_imc = in_mem: {
1061310613 for (field_tys, 0..) |field_ty, i| {
10614 if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, sema.mod.getTarget(), .unneeded, .unneeded)) {
10614 if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, sema.mod.getTarget(), LazySrcLoc.un(), LazySrcLoc.un())) {
1061510615 break :in_mem i;
1061610616 }
1061710617 }
......@@ -10633,7 +10633,7 @@ const SwitchProngAnalysis = struct {
1063310633 {
1063410634 const next = first_non_imc + 1;
1063510635 for (field_tys[next..], next..) |field_ty, i| {
10636 if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, sema.mod.getTarget(), .unneeded, .unneeded)) {
10636 if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, sema.mod.getTarget(), LazySrcLoc.un(), LazySrcLoc.un())) {
1063710637 in_mem_coercible.unset(i);
1063810638 }
1063910639 }
......@@ -10662,8 +10662,8 @@ const SwitchProngAnalysis = struct {
1066210662 var coerce_block = block.makeSubBlock();
1066310663 defer coerce_block.instructions.deinit(sema.gpa);
1066410664
10665 const uncoerced = try coerce_block.addStructFieldVal(spa.operand, @as(u32, @intCast(idx)), field_tys[idx]);
10666 const coerced = sema.coerce(&coerce_block, capture_ty, uncoerced, .unneeded) catch |err| switch (err) {
10665 const uncoerced = try coerce_block.addStructFieldVal(spa.operand, @intCast(idx), field_tys[idx]);
10666 const coerced = sema.coerce(&coerce_block, capture_ty, uncoerced, LazySrcLoc.un()) catch |err| switch (err) {
1066710667 error.NeededSourceLocation => {
1066810668 const multi_idx = raw_capture_src.multi_capture;
1066910669 const src_decl_ptr = sema.mod.declPtr(block.src_decl);
......@@ -10735,7 +10735,7 @@ const SwitchProngAnalysis = struct {
1073510735 }
1073610736
1073710737 if (case_vals.len == 1) {
10738 const item_val = sema.resolveConstValue(block, .unneeded, case_vals[0], "") catch unreachable;
10738 const item_val = sema.resolveConstValue(block, LazySrcLoc.un(), case_vals[0], "") catch unreachable;
1073910739 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);
1074010740 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);
1074110741 }
......@@ -10743,7 +10743,7 @@ const SwitchProngAnalysis = struct {
1074310743 var names: Module.Fn.InferredErrorSet.NameMap = .{};
1074410744 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
1074510745 for (case_vals) |err| {
10746 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;
10746 const err_val = sema.resolveConstValue(block, LazySrcLoc.un(), err, "") catch unreachable;
1074710747 names.putAssumeCapacityNoClobber(err_val.getErrorName(mod).unwrap().?, {});
1074810748 }
1074910749 const error_ty = try mod.errorSetFromUnsortedNames(names.keys());
......@@ -11507,7 +11507,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1150711507 extra_index += info.body_len;
1150811508
1150911509 const item = case_vals.items[scalar_i];
11510 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11510 const item_val = sema.resolveConstValue(&child_block, LazySrcLoc.un(), item, "") catch unreachable;
1151111511 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
1151211512 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
1151311513 return spa.resolveProngComptime(
......@@ -11541,7 +11541,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1154111541
1154211542 for (items) |item| {
1154311543 // Validation above ensured these will succeed.
11544 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11544 const item_val = sema.resolveConstValue(&child_block, LazySrcLoc.un(), item, "") catch unreachable;
1154511545 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
1154611546 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
1154711547 return spa.resolveProngComptime(
......@@ -11565,8 +11565,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1156511565 case_val_idx += 2;
1156611566
1156711567 // Validation above ensured these will succeed.
11568 const first_val = sema.resolveConstValue(&child_block, .unneeded, range_items[0], "") catch unreachable;
11569 const last_val = sema.resolveConstValue(&child_block, .unneeded, range_items[1], "") catch unreachable;
11568 const first_val = sema.resolveConstValue(&child_block, LazySrcLoc.un(), range_items[0], "") catch unreachable;
11569 const last_val = sema.resolveConstValue(&child_block, LazySrcLoc.un(), range_items[1], "") catch unreachable;
1157011570 if ((try sema.compareAll(resolved_operand_val, .gte, first_val, operand_ty)) and
1157111571 (try sema.compareAll(resolved_operand_val, .lte, last_val, operand_ty)))
1157211572 {
......@@ -11676,7 +11676,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1167611676 // `item` is already guaranteed to be constant known.
1167711677
1167811678 const analyze_body = if (union_originally) blk: {
11679 const item_val = sema.resolveConstLazyValue(block, .unneeded, item, "") catch unreachable;
11679 const item_val = sema.resolveConstLazyValue(block, LazySrcLoc.un(), item, "") catch unreachable;
1168011680 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
1168111681 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
1168211682 } else true;
......@@ -11746,8 +11746,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1174611746 const item_first_ref = range_items[0];
1174711747 const item_last_ref = range_items[1];
1174811748
11749 var item = sema.resolveConstValue(block, .unneeded, item_first_ref, undefined) catch unreachable;
11750 const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable;
11749 var item = sema.resolveConstValue(block, LazySrcLoc.un(), item_first_ref, undefined) catch unreachable;
11750 const item_last = sema.resolveConstValue(block, LazySrcLoc.un(), item_last_ref, undefined) catch unreachable;
1175111751
1175211752 while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({
1175311753 // Previous validation has resolved any possible lazy values.
......@@ -11763,7 +11763,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1176311763 case_block.instructions.shrinkRetainingCapacity(0);
1176411764 case_block.wip_capture_scope = child_block.wip_capture_scope;
1176511765
11766 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {
11766 if (emit_bb) sema.emitBackwardBranch(block, LazySrcLoc.un()) catch |err| switch (err) {
1176711767 error.NeededSourceLocation => {
1176811768 const case_src = Module.SwitchProngSrc{ .range = .{ .prong = multi_i, .item = range_i } };
1176911769 const decl = mod.declPtr(case_block.src_decl);
......@@ -11802,12 +11802,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1180211802 case_block.wip_capture_scope = child_block.wip_capture_scope;
1180311803
1180411804 const analyze_body = if (union_originally) blk: {
11805 const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable;
11805 const item_val = sema.resolveConstValue(block, LazySrcLoc.un(), item, undefined) catch unreachable;
1180611806 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
1180711807 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
1180811808 } else true;
1180911809
11810 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {
11810 if (emit_bb) sema.emitBackwardBranch(block, LazySrcLoc.un()) catch |err| switch (err) {
1181111811 error.NeededSourceLocation => {
1181211812 const case_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_i, .item = @as(u32, @intCast(item_i)) } };
1181311813 const decl = mod.declPtr(case_block.src_decl);
......@@ -11854,7 +11854,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1185411854
1185511855 const analyze_body = if (union_originally)
1185611856 for (items) |item| {
11857 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
11857 const item_val = sema.resolveConstValue(block, LazySrcLoc.un(), item, "") catch unreachable;
1185811858 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
1185911859 if (field_ty.zigTypeTag(mod) != .NoReturn) break true;
1186011860 } else false
......@@ -12345,7 +12345,7 @@ fn resolveSwitchItemVal(
1234512345 // Only if we know for sure we need to report a compile error do we resolve the
1234612346 // full source locations.
1234712347
12348 const item = sema.coerce(block, coerce_ty, uncoerced_item, .unneeded) catch |err| switch (err) {
12348 const item = sema.coerce(block, coerce_ty, uncoerced_item, LazySrcLoc.un()) catch |err| switch (err) {
1234912349 error.NeededSourceLocation => {
1235012350 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand);
1235112351 _ = try sema.coerce(block, coerce_ty, uncoerced_item, src);
......@@ -12354,7 +12354,7 @@ fn resolveSwitchItemVal(
1235412354 else => |e| return e,
1235512355 };
1235612356
12357 const maybe_lazy = sema.resolveConstValue(block, .unneeded, item, "") catch |err| switch (err) {
12357 const maybe_lazy = sema.resolveConstValue(block, LazySrcLoc.un(), item, "") catch |err| switch (err) {
1235812358 error.NeededSourceLocation => {
1235912359 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand);
1236012360 _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");
......@@ -13479,8 +13479,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1347913479 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";
1348013480 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;
1348113481 const elem_val_inst = try sema.addConstant(elem_val);
13482 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
13483 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, "");
13482 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, LazySrcLoc.un());
13483 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, LazySrcLoc.un(), coerced_elem_val_inst, "");
1348413484 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
1348513485 }
1348613486 while (elem_i < result_len) : (elem_i += 1) {
......@@ -13488,8 +13488,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1348813488 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";
1348913489 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;
1349013490 const elem_val_inst = try sema.addConstant(elem_val);
13491 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
13492 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, "");
13491 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, LazySrcLoc.un());
13492 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, LazySrcLoc.un(), coerced_elem_val_inst, "");
1349313493 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
1349413494 }
1349513495 return sema.addConstantMaybeRef(block, result_ty, (try mod.intern(.{ .aggregate = .{
......@@ -18361,7 +18361,7 @@ fn zirRetImplicit(
1836118361 return sema.failWithOwnedErrorMsg(msg);
1836218362 }
1836318363
18364 return sema.analyzeRet(block, operand, .unneeded);
18364 return sema.analyzeRet(block, operand, LazySrcLoc.un());
1836518365}
1836618366
1836718367fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
......@@ -19069,7 +19069,7 @@ fn finishStructInit(
1906919069 return sema.makePtrConst(block, alloc);
1907019070 }
1907119071
19072 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
19072 sema.requireRuntimeBlock(block, LazySrcLoc.un(), null) catch |err| switch (err) {
1907319073 error.NeededSourceLocation => {
1907419074 const decl = mod.declPtr(block.src_decl);
1907519075 const field_src = mod.initSrc(dest_src.node_offset.x, decl, runtime_index);
......@@ -19163,7 +19163,7 @@ fn zirStructInitAnon(
1916319163 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
1916419164 };
1916519165
19166 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
19166 sema.requireRuntimeBlock(block, LazySrcLoc.un(), null) catch |err| switch (err) {
1916719167 error.NeededSourceLocation => {
1916819168 const decl = mod.declPtr(block.src_decl);
1916919169 const field_src = mod.initSrc(src.node_offset.x, decl, runtime_index);
......@@ -19237,7 +19237,7 @@ fn zirArrayInit(
1923719237 array_ty.structFieldType(i, mod)
1923819238 else
1923919239 array_ty.elemType2(mod);
19240 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {
19240 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, LazySrcLoc.un()) catch |err| switch (err) {
1924119241 error.NeededSourceLocation => {
1924219242 const decl = mod.declPtr(block.src_decl);
1924319243 const elem_src = mod.initSrc(src.node_offset.x, decl, i);
......@@ -19273,7 +19273,7 @@ fn zirArrayInit(
1927319273 } })).toValue(), is_ref);
1927419274 };
1927519275
19276 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
19276 sema.requireRuntimeBlock(block, LazySrcLoc.un(), null) catch |err| switch (err) {
1927719277 error.NeededSourceLocation => {
1927819278 const decl = mod.declPtr(block.src_decl);
1927919279 const elem_src = mod.initSrc(src.node_offset.x, decl, runtime_index);
......@@ -19667,7 +19667,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1966719667 try sema.resolveTypeLayout(operand_ty);
1966819668 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {
1966919669 .EnumLiteral => {
19670 const val = try sema.resolveConstValue(block, .unneeded, operand, "");
19670 const val = try sema.resolveConstValue(block, LazySrcLoc.un(), operand, "");
1967119671 const tag_name = ip.indexToKey(val.toIntern()).enum_literal;
1967219672 return sema.addStrLit(block, ip.stringToSlice(tag_name));
1967319673 },
......@@ -22213,7 +22213,7 @@ fn checkVectorizableBinaryOperands(
2221322213}
2221422214
2221522215fn maybeOptionsSrc(sema: *Sema, block: *Block, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
22216 if (base_src == .unneeded) return .unneeded;
22216 if (base_src == .unneeded) return LazySrcLoc.un();
2221722217 const mod = sema.mod;
2221822218 return mod.optionsSrc(mod.declPtr(block.src_decl), base_src, wanted);
2221922219}
......@@ -23655,7 +23655,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2365523655 } else if (dest_len == .none and len_val == null) {
2365623656 // Change the dest to a slice, since its type must have the length.
2365723657 const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr);
23658 new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false);
23658 new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, LazySrcLoc.un(), dest_src, dest_src, dest_src, false);
2365923659 const new_src_ptr_ty = sema.typeOf(new_src_ptr);
2366023660 if (new_src_ptr_ty.isSlice(mod)) {
2366123661 new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
......@@ -24221,7 +24221,7 @@ fn zirPrefetch(
2422124221 const ptr = try sema.resolveInst(extra.lhs);
2422224222 try sema.checkPtrOperand(block, ptr_src, sema.typeOf(ptr));
2422324223
24224 const options = sema.resolvePrefetchOptions(block, .unneeded, extra.rhs) catch |err| switch (err) {
24224 const options = sema.resolvePrefetchOptions(block, LazySrcLoc.un(), extra.rhs) catch |err| switch (err) {
2422524225 error.NeededSourceLocation => {
2422624226 _ = try sema.resolvePrefetchOptions(block, opts_src, extra.rhs);
2422724227 unreachable;
......@@ -24330,7 +24330,7 @@ fn zirBuiltinExtern(
2433024330 return sema.failWithOwnedErrorMsg(msg);
2433124331 }
2433224332
24333 const options = sema.resolveExternOptions(block, .unneeded, extra.rhs) catch |err| switch (err) {
24333 const options = sema.resolveExternOptions(block, LazySrcLoc.un(), extra.rhs) catch |err| switch (err) {
2433424334 error.NeededSourceLocation => {
2433524335 _ = try sema.resolveExternOptions(block, options_src, extra.rhs);
2433624336 unreachable;
......@@ -25036,7 +25036,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void {
2503625036 try sema.prepareSimplePanic(block);
2503725037
2503825038 const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;
25039 const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl);
25039 const panic_fn = try sema.analyzeDeclVal(block, LazySrcLoc.un(), panic_func.owner_decl);
2504025040 const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue());
2504125041
2504225042 const opt_usize_ty = try mod.optionalType(.usize_type);
......@@ -25530,7 +25530,7 @@ fn fieldPtr(
2553025530 }
2553125531 },
2553225532 .Type => {
25533 _ = try sema.resolveConstValue(block, .unneeded, object_ptr, "");
25533 _ = try sema.resolveConstValue(block, LazySrcLoc.un(), object_ptr, "");
2553425534 const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src);
2553525535 const inner = if (is_pointer_to)
2553625536 try sema.analyzeLoad(block, src, result, object_ptr_src)
......@@ -27026,7 +27026,7 @@ fn coerceExtra(
2702627026
2702727027 // Function body to function pointer.
2702827028 if (inst_ty.zigTypeTag(mod) == .Fn) {
27029 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
27029 const fn_val = try sema.resolveConstValue(block, LazySrcLoc.un(), inst, "");
2703027030 const fn_decl = fn_val.pointerDecl(mod).?;
2703127031 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
2703227032 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
......@@ -27366,7 +27366,7 @@ fn coerceExtra(
2736627366 },
2736727367 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag(mod)) {
2736827368 .ComptimeFloat => {
27369 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
27369 const val = try sema.resolveConstValue(block, LazySrcLoc.un(), inst, "");
2737027370 const result_val = try val.floatCast(dest_ty, mod);
2737127371 return try sema.addConstant(result_val);
2737227372 },
......@@ -27430,7 +27430,7 @@ fn coerceExtra(
2743027430 .Enum => switch (inst_ty.zigTypeTag(mod)) {
2743127431 .EnumLiteral => {
2743227432 // enum literal to enum
27433 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
27433 const val = try sema.resolveConstValue(block, LazySrcLoc.un(), inst, "");
2743427434 const string = mod.intern_pool.indexToKey(val.toIntern()).enum_literal;
2743527435 const field_index = dest_ty.enumFieldIndex(string, mod) orelse {
2743627436 const msg = msg: {
......@@ -28544,7 +28544,7 @@ fn coerceVarArgParam(
2854428544 .{},
2854528545 ),
2854628546 .Fn => blk: {
28547 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
28547 const fn_val = try sema.resolveConstValue(block, LazySrcLoc.un(), inst, "");
2854828548 const fn_decl = fn_val.pointerDecl(mod).?;
2854928549 break :blk try sema.analyzeDeclRef(fn_decl);
2855028550 },
......@@ -34522,7 +34522,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3452234522 for (fields, 0..) |zir_field, field_i| {
3452334523 const field_ty: Type = ty: {
3452434524 if (zir_field.type_ref != .none) {
34525 break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) {
34525 break :ty sema.resolveType(&block_scope, LazySrcLoc.un(), zir_field.type_ref) catch |err| switch (err) {
3452634526 error.NeededSourceLocation => {
3452734527 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3452834528 .index = field_i,
......@@ -34538,7 +34538,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3453834538 const body = zir.extra[extra_index..][0..zir_field.type_body_len];
3453934539 extra_index += body.len;
3454034540 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
34541 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
34541 break :ty sema.analyzeAsType(&block_scope, LazySrcLoc.un(), ty_ref) catch |err| switch (err) {
3454234542 error.NeededSourceLocation => {
3454334543 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3454434544 .index = field_i,
......@@ -34621,7 +34621,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3462134621 const body = zir.extra[extra_index..][0..zir_field.align_body_len];
3462234622 extra_index += body.len;
3462334623 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
34624 field.abi_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
34624 field.abi_align = sema.analyzeAsAlign(&block_scope, LazySrcLoc.un(), align_ref) catch |err| switch (err) {
3462534625 error.NeededSourceLocation => {
3462634626 const align_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3462734627 .index = field_i,
......@@ -34649,7 +34649,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3464934649 extra_index += body.len;
3465034650 const init = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
3465134651 const field = &struct_obj.fields.values()[field_i];
34652 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {
34652 const coerced = sema.coerce(&block_scope, field.ty, init, LazySrcLoc.un()) catch |err| switch (err) {
3465334653 error.NeededSourceLocation => {
3465434654 const init_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3465534655 .index = field_i,
......@@ -34881,7 +34881,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3488134881
3488234882 if (enum_field_vals.capacity() > 0) {
3488334883 const enum_tag_val = if (tag_ref != .none) blk: {
34884 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
34884 const val = sema.semaUnionFieldVal(&block_scope, LazySrcLoc.un(), int_tag_ty, tag_ref) catch |err| switch (err) {
3488534885 error.NeededSourceLocation => {
3488634886 const val_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3488734887 .index = field_i,
......@@ -34929,7 +34929,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3492934929 else if (field_type_ref == .none)
3493034930 Type.noreturn
3493134931 else
34932 sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {
34932 sema.resolveType(&block_scope, LazySrcLoc.un(), field_type_ref) catch |err| switch (err) {
3493334933 error.NeededSourceLocation => {
3493434934 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3493534935 .index = field_i,
......@@ -35038,7 +35038,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3503835038 };
3503935039
3504035040 if (align_ref != .none) {
35041 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
35041 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, LazySrcLoc.un(), align_ref) catch |err| switch (err) {
3504235042 error.NeededSourceLocation => {
3504335043 const align_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3504435044 .index = field_i,
src/codegen/llvm.zig+270-129
......@@ -2348,7 +2348,24 @@ pub const Object = struct {
23482348 .Null => unreachable,
23492349 .EnumLiteral => unreachable,
23502350
2351 .Frame => @panic("TODO implement lowerDebugType for Frame types"),
2351 .Frame => {
2352 // TODO make this more useful than just a pointer to u8
2353 // TODO this also does not account for async functions with
2354 // any spilled locals that are aligned to more than 16 bytes
2355 const elem_di_ty = try o.lowerDebugType(Type.u8, .full);
2356 const name = try o.allocTypeName(ty);
2357 defer gpa.free(name);
2358 const ptr_di_ty = dib.createPointerType(
2359 elem_di_ty,
2360 target.ptrBitWidth(),
2361 target.ptrBitWidth() * 2, // alignment
2362 name,
2363 );
2364 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2365 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(ptr_di_ty));
2366 return ptr_di_ty;
2367 },
2368
23522369 .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"),
23532370 }
23542371 }
......@@ -3045,6 +3062,17 @@ pub const Object = struct {
30453062 }
30463063 }
30473064
3065 fn lowerAsyncFrameHeader(o: *Object, ret_ty: Type) !*llvm.Type {
3066 const opaque_ptr_ty = o.context.pointerType(0);
3067 const l = asyncFrameLayout();
3068 var fields: [4]*llvm.Type = undefined;
3069 fields[l.fn_ptr] = opaque_ptr_ty;
3070 fields[l.resume_index] = try o.lowerType(Type.usize);
3071 fields[l.awaiter] = opaque_ptr_ty;
3072 fields[l.ret_val] = try o.lowerType(ret_ty);
3073 return o.context.structType(&fields, fields.len, .False);
3074 }
3075
30483076 fn lowerAsyncFrameType(
30493077 o: *Object,
30503078 func: *Module.Fn,
......@@ -4668,6 +4696,200 @@ pub const FuncGen = struct {
46684696 try llvm_args.append(self.err_ret_trace.?);
46694697 }
46704698
4699 try addCallArgs(self, args, &llvm_args, fn_info);
4700
4701 const call = self.builder.buildCall(
4702 try o.lowerType(zig_fn_ty),
4703 llvm_fn,
4704 llvm_args.items.ptr,
4705 @intCast(llvm_args.items.len),
4706 toLlvmCallConv(fn_info.cc, target),
4707 attr,
4708 "",
4709 );
4710
4711 if (callee_ty.zigTypeTag(mod) == .Pointer) {
4712 // Add argument attributes for function pointer calls.
4713 var it = iterateParamTypes(o, fn_info);
4714 it.llvm_index += @intFromBool(sret);
4715 it.llvm_index += @intFromBool(err_return_tracing);
4716 while (it.next()) |lowering| switch (lowering) {
4717 .byval => {
4718 const param_index = it.zig_index - 1;
4719 const param_ty = fn_info.param_types[param_index].toType();
4720 if (!isByRef(param_ty, mod)) {
4721 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
4722 }
4723 },
4724 .byref => {
4725 const param_index = it.zig_index - 1;
4726 const param_ty = fn_info.param_types[param_index].toType();
4727 const param_llvm_ty = try o.lowerType(param_ty);
4728 const alignment = param_ty.abiAlignment(mod);
4729 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
4730 },
4731 .byref_mut => {
4732 o.addArgAttr(call, it.llvm_index - 1, "noundef");
4733 },
4734 // No attributes needed for these.
4735 .no_bits,
4736 .abi_sized_int,
4737 .multiple_llvm_types,
4738 .as_u16,
4739 .float_array,
4740 .i32_array,
4741 .i64_array,
4742 => continue,
4743
4744 .slice => {
4745 assert(!it.byval_attr);
4746 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
4747 const ptr_info = param_ty.ptrInfo(mod);
4748 const llvm_arg_i = it.llvm_index - 2;
4749
4750 if (math.cast(u5, it.zig_index - 1)) |i| {
4751 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
4752 o.addArgAttr(call, llvm_arg_i, "noalias");
4753 }
4754 }
4755 if (param_ty.zigTypeTag(mod) != .Optional) {
4756 o.addArgAttr(call, llvm_arg_i, "nonnull");
4757 }
4758 if (ptr_info.flags.is_const) {
4759 o.addArgAttr(call, llvm_arg_i, "readonly");
4760 }
4761 const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse
4762 @max(ptr_info.child.toType().abiAlignment(mod), 1);
4763 o.addArgAttrInt(call, llvm_arg_i, "align", elem_align);
4764 },
4765 };
4766 }
4767
4768 if (fn_info.return_type == .noreturn_type and attr != .AlwaysTail) {
4769 return null;
4770 }
4771
4772 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) {
4773 return null;
4774 }
4775
4776 const llvm_ret_ty = try o.lowerType(return_type);
4777
4778 if (ret_ptr) |rp| {
4779 call.setCallSret(llvm_ret_ty);
4780 if (isByRef(return_type, mod)) {
4781 return rp;
4782 } else {
4783 // our by-ref status disagrees with sret so we must load.
4784 const loaded = self.builder.buildLoad(llvm_ret_ty, rp, "");
4785 loaded.setAlignment(return_type.abiAlignment(mod));
4786 return loaded;
4787 }
4788 }
4789
4790 const abi_ret_ty = try lowerFnRetTy(o, fn_info);
4791
4792 if (abi_ret_ty != llvm_ret_ty) {
4793 // In this case the function return type is honoring the calling convention by having
4794 // a different LLVM type than the usual one. We solve this here at the callsite
4795 // by using our canonical type, then loading it if necessary.
4796 const alignment = o.target_data.abiAlignmentOfType(abi_ret_ty);
4797 const rp = self.buildAlloca(llvm_ret_ty, alignment);
4798 const store_inst = self.builder.buildStore(call, rp);
4799 store_inst.setAlignment(alignment);
4800 if (isByRef(return_type, mod)) {
4801 return rp;
4802 } else {
4803 const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, "");
4804 load_inst.setAlignment(alignment);
4805 return load_inst;
4806 }
4807 }
4808
4809 if (isByRef(return_type, mod)) {
4810 // our by-ref status disagrees with sret so we must allocate, store,
4811 // and return the allocation pointer.
4812 const alignment = return_type.abiAlignment(mod);
4813 const rp = self.buildAlloca(llvm_ret_ty, alignment);
4814 const store_inst = self.builder.buildStore(call, rp);
4815 store_inst.setAlignment(alignment);
4816 return rp;
4817 } else {
4818 return call;
4819 }
4820 }
4821
4822 fn airCallAsync(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4823 _ = inst;
4824 return self.todo("lower call_async", .{});
4825 }
4826
4827 fn airCallAsyncAlloc(fg: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4828 const o = fg.dg.object;
4829 const mod = o.module;
4830 const ty_pl = fg.air.instructions.items(.data)[inst].ty_pl;
4831 const extra = fg.air.extraData(Air.AsyncCallAlloc, ty_pl.payload);
4832 const args: []const Air.Inst.Ref = @ptrCast(fg.air.extra[extra.end..][0..extra.data.args_len]);
4833 const callee = try fg.resolveInst(extra.data.callee);
4834 const callee_ty = fg.typeOf(extra.data.callee);
4835 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
4836 .Fn => callee_ty,
4837 .Pointer => callee_ty.childType(mod),
4838 else => unreachable,
4839 };
4840 const fn_info = mod.typeToFunc(zig_fn_ty).?;
4841 // Remember that we want to lower calls to functions which have not yet
4842 // been semantically analyzed. So we must not call lowerType on the
4843 // frame type. Instead we runtime-call a function to learn the frame
4844 // size of the callee, allocate that many bytes, and then pointer-cast
4845 // it to the anytype->T header that we know based on the type alone.
4846 const target = mod.getTarget();
4847 const llvm_i8 = o.context.intType(8);
4848 const frame_size = fg.genFrameSize(callee);
4849 const frame_alloca = fg.builder.buildArrayAlloca(llvm_i8, frame_size, "");
4850 frame_alloca.setAlignment(target.ptrBitWidth() / 4);
4851 const frame_llvm_ty = try o.lowerAsyncFrameHeader(fn_info.return_type.toType());
4852 const llvm_ptr_ty = fg.context.pointerType(0);
4853 const frame_ptr = fg.builder.buildBitCast(frame_alloca, llvm_ptr_ty, "");
4854 const l = asyncFrameLayout();
4855 const fn_ptr_ptr = fg.builder.buildStructGEP(frame_llvm_ty, frame_ptr, l.fn_ptr, "");
4856 _ = fg.builder.buildStore(callee, fn_ptr_ptr);
4857
4858 const resume_index_ptr = fg.builder.buildStructGEP(frame_llvm_ty, frame_ptr, l.resume_index, "");
4859 const llvm_usize = o.context.intType(target.ptrBitWidth());
4860 const zero = llvm_usize.constNull();
4861 _ = fg.builder.buildStore(zero, resume_index_ptr);
4862
4863 const awaiter_ptr = fg.builder.buildStructGEP(frame_llvm_ty, frame_ptr, l.awaiter, "");
4864 _ = fg.builder.buildStore(zero, awaiter_ptr);
4865
4866 var llvm_args = std.ArrayList(*llvm.Value).init(fg.gpa);
4867 defer llvm_args.deinit();
4868
4869 try addCallArgs(fg, args, &llvm_args, fn_info);
4870
4871 _ = fg.builder.buildCall(
4872 try o.lowerType(zig_fn_ty),
4873 callee,
4874 llvm_args.items.ptr,
4875 @intCast(llvm_args.items.len),
4876 .Fast,
4877 .Auto,
4878 "",
4879 );
4880
4881 return frame_ptr;
4882 }
4883
4884 fn addCallArgs(
4885 self: *FuncGen,
4886 args: []const Air.Inst.Ref,
4887 llvm_args: *std.ArrayList(*llvm.Value),
4888 fn_info: InternPool.Key.FuncType,
4889 ) !void {
4890 const o = self.dg.object;
4891 const mod = o.module;
4892 const target = mod.getTarget();
46714893 var it = iterateParamTypes(o, fn_info);
46724894 while (it.nextCall(self, args)) |lowering| switch (lowering) {
46734895 .no_bits => continue,
......@@ -4824,126 +5046,6 @@ pub const FuncGen = struct {
48245046 try llvm_args.append(load_inst);
48255047 },
48265048 };
4827
4828 const call = self.builder.buildCall(
4829 try o.lowerType(zig_fn_ty),
4830 llvm_fn,
4831 llvm_args.items.ptr,
4832 @as(c_uint, @intCast(llvm_args.items.len)),
4833 toLlvmCallConv(fn_info.cc, target),
4834 attr,
4835 "",
4836 );
4837
4838 if (callee_ty.zigTypeTag(mod) == .Pointer) {
4839 // Add argument attributes for function pointer calls.
4840 it = iterateParamTypes(o, fn_info);
4841 it.llvm_index += @intFromBool(sret);
4842 it.llvm_index += @intFromBool(err_return_tracing);
4843 while (it.next()) |lowering| switch (lowering) {
4844 .byval => {
4845 const param_index = it.zig_index - 1;
4846 const param_ty = fn_info.param_types[param_index].toType();
4847 if (!isByRef(param_ty, mod)) {
4848 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
4849 }
4850 },
4851 .byref => {
4852 const param_index = it.zig_index - 1;
4853 const param_ty = fn_info.param_types[param_index].toType();
4854 const param_llvm_ty = try o.lowerType(param_ty);
4855 const alignment = param_ty.abiAlignment(mod);
4856 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
4857 },
4858 .byref_mut => {
4859 o.addArgAttr(call, it.llvm_index - 1, "noundef");
4860 },
4861 // No attributes needed for these.
4862 .no_bits,
4863 .abi_sized_int,
4864 .multiple_llvm_types,
4865 .as_u16,
4866 .float_array,
4867 .i32_array,
4868 .i64_array,
4869 => continue,
4870
4871 .slice => {
4872 assert(!it.byval_attr);
4873 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
4874 const ptr_info = param_ty.ptrInfo(mod);
4875 const llvm_arg_i = it.llvm_index - 2;
4876
4877 if (math.cast(u5, it.zig_index - 1)) |i| {
4878 if (@as(u1, @truncate(fn_info.noalias_bits >> i)) != 0) {
4879 o.addArgAttr(call, llvm_arg_i, "noalias");
4880 }
4881 }
4882 if (param_ty.zigTypeTag(mod) != .Optional) {
4883 o.addArgAttr(call, llvm_arg_i, "nonnull");
4884 }
4885 if (ptr_info.flags.is_const) {
4886 o.addArgAttr(call, llvm_arg_i, "readonly");
4887 }
4888 const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse
4889 @max(ptr_info.child.toType().abiAlignment(mod), 1);
4890 o.addArgAttrInt(call, llvm_arg_i, "align", elem_align);
4891 },
4892 };
4893 }
4894
4895 if (fn_info.return_type == .noreturn_type and attr != .AlwaysTail) {
4896 return null;
4897 }
4898
4899 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) {
4900 return null;
4901 }
4902
4903 const llvm_ret_ty = try o.lowerType(return_type);
4904
4905 if (ret_ptr) |rp| {
4906 call.setCallSret(llvm_ret_ty);
4907 if (isByRef(return_type, mod)) {
4908 return rp;
4909 } else {
4910 // our by-ref status disagrees with sret so we must load.
4911 const loaded = self.builder.buildLoad(llvm_ret_ty, rp, "");
4912 loaded.setAlignment(return_type.abiAlignment(mod));
4913 return loaded;
4914 }
4915 }
4916
4917 const abi_ret_ty = try lowerFnRetTy(o, fn_info);
4918
4919 if (abi_ret_ty != llvm_ret_ty) {
4920 // In this case the function return type is honoring the calling convention by having
4921 // a different LLVM type than the usual one. We solve this here at the callsite
4922 // by using our canonical type, then loading it if necessary.
4923 const alignment = o.target_data.abiAlignmentOfType(abi_ret_ty);
4924 const rp = self.buildAlloca(llvm_ret_ty, alignment);
4925 const store_inst = self.builder.buildStore(call, rp);
4926 store_inst.setAlignment(alignment);
4927 if (isByRef(return_type, mod)) {
4928 return rp;
4929 } else {
4930 const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, "");
4931 load_inst.setAlignment(alignment);
4932 return load_inst;
4933 }
4934 }
4935
4936 if (isByRef(return_type, mod)) {
4937 // our by-ref status disagrees with sret so we must allocate, store,
4938 // and return the allocation pointer.
4939 const alignment = return_type.abiAlignment(mod);
4940 const rp = self.buildAlloca(llvm_ret_ty, alignment);
4941 const store_inst = self.builder.buildStore(call, rp);
4942 store_inst.setAlignment(alignment);
4943 return rp;
4944 } else {
4945 return call;
4946 }
49475049 }
49485050
49495051 fn buildSimplePanic(fg: *FuncGen, panic_id: Module.PanicId) !void {
......@@ -4988,14 +5090,27 @@ pub const FuncGen = struct {
49885090 _ = fg.builder.buildUnreachable();
49895091 }
49905092
4991 fn airCallAsync(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4992 _ = inst;
4993 return self.todo("lower call_async", .{});
4994 }
4995
4996 fn airCallAsyncAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4997 _ = inst;
4998 return self.todo("lower call_async_alloc", .{});
5093 fn genFrameSize(fg: *FuncGen, llvm_fn: *llvm.Value) *llvm.Value {
5094 const o = fg.dg.object;
5095 const mod = o.module;
5096 const target = mod.getTarget();
5097 const llvm_usize = o.context.intType(target.ptrBitWidth());
5098 const llvm_ptr_ty = o.context.pointerType(0);
5099 const casted_fn_val = fg.builder.buildBitCast(llvm_fn, llvm_ptr_ty, "");
5100 const indices: [1]*llvm.Value = .{
5101 o.context.intType(32).constInt(@bitCast(@as(c_longlong, -1)), .True),
5102 };
5103 const prefix_ptr = fg.builder.buildInBoundsGEP(llvm_usize, casted_fn_val, &indices, indices.len, "");
5104 const load_inst = fg.builder.buildLoad(llvm_usize, prefix_ptr, "");
5105
5106 // Some architectures (e.g SPARCv9) has different alignment
5107 // requirements between a function/usize pointer and also require all
5108 // loads to be aligned. On those architectures, not explicitly setting
5109 // the alignment will lead into @frameSize generating usize-aligned
5110 // load instruction that could crash if the function pointer happens to
5111 // be not usize-aligned.
5112 load_inst.setAlignment(1);
5113 return load_inst;
49995114 }
50005115
50015116 fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
......@@ -11452,3 +11567,29 @@ fn constraintAllowsRegister(constraint: []const u8) bool {
1145211567 }
1145311568 } else return false;
1145411569}
11570
11571/// Each field is the index in the LLVM struct. The doc comments describe what
11572/// the corresponding field of the LLVM struct does; not the field of the
11573/// AsyncFrameLayout struct.
11574const AsyncFrameLayout = struct {
11575 /// Points to the return value inside the frame.
11576 ret_val: u16,
11577 /// This field of the frame points to the owner function so that a resume
11578 /// on the frame pointer knows which function to call.
11579 fn_ptr: u16,
11580 /// This field tells which suspension point to resume from next time the function is called.
11581 resume_index: u16,
11582 /// This field tracks which frame is the one awaiting the frame for the purposes of resuming
11583 /// on return.
11584 /// A value of zero means the async function has been started, and there is no awaiter yet.
11585 awaiter: u16,
11586};
11587
11588fn asyncFrameLayout() AsyncFrameLayout {
11589 return .{
11590 .fn_ptr = 0,
11591 .resume_index = 1,
11592 .awaiter = 2,
11593 .ret_val = 3,
11594 };
11595}
src/codegen/llvm/bindings.zig+3
......@@ -549,6 +549,9 @@ pub const Builder = opaque {
549549 pub const buildAlloca = LLVMBuildAlloca;
550550 extern fn LLVMBuildAlloca(*Builder, Ty: *Type, Name: [*:0]const u8) *Value;
551551
552 pub const buildArrayAlloca = LLVMBuildArrayAlloca;
553 extern fn LLVMBuildArrayAlloca(*Builder, Ty: *Type, Val: *Value, Name: [*:0]const u8) *Value;
554
552555 pub const buildStore = LLVMBuildStore;
553556 extern fn LLVMBuildStore(*Builder, Val: *Value, Ptr: *Value) *Value;
554557
src/link/Coff.zig+1-1
......@@ -1222,7 +1222,7 @@ fn updateLazySymbolAtom(
12221222 Module.SrcLoc{
12231223 .file_scope = undefined,
12241224 .parent_decl_node = undefined,
1225 .lazy = .unneeded,
1225 .lazy = Module.LazySrcLoc.un(),
12261226 };
12271227 const res = try codegen.generateLazySymbol(
12281228 &self.base,
src/link/Elf.zig+1-1
......@@ -2743,7 +2743,7 @@ fn updateLazySymbolAtom(
27432743 Module.SrcLoc{
27442744 .file_scope = undefined,
27452745 .parent_decl_node = undefined,
2746 .lazy = .unneeded,
2746 .lazy = Module.LazySrcLoc.un(),
27472747 };
27482748 const res = try codegen.generateLazySymbol(
27492749 &self.base,
src/link/MachO.zig+1-1
......@@ -2084,7 +2084,7 @@ fn updateLazySymbolAtom(
20842084 Module.SrcLoc{
20852085 .file_scope = undefined,
20862086 .parent_decl_node = undefined,
2087 .lazy = .unneeded,
2087 .lazy = Module.LazySrcLoc.un(),
20882088 };
20892089 const res = try codegen.generateLazySymbol(
20902090 &self.base,
src/link/Plan9.zig+1-1
......@@ -1051,7 +1051,7 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind
10511051 Module.SrcLoc{
10521052 .file_scope = undefined,
10531053 .parent_decl_node = undefined,
1054 .lazy = .unneeded,
1054 .lazy = Module.LazySrcLoc.un(),
10551055 };
10561056 const res = try codegen.generateLazySymbol(
10571057 &self.base,