authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-06 23:10:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-05-06 23:10:14-07:00
logc098a8f5223855b410895b5396948e3e2b3aacba
treeac3c4e5fa9de71a1b703d52433e0e1cec3abe7cf
parent271a37b418828c8ee79402f97016be42c5fa2884

add frame_address and return_address builtins


4 files changed, 50 insertions(+), 0 deletions(-)

src/all_types.hpp+3
......@@ -1055,6 +1055,7 @@ struct FnTableEntry {
10551055 bool is_test;
10561056 bool is_pure;
10571057 bool safety_off;
1058 bool is_noinline;
10581059 BlockContext *parent_block_context;
10591060 FnAnalState anal_state;
10601061
......@@ -1116,6 +1117,8 @@ enum BuiltinFnId {
11161117 BuiltinFnIdCImport,
11171118 BuiltinFnIdErrName,
11181119 BuiltinFnIdBreakpoint,
1120 BuiltinFnIdReturnAddress,
1121 BuiltinFnIdFrameAddress,
11191122 BuiltinFnIdEmbedFile,
11201123 BuiltinFnIdCmpExchange,
11211124 BuiltinFnIdFence,
src/analyze.cpp+18
......@@ -980,6 +980,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
980980 bool is_cold = false;
981981 bool is_naked = false;
982982 bool is_test = false;
983 bool is_noinline = false;
983984
984985 if (fn_proto->top_level_decl.directives) {
985986 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
993994 if (attr_name) {
994995 if (buf_eql_str(attr_name, "naked")) {
995996 is_naked = true;
997 } else if (buf_eql_str(attr_name, "noinline")) {
998 is_noinline = true;
996999 } else if (buf_eql_str(attr_name, "cold")) {
9971000 is_cold = true;
9981001 } else if (buf_eql_str(attr_name, "test")) {
......@@ -1062,12 +1065,20 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
10621065
10631066 fn_table_entry->type_entry = fn_type;
10641067 fn_table_entry->is_test = is_test;
1068 fn_table_entry->is_noinline = is_noinline;
10651069
10661070 if (fn_type->id == TypeTableEntryIdInvalid) {
10671071 fn_proto->skip = true;
10681072 return;
10691073 }
10701074
1075 if (fn_table_entry->is_inline && fn_table_entry->is_noinline) {
1076 add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
1077 fn_proto->skip = true;
1078 return;
1079 }
1080
1081
10711082 Buf *symbol_name;
10721083 if (is_c_compat) {
10731084 symbol_name = &fn_table_entry->symbol_name;
......@@ -1081,6 +1092,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
10811092 if (fn_table_entry->is_inline) {
10821093 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);
10831094 }
1095 if (fn_table_entry->is_noinline) {
1096 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoInlineAttribute);
1097 }
10841098 if (fn_type->data.fn.fn_type_id.is_naked) {
10851099 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);
10861100 }
......@@ -4866,6 +4880,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
48664880 case BuiltinFnIdBreakpoint:
48674881 mark_impure_fn(context);
48684882 return g->builtin_types.entry_void;
4883 case BuiltinFnIdReturnAddress:
4884 case BuiltinFnIdFrameAddress:
4885 mark_impure_fn(context);
4886 return builtin_fn->return_type;
48694887 case BuiltinFnIdEmbedFile:
48704888 return analyze_embed_file(g, import, context, node);
48714889 case BuiltinFnIdCmpExchange:
src/codegen.cpp+27
......@@ -634,6 +634,13 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
634634 case BuiltinFnIdBreakpoint:
635635 set_debug_source_node(g, node);
636636 return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
637 case BuiltinFnIdFrameAddress:
638 case BuiltinFnIdReturnAddress:
639 {
640 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
641 set_debug_source_node(g, node);
642 return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, "");
643 }
637644 case BuiltinFnIdCmpExchange:
638645 return gen_cmp_exchange(g, node);
639646 case BuiltinFnIdFence:
......@@ -4330,6 +4337,26 @@ static void define_builtin_fns(CodeGen *g) {
43304337
43314338 g->trap_fn_val = builtin_fn->fn_val;
43324339 }
4340 {
4341 BuiltinFnEntry *builtin_fn = create_builtin_fn_with_arg_count(g, BuiltinFnIdReturnAddress,
4342 "return_address", 0);
4343 builtin_fn->return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
4344
4345 LLVMTypeRef fn_type = LLVMFunctionType(builtin_fn->return_type->type_ref,
4346 &g->builtin_types.entry_i32->type_ref, 1, false);
4347 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
4348 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
4349 }
4350 {
4351 BuiltinFnEntry *builtin_fn = create_builtin_fn_with_arg_count(g, BuiltinFnIdFrameAddress,
4352 "frame_address", 0);
4353 builtin_fn->return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
4354
4355 LLVMTypeRef fn_type = LLVMFunctionType(builtin_fn->return_type->type_ref,
4356 &g->builtin_types.entry_i32->type_ref, 1, false);
4357 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.frameaddress", fn_type);
4358 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
4359 }
43334360 {
43344361 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
43354362 builtin_fn->return_type = g->builtin_types.entry_void;
src/eval.cpp+2
......@@ -787,6 +787,8 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
787787 zig_panic("TODO");
788788 case BuiltinFnIdBreakpoint:
789789 case BuiltinFnIdInvalid:
790 case BuiltinFnIdFrameAddress:
791 case BuiltinFnIdReturnAddress:
790792 zig_unreachable();
791793 }
792794