Commit 7ec783876a
Changed files (5)
src/all_types.hpp
@@ -1595,6 +1595,8 @@ struct CodeGen {
ZigList<AstNode *> tld_ref_source_node_stack;
TypeTableEntry *align_amt_type;
+ TypeTableEntry *stack_trace_type;
+ TypeTableEntry *ptr_to_stack_trace_type;
};
enum VarLinkage {
src/analyze.cpp
@@ -869,6 +869,16 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) {
zig_unreachable();
}
+static TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g) {
+ if (g->stack_trace_type == nullptr) {
+ ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");
+ assert(stack_trace_type_val->type->id == TypeTableEntryIdMetaType);
+ g->stack_trace_type = stack_trace_type_val->data.x_type;
+ g->ptr_to_stack_trace_type = get_pointer_to_type(g, g->stack_trace_type, false);
+ }
+ return g->ptr_to_stack_trace_type;
+}
+
TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
auto table_entry = g->fn_type_table.maybe_get(fn_type_id);
if (table_entry) {
@@ -915,10 +925,15 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
if (!skip_debug_info) {
bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&
handle_is_ptr(fn_type_id->return_type);
+ bool last_arg_error_return_trace = fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
+ fn_type_id->return_type->id == TypeTableEntryIdPureError;
// +1 for maybe making the first argument the return value
- LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count);
- // +1 because 0 is the return type and +1 for maybe making first arg ret val
- ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(2 + fn_type_id->param_count);
+ // +1 for maybe last argument the error return trace
+ LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);
+ // +1 because 0 is the return type and
+ // +1 for maybe making first arg ret val and
+ // +1 for maybe last argument the error return trace
+ ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(3 + fn_type_id->param_count);
param_di_types[0] = fn_type_id->return_type->di_type;
size_t gen_param_index = 0;
TypeTableEntry *gen_return_type;
@@ -965,6 +980,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
}
}
+ if (last_arg_error_return_trace) {
+ TypeTableEntry *gen_type = get_ptr_to_stack_trace_type(g);
+ gen_param_types[gen_param_index] = gen_type->type_ref;
+ gen_param_index += 1;
+ // after the gen_param_index += 1 because 0 is the return type
+ param_di_types[gen_param_index] = gen_type->di_type;
+ }
+
fn_type->data.fn.gen_param_count = gen_param_index;
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) {
return a == b;
}
+ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
+ Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name));
+ resolve_top_level_decl(codegen, tld, false, nullptr);
+ assert(tld->id == TldIdVar);
+ TldVar *tld_var = (TldVar *)tld;
+ ConstExprValue *var_value = tld_var->var->value;
+ assert(var_value != nullptr);
+ return var_value;
+}
+
src/analyze.hpp
@@ -185,4 +185,8 @@ PackageTableEntry *new_anonymous_package(void);
Buf *const_value_to_buffer(ConstExprValue *const_val);
void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
+
+ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
+
+
#endif
src/codegen.cpp
@@ -483,7 +483,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true);
}
- if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) {
+ TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
+ if (return_type->id == TypeTableEntryIdUnreachable) {
addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn");
}
@@ -520,13 +521,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
// use the ABI alignment, which is fine.
}
- if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) {
+ if (!type_has_bits(return_type)) {
// nothing to do
- } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer ||
- fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn)
- {
+ } else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) {
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
- } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) &&
+ } else if (handle_is_ptr(return_type) &&
calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
{
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
@@ -562,6 +561,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval");
}
}
+ if (return_type->id == TypeTableEntryIdErrorUnion || return_type->id == TypeTableEntryIdPureError) {
+ unsigned gen_index = LLVMCountParamTypes(fn_llvm_type) - 1;
+ addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull");
+ }
return fn_table_entry->llvm_value;
}
@@ -2330,7 +2333,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
TypeTableEntry *src_return_type = fn_type_id->return_type;
bool ret_has_bits = type_has_bits(src_return_type);
bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
- size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0);
+ bool last_arg_err_ret_stack = src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError;
+ size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (last_arg_err_ret_stack ? 1 : 0);
bool is_var_args = fn_type_id->is_var_args;
LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
size_t gen_param_index = 0;
@@ -2348,6 +2352,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
gen_param_index += 1;
}
}
+ if (last_arg_err_ret_stack) {
+ gen_param_values[gen_param_index] = LLVMGetUndef(g->ptr_to_stack_trace_type->type_ref);
+ gen_param_index += 1;
+ }
ZigLLVM_FnInline fn_inline;
switch (instruction->fn_inline) {
@@ -5088,6 +5096,13 @@ static void define_builtin_compile_vars(CodeGen *g) {
os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
Buf *contents = buf_alloc();
+ buf_append_str(contents,
+ "pub const StackTrace = struct {\n"
+ " index: usize,\n"
+ " instruction_addresses: [31]usize,\n"
+ "};\n\n"
+ );
+
const char *cur_os = nullptr;
{
buf_appendf(contents, "pub const Os = enum {\n");
src/ir.cpp
@@ -8230,16 +8230,6 @@ static bool ir_resolve_comptime(IrAnalyze *ira, IrInstruction *value, bool *out)
return ir_resolve_bool(ira, value, out);
}
-static ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
- Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name));
- resolve_top_level_decl(codegen, tld, false, nullptr);
- assert(tld->id == TldIdVar);
- TldVar *tld_var = (TldVar *)tld;
- ConstExprValue *var_value = tld_var->var->value;
- assert(var_value != nullptr);
- return var_value;
-}
-
static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) {
if (type_is_invalid(value->value.type))
return false;