@@ -964,7 +964,9 @@ static ZigType *ptr_to_stack_trace_type(CodeGen *g) {
964
964
return get_pointer_to_type (g, get_stack_trace_type (g), false );
965
965
}
966
966
967
- static void gen_panic (CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg) {
967
+ static void gen_panic (CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg,
968
+ bool stack_trace_is_llvm_alloca)
969
+ {
968
970
assert (g->panic_fn != nullptr );
969
971
LLVMValueRef fn_val = fn_llvm_value (g, g->panic_fn );
970
972
LLVMCallConv llvm_cc = get_llvm_cc (g, g->panic_fn ->type_entry ->data .fn .fn_type_id .cc );
@@ -975,14 +977,20 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace
975
977
msg_arg,
976
978
stack_trace_arg,
977
979
};
978
- LLVMValueRef call_instruction = ZigLLVMBuildCall (g->builder , fn_val, args, 2 , llvm_cc, ZigLLVM_FnInlineAuto, " " );
979
- LLVMSetTailCall (call_instruction, true );
980
+ ZigLLVMBuildCall (g->builder , fn_val, args, 2 , llvm_cc, ZigLLVM_FnInlineAuto, " " );
981
+ if (!stack_trace_is_llvm_alloca) {
982
+ // The stack trace argument is not in the stack of the caller, so
983
+ // we'd like to set tail call here, but because slices (the type of msg_arg) are
984
+ // still passed as pointers (see https://github.com/ziglang/zig/issues/561) we still
985
+ // cannot make this a tail call.
986
+ // LLVMSetTailCall(call_instruction, true);
987
+ }
980
988
LLVMBuildUnreachable (g->builder );
981
989
}
982
990
983
991
// TODO update most callsites to call gen_assertion instead of this
984
992
static void gen_safety_crash (CodeGen *g, PanicMsgId msg_id) {
985
- gen_panic (g, get_panic_msg_ptr_val (g, msg_id), nullptr );
993
+ gen_panic (g, get_panic_msg_ptr_val (g, msg_id), nullptr , false );
986
994
}
987
995
988
996
static void gen_assertion_scope (CodeGen *g, PanicMsgId msg_id, Scope *source_scope) {
@@ -1320,7 +1328,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1320
1328
gen_store_untyped (g, slice_len, msg_slice_len_field_ptr, 0 , false );
1321
1329
1322
1330
// Call panic()
1323
- gen_panic (g, msg_slice, err_ret_trace_arg);
1331
+ gen_panic (g, msg_slice, err_ret_trace_arg, false );
1324
1332
1325
1333
LLVMPositionBuilderAtEnd (g->builder , prev_block);
1326
1334
if (!g->strip_debug_symbols ) {
@@ -1331,21 +1339,25 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
1331
1339
return fn_val;
1332
1340
}
1333
1341
1334
- static LLVMValueRef get_cur_err_ret_trace_val (CodeGen *g, Scope *scope) {
1342
+ static LLVMValueRef get_cur_err_ret_trace_val (CodeGen *g, Scope *scope, bool *is_llvm_alloca ) {
1335
1343
if (!g->have_err_ret_tracing ) {
1344
+ *is_llvm_alloca = false ;
1336
1345
return nullptr ;
1337
1346
}
1338
1347
if (g->cur_err_ret_trace_val_stack != nullptr ) {
1348
+ *is_llvm_alloca = !fn_is_async (g->cur_fn );
1339
1349
return g->cur_err_ret_trace_val_stack ;
1340
1350
}
1351
+ *is_llvm_alloca = false ;
1341
1352
return g->cur_err_ret_trace_val_arg ;
1342
1353
}
1343
1354
1344
1355
static void gen_safety_crash_for_err (CodeGen *g, LLVMValueRef err_val, Scope *scope) {
1345
1356
LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn (g);
1346
1357
LLVMValueRef call_instruction;
1358
+ bool is_llvm_alloca = false ;
1347
1359
if (g->have_err_ret_tracing ) {
1348
- LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val (g, scope);
1360
+ LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val (g, scope, &is_llvm_alloca );
1349
1361
if (err_ret_trace_val == nullptr ) {
1350
1362
err_ret_trace_val = LLVMConstNull (get_llvm_type (g, ptr_to_stack_trace_type (g)));
1351
1363
}
@@ -1362,7 +1374,9 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc
1362
1374
call_instruction = ZigLLVMBuildCall (g->builder , safety_crash_err_fn, args, 1 ,
1363
1375
get_llvm_cc (g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, " " );
1364
1376
}
1365
- LLVMSetTailCall (call_instruction, true );
1377
+ if (!is_llvm_alloca) {
1378
+ LLVMSetTailCall (call_instruction, true );
1379
+ }
1366
1380
LLVMBuildUnreachable (g->builder );
1367
1381
}
1368
1382
@@ -2202,7 +2216,9 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
2202
2216
assert (g->have_err_ret_tracing );
2203
2217
2204
2218
LLVMValueRef return_err_fn = get_return_err_fn (g);
2205
- LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val (g, save_err_ret_addr_instruction->base .scope );
2219
+ bool is_llvm_alloca;
2220
+ LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val (g, save_err_ret_addr_instruction->base .scope ,
2221
+ &is_llvm_alloca);
2206
2222
ZigLLVMBuildCall (g->builder , return_err_fn, &my_err_trace_val, 1 ,
2207
2223
get_llvm_cc (g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, " " );
2208
2224
@@ -2256,6 +2272,10 @@ static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
2256
2272
return resume_bb;
2257
2273
}
2258
2274
2275
+ // Be careful setting tail call. According to LLVM lang ref,
2276
+ // tail and musttail imply that the callee does not access allocas from the caller.
2277
+ // This works for async functions since the locals are spilled.
2278
+ // http://llvm.org/docs/LangRef.html#id320
2259
2279
static void set_tail_call_if_appropriate (CodeGen *g, LLVMValueRef call_inst) {
2260
2280
LLVMSetTailCall (call_inst, true );
2261
2281
}
@@ -2361,7 +2381,8 @@ static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) {
2361
2381
LLVMValueRef awaiter_trace_ptr_ptr = LLVMBuildStructGEP (g->builder , g->cur_frame_ptr ,
2362
2382
frame_index_trace_arg (g, ret_type) + 1 , " " );
2363
2383
LLVMValueRef dest_trace_ptr = LLVMBuildLoad (g->builder , awaiter_trace_ptr_ptr, " " );
2364
- LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope );
2384
+ bool is_llvm_alloca;
2385
+ LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope , &is_llvm_alloca);
2365
2386
LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };
2366
2387
ZigLLVMBuildCall (g->builder , get_merge_err_ret_traces_fn_val (g), args, 2 ,
2367
2388
get_llvm_cc (g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, " " );
@@ -3967,7 +3988,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3967
3988
if (prefix_arg_err_ret_stack) {
3968
3989
LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP (g->builder , frame_result_loc,
3969
3990
frame_index_trace_arg (g, src_return_type) + 1 , " " );
3970
- LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope );
3991
+ bool is_llvm_alloca;
3992
+ LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope ,
3993
+ &is_llvm_alloca);
3971
3994
LLVMBuildStore (g->builder , my_err_ret_trace_val, err_ret_trace_ptr_ptr);
3972
3995
}
3973
3996
}
@@ -4024,15 +4047,17 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4024
4047
4025
4048
gen_init_stack_trace (g, trace_field_ptr, addrs_field_ptr);
4026
4049
4027
- gen_param_values.append (get_cur_err_ret_trace_val (g, instruction->base .scope ));
4050
+ bool is_llvm_alloca;
4051
+ gen_param_values.append (get_cur_err_ret_trace_val (g, instruction->base .scope , &is_llvm_alloca));
4028
4052
}
4029
4053
}
4030
4054
} else {
4031
4055
if (first_arg_ret) {
4032
4056
gen_param_values.append (result_loc);
4033
4057
}
4034
4058
if (prefix_arg_err_ret_stack) {
4035
- gen_param_values.append (get_cur_err_ret_trace_val (g, instruction->base .scope ));
4059
+ bool is_llvm_alloca;
4060
+ gen_param_values.append (get_cur_err_ret_trace_val (g, instruction->base .scope , &is_llvm_alloca));
4036
4061
}
4037
4062
}
4038
4063
FnWalk fn_walk = {};
@@ -4912,7 +4937,8 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
4912
4937
static LLVMValueRef ir_render_error_return_trace (CodeGen *g, IrExecutable *executable,
4913
4938
IrInstructionErrorReturnTrace *instruction)
4914
4939
{
4915
- LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope );
4940
+ bool is_llvm_alloca;
4941
+ LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope , &is_llvm_alloca);
4916
4942
if (cur_err_ret_trace_val == nullptr ) {
4917
4943
return LLVMConstNull (get_llvm_type (g, ptr_to_stack_trace_type (g)));
4918
4944
}
@@ -5496,7 +5522,9 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
5496
5522
}
5497
5523
5498
5524
static LLVMValueRef ir_render_panic (CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
5499
- gen_panic (g, ir_llvm_value (g, instruction->msg ), get_cur_err_ret_trace_val (g, instruction->base .scope ));
5525
+ bool is_llvm_alloca;
5526
+ LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope , &is_llvm_alloca);
5527
+ gen_panic (g, ir_llvm_value (g, instruction->msg ), err_ret_trace_val, is_llvm_alloca);
5500
5528
return nullptr ;
5501
5529
}
5502
5530
@@ -5753,7 +5781,8 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_ins
5753
5781
LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP (g->builder , target_frame_ptr,
5754
5782
frame_index_trace_arg (g, result_type), " " );
5755
5783
LLVMValueRef src_trace_ptr = LLVMBuildLoad (g->builder , their_trace_ptr_ptr, " " );
5756
- LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val (g, source_instr->scope );
5784
+ bool is_llvm_alloca;
5785
+ LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val (g, source_instr->scope , &is_llvm_alloca);
5757
5786
LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
5758
5787
ZigLLVMBuildCall (g->builder , get_merge_err_ret_traces_fn_val (g), args, 2 ,
5759
5788
get_llvm_cc (g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, " " );
@@ -5802,7 +5831,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
5802
5831
5803
5832
// supply the error return trace pointer
5804
5833
if (codegen_fn_has_err_ret_tracing_arg (g, result_type)) {
5805
- LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope );
5834
+ bool is_llvm_alloca;
5835
+ LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val (g, instruction->base .scope , &is_llvm_alloca);
5806
5836
assert (my_err_ret_trace_val != nullptr );
5807
5837
LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP (g->builder , target_frame_ptr,
5808
5838
frame_index_trace_arg (g, result_type) + 1 , " " );
0 commit comments