authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-11 23:04:08-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-11 23:04:08-05:00
log7ec783876a565662223268a70ba984e0a132b94a
treeaf0c952df4dd3896721713cfa54117cb30b0a1e3
parent3268276b58d8b65cb295b738d7c14174005bd84e

functions which can return errors have secret stack trace param

See #651

5 files changed, 64 insertions(+), 20 deletions(-)

src/all_types.hpp+2
......@@ -1595,6 +1595,8 @@ struct CodeGen {
15951595 ZigList<AstNode *> tld_ref_source_node_stack;
15961596
15971597 TypeTableEntry *align_amt_type;
1598 TypeTableEntry *stack_trace_type;
1599 TypeTableEntry *ptr_to_stack_trace_type;
15981600};
15991601
16001602enum VarLinkage {
src/analyze.cpp+36-3
......@@ -869,6 +869,16 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) {
869869 zig_unreachable();
870870}
871871
872static TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g) {
873 if (g->stack_trace_type == nullptr) {
874 ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");
875 assert(stack_trace_type_val->type->id == TypeTableEntryIdMetaType);
876 g->stack_trace_type = stack_trace_type_val->data.x_type;
877 g->ptr_to_stack_trace_type = get_pointer_to_type(g, g->stack_trace_type, false);
878 }
879 return g->ptr_to_stack_trace_type;
880}
881
872882TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
873883 auto table_entry = g->fn_type_table.maybe_get(fn_type_id);
874884 if (table_entry) {
......@@ -915,10 +925,15 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
915925 if (!skip_debug_info) {
916926 bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&
917927 handle_is_ptr(fn_type_id->return_type);
928 bool last_arg_error_return_trace = fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
929 fn_type_id->return_type->id == TypeTableEntryIdPureError;
918930 // +1 for maybe making the first argument the return value
919 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count);
920 // +1 because 0 is the return type and +1 for maybe making first arg ret val
921 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(2 + fn_type_id->param_count);
931 // +1 for maybe last argument the error return trace
932 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);
933 // +1 because 0 is the return type and
934 // +1 for maybe making first arg ret val and
935 // +1 for maybe last argument the error return trace
936 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(3 + fn_type_id->param_count);
922937 param_di_types[0] = fn_type_id->return_type->di_type;
923938 size_t gen_param_index = 0;
924939 TypeTableEntry *gen_return_type;
......@@ -965,6 +980,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
965980 }
966981 }
967982
983 if (last_arg_error_return_trace) {
984 TypeTableEntry *gen_type = get_ptr_to_stack_trace_type(g);
985 gen_param_types[gen_param_index] = gen_type->type_ref;
986 gen_param_index += 1;
987 // after the gen_param_index += 1 because 0 is the return type
988 param_di_types[gen_param_index] = gen_type->di_type;
989 }
990
968991 fn_type->data.fn.gen_param_count = gen_param_index;
969992
970993 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
......@@ -5527,3 +5550,13 @@ bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b) {
55275550 return a == b;
55285551}
55295552
5553ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
5554 Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name));
5555 resolve_top_level_decl(codegen, tld, false, nullptr);
5556 assert(tld->id == TldIdVar);
5557 TldVar *tld_var = (TldVar *)tld;
5558 ConstExprValue *var_value = tld_var->var->value;
5559 assert(var_value != nullptr);
5560 return var_value;
5561}
5562
src/analyze.hpp+4
......@@ -185,4 +185,8 @@ PackageTableEntry *new_anonymous_package(void);
185185Buf *const_value_to_buffer(ConstExprValue *const_val);
186186void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
187187
188
189ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
190
191
188192#endif
src/codegen.cpp+22-7
......@@ -483,7 +483,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
483483 LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true);
484484 }
485485
486 if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) {
486 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
487 if (return_type->id == TypeTableEntryIdUnreachable) {
487488 addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn");
488489 }
489490
......@@ -520,13 +521,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
520521 // use the ABI alignment, which is fine.
521522 }
522523
523 if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) {
524 if (!type_has_bits(return_type)) {
524525 // nothing to do
525 } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer ||
526 fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn)
527 {
526 } else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) {
528527 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
529 } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) &&
528 } else if (handle_is_ptr(return_type) &&
530529 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
531530 {
532531 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
......@@ -562,6 +561,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
562561 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval");
563562 }
564563 }
564 if (return_type->id == TypeTableEntryIdErrorUnion || return_type->id == TypeTableEntryIdPureError) {
565 unsigned gen_index = LLVMCountParamTypes(fn_llvm_type) - 1;
566 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull");
567 }
565568
566569 return fn_table_entry->llvm_value;
567570}
......@@ -2330,7 +2333,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
23302333 TypeTableEntry *src_return_type = fn_type_id->return_type;
23312334 bool ret_has_bits = type_has_bits(src_return_type);
23322335 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
2333 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0);
2336 bool last_arg_err_ret_stack = src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError;
2337 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (last_arg_err_ret_stack ? 1 : 0);
23342338 bool is_var_args = fn_type_id->is_var_args;
23352339 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
23362340 size_t gen_param_index = 0;
......@@ -2348,6 +2352,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
23482352 gen_param_index += 1;
23492353 }
23502354 }
2355 if (last_arg_err_ret_stack) {
2356 gen_param_values[gen_param_index] = LLVMGetUndef(g->ptr_to_stack_trace_type->type_ref);
2357 gen_param_index += 1;
2358 }
23512359
23522360 ZigLLVM_FnInline fn_inline;
23532361 switch (instruction->fn_inline) {
......@@ -5088,6 +5096,13 @@ static void define_builtin_compile_vars(CodeGen *g) {
50885096 os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
50895097 Buf *contents = buf_alloc();
50905098
5099 buf_append_str(contents,
5100 "pub const StackTrace = struct {\n"
5101 " index: usize,\n"
5102 " instruction_addresses: [31]usize,\n"
5103 "};\n\n"
5104 );
5105
50915106 const char *cur_os = nullptr;
50925107 {
50935108 buf_appendf(contents, "pub const Os = enum {\n");
src/ir.cpp-10
......@@ -8230,16 +8230,6 @@ static bool ir_resolve_comptime(IrAnalyze *ira, IrInstruction *value, bool *out)
82308230 return ir_resolve_bool(ira, value, out);
82318231}
82328232
8233static ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
8234 Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name));
8235 resolve_top_level_decl(codegen, tld, false, nullptr);
8236 assert(tld->id == TldIdVar);
8237 TldVar *tld_var = (TldVar *)tld;
8238 ConstExprValue *var_value = tld_var->var->value;
8239 assert(var_value != nullptr);
8240 return var_value;
8241}
8242
82438233static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) {
82448234 if (type_is_invalid(value->value.type))
82458235 return false;