| ... | ... | @@ -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,7 +4047,8 @@ 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 { |
| ... | ... | @@ -4032,7 +4056,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 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, ""); |