add stack protector safety when linking libc
* introduce zigrt file. it contains only weak symbols so that multiple instances can be merged. it contains __zig_panic so that multiple .o files can call the same panic function. * remove `@setFnVisible` builtin and add @setGlobalLinkage builtin which is more powerful * add `@panic` builtin function. * fix collision of symbols with extern prototypes and internal function names * add stack protector safety when linking against libc. To add the safety mechanism without libc requires implementing Thread Local Storage. See #276master
parent
8aeea72654
commit
a32b5929cc
|
@ -233,8 +233,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
|
|||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/panic.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/zigrt.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/target.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
|
||||
add_executable(run_tests ${TEST_SOURCES})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(setq zig
|
||||
'(("\\b\\(@sizeOf\\|@alignOf\\|@maxValue\\|@minValue\\|@memberCount\\|@typeOf\\|@addWithOverflow\\|@subWithOverflow\\|@mulWithOverflow\\|@shlWithOverflow\\|@cInclude\\|@cDefine\\|@cUndef\\|@compileVar\\|@generatedCode\\|@ctz\\|@clz\\|@import\\|@cImport\\|@errorName\\|@typeName\\|@isInteger\\|@isFloat\\|@canImplicitCast\\|@embedFile\\|@cmpxchg\\|@fence\\|@divExact\\|@truncate\\|@compileError\\|@compileLog\\|@intType\\|@unreachable\\|@setFnTest\\|@setFnVisible\\|@setDebugSafety\\|@alloca\\|@setGlobalAlign\\|@setGlobalSection\\)" . font-lock-builtin-face)
|
||||
'(("\\b\\(@sizeOf\\|@alignOf\\|@maxValue\\|@minValue\\|@memberCount\\|@typeOf\\|@addWithOverflow\\|@subWithOverflow\\|@mulWithOverflow\\|@shlWithOverflow\\|@cInclude\\|@cDefine\\|@cUndef\\|@compileVar\\|@generatedCode\\|@ctz\\|@clz\\|@import\\|@cImport\\|@errorName\\|@typeName\\|@isInteger\\|@isFloat\\|@canImplicitCast\\|@embedFile\\|@cmpxchg\\|@fence\\|@divExact\\|@truncate\\|@compileError\\|@compileLog\\|@intType\\|@unreachable\\|@setDebugSafety\\|@alloca\\|@setGlobalAlign\\|@setGlobalLinkage\\|@setGlobalSection\\)" . font-lock-builtin-face)
|
||||
|
||||
("\\b\\(fn\\|use\\|while\\|for\\|break\\|continue\\|goto\\|if\\|else\\|switch\\|try\\|return\\|defer\\|asm\\|unreachable\\|const\\|var\\|extern\\|packed\\|export\\|pub\\|noalias\\|inline\\|comptime\\|nakedcc\\|coldcc\\|volatile\\|struct\\|enum\\|union\\)\\b" . font-lock-keyword-face)
|
||||
|
||||
|
|
|
@ -626,3 +626,10 @@ Sets the alignment property of a global variable.
|
|||
### @setGlobalSection(global_variable_name, section_name: []u8) -> bool
|
||||
|
||||
Puts the global variable in the specified section.
|
||||
|
||||
### @panic(message: []const u8) -> noreturn
|
||||
|
||||
Invokes the panic handler function. By default the panic handler function
|
||||
calls the public `panic` function exposed in the root source file, or
|
||||
if there is not one specified, invokes the one provided in
|
||||
`std/special/panic.zig`.
|
||||
|
|
|
@ -237,6 +237,13 @@ enum VisibMod {
|
|||
VisibModExport,
|
||||
};
|
||||
|
||||
enum GlobalLinkageId {
|
||||
GlobalLinkageIdInternal,
|
||||
GlobalLinkageIdStrong,
|
||||
GlobalLinkageIdWeak,
|
||||
GlobalLinkageIdLinkOnce,
|
||||
};
|
||||
|
||||
enum TldId {
|
||||
TldIdVar,
|
||||
TldIdFn,
|
||||
|
@ -273,6 +280,8 @@ struct TldVar {
|
|||
uint64_t alignment;
|
||||
AstNode *set_global_section_node;
|
||||
Buf *section_name;
|
||||
AstNode *set_global_linkage_node;
|
||||
GlobalLinkageId linkage;
|
||||
};
|
||||
|
||||
struct TldFn {
|
||||
|
@ -1116,8 +1125,6 @@ struct FnTableEntry {
|
|||
Buf symbol_name;
|
||||
TypeTableEntry *type_entry; // function type
|
||||
TypeTableEntry *implicit_return_type;
|
||||
bool internal_linkage;
|
||||
bool disable_export;
|
||||
bool is_test;
|
||||
FnInline fn_inline;
|
||||
FnAnalState anal_state;
|
||||
|
@ -1128,7 +1135,6 @@ struct FnTableEntry {
|
|||
Buf **param_names;
|
||||
|
||||
AstNode *fn_no_inline_set_node;
|
||||
AstNode *fn_export_set_node;
|
||||
AstNode *fn_static_eval_set_node;
|
||||
|
||||
ZigList<IrInstruction *> alloca_list;
|
||||
|
@ -1138,6 +1144,8 @@ struct FnTableEntry {
|
|||
uint64_t alignment;
|
||||
AstNode *set_global_section_node;
|
||||
Buf *section_name;
|
||||
AstNode *set_global_linkage_node;
|
||||
GlobalLinkageId linkage;
|
||||
};
|
||||
|
||||
uint32_t fn_table_entry_hash(FnTableEntry*);
|
||||
|
@ -1178,7 +1186,6 @@ enum BuiltinFnId {
|
|||
BuiltinFnIdDivExact,
|
||||
BuiltinFnIdTruncate,
|
||||
BuiltinFnIdIntType,
|
||||
BuiltinFnIdSetFnVisible,
|
||||
BuiltinFnIdSetDebugSafety,
|
||||
BuiltinFnIdAlloca,
|
||||
BuiltinFnIdTypeName,
|
||||
|
@ -1187,6 +1194,8 @@ enum BuiltinFnId {
|
|||
BuiltinFnIdCanImplicitCast,
|
||||
BuiltinFnIdSetGlobalAlign,
|
||||
BuiltinFnIdSetGlobalSection,
|
||||
BuiltinFnIdSetGlobalLinkage,
|
||||
BuiltinFnIdPanic,
|
||||
};
|
||||
|
||||
struct BuiltinFnEntry {
|
||||
|
@ -1300,7 +1309,8 @@ struct CodeGen {
|
|||
HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
|
||||
HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
|
||||
HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> compile_vars;
|
||||
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_symbol_names;
|
||||
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names;
|
||||
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
|
||||
|
||||
ZigList<ImportTableEntry *> import_queue;
|
||||
size_t import_queue_index;
|
||||
|
@ -1346,6 +1356,7 @@ struct CodeGen {
|
|||
TypeTableEntry *entry_environ_enum;
|
||||
TypeTableEntry *entry_oformat_enum;
|
||||
TypeTableEntry *entry_atomic_order_enum;
|
||||
TypeTableEntry *entry_global_linkage_enum;
|
||||
TypeTableEntry *entry_arg_tuple;
|
||||
} builtin_types;
|
||||
|
||||
|
@ -1378,7 +1389,7 @@ struct CodeGen {
|
|||
bool is_native_target;
|
||||
PackageTableEntry *root_package;
|
||||
PackageTableEntry *std_package;
|
||||
PackageTableEntry *panic_package;
|
||||
PackageTableEntry *zigrt_package;
|
||||
Buf *root_out_name;
|
||||
bool windows_subsystem_windows;
|
||||
bool windows_subsystem_console;
|
||||
|
@ -1388,6 +1399,7 @@ struct CodeGen {
|
|||
Buf *mios_version_min;
|
||||
bool linker_rdynamic;
|
||||
const char *linker_script;
|
||||
bool omit_zigrt;
|
||||
|
||||
// The function definitions this module includes. There must be a corresponding
|
||||
// fn_protos entry.
|
||||
|
@ -1401,7 +1413,8 @@ struct CodeGen {
|
|||
OutType out_type;
|
||||
FnTableEntry *cur_fn;
|
||||
FnTableEntry *main_fn;
|
||||
FnTableEntry *panic_fn;
|
||||
FnTableEntry *user_panic_fn;
|
||||
FnTableEntry *extern_panic_fn;
|
||||
LLVMValueRef cur_ret_ptr;
|
||||
LLVMValueRef cur_fn_val;
|
||||
ZigList<LLVMBasicBlockRef> break_block_stack;
|
||||
|
@ -1656,7 +1669,6 @@ enum IrInstructionId {
|
|||
IrInstructionIdTypeOf,
|
||||
IrInstructionIdToPtrType,
|
||||
IrInstructionIdPtrTypeChild,
|
||||
IrInstructionIdSetFnVisible,
|
||||
IrInstructionIdSetDebugSafety,
|
||||
IrInstructionIdArrayType,
|
||||
IrInstructionIdSliceType,
|
||||
|
@ -1718,7 +1730,9 @@ enum IrInstructionId {
|
|||
IrInstructionIdCanImplicitCast,
|
||||
IrInstructionIdSetGlobalAlign,
|
||||
IrInstructionIdSetGlobalSection,
|
||||
IrInstructionIdSetGlobalLinkage,
|
||||
IrInstructionIdDeclRef,
|
||||
IrInstructionIdPanic,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
|
@ -1999,13 +2013,6 @@ struct IrInstructionPtrTypeChild {
|
|||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionSetFnVisible {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *fn_value;
|
||||
IrInstruction *is_visible;
|
||||
};
|
||||
|
||||
struct IrInstructionSetDebugSafety {
|
||||
IrInstruction base;
|
||||
|
||||
|
@ -2439,6 +2446,13 @@ struct IrInstructionSetGlobalSection {
|
|||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionSetGlobalLinkage {
|
||||
IrInstruction base;
|
||||
|
||||
Tld *tld;
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionDeclRef {
|
||||
IrInstruction base;
|
||||
|
||||
|
@ -2446,6 +2460,12 @@ struct IrInstructionDeclRef {
|
|||
LVal lval;
|
||||
};
|
||||
|
||||
struct IrInstructionPanic {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *msg;
|
||||
};
|
||||
|
||||
static const size_t slice_ptr_index = 0;
|
||||
static const size_t slice_len_index = 1;
|
||||
|
||||
|
|
|
@ -1762,7 +1762,7 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) {
|
|||
buf_append_buf(buf, tld->name);
|
||||
}
|
||||
|
||||
FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) {
|
||||
FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage) {
|
||||
FnTableEntry *fn_entry = allocate<FnTableEntry>(1);
|
||||
|
||||
fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc;
|
||||
|
@ -1770,7 +1770,7 @@ FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) {
|
|||
fn_entry->analyzed_executable.fn_entry = fn_entry;
|
||||
fn_entry->ir_executable.fn_entry = fn_entry;
|
||||
fn_entry->fn_inline = inline_value;
|
||||
fn_entry->internal_linkage = internal_linkage;
|
||||
fn_entry->linkage = linkage;
|
||||
|
||||
return fn_entry;
|
||||
}
|
||||
|
@ -1780,8 +1780,9 @@ FnTableEntry *create_fn(AstNode *proto_node) {
|
|||
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
|
||||
|
||||
FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto;
|
||||
bool internal_linkage = (fn_proto->visib_mod != VisibModExport && !proto_node->data.fn_proto.is_extern);
|
||||
FnTableEntry *fn_entry = create_fn_raw(inline_value, internal_linkage);
|
||||
GlobalLinkageId linkage = (fn_proto->visib_mod == VisibModExport || proto_node->data.fn_proto.is_extern) ?
|
||||
GlobalLinkageIdStrong : GlobalLinkageIdInternal;
|
||||
FnTableEntry *fn_entry = create_fn_raw(inline_value, linkage);
|
||||
|
||||
fn_entry->proto_node = proto_node;
|
||||
fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
|
||||
|
@ -1807,12 +1808,10 @@ static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntr
|
|||
buf_ptr(&fn_type->name)));
|
||||
}
|
||||
|
||||
static void typecheck_panic_fn(CodeGen *g) {
|
||||
assert(g->panic_fn);
|
||||
|
||||
AstNode *proto_node = g->panic_fn->proto_node;
|
||||
static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {
|
||||
AstNode *proto_node = panic_fn->proto_node;
|
||||
assert(proto_node->type == NodeTypeFnProto);
|
||||
TypeTableEntry *fn_type = g->panic_fn->type_entry;
|
||||
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) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
|
@ -1862,6 +1861,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
|
|||
add_node_error(g, param_node, buf_sprintf("missing parameter name"));
|
||||
}
|
||||
}
|
||||
} else if (fn_table_entry->linkage != GlobalLinkageIdInternal) {
|
||||
g->external_prototypes.put_unique(tld_fn->base.name, &tld_fn->base);
|
||||
}
|
||||
|
||||
Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
|
||||
|
@ -1892,18 +1893,16 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
|
|||
}
|
||||
}
|
||||
} else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
|
||||
g->panic_fn = fn_table_entry;
|
||||
typecheck_panic_fn(g);
|
||||
typecheck_panic_fn(g, fn_table_entry);
|
||||
}
|
||||
} else if (import->package == g->panic_package && scope_is_root_decls(tld_fn->base.parent_scope)) {
|
||||
if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
|
||||
g->panic_fn = fn_table_entry;
|
||||
typecheck_panic_fn(g);
|
||||
} else if (import->package == g->zigrt_package && scope_is_root_decls(tld_fn->base.parent_scope)) {
|
||||
if (buf_eql_str(&fn_table_entry->symbol_name, "__zig_panic")) {
|
||||
g->extern_panic_fn = fn_table_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (source_node->type == NodeTypeTestDecl) {
|
||||
FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto, false);
|
||||
FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong);
|
||||
|
||||
get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
|
||||
|
||||
|
@ -1931,16 +1930,12 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
|
|||
}
|
||||
|
||||
static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
|
||||
if (tld->visib_mod == VisibModExport ||
|
||||
(buf_eql_str(tld->name, "panic") &&
|
||||
(decls_scope->import->package == g->panic_package || decls_scope->import == g->root_import)) ||
|
||||
(tld->id == TldIdVar && g->is_test_build))
|
||||
{
|
||||
if (tld->visib_mod == VisibModExport || (tld->id == TldIdVar && g->is_test_build)) {
|
||||
g->resolve_queue.append(tld);
|
||||
}
|
||||
|
||||
if (tld->visib_mod == VisibModExport) {
|
||||
auto entry = g->external_symbol_names.put_unique(tld->name, tld);
|
||||
auto entry = g->exported_symbol_names.put_unique(tld->name, tld);
|
||||
if (entry) {
|
||||
Tld *other_tld = entry->value;
|
||||
ErrorMsg *msg = add_node_error(g, tld->source_node,
|
||||
|
@ -2060,6 +2055,15 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
|||
TldFn *tld_fn = allocate<TldFn>(1);
|
||||
init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base);
|
||||
add_top_level_decl(g, decls_scope, &tld_fn->base);
|
||||
|
||||
ImportTableEntry *import = get_scope_import(&decls_scope->base);
|
||||
if (import == g->root_import && scope_is_root_decls(&decls_scope->base) &&
|
||||
buf_eql_str(fn_name, "panic"))
|
||||
{
|
||||
g->compile_vars.put(buf_create_from_str("panic_implementation_provided"),
|
||||
create_const_bool(g, true));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NodeTypeUse:
|
||||
|
@ -4206,3 +4210,36 @@ ConstParent *get_const_val_parent(ConstExprValue *value) {
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FnTableEntry *get_extern_panic_fn(CodeGen *g) {
|
||||
if (g->extern_panic_fn)
|
||||
return g->extern_panic_fn;
|
||||
|
||||
FnTypeId fn_type_id = {0};
|
||||
fn_type_id.is_extern = true;
|
||||
fn_type_id.is_cold = true;
|
||||
fn_type_id.param_count = 2;
|
||||
fn_type_id.param_info = allocate<FnTypeParamInfo>(2);
|
||||
fn_type_id.next_param_index = 0;
|
||||
fn_type_id.param_info[0].type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
fn_type_id.param_info[1].type = g->builtin_types.entry_usize;
|
||||
fn_type_id.return_type = g->builtin_types.entry_unreachable;
|
||||
|
||||
TypeTableEntry *fn_type = get_fn_type(g, &fn_type_id);
|
||||
assert(!type_is_invalid(fn_type));
|
||||
|
||||
FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong);
|
||||
buf_init_from_str(&fn_entry->symbol_name, "__zig_panic");
|
||||
|
||||
TldFn *tld_fn = allocate<TldFn>(1);
|
||||
init_tld(&tld_fn->base, TldIdFn, &fn_entry->symbol_name, VisibModPrivate, nullptr, nullptr);
|
||||
tld_fn->fn_entry = fn_entry;
|
||||
|
||||
g->external_prototypes.put_unique(tld_fn->base.name, &tld_fn->base);
|
||||
|
||||
fn_entry->type_entry = fn_type;
|
||||
|
||||
g->extern_panic_fn = fn_entry;
|
||||
return g->extern_panic_fn;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent
|
|||
bool is_const, ConstExprValue *init_value, Tld *src_tld);
|
||||
TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
|
||||
FnTableEntry *create_fn(AstNode *proto_node);
|
||||
FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage);
|
||||
FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
|
||||
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
|
||||
AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index);
|
||||
FnTableEntry *scope_get_fn_if_root(Scope *scope);
|
||||
|
@ -148,5 +148,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
|
|||
|
||||
TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits);
|
||||
ConstParent *get_const_val_parent(ConstExprValue *value);
|
||||
FnTableEntry *get_extern_panic_fn(CodeGen *g);
|
||||
|
||||
#endif
|
||||
|
|
148
src/codegen.cpp
148
src/codegen.cpp
|
@ -67,7 +67,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
|
|||
g->llvm_fn_table.init(16);
|
||||
g->memoized_fn_eval_table.init(16);
|
||||
g->compile_vars.init(16);
|
||||
g->external_symbol_names.init(8);
|
||||
g->exported_symbol_names.init(8);
|
||||
g->external_prototypes.init(8);
|
||||
g->is_release_build = false;
|
||||
g->is_test_build = false;
|
||||
g->want_h_file = true;
|
||||
|
@ -140,6 +141,10 @@ void codegen_set_is_release(CodeGen *g, bool is_release_build) {
|
|||
g->is_release_build = is_release_build;
|
||||
}
|
||||
|
||||
void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt) {
|
||||
g->omit_zigrt = omit_zigrt;
|
||||
}
|
||||
|
||||
void codegen_set_is_test(CodeGen *g, bool is_test_build) {
|
||||
g->is_test_build = is_test_build;
|
||||
}
|
||||
|
@ -256,10 +261,22 @@ static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const c
|
|||
LLVMAddAttributeAtIndex(val, attr_index, llvm_attr);
|
||||
}
|
||||
|
||||
static void addLLVMAttrStr(LLVMValueRef val, LLVMAttributeIndex attr_index,
|
||||
const char *attr_name, const char *attr_val)
|
||||
{
|
||||
LLVMAttributeRef llvm_attr = LLVMCreateStringAttribute(LLVMGetGlobalContext(),
|
||||
attr_name, strlen(attr_name), attr_val, strlen(attr_val));
|
||||
LLVMAddAttributeAtIndex(val, attr_index, llvm_attr);
|
||||
}
|
||||
|
||||
static void addLLVMFnAttr(LLVMValueRef fn_val, const char *attr_name) {
|
||||
return addLLVMAttr(fn_val, -1, attr_name);
|
||||
}
|
||||
|
||||
static void addLLVMFnAttrStr(LLVMValueRef fn_val, const char *attr_name, const char *attr_val) {
|
||||
return addLLVMAttrStr(fn_val, -1, attr_name, attr_val);
|
||||
}
|
||||
|
||||
static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const char *attr_name) {
|
||||
return addLLVMAttr(arg_val, param_index + 1, attr_name);
|
||||
}
|
||||
|
@ -271,15 +288,19 @@ static void addLLVMCallsiteAttr(LLVMValueRef call_instr, unsigned param_index, c
|
|||
LLVMAddCallSiteAttribute(call_instr, param_index + 1, llvm_attr);
|
||||
}
|
||||
|
||||
static bool is_symbol_available(CodeGen *g, Buf *name) {
|
||||
return g->exported_symbol_names.maybe_get(name) == nullptr && g->external_prototypes.maybe_get(name) == nullptr;
|
||||
}
|
||||
|
||||
static Buf *get_mangled_name(CodeGen *g, Buf *original_name, bool external_linkage) {
|
||||
if (external_linkage || g->external_symbol_names.maybe_get(original_name) == nullptr) {
|
||||
if (external_linkage || is_symbol_available(g, original_name)) {
|
||||
return original_name;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
for (;; n += 1) {
|
||||
Buf *new_name = buf_sprintf("%s.%d", buf_ptr(original_name), n);
|
||||
if (g->external_symbol_names.maybe_get(new_name) == nullptr) {
|
||||
if (is_symbol_available(g, new_name)) {
|
||||
return new_name;
|
||||
}
|
||||
}
|
||||
|
@ -289,11 +310,12 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
|||
if (fn_table_entry->llvm_value)
|
||||
return fn_table_entry->llvm_value;
|
||||
|
||||
Buf *symbol_name = get_mangled_name(g, &fn_table_entry->symbol_name, !fn_table_entry->internal_linkage);
|
||||
bool external_linkage = (fn_table_entry->linkage != GlobalLinkageIdInternal);
|
||||
Buf *symbol_name = get_mangled_name(g, &fn_table_entry->symbol_name, external_linkage);
|
||||
|
||||
TypeTableEntry *fn_type = fn_table_entry->type_entry;
|
||||
LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref;
|
||||
if (!fn_table_entry->internal_linkage && fn_table_entry->body_node == nullptr) {
|
||||
if (external_linkage && fn_table_entry->body_node == nullptr) {
|
||||
LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
|
||||
if (existing_llvm_fn) {
|
||||
fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));
|
||||
|
@ -318,12 +340,35 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
|
|||
addLLVMFnAttr(fn_table_entry->llvm_value, "naked");
|
||||
}
|
||||
|
||||
LLVMSetLinkage(fn_table_entry->llvm_value, fn_table_entry->internal_linkage ?
|
||||
LLVMInternalLinkage : LLVMExternalLinkage);
|
||||
switch (fn_table_entry->linkage) {
|
||||
case GlobalLinkageIdInternal:
|
||||
LLVMSetLinkage(fn_table_entry->llvm_value, LLVMInternalLinkage);
|
||||
break;
|
||||
case GlobalLinkageIdStrong:
|
||||
LLVMSetLinkage(fn_table_entry->llvm_value, LLVMExternalLinkage);
|
||||
break;
|
||||
case GlobalLinkageIdWeak:
|
||||
LLVMSetLinkage(fn_table_entry->llvm_value, LLVMWeakODRLinkage);
|
||||
break;
|
||||
case GlobalLinkageIdLinkOnce:
|
||||
LLVMSetLinkage(fn_table_entry->llvm_value, LLVMLinkOnceODRLinkage);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) {
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn");
|
||||
}
|
||||
|
||||
if (fn_table_entry->body_node != nullptr) {
|
||||
bool want_fn_safety = !g->is_release_build && !fn_table_entry->def_scope->safety_off;
|
||||
if (want_fn_safety) {
|
||||
if (g->link_libc) {
|
||||
addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");
|
||||
addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLVMSetFunctionCallConv(fn_table_entry->llvm_value, fn_type->data.fn.calling_convention);
|
||||
if (fn_type->data.fn.fn_type_id.is_cold) {
|
||||
ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);
|
||||
|
@ -363,10 +408,11 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
|
|||
bool is_definition = fn_table_entry->body_node != nullptr;
|
||||
unsigned flags = 0;
|
||||
bool is_optimized = g->is_release_build;
|
||||
bool is_internal_linkage = (fn_table_entry->linkage == GlobalLinkageIdInternal);
|
||||
ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
|
||||
get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "",
|
||||
import->di_file, line_number,
|
||||
fn_table_entry->type_entry->di_type, fn_table_entry->internal_linkage,
|
||||
fn_table_entry->type_entry->di_type, is_internal_linkage,
|
||||
is_definition, scope_line, flags, is_optimized, nullptr);
|
||||
|
||||
scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
|
||||
|
@ -544,13 +590,28 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
|
|||
return val->llvm_global;
|
||||
}
|
||||
|
||||
static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) {
|
||||
LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
|
||||
LLVMValueRef msg_arg = get_panic_msg_ptr_val(g, msg_id);
|
||||
ZigLLVMBuildCall(g->builder, fn_val, &msg_arg, 1, g->panic_fn->type_entry->data.fn.calling_convention, "");
|
||||
static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) {
|
||||
FnTableEntry *panic_fn = get_extern_panic_fn(g);
|
||||
LLVMValueRef fn_val = fn_llvm_value(g, panic_fn);
|
||||
|
||||
TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
|
||||
size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index;
|
||||
LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, msg_arg, ptr_index, "");
|
||||
LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, msg_arg, len_index, "");
|
||||
|
||||
LLVMValueRef args[] = {
|
||||
LLVMBuildLoad(g->builder, ptr_ptr, ""),
|
||||
LLVMBuildLoad(g->builder, len_ptr, ""),
|
||||
};
|
||||
ZigLLVMBuildCall(g->builder, fn_val, args, 2, panic_fn->type_entry->data.fn.calling_convention, "");
|
||||
LLVMBuildUnreachable(g->builder);
|
||||
}
|
||||
|
||||
static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) {
|
||||
gen_panic(g, get_panic_msg_ptr_val(g, msg_id));
|
||||
}
|
||||
|
||||
static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
|
||||
LLVMIntPredicate lower_pred, LLVMValueRef lower_value,
|
||||
LLVMIntPredicate upper_pred, LLVMValueRef upper_value)
|
||||
|
@ -2564,6 +2625,11 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec
|
|||
return tmp_array_ptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
|
||||
gen_panic(g, ir_llvm_value(g, instruction->msg));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||
AstNode *source_node = instruction->source_node;
|
||||
Scope *scope = instruction->scope;
|
||||
|
@ -2584,7 +2650,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
case IrInstructionIdToPtrType:
|
||||
case IrInstructionIdPtrTypeChild:
|
||||
case IrInstructionIdFieldPtr:
|
||||
case IrInstructionIdSetFnVisible:
|
||||
case IrInstructionIdSetDebugSafety:
|
||||
case IrInstructionIdArrayType:
|
||||
case IrInstructionIdSliceType:
|
||||
|
@ -2615,7 +2680,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
case IrInstructionIdCanImplicitCast:
|
||||
case IrInstructionIdSetGlobalAlign:
|
||||
case IrInstructionIdSetGlobalSection:
|
||||
case IrInstructionIdSetGlobalLinkage:
|
||||
case IrInstructionIdDeclRef:
|
||||
case IrInstructionIdSwitchVar:
|
||||
zig_unreachable();
|
||||
case IrInstructionIdReturn:
|
||||
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
|
||||
|
@ -2721,8 +2788,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
return ir_render_int_to_enum(g, executable, (IrInstructionIntToEnum *)instruction);
|
||||
case IrInstructionIdContainerInitList:
|
||||
return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
|
||||
case IrInstructionIdSwitchVar:
|
||||
zig_panic("TODO render switch var instruction to LLVM");
|
||||
case IrInstructionIdPanic:
|
||||
return ir_render_panic(g, executable, (IrInstructionPanic *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -3659,6 +3726,18 @@ static const CIntTypeInfo c_int_type_infos[] = {
|
|||
|
||||
static const bool is_signed_list[] = { false, true, };
|
||||
|
||||
struct GlobalLinkageValue {
|
||||
GlobalLinkageId id;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const GlobalLinkageValue global_linkage_values[] = {
|
||||
{GlobalLinkageIdInternal, "Internal"},
|
||||
{GlobalLinkageIdStrong, "Strong"},
|
||||
{GlobalLinkageIdWeak, "Weak"},
|
||||
{GlobalLinkageIdLinkOnce, "LinkOnce"},
|
||||
};
|
||||
|
||||
static void define_builtin_types(CodeGen *g) {
|
||||
{
|
||||
// if this type is anywhere in the AST, we should never hit codegen.
|
||||
|
@ -3995,6 +4074,30 @@ static void define_builtin_types(CodeGen *g) {
|
|||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
|
||||
entry->zero_bits = true; // only allowed at compile time
|
||||
buf_init_from_str(&entry->name, "GlobalLinkage");
|
||||
uint32_t field_count = array_length(global_linkage_values);
|
||||
entry->data.enumeration.src_field_count = field_count;
|
||||
entry->data.enumeration.fields = allocate<TypeEnumField>(field_count);
|
||||
for (uint32_t i = 0; i < field_count; i += 1) {
|
||||
TypeEnumField *type_enum_field = &entry->data.enumeration.fields[i];
|
||||
const GlobalLinkageValue *value = &global_linkage_values[i];
|
||||
type_enum_field->name = buf_create_from_str(value->name);
|
||||
type_enum_field->value = i;
|
||||
type_enum_field->type_entry = g->builtin_types.entry_void;
|
||||
}
|
||||
entry->data.enumeration.complete = true;
|
||||
entry->data.enumeration.zero_bits_known = true;
|
||||
|
||||
TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
|
||||
entry->data.enumeration.tag_type = tag_type_entry;
|
||||
|
||||
g->builtin_types.entry_global_linkage_enum = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
|
||||
entry->zero_bits = true; // only allowed at compile time
|
||||
|
@ -4145,11 +4248,12 @@ static void define_builtin_fns(CodeGen *g) {
|
|||
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
|
||||
create_builtin_fn(g, BuiltinFnIdIntType, "intType", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
|
||||
}
|
||||
|
||||
static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) {
|
||||
|
@ -4180,6 +4284,7 @@ static void define_builtin_compile_vars(CodeGen *g) {
|
|||
|
||||
add_compile_var(g, "link_libs", const_val);
|
||||
}
|
||||
add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false));
|
||||
}
|
||||
|
||||
static void init(CodeGen *g, Buf *source_path) {
|
||||
|
@ -4309,9 +4414,10 @@ static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
|
|||
return package;
|
||||
}
|
||||
|
||||
static PackageTableEntry *create_panic_pkg(CodeGen *g) {
|
||||
static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {
|
||||
PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), "");
|
||||
package->package_table.put(buf_create_from_str("std"), g->std_package);
|
||||
package->package_table.put(buf_create_from_str("@root"), g->root_package);
|
||||
return package;
|
||||
}
|
||||
|
||||
|
@ -4337,9 +4443,9 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
|
|||
if (!g->is_test_build && g->have_pub_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) {
|
||||
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
|
||||
}
|
||||
if (!g->have_pub_panic) {
|
||||
g->panic_package = create_panic_pkg(g);
|
||||
add_special_code(g, g->panic_package, "panic.zig");
|
||||
if (!g->omit_zigrt) {
|
||||
g->zigrt_package = create_zigrt_pkg(g);
|
||||
add_special_code(g, g->zigrt_package, "zigrt.zig");
|
||||
}
|
||||
|
||||
if (g->verbose) {
|
||||
|
@ -4509,7 +4615,7 @@ void codegen_generate_h_file(CodeGen *g) {
|
|||
for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
|
||||
FnTableEntry *fn_table_entry = g->fn_defs.at(fn_def_i);
|
||||
|
||||
if (fn_table_entry->internal_linkage)
|
||||
if (fn_table_entry->linkage == GlobalLinkageIdInternal)
|
||||
continue;
|
||||
|
||||
FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
|
||||
|
|
|
@ -43,6 +43,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic);
|
|||
void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min);
|
||||
void codegen_set_mios_version_min(CodeGen *g, Buf *mios_version_min);
|
||||
void codegen_set_linker_script(CodeGen *g, const char *linker_script);
|
||||
void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);
|
||||
|
||||
void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
|
||||
|
||||
|
|
230
src/ir.cpp
230
src/ir.cpp
|
@ -276,10 +276,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *)
|
|||
return IrInstructionIdPtrTypeChild;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnVisible *) {
|
||||
return IrInstructionIdSetFnVisible;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) {
|
||||
return IrInstructionIdSetDebugSafety;
|
||||
}
|
||||
|
@ -528,10 +524,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection
|
|||
return IrInstructionIdSetGlobalSection;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalLinkage *) {
|
||||
return IrInstructionIdSetGlobalLinkage;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) {
|
||||
return IrInstructionIdDeclRef;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) {
|
||||
return IrInstructionIdPanic;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
T *special_instruction = allocate<T>(1);
|
||||
|
@ -1147,19 +1151,6 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstN
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_set_fn_visible(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn_value,
|
||||
IrInstruction *is_visible)
|
||||
{
|
||||
IrInstructionSetFnVisible *instruction = ir_build_instruction<IrInstructionSetFnVisible>(irb, scope, source_node);
|
||||
instruction->fn_value = fn_value;
|
||||
instruction->is_visible = is_visible;
|
||||
|
||||
ir_ref_instruction(fn_value, irb->current_basic_block);
|
||||
ir_ref_instruction(is_visible, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *scope_value, IrInstruction *debug_safety_on)
|
||||
{
|
||||
|
@ -2092,6 +2083,19 @@ static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope,
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_set_global_linkage(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
Tld *tld, IrInstruction *value)
|
||||
{
|
||||
IrInstructionSetGlobalLinkage *instruction = ir_build_instruction<IrInstructionSetGlobalLinkage>(
|
||||
irb, scope, source_node);
|
||||
instruction->tld = tld;
|
||||
instruction->value = value;
|
||||
|
||||
ir_ref_instruction(value, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
Tld *tld, LVal lval)
|
||||
{
|
||||
|
@ -2103,6 +2107,17 @@ static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *s
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) {
|
||||
IrInstructionPanic *instruction = ir_build_instruction<IrInstructionPanic>(irb, scope, source_node);
|
||||
instruction->base.value.special = ConstValSpecialStatic;
|
||||
instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
|
||||
instruction->msg = msg;
|
||||
|
||||
ir_ref_instruction(msg, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2287,14 +2302,6 @@ static IrInstruction *ir_instruction_ptrtypechild_get_dep(IrInstructionPtrTypeCh
|
|||
}
|
||||
}
|
||||
|
||||
static IrInstruction *ir_instruction_setfnvisible_get_dep(IrInstructionSetFnVisible *instruction, size_t index) {
|
||||
switch (index) {
|
||||
case 0: return instruction->fn_value;
|
||||
case 1: return instruction->is_visible;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static IrInstruction *ir_instruction_setdebugsafety_get_dep(IrInstructionSetDebugSafety *instruction, size_t index) {
|
||||
switch (index) {
|
||||
case 0: return instruction->scope_value;
|
||||
|
@ -2742,10 +2749,24 @@ static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGl
|
|||
}
|
||||
}
|
||||
|
||||
static IrInstruction *ir_instruction_setgloballinkage_get_dep(IrInstructionSetGlobalLinkage *instruction, size_t index) {
|
||||
switch (index) {
|
||||
case 0: return instruction->value;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instruction, size_t index) {
|
||||
switch (index) {
|
||||
case 0: return instruction->msg;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
|
||||
switch (instruction->id) {
|
||||
case IrInstructionIdInvalid:
|
||||
|
@ -2804,8 +2825,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
|
|||
return ir_instruction_toptrtype_get_dep((IrInstructionToPtrType *) instruction, index);
|
||||
case IrInstructionIdPtrTypeChild:
|
||||
return ir_instruction_ptrtypechild_get_dep((IrInstructionPtrTypeChild *) instruction, index);
|
||||
case IrInstructionIdSetFnVisible:
|
||||
return ir_instruction_setfnvisible_get_dep((IrInstructionSetFnVisible *) instruction, index);
|
||||
case IrInstructionIdSetDebugSafety:
|
||||
return ir_instruction_setdebugsafety_get_dep((IrInstructionSetDebugSafety *) instruction, index);
|
||||
case IrInstructionIdArrayType:
|
||||
|
@ -2928,8 +2947,12 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
|
|||
return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index);
|
||||
case IrInstructionIdSetGlobalSection:
|
||||
return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index);
|
||||
case IrInstructionIdSetGlobalLinkage:
|
||||
return ir_instruction_setgloballinkage_get_dep((IrInstructionSetGlobalLinkage *) instruction, index);
|
||||
case IrInstructionIdDeclRef:
|
||||
return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index);
|
||||
case IrInstructionIdPanic:
|
||||
return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -3759,20 +3782,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
|||
return arg;
|
||||
return ir_build_typeof(irb, scope, node, arg);
|
||||
}
|
||||
case BuiltinFnIdSetFnVisible:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
|
||||
IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
|
||||
if (arg1_value == irb->codegen->invalid_instruction)
|
||||
return arg1_value;
|
||||
|
||||
return ir_build_set_fn_visible(irb, scope, node, arg0_value, arg1_value);
|
||||
}
|
||||
case BuiltinFnIdSetDebugSafety:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
|
@ -4145,6 +4154,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
|||
}
|
||||
case BuiltinFnIdSetGlobalAlign:
|
||||
case BuiltinFnIdSetGlobalSection:
|
||||
case BuiltinFnIdSetGlobalLinkage:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
if (arg0_node->type != NodeTypeSymbol) {
|
||||
|
@ -4170,10 +4180,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
|||
|
||||
if (builtin_fn->id == BuiltinFnIdSetGlobalAlign) {
|
||||
return ir_build_set_global_align(irb, scope, node, tld, arg1_value);
|
||||
} else {
|
||||
} else if (builtin_fn->id == BuiltinFnIdSetGlobalSection) {
|
||||
return ir_build_set_global_section(irb, scope, node, tld, arg1_value);
|
||||
} else if (builtin_fn->id == BuiltinFnIdSetGlobalLinkage) {
|
||||
return ir_build_set_global_linkage(irb, scope, node, tld, arg1_value);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
case BuiltinFnIdPanic:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
return ir_build_panic(irb, scope, node, arg0_value);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -4624,6 +4647,10 @@ static IrInstruction *ir_gen_this_literal(IrBuilder *irb, Scope *scope, AstNode
|
|||
if (fn_entry)
|
||||
return ir_build_const_fn(irb, scope, node, fn_entry);
|
||||
|
||||
while (scope->id != ScopeIdBlock && scope->id != ScopeIdDecls) {
|
||||
scope = scope->parent;
|
||||
}
|
||||
|
||||
if (scope->id == ScopeIdDecls) {
|
||||
ScopeDecls *decls_scope = (ScopeDecls *)scope;
|
||||
TypeTableEntry *container_type = decls_scope->container_type;
|
||||
|
@ -7096,6 +7123,23 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, GlobalLinkageId *out) {
|
||||
if (type_is_invalid(value->value.type))
|
||||
return false;
|
||||
|
||||
IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_linkage_enum);
|
||||
if (type_is_invalid(casted_value->value.type))
|
||||
return false;
|
||||
|
||||
ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
|
||||
if (!const_val)
|
||||
return false;
|
||||
|
||||
*out = (GlobalLinkageId)const_val->data.x_enum.tag;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
|
||||
if (type_is_invalid(value->value.type))
|
||||
return nullptr;
|
||||
|
@ -9557,42 +9601,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
|
|||
return ira->codegen->builtin_types.entry_type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira,
|
||||
IrInstructionSetFnVisible *set_fn_visible_instruction)
|
||||
{
|
||||
IrInstruction *fn_value = set_fn_visible_instruction->fn_value->other;
|
||||
IrInstruction *is_visible_value = set_fn_visible_instruction->is_visible->other;
|
||||
|
||||
FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value);
|
||||
if (!fn_entry)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
bool want_export;
|
||||
if (!ir_resolve_bool(ira, is_visible_value, &want_export))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
AstNode *source_node = set_fn_visible_instruction->base.source_node;
|
||||
if (fn_entry->fn_export_set_node) {
|
||||
ErrorMsg *msg = ir_add_error_node(ira, source_node,
|
||||
buf_sprintf("function visibility set twice"));
|
||||
add_error_note(ira->codegen, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
fn_entry->fn_export_set_node = source_node;
|
||||
|
||||
AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
|
||||
if (fn_proto->visib_mod != VisibModExport) {
|
||||
ErrorMsg *msg = ir_add_error_node(ira, source_node,
|
||||
buf_sprintf("function must be marked export to set function visibility"));
|
||||
add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
fn_entry->internal_linkage = !want_export;
|
||||
|
||||
ir_build_const_from(ira, &set_fn_visible_instruction->base);
|
||||
return ira->codegen->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira,
|
||||
IrInstructionSetGlobalAlign *instruction)
|
||||
{
|
||||
|
@ -9677,6 +9685,45 @@ static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira,
|
|||
return ira->codegen->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_set_global_linkage(IrAnalyze *ira,
|
||||
IrInstructionSetGlobalLinkage *instruction)
|
||||
{
|
||||
Tld *tld = instruction->tld;
|
||||
IrInstruction *linkage_value = instruction->value->other;
|
||||
|
||||
GlobalLinkageId linkage_scalar;
|
||||
if (!ir_resolve_global_linkage(ira, linkage_value, &linkage_scalar))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
AstNode **set_global_linkage_node;
|
||||
GlobalLinkageId *dest_linkage_ptr;
|
||||
if (tld->id == TldIdVar) {
|
||||
TldVar *tld_var = (TldVar *)tld;
|
||||
set_global_linkage_node = &tld_var->set_global_linkage_node;
|
||||
dest_linkage_ptr = &tld_var->linkage;
|
||||
} else if (tld->id == TldIdFn) {
|
||||
TldFn *tld_fn = (TldFn *)tld;
|
||||
FnTableEntry *fn_entry = tld_fn->fn_entry;
|
||||
set_global_linkage_node = &fn_entry->set_global_linkage_node;
|
||||
dest_linkage_ptr = &fn_entry->linkage;
|
||||
} else {
|
||||
// error is caught in pass1 IR gen
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
AstNode *source_node = instruction->base.source_node;
|
||||
if (*set_global_linkage_node) {
|
||||
ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("linkage set twice"));
|
||||
add_error_note(ira->codegen, msg, *set_global_linkage_node, buf_sprintf("first set here"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
*set_global_linkage_node = source_node;
|
||||
*dest_linkage_ptr = linkage_scalar;
|
||||
|
||||
ir_build_const_from(ira, &instruction->base);
|
||||
return ira->codegen->builtin_types.entry_void;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
|
||||
IrInstructionSetDebugSafety *set_debug_safety_instruction)
|
||||
{
|
||||
|
@ -12147,6 +12194,22 @@ static TypeTableEntry *ir_analyze_instruction_can_implicit_cast(IrAnalyze *ira,
|
|||
return ira->codegen->builtin_types.entry_bool;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic *instruction) {
|
||||
IrInstruction *msg = instruction->msg->other;
|
||||
if (type_is_invalid(msg->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
|
||||
IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);
|
||||
if (type_is_invalid(casted_msg->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
IrInstruction *new_instruction = ir_build_panic(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, casted_msg);
|
||||
ir_link_new_instruction(new_instruction, &instruction->base);
|
||||
return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
|
||||
IrInstructionDeclRef *instruction)
|
||||
{
|
||||
|
@ -12266,12 +12329,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
|||
return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);
|
||||
case IrInstructionIdPtrTypeChild:
|
||||
return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
|
||||
case IrInstructionIdSetFnVisible:
|
||||
return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction);
|
||||
case IrInstructionIdSetGlobalAlign:
|
||||
return ir_analyze_instruction_set_global_align(ira, (IrInstructionSetGlobalAlign *)instruction);
|
||||
case IrInstructionIdSetGlobalSection:
|
||||
return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction);
|
||||
case IrInstructionIdSetGlobalLinkage:
|
||||
return ir_analyze_instruction_set_global_linkage(ira, (IrInstructionSetGlobalLinkage *)instruction);
|
||||
case IrInstructionIdSetDebugSafety:
|
||||
return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);
|
||||
case IrInstructionIdSliceType:
|
||||
|
@ -12384,6 +12447,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
|||
return ir_analyze_instruction_can_implicit_cast(ira, (IrInstructionCanImplicitCast *)instruction);
|
||||
case IrInstructionIdDeclRef:
|
||||
return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
|
||||
case IrInstructionIdPanic:
|
||||
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
|
||||
case IrInstructionIdMaybeWrap:
|
||||
case IrInstructionIdErrWrapCode:
|
||||
case IrInstructionIdErrWrapPayload:
|
||||
|
@ -12482,7 +12547,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdCall:
|
||||
case IrInstructionIdReturn:
|
||||
case IrInstructionIdUnreachable:
|
||||
case IrInstructionIdSetFnVisible:
|
||||
case IrInstructionIdSetDebugSafety:
|
||||
case IrInstructionIdImport:
|
||||
case IrInstructionIdCompileErr:
|
||||
|
@ -12500,6 +12564,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdCheckSwitchProngs:
|
||||
case IrInstructionIdSetGlobalAlign:
|
||||
case IrInstructionIdSetGlobalSection:
|
||||
case IrInstructionIdSetGlobalLinkage:
|
||||
case IrInstructionIdPanic:
|
||||
return true;
|
||||
case IrInstructionIdPhi:
|
||||
case IrInstructionIdUnOp:
|
||||
|
@ -12580,7 +12646,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
}
|
||||
|
||||
FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope) {
|
||||
FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, true);
|
||||
FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdInternal);
|
||||
buf_init_from_buf(&fn_entry->symbol_name, fn_name);
|
||||
|
||||
fn_entry->fndef_scope = create_fndef_scope(nullptr, parent_scope, fn_entry);
|
||||
|
|
|
@ -339,14 +339,6 @@ static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *ins
|
|||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_set_fn_visible(IrPrint *irp, IrInstructionSetFnVisible *instruction) {
|
||||
fprintf(irp->f, "@setFnVisible(");
|
||||
ir_print_other_instruction(irp, instruction->fn_value);
|
||||
fprintf(irp->f, ", ");
|
||||
ir_print_other_instruction(irp, instruction->is_visible);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) {
|
||||
fprintf(irp->f, "@setDebugSafety(");
|
||||
ir_print_other_instruction(irp, instruction->scope_value);
|
||||
|
@ -849,6 +841,13 @@ static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSect
|
|||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_set_global_linkage(IrPrint *irp, IrInstructionSetGlobalLinkage *instruction) {
|
||||
fprintf(irp->f, "@setGlobalLinkage(%s,", buf_ptr(instruction->tld->name));
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
|
||||
static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) {
|
||||
const char *ptr_str = instruction->lval.is_ptr ? "ptr " : "";
|
||||
const char *const_str = instruction->lval.is_const ? "const " : "";
|
||||
|
@ -856,6 +855,13 @@ static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) {
|
|||
fprintf(irp->f, "declref %s%s%s%s", const_str, volatile_str, ptr_str, buf_ptr(instruction->tld->name));
|
||||
}
|
||||
|
||||
static void ir_print_panic(IrPrint *irp, IrInstructionPanic *instruction) {
|
||||
fprintf(irp->f, "@panic(");
|
||||
ir_print_other_instruction(irp, instruction->msg);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
|
||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
switch (instruction->id) {
|
||||
|
@ -933,9 +939,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdEnumFieldPtr:
|
||||
ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
|
||||
break;
|
||||
case IrInstructionIdSetFnVisible:
|
||||
ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction);
|
||||
break;
|
||||
case IrInstructionIdSetDebugSafety:
|
||||
ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
|
||||
break;
|
||||
|
@ -1128,9 +1131,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdSetGlobalSection:
|
||||
ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction);
|
||||
break;
|
||||
case IrInstructionIdSetGlobalLinkage:
|
||||
ir_print_set_global_linkage(irp, (IrInstructionSetGlobalLinkage *)instruction);
|
||||
break;
|
||||
case IrInstructionIdDeclRef:
|
||||
ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction);
|
||||
break;
|
||||
case IrInstructionIdPanic:
|
||||
ir_print_panic(irp, (IrInstructionPanic *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
|
|||
child_gen->link_libs.items[i] = parent_gen->link_libs.items[i];
|
||||
}
|
||||
|
||||
codegen_set_omit_zigrt(child_gen, true);
|
||||
child_gen->want_h_file = false;
|
||||
|
||||
codegen_set_is_release(child_gen, parent_gen->is_release_build);
|
||||
|
|
|
@ -635,8 +635,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
|
|||
}
|
||||
assert(fn_type->id == TypeTableEntryIdFn);
|
||||
|
||||
bool internal_linkage = false;
|
||||
FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, internal_linkage);
|
||||
FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong);
|
||||
buf_init_from_buf(&fn_entry->symbol_name, fn_name);
|
||||
fn_entry->type_entry = fn_type;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ var argc: usize = undefined;
|
|||
var argv: &&u8 = undefined;
|
||||
|
||||
export nakedcc fn _start() -> noreturn {
|
||||
@setFnVisible(this, want_start_symbol);
|
||||
@setGlobalLinkage(_start, if (want_start_symbol) GlobalLinkage.Strong else GlobalLinkage.Internal);
|
||||
if (!want_start_symbol) {
|
||||
unreachable;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ fn callMainAndExit() -> noreturn {
|
|||
}
|
||||
|
||||
export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
|
||||
@setFnVisible(this, want_main_symbol);
|
||||
@setGlobalLinkage(main, if (want_main_symbol) GlobalLinkage.Strong else GlobalLinkage.Internal);
|
||||
if (!want_main_symbol) {
|
||||
unreachable;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) {
|
|||
d[index] = s[index];
|
||||
}
|
||||
|
||||
// Avoid dragging in the debug safety mechanisms into this .o file.
|
||||
pub fn panic(message: []const u8) -> noreturn {
|
||||
unreachable;
|
||||
export fn __stack_chk_fail() {
|
||||
@panic("stack smashing detected");
|
||||
}
|
||||
|
|
|
@ -1,13 +1,3 @@
|
|||
// Avoid dragging in the debug safety mechanisms into this .o file,
|
||||
// unless we're trying to test this file.
|
||||
pub fn panic(message: []const u8) -> noreturn {
|
||||
if (@compileVar("is_test")) {
|
||||
@import("std").debug.panic(message);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
const CHAR_BIT = 8;
|
||||
const du_int = u64;
|
||||
const di_int = i64;
|
||||
|
@ -262,7 +252,7 @@ export nakedcc fn __aeabi_uidivmod() {
|
|||
unreachable;
|
||||
}
|
||||
|
||||
@setFnVisible(this, false);
|
||||
@setGlobalLinkage(__aeabi_uidivmod, GlobalLinkage.Internal);
|
||||
}
|
||||
|
||||
export fn __udivmodsi4(a: su_int, b: su_int, rem: &su_int) -> su_int {
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
// This file is included if and only if the user's main source file does not
|
||||
// include a public panic function.
|
||||
// If this file wants to import other files *by name*, support for that would
|
||||
// have to be added in the compiler.
|
||||
|
||||
pub coldcc fn panic(message: []const u8) -> noreturn {
|
||||
if (@compileVar("os") == Os.freestanding) {
|
||||
while (true) {}
|
||||
} else {
|
||||
@import("std").debug.panic(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// This file contains functions that zig depends on to coordinate between
|
||||
// multiple .o files. The symbols are defined LinkOnce so that multiple
|
||||
// instances of zig_rt.zig do not conflict with each other.
|
||||
|
||||
export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> noreturn {
|
||||
@setGlobalLinkage(__zig_panic, GlobalLinkage.Weak);
|
||||
@setDebugSafety(this, false);
|
||||
|
||||
if (@compileVar("panic_implementation_provided")) {
|
||||
@import("@root").panic(message_ptr[0...message_len]);
|
||||
} else if (@compileVar("os") == Os.freestanding) {
|
||||
while (true) {}
|
||||
} else {
|
||||
@import("std").debug.panic(message_ptr[0...message_len]);
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ test "emptyFunctionWithComments" {
|
|||
}
|
||||
|
||||
export fn disabledExternFn() {
|
||||
@setFnVisible(this, false);
|
||||
@setGlobalLinkage(disabledExternFn, GlobalLinkage.Internal);
|
||||
}
|
||||
|
||||
test "callDisabledExternFn" {
|
||||
|
|
|
@ -1828,6 +1828,18 @@ export fn entry() {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void add_debug_safety_test_cases(void) {
|
||||
add_debug_safety_case("calling panic", R"SOURCE(
|
||||
pub fn panic(message: []const u8) -> noreturn {
|
||||
@breakpoint();
|
||||
while (true) {}
|
||||
}
|
||||
pub fn main(args: [][]u8) -> %void {
|
||||
if (!@compileVar("is_release")) {
|
||||
@panic("oh no");
|
||||
}
|
||||
}
|
||||
)SOURCE");
|
||||
|
||||
add_debug_safety_case("out of bounds slice access", R"SOURCE(
|
||||
pub fn panic(message: []const u8) -> noreturn {
|
||||
@breakpoint();
|
||||
|
|
Loading…
Reference in New Issue