authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-16 23:18:35-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-17 00:22:53-05:00
log4bdfc8a10aec3c7bd02037312840315a5fccbbb0
treea0074f9099e22d852dc38ba17ca8e3a072c431f8
parent24c2ff5caea15d3d6953414cd4a984993e8fa36e

fix error return traces pointing to off-by-one source line

See #651

1 files changed, 20 insertions(+), 28 deletions(-)

src/codegen.cpp+20-28
...@@ -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}
923923
924static 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
924static LLVMValueRef get_return_err_fn(CodeGen *g) {938static 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;
927941
928 assert(g->err_tag_type != nullptr);942 assert(g->err_tag_type != nullptr);
929943
930 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
931
932 LLVMTypeRef arg_types[] = {944 LLVMTypeRef arg_types[] = {
933 // error return trace pointer945 // 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);
939949
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, "");
985995
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, "");
987999
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}
32933299
3294static 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
3308static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable,3300static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable,
3309 IrInstructionReturnAddress *instruction)3301 IrInstructionReturnAddress *instruction)
3310{3302{