| ... | @@ -921,31 +921,41 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { | ... | @@ -921,31 +921,41 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { |
| 921 | return g->memcpy_fn_val; | 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 | static LLVMValueRef get_return_err_fn(CodeGen *g) { | 938 | static LLVMValueRef get_return_err_fn(CodeGen *g) { |
| 925 | if (g->return_err_fn != nullptr) | 939 | if (g->return_err_fn != nullptr) |
| 926 | return g->return_err_fn; | 940 | return g->return_err_fn; |
| 927 | | 941 | |
| 928 | assert(g->err_tag_type != nullptr); | 942 | assert(g->err_tag_type != nullptr); |
| 929 | | 943 | |
| 930 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | | |
| 931 | | | |
| 932 | LLVMTypeRef arg_types[] = { | 944 | LLVMTypeRef arg_types[] = { |
| 933 | // error return trace pointer | 945 | // error return trace pointer |
| 934 | get_ptr_to_stack_trace_type(g)->type_ref, | 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 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false); | 950 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false); |
| 941 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); | 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 | addLLVMFnAttr(fn_val, "cold"); | 953 | addLLVMFnAttr(fn_val, "cold"); |
| 943 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | 954 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| 944 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); | 955 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); |
| 945 | addLLVMFnAttr(fn_val, "nounwind"); | 956 | addLLVMFnAttr(fn_val, "nounwind"); |
| 946 | add_uwtable_attr(g, fn_val); | 957 | add_uwtable_attr(g, fn_val); |
| 947 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); | 958 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); |
| 948 | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); | | |
| 949 | if (g->build_mode == BuildModeDebug) { | 959 | if (g->build_mode == BuildModeDebug) { |
| 950 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); | 960 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| 951 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); | 961 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); |
| ... | @@ -983,7 +993,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { | ... | @@ -983,7 +993,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { |
| 983 | LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); | 993 | LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); |
| 984 | LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, ""); | 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 | LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, ""); | 1000 | LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, ""); |
| 989 | gen_store_untyped(g, address_value, address_slot, 0, false); | 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,17 +1443,11 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 1431 | is_err_return = true; | 1443 | is_err_return = true; |
| 1432 | } | 1444 | } |
| 1433 | if (is_err_return) { | 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 | LLVMValueRef return_err_fn = get_return_err_fn(g); | 1446 | LLVMValueRef return_err_fn = get_return_err_fn(g); |
| 1438 | LLVMValueRef args[] = { | 1447 | LLVMValueRef args[] = { |
| 1439 | g->cur_err_ret_trace_val, | 1448 | g->cur_err_ret_trace_val, |
| 1440 | block_address, | | |
| 1441 | }; | 1449 | }; |
| 1442 | LLVMBuildBr(g->builder, return_block); | 1450 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1, |
| 1443 | LLVMPositionBuilderAtEnd(g->builder, return_block); | | |
| 1444 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2, | | |
| 1445 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); | 1451 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); |
| 1446 | LLVMSetTailCall(call_instruction, true); | 1452 | LLVMSetTailCall(call_instruction, true); |
| 1447 | } | 1453 | } |
| ... | @@ -3291,20 +3297,6 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I | ... | @@ -3291,20 +3297,6 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I |
| 3291 | return nullptr; | 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 | static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable, | 3300 | static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable, |
| 3309 | IrInstructionReturnAddress *instruction) | 3301 | IrInstructionReturnAddress *instruction) |
| 3310 | { | 3302 | { |