| ... | ... | @@ -921,31 +921,41 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { |
| 921 | 921 | return g->memcpy_fn_val; |
| 922 | 922 | } |
| 923 | 923 | |
| 924 | static LLVMValueRef get_return_address_fn_val(CodeGen *g) { |
| 925 | if (g->return_address_fn_val) |
| 926 | return g->return_address_fn_val; |
| 927 | |
| 928 | TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); |
| 929 | |
| 930 | LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref, |
| 931 | &g->builtin_types.entry_i32->type_ref, 1, false); |
| 932 | g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type); |
| 933 | assert(LLVMGetIntrinsicID(g->return_address_fn_val)); |
| 934 | |
| 935 | return g->return_address_fn_val; |
| 936 | } |
| 937 | |
| 924 | 938 | static LLVMValueRef get_return_err_fn(CodeGen *g) { |
| 925 | 939 | if (g->return_err_fn != nullptr) |
| 926 | 940 | return g->return_err_fn; |
| 927 | 941 | |
| 928 | 942 | assert(g->err_tag_type != nullptr); |
| 929 | 943 | |
| 930 | | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 931 | | |
| 932 | 944 | LLVMTypeRef arg_types[] = { |
| 933 | 945 | // error return trace pointer |
| 934 | 946 | get_ptr_to_stack_trace_type(g)->type_ref, |
| 935 | | // return address |
| 936 | | ptr_u8, |
| 937 | 947 | }; |
| 938 | | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); |
| 948 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false); |
| 939 | 949 | |
| 940 | 950 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false); |
| 941 | 951 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); |
| 952 | addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address |
| 942 | 953 | addLLVMFnAttr(fn_val, "cold"); |
| 943 | 954 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| 944 | 955 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 945 | 956 | addLLVMFnAttr(fn_val, "nounwind"); |
| 946 | 957 | add_uwtable_attr(g, fn_val); |
| 947 | 958 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 948 | | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); |
| 949 | 959 | if (g->build_mode == BuildModeDebug) { |
| 950 | 960 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| 951 | 961 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); |
| ... | ... | @@ -983,7 +993,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { |
| 983 | 993 | LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); |
| 984 | 994 | LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, ""); |
| 985 | 995 | |
| 986 | | LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, LLVMGetParam(fn_val, 1), usize_type_ref, ""); |
| 996 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref); |
| 997 | LLVMValueRef return_address_ptr = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); |
| 998 | LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, ""); |
| 987 | 999 | |
| 988 | 1000 | LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, ""); |
| 989 | 1001 | gen_store_untyped(g, address_value, address_slot, 0, false); |
| ... | ... | @@ -1431,17 +1443,11 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 1431 | 1443 | is_err_return = true; |
| 1432 | 1444 | } |
| 1433 | 1445 | if (is_err_return) { |
| 1434 | | LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError"); |
| 1435 | | LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block); |
| 1436 | | |
| 1437 | 1446 | LLVMValueRef return_err_fn = get_return_err_fn(g); |
| 1438 | 1447 | LLVMValueRef args[] = { |
| 1439 | 1448 | g->cur_err_ret_trace_val, |
| 1440 | | block_address, |
| 1441 | 1449 | }; |
| 1442 | | LLVMBuildBr(g->builder, return_block); |
| 1443 | | LLVMPositionBuilderAtEnd(g->builder, return_block); |
| 1444 | | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2, |
| 1450 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1, |
| 1445 | 1451 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); |
| 1446 | 1452 | LLVMSetTailCall(call_instruction, true); |
| 1447 | 1453 | } |
| ... | ... | @@ -3291,20 +3297,6 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I |
| 3291 | 3297 | return nullptr; |
| 3292 | 3298 | } |
| 3293 | 3299 | |
| 3294 | | static LLVMValueRef get_return_address_fn_val(CodeGen *g) { |
| 3295 | | if (g->return_address_fn_val) |
| 3296 | | return g->return_address_fn_val; |
| 3297 | | |
| 3298 | | TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); |
| 3299 | | |
| 3300 | | LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref, |
| 3301 | | &g->builtin_types.entry_i32->type_ref, 1, false); |
| 3302 | | g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type); |
| 3303 | | assert(LLVMGetIntrinsicID(g->return_address_fn_val)); |
| 3304 | | |
| 3305 | | return g->return_address_fn_val; |
| 3306 | | } |
| 3307 | | |
| 3308 | 3300 | static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable, |
| 3309 | 3301 | IrInstructionReturnAddress *instruction) |
| 3310 | 3302 | { |