Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const ArrayList = std.ArrayList;
const Buffer = std.Buffer;
const io = std.io;

pub fn build(b: &Builder) {
pub fn build(b: &Builder) -> %void {
const mode = b.standardReleaseOptions();

var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
Expand All @@ -36,7 +36,7 @@ pub fn build(b: &Builder) {
const test_step = b.step("test", "Run all the tests");

// find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
const build_info = b.exec([][]const u8{b.zig_exe, "BUILD_INFO"});
const build_info = try b.exec([][]const u8{b.zig_exe, "BUILD_INFO"});
var index: usize = 0;
const cmake_binary_dir = nextValue(&index, build_info);
const cxx_compiler = nextValue(&index, build_info);
Expand Down Expand Up @@ -68,7 +68,7 @@ pub fn build(b: &Builder) {
dependOnLib(exe, llvm);

if (exe.target.getOs() == builtin.Os.linux) {
const libstdcxx_path_padded = b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"});
const libstdcxx_path_padded = try b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"});
const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next();
exe.addObjectFile(libstdcxx_path);

Expand Down Expand Up @@ -155,9 +155,9 @@ const LibraryDep = struct {
};

fn findLLVM(b: &Builder, llvm_config_exe: []const u8) -> %LibraryDep {
const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"});
const libdir_output = b.exec([][]const u8{llvm_config_exe, "--libdir"});
const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"});
const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"});

var result = LibraryDep {
.libs = ArrayList([]const u8).init(b.allocator),
Expand Down
8 changes: 8 additions & 0 deletions doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
<li><a href="#builtin-TagType">@TagType</a></li>
<li><a href="#builtin-EnumTagType">@EnumTagType</a></li>
<li><a href="#builtin-errorName">@errorName</a></li>
<li><a href="#builtin-errorReturnTrace">@errorReturnTrace</a></li>
<li><a href="#builtin-fence">@fence</a></li>
<li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
<li><a href="#builtin-frameAddress">@frameAddress</a></li>
Expand Down Expand Up @@ -4412,6 +4413,13 @@ test.zig:6:2: error: found compile log statement
or all calls have a compile-time known value for <code>err</code>, then no
error name table will be generated.
</p>
<h3 id="builtin-errorReturnTrace">@errorReturnTrace</h3>
<pre><code class="zig">@errorReturnTrace() -&gt; ?&amp;builtin.StackTrace</code></pre>
<p>
If the binary is built with error return tracing, and this function is invoked in a
function that calls a function with an error or error union return type, returns a
stack trace object. Otherwise returns `null`.
</p>
<h3 id="builtin-fence">@fence</h3>
<pre><code class="zig">@fence(order: AtomicOrder)</code></pre>
<p>
Expand Down
2 changes: 1 addition & 1 deletion example/mix_o_files/build.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Builder = @import("std").build.Builder;

pub fn build(b: &Builder) {
pub fn build(b: &Builder) -> %void {
const obj = b.addObject("base64", "base64.zig");

const exe = b.addCExecutable("test");
Expand Down
2 changes: 1 addition & 1 deletion example/shared_library/build.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const Builder = @import("std").build.Builder;

pub fn build(b: &Builder) {
pub fn build(b: &Builder) -> %void {
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));

const exe = b.addCExecutable("test");
Expand Down
13 changes: 13 additions & 0 deletions src/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,7 @@ struct FnTableEntry {
uint32_t alignstack_value;

ZigList<FnExport> export_list;
bool calls_errorable_function;
};

uint32_t fn_table_entry_hash(FnTableEntry*);
Expand Down Expand Up @@ -1273,6 +1274,7 @@ enum BuiltinFnId {
BuiltinFnIdSetAlignStack,
BuiltinFnIdArgType,
BuiltinFnIdExport,
BuiltinFnIdErrorReturnTrace,
};

struct BuiltinFnEntry {
Expand Down Expand Up @@ -1498,6 +1500,7 @@ struct CodeGen {
Buf triple_str;
BuildMode build_mode;
bool is_test_build;
bool have_err_ret_tracing;
uint32_t target_os_index;
uint32_t target_arch_index;
uint32_t target_environ_index;
Expand Down Expand Up @@ -1530,6 +1533,7 @@ struct CodeGen {
FnTableEntry *panic_fn;
LLVMValueRef cur_ret_ptr;
LLVMValueRef cur_fn_val;
LLVMValueRef cur_err_ret_trace_val;
bool c_want_stdint;
bool c_want_stdbool;
AstNode *root_export_decl;
Expand Down Expand Up @@ -1572,6 +1576,8 @@ struct CodeGen {
size_t largest_err_name_len;
LLVMValueRef safety_crash_err_fn;

LLVMValueRef return_err_fn;

IrInstruction *invalid_instruction;
ConstExprValue const_void_val;

Expand All @@ -1595,6 +1601,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 {
Expand Down Expand Up @@ -1896,6 +1904,7 @@ enum IrInstructionId {
IrInstructionIdSetAlignStack,
IrInstructionIdArgType,
IrInstructionIdExport,
IrInstructionIdErrorReturnTrace,
};

struct IrInstruction {
Expand Down Expand Up @@ -2717,6 +2726,10 @@ struct IrInstructionExport {
IrInstruction *target;
};

struct IrInstructionErrorReturnTrace {
IrInstruction base;
};

static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;

Expand Down
59 changes: 47 additions & 12 deletions src/analyze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,16 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) {
zig_unreachable();
}

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) {
Expand Down Expand Up @@ -915,10 +925,16 @@ 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 prefix_arg_error_return_trace = g->have_err_ret_tracing &&
(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;
Expand All @@ -936,6 +952,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
}
fn_type->data.fn.gen_return_type = gen_return_type;

if (prefix_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_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i];
Expand Down Expand Up @@ -1168,6 +1192,9 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
}

TypeTableEntry *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type);
if (type_is_invalid(type_entry)) {
return g->builtin_types.entry_invalid;
}
if (fn_type_id.cc != CallingConventionUnspecified) {
type_ensure_zero_bits_known(g, type_entry);
if (!type_has_bits(type_entry)) {
Expand Down Expand Up @@ -2558,7 +2585,7 @@ static bool scope_is_root_decls(Scope *scope) {

static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntry *fn_type) {
add_node_error(g, proto_node,
buf_sprintf("expected 'fn([]const u8) -> unreachable', found '%s'",
buf_sprintf("expected 'fn([]const u8, ?&builtin.StackTrace) -> unreachable', found '%s'",
buf_ptr(&fn_type->name)));
}

Expand All @@ -2567,7 +2594,7 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {
assert(proto_node->type == NodeTypeFnProto);
TypeTableEntry *fn_type = panic_fn->type_entry;
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
if (fn_type_id->param_count != 1) {
if (fn_type_id->param_count != 2) {
return wrong_panic_prototype(g, proto_node, fn_type);
}
TypeTableEntry *const_u8_ptr = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
Expand All @@ -2576,6 +2603,11 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {
return wrong_panic_prototype(g, proto_node, fn_type);
}

TypeTableEntry *nullable_ptr_to_stack_trace_type = get_maybe_type(g, get_ptr_to_stack_trace_type(g));
if (fn_type_id->param_info[1].type != nullable_ptr_to_stack_trace_type) {
return wrong_panic_prototype(g, proto_node, fn_type);
}

TypeTableEntry *actual_return_type = fn_type_id->return_type;
if (actual_return_type != g->builtin_types.entry_unreachable) {
return wrong_panic_prototype(g, proto_node, fn_type);
Expand Down Expand Up @@ -2680,13 +2712,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
{
if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
g->main_fn = fn_table_entry;
TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void);
TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;
if (actual_return_type != err_void) {
add_node_error(g, fn_proto->return_type,
buf_sprintf("expected return type of main to be '%%void', instead is '%s'",
buf_ptr(&actual_return_type->name)));
}
} else if ((import->package == g->panic_package || g->have_pub_panic) &&
buf_eql_str(&fn_table_entry->symbol_name, "panic"))
{
Expand Down Expand Up @@ -5527,3 +5552,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;
}

5 changes: 5 additions & 0 deletions src/analyze.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,9 @@ 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);
TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g);


#endif
Loading