| ... | ... | @@ -892,7 +892,8 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace |
| 892 | 892 | msg_arg, |
| 893 | 893 | stack_trace_arg, |
| 894 | 894 | }; |
| 895 | | ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_FnInlineAuto, ""); |
| 895 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_FnInlineAuto, ""); |
| 896 | LLVMSetTailCall(call_instruction, true); |
| 896 | 897 | LLVMBuildUnreachable(g->builder); |
| 897 | 898 | } |
| 898 | 899 | |
| ... | ... | @@ -919,6 +920,79 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { |
| 919 | 920 | return g->memcpy_fn_val; |
| 920 | 921 | } |
| 921 | 922 | |
| 923 | static LLVMValueRef get_return_err_fn(CodeGen *g) { |
| 924 | if (g->return_err_fn != nullptr) |
| 925 | return g->return_err_fn; |
| 926 | |
| 927 | assert(g->err_tag_type != nullptr); |
| 928 | |
| 929 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 930 | |
| 931 | LLVMTypeRef arg_types[] = { |
| 932 | // error return trace pointer |
| 933 | get_ptr_to_stack_trace_type(g)->type_ref, |
| 934 | // return address |
| 935 | ptr_u8, |
| 936 | }; |
| 937 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); |
| 938 | |
| 939 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false); |
| 940 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); |
| 941 | addLLVMFnAttr(fn_val, "cold"); |
| 942 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| 943 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 944 | addLLVMFnAttr(fn_val, "nounwind"); |
| 945 | add_uwtable_attr(g, fn_val); |
| 946 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 947 | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); |
| 948 | if (g->build_mode == BuildModeDebug) { |
| 949 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| 950 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); |
| 951 | } |
| 952 | |
| 953 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); |
| 954 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); |
| 955 | LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); |
| 956 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 957 | ZigLLVMClearCurrentDebugLocation(g->builder); |
| 958 | |
| 959 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; |
| 960 | |
| 961 | // stack_trace.instruction_addresses[stack_trace.index % stack_trace_ptr_count] = return_address; |
| 962 | |
| 963 | LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0); |
| 964 | size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; |
| 965 | LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)index_field_index, ""); |
| 966 | size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; |
| 967 | LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, ""); |
| 968 | |
| 969 | LLVMValueRef index_val = gen_load_untyped(g, index_field_ptr, 0, false, ""); |
| 970 | LLVMValueRef modded_val = LLVMBuildURem(g->builder, index_val, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), ""); |
| 971 | LLVMValueRef address_indices[] = { |
| 972 | LLVMConstNull(usize_type_ref), |
| 973 | modded_val, |
| 974 | }; |
| 975 | LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, addresses_field_ptr, address_indices, 2, ""); |
| 976 | |
| 977 | LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, LLVMGetParam(fn_val, 1), usize_type_ref, ""); |
| 978 | |
| 979 | LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, ""); |
| 980 | gen_store_untyped(g, address_value, address_slot, 0, false); |
| 981 | |
| 982 | // stack_trace.index += 1; |
| 983 | LLVMValueRef index_plus_one_val = LLVMBuildAdd(g->builder, index_val, LLVMConstInt(usize_type_ref, 1, false), ""); |
| 984 | gen_store_untyped(g, index_plus_one_val, index_field_ptr, 0, false); |
| 985 | |
| 986 | // return; |
| 987 | LLVMBuildRetVoid(g->builder); |
| 988 | |
| 989 | LLVMPositionBuilderAtEnd(g->builder, prev_block); |
| 990 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); |
| 991 | |
| 992 | g->return_err_fn = fn_val; |
| 993 | return fn_val; |
| 994 | } |
| 995 | |
| 922 | 996 | static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 923 | 997 | if (g->safety_crash_err_fn != nullptr) |
| 924 | 998 | return g->safety_crash_err_fn; |
| ... | ... | @@ -1053,8 +1127,9 @@ static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) { |
| 1053 | 1127 | err_val, |
| 1054 | 1128 | err_ret_trace_val, |
| 1055 | 1129 | }; |
| 1056 | | ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified), |
| 1130 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified), |
| 1057 | 1131 | ZigLLVM_FnInlineAuto, ""); |
| 1132 | LLVMSetTailCall(call_instruction, true); |
| 1058 | 1133 | LLVMBuildUnreachable(g->builder); |
| 1059 | 1134 | } |
| 1060 | 1135 | |
| ... | ... | @@ -1346,36 +1421,19 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 1346 | 1421 | is_err_return = true; |
| 1347 | 1422 | } |
| 1348 | 1423 | if (is_err_return) { |
| 1349 | | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; |
| 1350 | | |
| 1351 | | // stack_trace.instruction_addresses[stack_trace.index % stack_trace_ptr_count] = @instructionPointer(); |
| 1352 | | // stack_trace.index += 1; |
| 1353 | | |
| 1354 | 1424 | LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError"); |
| 1355 | | |
| 1356 | 1425 | LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block); |
| 1357 | | size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; |
| 1358 | | LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)index_field_index, ""); |
| 1359 | | size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; |
| 1360 | | LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)addresses_field_index, ""); |
| 1361 | | |
| 1362 | | // stack_trace.instruction_addresses[stack_trace.index % stack_trace_ptr_count] = @instructionPointer(); |
| 1363 | | LLVMValueRef index_val = gen_load_untyped(g, index_field_ptr, 0, false, ""); |
| 1364 | | LLVMValueRef modded_val = LLVMBuildURem(g->builder, index_val, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), ""); |
| 1365 | | LLVMValueRef address_indices[] = { |
| 1366 | | LLVMConstNull(usize_type_ref), |
| 1367 | | modded_val, |
| 1368 | | }; |
| 1369 | | LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, addresses_field_ptr, address_indices, 2, ""); |
| 1370 | | LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, block_address, usize_type_ref, ""); |
| 1371 | | gen_store_untyped(g, address_value, address_slot, 0, false); |
| 1372 | | |
| 1373 | | // stack_trace.index += 1; |
| 1374 | | LLVMValueRef index_plus_one_val = LLVMBuildAdd(g->builder, index_val, LLVMConstInt(usize_type_ref, 1, false), ""); |
| 1375 | | gen_store_untyped(g, index_plus_one_val, index_field_ptr, 0, false); |
| 1376 | 1426 | |
| 1427 | LLVMValueRef return_err_fn = get_return_err_fn(g); |
| 1428 | LLVMValueRef args[] = { |
| 1429 | g->cur_err_ret_trace_val, |
| 1430 | block_address, |
| 1431 | }; |
| 1377 | 1432 | LLVMBuildBr(g->builder, return_block); |
| 1378 | 1433 | LLVMPositionBuilderAtEnd(g->builder, return_block); |
| 1434 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2, |
| 1435 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); |
| 1436 | LLVMSetTailCall(call_instruction, true); |
| 1379 | 1437 | } |
| 1380 | 1438 | if (handle_is_ptr(return_type)) { |
| 1381 | 1439 | if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) { |