authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-22 20:07:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-26 15:57:07-07:00
log3faa550dc2d6b9a3a8e3be22fc927c8c5682d6c8
tree59d3607cc15c1dbe1fc1928cdafacd29a75c1e1a
parente45b10f3d453f3bd8326631ee786a2ef247e8953

stage2 async progress

After analyzing function body, check call instructions and determine whether it is an async function or not. LLVM backend: support lowering trivial async functions

4 files changed, 155 insertions(+), 44 deletions(-)

BRANCH_TODO+7
...@@ -1,3 +1,9 @@...@@ -1,3 +1,9 @@
1 * calling getFuncAsyncStatus is triggering machine code lowering too early,
2 because the function which does not yet know its own async status may get called
3 recursively by one of the callees.
4 - don't do any lowering to machine code until async status has been resolved for
5 the local call graph sub-tree.
6
1 * detect when a called function is async and make the caller async too7 * detect when a called function is async and make the caller async too
2 * generate the async frame type *after* lowering the function to LLVM IR8 * generate the async frame type *after* lowering the function to LLVM IR
3 * calculate frame size after llvm lowering, ability to inspect with `@sizeOf`9 * calculate frame size after llvm lowering, ability to inspect with `@sizeOf`
...@@ -11,3 +17,4 @@...@@ -11,3 +17,4 @@
11 * use function pointers instead of resume index to...17 * use function pointers instead of resume index to...
12 - reduce the number of runtime branches from 2 to 118 - reduce the number of runtime branches from 2 to 1
13 - pass function arguments as normal arguments to the first segment19 - pass function arguments as normal arguments to the first segment
20
src/Module.zig+60-9
...@@ -5692,10 +5692,9 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5692,10 +5692,9 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5692 inner_block.error_return_trace_index = error_return_trace_index;5692 inner_block.error_return_trace_index = error_return_trace_index;
56935693
5694 sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {5694 sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
5695 // TODO make these unreachable instead of @panic5695 error.NeededSourceLocation => unreachable,
5696 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),5696 error.GenericPoison => unreachable,
5697 error.GenericPoison => @panic("zig compiler bug: GenericPoison"),5697 error.ComptimeReturn => unreachable,
5698 error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"),
5699 else => |e| return e,5698 else => |e| return e,
5700 };5699 };
57015700
...@@ -5717,11 +5716,10 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5717,11 +5716,10 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5717 !sema.fn_ret_ty.isError(mod))5716 !sema.fn_ret_ty.isError(mod))
5718 {5717 {
5719 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {5718 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
5720 // TODO make these unreachable instead of @panic5719 error.NeededSourceLocation => unreachable,
5721 error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),5720 error.GenericPoison => unreachable,
5722 error.GenericPoison => @panic("zig compiler bug: GenericPoison"),5721 error.ComptimeReturn => unreachable,
5723 error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"),5722 error.ComptimeBreak => unreachable,
5724 error.ComptimeBreak => @panic("zig compiler bug: ComptimeBreak"),
5725 else => |e| return e,5723 else => |e| return e,
5726 };5724 };
5727 }5725 }
...@@ -5742,6 +5740,59 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5742,6 +5740,59 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5742 sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;5740 sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;
57435741
5744 func.state = .success;5742 func.state = .success;
5743
5744 // Next we must look at all the function calls and determine two pieces of information:
5745 // * for each call, whether the called function is async
5746 // * whether this function making the calls is async
5747 // This happens *after* setting func.state to success above so that any
5748 // recursive check on this function will not cause an infinite loop.
5749 // Both of these pieces of information are needed by backends for machine code lowering.
5750 {
5751 const air = sema.getTmpAir();
5752 const air_tags = air.instructions.items(.tag);
5753 const air_datas = air.instructions.items(.data);
5754 for (air_tags, 0..) |air_tag, inst| {
5755 var is_suspend_point = false;
5756 const callee = switch (air_tag) {
5757 .call, .call_always_tail, .call_never_tail, .call_never_inline => c: {
5758 is_suspend_point = true;
5759 const pl_op = air_datas[inst].pl_op;
5760 break :c pl_op.operand;
5761 },
5762 .call_async => c: {
5763 const pl_op = air_datas[inst].pl_op;
5764 break :c pl_op.operand;
5765 },
5766 .call_async_alloc => c: {
5767 const ty_pl = air.instructions.items(.data)[inst].ty_pl;
5768 const extra = air.extraData(Air.AsyncCallAlloc, ty_pl.payload);
5769 break :c extra.data.callee;
5770 },
5771 else => continue,
5772 };
5773 const callee_val = (try air.value(callee, mod)) orelse continue;
5774 const callee_decl_index = switch (mod.intern_pool.indexToKey(callee_val.toIntern())) {
5775 .extern_func => continue, // extern functions cannot be async
5776 .func => |f| mod.funcPtr(f.index).owner_decl,
5777 else => unreachable,
5778 };
5779 const callee_decl = mod.declPtr(callee_decl_index);
5780 const callee_func_index = callee_decl.getOwnedFunctionIndex(mod).unwrap() orelse continue;
5781 const callee_status = sema.getFuncAsyncStatus(callee_func_index) catch |err| switch (err) {
5782 error.NeededSourceLocation => unreachable,
5783 error.GenericPoison => unreachable,
5784 error.ComptimeReturn => unreachable,
5785 error.ComptimeBreak => unreachable,
5786 error.AnalysisFail => continue, // treat this callee as non-async
5787 else => |e| return e,
5788 };
5789 if (is_suspend_point) switch (callee_status) {
5790 .unknown => unreachable,
5791 .not_async => continue,
5792 .yes_async => func.async_status = .yes_async,
5793 };
5794 }
5795 }
5745 if (func.async_status == .unknown) {5796 if (func.async_status == .unknown) {
5746 func.async_status = .not_async;5797 func.async_status = .not_async;
5747 }5798 }
src/Sema.zig+27-2
...@@ -9322,7 +9322,8 @@ fn funcCommon(...@@ -9322,7 +9322,8 @@ fn funcCommon(
9322 return sema.addType(fn_ty);9322 return sema.addType(fn_ty);
9323 }9323 }
93249324
9325 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;9325 const init_cc = fn_ty.fnCallingConvention(mod);
9326 const is_inline = init_cc == .Inline;
9326 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;9327 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
93279328
9328 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {9329 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
...@@ -9334,7 +9335,7 @@ fn funcCommon(...@@ -9334,7 +9335,7 @@ fn funcCommon(
9334 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;9335 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;
9335 new_func.* = .{9336 new_func.* = .{
9336 .state = anal_state,9337 .state = anal_state,
9337 .async_status = .unknown,9338 .async_status = initAsyncSatus(init_cc),
9338 .zir_body_inst = func_inst,9339 .zir_body_inst = func_inst,
9339 .owner_decl = sema.owner_decl_index,9340 .owner_decl = sema.owner_decl_index,
9340 .generic_owner_decl = generic_owner_decl,9341 .generic_owner_decl = generic_owner_decl,
...@@ -9353,6 +9354,14 @@ fn funcCommon(...@@ -9353,6 +9354,14 @@ fn funcCommon(
9353 } })).toValue());9354 } })).toValue());
9354}9355}
93559356
9357fn initAsyncSatus(cc: std.builtin.CallingConvention) Module.Fn.AsyncStatus {
9358 return switch (cc) {
9359 .Unspecified => .unknown,
9360 .Async => .yes_async,
9361 else => .not_async,
9362 };
9363}
9364
9356fn analyzeParameter(9365fn analyzeParameter(
9357 sema: *Sema,9366 sema: *Sema,
9358 block: *Block,9367 block: *Block,
...@@ -30557,6 +30566,22 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void...@@ -30557,6 +30566,22 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void
30557 };30566 };
30558}30567}
3055930568
30569pub fn getFuncAsyncStatus(sema: *Sema, func_index: Module.Fn.Index) CompileError!Module.Fn.AsyncStatus {
30570 const mod = sema.mod;
30571 const func = mod.funcPtr(func_index);
30572 switch (func.async_status) {
30573 .yes_async => return .yes_async,
30574 .not_async => return .not_async,
30575 .unknown => {
30576 try ensureFuncBodyAnalyzed(sema, func_index);
30577 switch (func.async_status) {
30578 .yes_async => return .yes_async,
30579 .not_async, .unknown => return .not_async,
30580 }
30581 },
30582 }
30583}
30584
30560fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {30585fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
30561 const mod = sema.mod;30586 const mod = sema.mod;
30562 var anon_decl = try block.startAnonDecl();30587 var anon_decl = try block.startAnonDecl();
src/codegen/llvm.zig+61-33
...@@ -961,7 +961,11 @@ pub const Object = struct {...@@ -961,7 +961,11 @@ pub const Object = struct {
961 defer args.deinit();961 defer args.deinit();
962962
963 {963 {
964 var llvm_arg_i = @as(c_uint, @intFromBool(ret_ptr != null)) + @intFromBool(err_return_tracing);964 var llvm_arg_i =
965 @as(c_uint, @intFromBool(ret_ptr != null)) +
966 @intFromBool(err_return_tracing) +
967 @intFromBool(func.isAsync());
968
965 var it = iterateParamTypes(o, fn_info);969 var it = iterateParamTypes(o, fn_info);
966 while (it.next()) |lowering| switch (lowering) {970 while (it.next()) |lowering| switch (lowering) {
967 .no_bits => continue,971 .no_bits => continue,
...@@ -1215,25 +1219,27 @@ pub const Object = struct {...@@ -1215,25 +1219,27 @@ pub const Object = struct {
1215 };1219 };
1216 defer fg.deinit();1220 defer fg.deinit();
12171221
1218 if (func.isAsync()) {1222 const llvm_usize = o.context.intType(target.ptrBitWidth());
1219 const frame_ty = try mod.asyncFrameType(func_index);
1220 const frame_size = frame_ty.abiSize(mod);
1221 const llvm_usize = dg.context.intType(target.ptrBitWidth());
1222 const size_val = llvm_usize.constInt(frame_size, .False);
1223 llvm_func.functionSetPrefixData(size_val);
12241223
1225 const async_preamble_bb = dg.context.appendBasicBlock(llvm_func, "AsyncSwitch");1224 if (func.isAsync()) {
1226 const bad_resume_bb = dg.context.appendBasicBlock(llvm_func, "BadResume");1225 const bad_resume_bb = o.context.appendBasicBlock(llvm_func, "BadResume");
1227 builder.positionBuilderAtEnd(bad_resume_bb);1226 builder.positionBuilderAtEnd(bad_resume_bb);
1228 _ = builder.buildUnreachable(); // TODO make this a safety panic1227 _ = builder.buildUnreachable(); // TODO make this a safety panic
12291228
1230 builder.positionBuilderAtEnd(async_preamble_bb);1229 builder.positionBuilderAtEnd(entry_block);
1231 const l = asyncFrameLayout();1230 const l = asyncFrameLayout();
1232 const frame_llvm_ty = try dg.lowerType(frame_ty);1231 const frame_llvm_ty = try o.lowerAsyncFrameHeader(fn_info.return_type.toType());
1233 const frame_ptr = llvm_func.getParam(0);1232 const frame_ptr = llvm_func.getParam(0);
1234 fg.resume_index_ptr = builder.buildStructGEP(frame_llvm_ty, frame_ptr, l.resume_index, "");1233 fg.resume_index_ptr = builder.buildStructGEP(frame_llvm_ty, frame_ptr, l.resume_index, "");
1235 const resume_index = builder.buildLoad(llvm_usize, fg.resume_index_ptr, "");1234 const resume_index = builder.buildLoad(llvm_usize, fg.resume_index_ptr, "");
1236 fg.async_switch = builder.buildSwitch(resume_index, bad_resume_bb, 4);1235 fg.async_switch = builder.buildSwitch(resume_index, bad_resume_bb, 4);
1236
1237 const init_bb = o.context.appendBasicBlock(llvm_func, "Init");
1238 const new_block_index = fg.resume_block_index;
1239 fg.resume_block_index += 1;
1240 const new_block_index_llvm_val = llvm_usize.constInt(new_block_index, .False);
1241 fg.async_switch.addCase(new_block_index_llvm_val, init_bb);
1242 builder.positionBuilderAtEnd(init_bb);
1237 }1243 }
12381244
1239 fg.genBody(air.getMainBody()) catch |err| switch (err) {1245 fg.genBody(air.getMainBody()) catch |err| switch (err) {
...@@ -1246,6 +1252,12 @@ pub const Object = struct {...@@ -1246,6 +1252,12 @@ pub const Object = struct {
1246 else => |e| return e,1252 else => |e| return e,
1247 };1253 };
12481254
1255 if (func.isAsync()) {
1256 const frame_size = 3 * (target.ptrBitWidth() / 8);
1257 const size_val = llvm_usize.constInt(frame_size, .False);
1258 llvm_func.functionSetPrefixData(size_val);
1259 }
1260
1249 try o.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));1261 try o.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
1250 }1262 }
12511263
...@@ -2499,16 +2511,20 @@ pub const Object = struct {...@@ -2499,16 +2511,20 @@ pub const Object = struct {
2499 const mod = o.module;2511 const mod = o.module;
2500 const gpa = o.gpa;2512 const gpa = o.gpa;
2501 const decl = mod.declPtr(decl_index);2513 const decl = mod.declPtr(decl_index);
2502 const zig_fn_type = decl.ty;
2503 const gop = try o.decl_map.getOrPut(gpa, decl_index);2514 const gop = try o.decl_map.getOrPut(gpa, decl_index);
2504 if (gop.found_existing) return gop.value_ptr.*;2515 if (gop.found_existing) return gop.value_ptr.*;
25052516
2506 assert(decl.has_tv);2517 assert(decl.has_tv);
2507 const fn_info = mod.typeToFunc(zig_fn_type).?;2518 const func = decl.getOwnedFunction(mod).?;
2519 const zig_fn_type = decl.ty;
2520 const fn_info = info: {
2521 var info = mod.typeToFunc(zig_fn_type).?;
2522 if (func.isAsync()) info.cc = .Async;
2523 break :info info;
2524 };
2508 const target = mod.getTarget();2525 const target = mod.getTarget();
2509 const sret = firstParamSRet(fn_info, mod);2526 const sret = firstParamSRet(fn_info, mod);
25102527 const fn_type = try o.lowerTypeFn(fn_info);
2511 const fn_type = try o.lowerType(zig_fn_type);
25122528
2513 const fqn = try decl.getFullyQualifiedName(mod);2529 const fqn = try decl.getFullyQualifiedName(mod);
25142530
...@@ -2531,32 +2547,33 @@ pub const Object = struct {...@@ -2531,32 +2547,33 @@ pub const Object = struct {
2531 }2547 }
2532 }2548 }
25332549
2550 var llvm_param_i: u32 = 0;
2551
2534 if (sret) {2552 if (sret) {
2535 o.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 02553 o.addArgAttr(llvm_fn, llvm_param_i, "nonnull"); // Sret pointers must not be address 0
2536 o.addArgAttr(llvm_fn, 0, "noalias");2554 o.addArgAttr(llvm_fn, llvm_param_i, "noalias");
25372555
2538 const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType());2556 const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType());
2539 llvm_fn.addSretAttr(raw_llvm_ret_ty);2557 llvm_fn.addSretAttr(raw_llvm_ret_ty);
2558
2559 llvm_param_i += 1;
2540 }2560 }
25412561
2542 const err_return_tracing = fn_info.return_type.toType().isError(mod) and2562 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
2543 mod.comp.bin_file.options.error_return_tracing;2563 mod.comp.bin_file.options.error_return_tracing;
25442564
2545 if (err_return_tracing) {2565 if (err_return_tracing) {
2546 o.addArgAttr(llvm_fn, @intFromBool(sret), "nonnull");2566 o.addArgAttr(llvm_fn, llvm_param_i, "nonnull");
2567 llvm_param_i += 1;
2547 }2568 }
25482569
2549 switch (fn_info.cc) {2570 switch (fn_info.cc) {
2550 .Unspecified, .Inline => {2571 .Unspecified, .Inline, .Async => {
2551 llvm_fn.setFunctionCallConv(.Fast);2572 llvm_fn.setFunctionCallConv(.Fast);
2552 },2573 },
2553 .Naked => {2574 .Naked => {
2554 o.addFnAttr(llvm_fn, "naked");2575 o.addFnAttr(llvm_fn, "naked");
2555 },2576 },
2556 .Async => {
2557 llvm_fn.setFunctionCallConv(.Fast);
2558 @panic("TODO: LLVM backend lower async function");
2559 },
2560 else => {2577 else => {
2561 llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target));2578 llvm_fn.setFunctionCallConv(toLlvmCallConv(fn_info.cc, target));
2562 },2579 },
...@@ -2577,8 +2594,7 @@ pub const Object = struct {...@@ -2577,8 +2594,7 @@ pub const Object = struct {
2577 // because functions with bodies are handled in `updateFunc`.2594 // because functions with bodies are handled in `updateFunc`.
2578 if (is_extern) {2595 if (is_extern) {
2579 var it = iterateParamTypes(o, fn_info);2596 var it = iterateParamTypes(o, fn_info);
2580 it.llvm_index += @intFromBool(sret);2597 it.llvm_index += llvm_param_i;
2581 it.llvm_index += @intFromBool(err_return_tracing);
2582 while (it.next()) |lowering| switch (lowering) {2598 while (it.next()) |lowering| switch (lowering) {
2583 .byval => {2599 .byval => {
2584 const param_index = it.zig_index - 1;2600 const param_index = it.zig_index - 1;
...@@ -3052,7 +3068,7 @@ pub const Object = struct {...@@ -3052,7 +3068,7 @@ pub const Object = struct {
3052 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);3068 llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);
3053 return llvm_union_ty;3069 return llvm_union_ty;
3054 },3070 },
3055 .Fn => return lowerTypeFn(o, t),3071 .Fn => return lowerTypeFn(o, mod.typeToFunc(t).?),
3056 .ComptimeInt => unreachable,3072 .ComptimeInt => unreachable,
3057 .ComptimeFloat => unreachable,3073 .ComptimeFloat => unreachable,
3058 .Type => unreachable,3074 .Type => unreachable,
...@@ -3089,12 +3105,16 @@ pub const Object = struct {...@@ -3089,12 +3105,16 @@ pub const Object = struct {
3089 }3105 }
30903106
3091 fn lowerAsyncFrameHeader(o: *Object, ret_ty: Type) !*llvm.Type {3107 fn lowerAsyncFrameHeader(o: *Object, ret_ty: Type) !*llvm.Type {
3108 const mod = o.module;
3092 const opaque_ptr_ty = o.context.pointerType(0);3109 const opaque_ptr_ty = o.context.pointerType(0);
3093 const l = asyncFrameLayout();3110 const l = asyncFrameLayout();
3094 var fields: [4]*llvm.Type = undefined;3111 var fields: [4]*llvm.Type = undefined;
3095 fields[l.fn_ptr] = opaque_ptr_ty;3112 fields[l.fn_ptr] = opaque_ptr_ty;
3096 fields[l.resume_index] = try o.lowerType(Type.usize);3113 fields[l.resume_index] = try o.lowerType(Type.usize);
3097 fields[l.awaiter] = opaque_ptr_ty;3114 fields[l.awaiter] = opaque_ptr_ty;
3115 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3116 return o.context.structType(&fields, 3, .False);
3117 }
3098 fields[l.ret_val] = try o.lowerType(ret_ty);3118 fields[l.ret_val] = try o.lowerType(ret_ty);
3099 return o.context.structType(&fields, fields.len, .False);3119 return o.context.structType(&fields, fields.len, .False);
3100 }3120 }
...@@ -3122,23 +3142,29 @@ pub const Object = struct {...@@ -3122,23 +3142,29 @@ pub const Object = struct {
3122 return llvm_struct_ty;3142 return llvm_struct_ty;
3123 }3143 }
31243144
3125 fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {3145 fn lowerTypeFn(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!*llvm.Type {
3126 const mod = o.module;3146 const mod = o.module;
3127 const fn_info = mod.typeToFunc(fn_ty).?;
3128 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);3147 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
31293148
3130 var llvm_params = std.ArrayList(*llvm.Type).init(o.gpa);3149 var llvm_params = std.ArrayList(*llvm.Type).init(o.gpa);
3131 defer llvm_params.deinit();3150 defer llvm_params.deinit();
31323151
3152 try llvm_params.ensureUnusedCapacity(3);
3153
3133 if (firstParamSRet(fn_info, mod)) {3154 if (firstParamSRet(fn_info, mod)) {
3134 try llvm_params.append(o.context.pointerType(0));3155 llvm_params.appendAssumeCapacity(o.context.pointerType(0));
3156 }
3157
3158 if (fn_info.cc == .Async) {
3159 // frame_ptr
3160 llvm_params.appendAssumeCapacity(o.context.pointerType(0));
3135 }3161 }
31363162
3137 if (fn_info.return_type.toType().isError(mod) and3163 if (fn_info.return_type.toType().isError(mod) and
3138 mod.comp.bin_file.options.error_return_tracing)3164 mod.comp.bin_file.options.error_return_tracing)
3139 {3165 {
3140 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());3166 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
3141 try llvm_params.append(try o.lowerType(ptr_ty));3167 llvm_params.appendAssumeCapacity(try o.lowerType(ptr_ty));
3142 }3168 }
31433169
3144 var it = iterateParamTypes(o, fn_info);3170 var it = iterateParamTypes(o, fn_info);
...@@ -4860,9 +4886,11 @@ pub const FuncGen = struct {...@@ -4860,9 +4886,11 @@ pub const FuncGen = struct {
4860 }4886 }
48614887
4862 fn genSuspendBegin(fg: *FuncGen, name_hint: [*:0]const u8) *llvm.BasicBlock {4888 fn genSuspendBegin(fg: *FuncGen, name_hint: [*:0]const u8) *llvm.BasicBlock {
4863 const target = fg.getTarget();4889 const o = fg.dg.object;
4864 const llvm_usize = fg.dg.context.intType(target.ptrBitWidth());4890 const mod = o.module;
4865 const resume_bb = fg.context.appendBasicBlock(fg.llvm_func, name_hint);4891 const target = mod.getTarget();
4892 const llvm_usize = o.context.intType(target.ptrBitWidth());
4893 const resume_bb = o.context.appendBasicBlock(fg.llvm_func, name_hint);
4866 const new_block_index = fg.resume_block_index;4894 const new_block_index = fg.resume_block_index;
4867 fg.resume_block_index += 1;4895 fg.resume_block_index += 1;
4868 const new_block_index_llvm_val = llvm_usize.constInt(new_block_index, .False);4896 const new_block_index_llvm_val = llvm_usize.constInt(new_block_index, .False);