mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
add frame_address and return_address builtins
This commit is contained in:
parent
271a37b418
commit
c098a8f522
@ -1055,6 +1055,7 @@ struct FnTableEntry {
|
||||
bool is_test;
|
||||
bool is_pure;
|
||||
bool safety_off;
|
||||
bool is_noinline;
|
||||
BlockContext *parent_block_context;
|
||||
FnAnalState anal_state;
|
||||
|
||||
@ -1116,6 +1117,8 @@ enum BuiltinFnId {
|
||||
BuiltinFnIdCImport,
|
||||
BuiltinFnIdErrName,
|
||||
BuiltinFnIdBreakpoint,
|
||||
BuiltinFnIdReturnAddress,
|
||||
BuiltinFnIdFrameAddress,
|
||||
BuiltinFnIdEmbedFile,
|
||||
BuiltinFnIdCmpExchange,
|
||||
BuiltinFnIdFence,
|
||||
|
||||
@ -980,6 +980,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
||||
bool is_cold = false;
|
||||
bool is_naked = false;
|
||||
bool is_test = false;
|
||||
bool is_noinline = false;
|
||||
|
||||
if (fn_proto->top_level_decl.directives) {
|
||||
for (int i = 0; i < fn_proto->top_level_decl.directives->length; i += 1) {
|
||||
@ -993,6 +994,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
||||
if (attr_name) {
|
||||
if (buf_eql_str(attr_name, "naked")) {
|
||||
is_naked = true;
|
||||
} else if (buf_eql_str(attr_name, "noinline")) {
|
||||
is_noinline = true;
|
||||
} else if (buf_eql_str(attr_name, "cold")) {
|
||||
is_cold = true;
|
||||
} else if (buf_eql_str(attr_name, "test")) {
|
||||
@ -1062,12 +1065,20 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
||||
|
||||
fn_table_entry->type_entry = fn_type;
|
||||
fn_table_entry->is_test = is_test;
|
||||
fn_table_entry->is_noinline = is_noinline;
|
||||
|
||||
if (fn_type->id == TypeTableEntryIdInvalid) {
|
||||
fn_proto->skip = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fn_table_entry->is_inline && fn_table_entry->is_noinline) {
|
||||
add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
|
||||
fn_proto->skip = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Buf *symbol_name;
|
||||
if (is_c_compat) {
|
||||
symbol_name = &fn_table_entry->symbol_name;
|
||||
@ -1081,6 +1092,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
|
||||
if (fn_table_entry->is_inline) {
|
||||
LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);
|
||||
}
|
||||
if (fn_table_entry->is_noinline) {
|
||||
LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoInlineAttribute);
|
||||
}
|
||||
if (fn_type->data.fn.fn_type_id.is_naked) {
|
||||
LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);
|
||||
}
|
||||
@ -4866,6 +4880,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
||||
case BuiltinFnIdBreakpoint:
|
||||
mark_impure_fn(context);
|
||||
return g->builtin_types.entry_void;
|
||||
case BuiltinFnIdReturnAddress:
|
||||
case BuiltinFnIdFrameAddress:
|
||||
mark_impure_fn(context);
|
||||
return builtin_fn->return_type;
|
||||
case BuiltinFnIdEmbedFile:
|
||||
return analyze_embed_file(g, import, context, node);
|
||||
case BuiltinFnIdCmpExchange:
|
||||
|
||||
@ -634,6 +634,13 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
||||
case BuiltinFnIdBreakpoint:
|
||||
set_debug_source_node(g, node);
|
||||
return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
|
||||
case BuiltinFnIdFrameAddress:
|
||||
case BuiltinFnIdReturnAddress:
|
||||
{
|
||||
LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
|
||||
set_debug_source_node(g, node);
|
||||
return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, "");
|
||||
}
|
||||
case BuiltinFnIdCmpExchange:
|
||||
return gen_cmp_exchange(g, node);
|
||||
case BuiltinFnIdFence:
|
||||
@ -4330,6 +4337,26 @@ static void define_builtin_fns(CodeGen *g) {
|
||||
|
||||
g->trap_fn_val = builtin_fn->fn_val;
|
||||
}
|
||||
{
|
||||
BuiltinFnEntry *builtin_fn = create_builtin_fn_with_arg_count(g, BuiltinFnIdReturnAddress,
|
||||
"return_address", 0);
|
||||
builtin_fn->return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
|
||||
LLVMTypeRef fn_type = LLVMFunctionType(builtin_fn->return_type->type_ref,
|
||||
&g->builtin_types.entry_i32->type_ref, 1, false);
|
||||
builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
|
||||
assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
|
||||
}
|
||||
{
|
||||
BuiltinFnEntry *builtin_fn = create_builtin_fn_with_arg_count(g, BuiltinFnIdFrameAddress,
|
||||
"frame_address", 0);
|
||||
builtin_fn->return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
|
||||
LLVMTypeRef fn_type = LLVMFunctionType(builtin_fn->return_type->type_ref,
|
||||
&g->builtin_types.entry_i32->type_ref, 1, false);
|
||||
builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.frameaddress", fn_type);
|
||||
assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
|
||||
}
|
||||
{
|
||||
BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
|
||||
builtin_fn->return_type = g->builtin_types.entry_void;
|
||||
|
||||
@ -787,6 +787,8 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
|
||||
zig_panic("TODO");
|
||||
case BuiltinFnIdBreakpoint:
|
||||
case BuiltinFnIdInvalid:
|
||||
case BuiltinFnIdFrameAddress:
|
||||
case BuiltinFnIdReturnAddress:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user