| author | |
| committer | |
| log | 7ec783876a565662223268a70ba984e0a132b94a |
| tree | af0c952df4dd3896721713cfa54117cb30b0a1e3 |
| parent | 3268276b58d8b65cb295b738d7c14174005bd84e |
See #6515 files changed, 64 insertions(+), 20 deletions(-)
src/all_types.hpp+2| ... | ... | @@ -1595,6 +1595,8 @@ struct CodeGen { |
| 1595 | 1595 | ZigList<AstNode *> tld_ref_source_node_stack; |
| 1596 | 1596 | |
| 1597 | 1597 | TypeTableEntry *align_amt_type; |
| 1598 | TypeTableEntry *stack_trace_type; | |
| 1599 | TypeTableEntry *ptr_to_stack_trace_type; | |
| 1598 | 1600 | }; |
| 1599 | 1601 | |
| 1600 | 1602 | enum VarLinkage { |
src/analyze.cpp+36-3| ... | ... | @@ -869,6 +869,16 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) { |
| 869 | 869 | zig_unreachable(); |
| 870 | 870 | } |
| 871 | 871 | |
| 872 | static 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 | ||
| 872 | 882 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 873 | 883 | auto table_entry = g->fn_type_table.maybe_get(fn_type_id); |
| 874 | 884 | if (table_entry) { |
| ... | ... | @@ -915,10 +925,15 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 915 | 925 | if (!skip_debug_info) { |
| 916 | 926 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && |
| 917 | 927 | 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; | |
| 918 | 930 | // +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); | |
| 922 | 937 | param_di_types[0] = fn_type_id->return_type->di_type; |
| 923 | 938 | size_t gen_param_index = 0; |
| 924 | 939 | TypeTableEntry *gen_return_type; |
| ... | ... | @@ -965,6 +980,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 965 | 980 | } |
| 966 | 981 | } |
| 967 | 982 | |
| 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 | ||
| 968 | 991 | fn_type->data.fn.gen_param_count = gen_param_index; |
| 969 | 992 | |
| 970 | 993 | 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) { |
| 5527 | 5550 | return a == b; |
| 5528 | 5551 | } |
| 5529 | 5552 | |
| 5553 | ConstExprValue *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); |
| 185 | 185 | Buf *const_value_to_buffer(ConstExprValue *const_val); |
| 186 | 186 | void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); |
| 187 | 187 | |
| 188 | ||
| 189 | ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name); | |
| 190 | ||
| 191 | ||
| 188 | 192 | #endif |
src/codegen.cpp+22-7| ... | ... | @@ -483,7 +483,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 483 | 483 | LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true); |
| 484 | 484 | } |
| 485 | 485 | |
| 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) { | |
| 487 | 488 | addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn"); |
| 488 | 489 | } |
| 489 | 490 | |
| ... | ... | @@ -520,13 +521,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 520 | 521 | // use the ABI alignment, which is fine. |
| 521 | 522 | } |
| 522 | 523 | |
| 523 | if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) { | |
| 524 | if (!type_has_bits(return_type)) { | |
| 524 | 525 | // 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) { | |
| 528 | 527 | 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) && | |
| 530 | 529 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) |
| 531 | 530 | { |
| 532 | 531 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); |
| ... | ... | @@ -562,6 +561,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 562 | 561 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval"); |
| 563 | 562 | } |
| 564 | 563 | } |
| 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 | } | |
| 565 | 568 | |
| 566 | 569 | return fn_table_entry->llvm_value; |
| 567 | 570 | } |
| ... | ... | @@ -2330,7 +2333,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2330 | 2333 | TypeTableEntry *src_return_type = fn_type_id->return_type; |
| 2331 | 2334 | bool ret_has_bits = type_has_bits(src_return_type); |
| 2332 | 2335 | 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); | |
| 2334 | 2338 | bool is_var_args = fn_type_id->is_var_args; |
| 2335 | 2339 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); |
| 2336 | 2340 | size_t gen_param_index = 0; |
| ... | ... | @@ -2348,6 +2352,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2348 | 2352 | gen_param_index += 1; |
| 2349 | 2353 | } |
| 2350 | 2354 | } |
| 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 | } | |
| 2351 | 2359 | |
| 2352 | 2360 | ZigLLVM_FnInline fn_inline; |
| 2353 | 2361 | switch (instruction->fn_inline) { |
| ... | ... | @@ -5088,6 +5096,13 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 5088 | 5096 | os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path); |
| 5089 | 5097 | Buf *contents = buf_alloc(); |
| 5090 | 5098 | |
| 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 | ||
| 5091 | 5106 | const char *cur_os = nullptr; |
| 5092 | 5107 | { |
| 5093 | 5108 | 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) |
| 8230 | 8230 | return ir_resolve_bool(ira, value, out); |
| 8231 | 8231 | } |
| 8232 | 8232 | |
| 8233 | static 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 | ||
| 8243 | 8233 | static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) { |
| 8244 | 8234 | if (type_is_invalid(value->value.type)) |
| 8245 | 8235 | return false; |