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 {...@@ -1055,6 +1055,7 @@ struct FnTableEntry {
1055 bool is_test;1055 bool is_test;
1056 bool is_pure;1056 bool is_pure;
1057 bool safety_off;1057 bool safety_off;
1058 bool is_noinline;
1058 BlockContext *parent_block_context;1059 BlockContext *parent_block_context;
1059 FnAnalState anal_state;1060 FnAnalState anal_state;
10601061
...@@ -1116,6 +1117,8 @@ enum BuiltinFnId {...@@ -1116,6 +1117,8 @@ enum BuiltinFnId {
1116 BuiltinFnIdCImport,1117 BuiltinFnIdCImport,
1117 BuiltinFnIdErrName,1118 BuiltinFnIdErrName,
1118 BuiltinFnIdBreakpoint,1119 BuiltinFnIdBreakpoint,
1120 BuiltinFnIdReturnAddress,
1121 BuiltinFnIdFrameAddress,
1119 BuiltinFnIdEmbedFile,1122 BuiltinFnIdEmbedFile,
1120 BuiltinFnIdCmpExchange,1123 BuiltinFnIdCmpExchange,
1121 BuiltinFnIdFence,1124 BuiltinFnIdFence,
src/analyze.cpp+18
...@@ -980,6 +980,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -980,6 +980,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
980 bool is_cold = false;980 bool is_cold = false;
981 bool is_naked = false;981 bool is_naked = false;
982 bool is_test = false;982 bool is_test = false;
983 bool is_noinline = false;
983984
984 if (fn_proto->top_level_decl.directives) {985 if (fn_proto->top_level_decl.directives) {
985 for (int i = 0; i < fn_proto->top_level_decl.directives->length; i += 1) {986 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...@@ -993,6 +994,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
993 if (attr_name) {994 if (attr_name) {
994 if (buf_eql_str(attr_name, "naked")) {995 if (buf_eql_str(attr_name, "naked")) {
995 is_naked = true;996 is_naked = true;
997 } else if (buf_eql_str(attr_name, "noinline")) {
998 is_noinline = true;
996 } else if (buf_eql_str(attr_name, "cold")) {999 } else if (buf_eql_str(attr_name, "cold")) {
997 is_cold = true;1000 is_cold = true;
998 } else if (buf_eql_str(attr_name, "test")) {1001 } else if (buf_eql_str(attr_name, "test")) {
...@@ -1062,12 +1065,20 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -1062,12 +1065,20 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
10621065
1063 fn_table_entry->type_entry = fn_type;1066 fn_table_entry->type_entry = fn_type;
1064 fn_table_entry->is_test = is_test;1067 fn_table_entry->is_test = is_test;
1068 fn_table_entry->is_noinline = is_noinline;
10651069
1066 if (fn_type->id == TypeTableEntryIdInvalid) {1070 if (fn_type->id == TypeTableEntryIdInvalid) {
1067 fn_proto->skip = true;1071 fn_proto->skip = true;
1068 return;1072 return;
1069 }1073 }
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
1071 Buf *symbol_name;1082 Buf *symbol_name;
1072 if (is_c_compat) {1083 if (is_c_compat) {
1073 symbol_name = &fn_table_entry->symbol_name;1084 symbol_name = &fn_table_entry->symbol_name;
...@@ -1081,6 +1092,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -1081,6 +1092,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
1081 if (fn_table_entry->is_inline) {1092 if (fn_table_entry->is_inline) {
1082 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);1093 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);
1083 }1094 }
1095 if (fn_table_entry->is_noinline) {
1096 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoInlineAttribute);
1097 }
1084 if (fn_type->data.fn.fn_type_id.is_naked) {1098 if (fn_type->data.fn.fn_type_id.is_naked) {
1085 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);1099 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);
1086 }1100 }
...@@ -4866,6 +4880,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -4866,6 +4880,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
4866 case BuiltinFnIdBreakpoint:4880 case BuiltinFnIdBreakpoint:
4867 mark_impure_fn(context);4881 mark_impure_fn(context);
4868 return g->builtin_types.entry_void;4882 return g->builtin_types.entry_void;
4883 case BuiltinFnIdReturnAddress:
4884 case BuiltinFnIdFrameAddress:
4885 mark_impure_fn(context);
4886 return builtin_fn->return_type;
4869 case BuiltinFnIdEmbedFile:4887 case BuiltinFnIdEmbedFile:
4870 return analyze_embed_file(g, import, context, node);4888 return analyze_embed_file(g, import, context, node);
4871 case BuiltinFnIdCmpExchange:4889 case BuiltinFnIdCmpExchange:
src/codegen.cpp+27
...@@ -634,6 +634,13 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -634,6 +634,13 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
634 case BuiltinFnIdBreakpoint:634 case BuiltinFnIdBreakpoint:
635 set_debug_source_node(g, node);635 set_debug_source_node(g, node);
636 return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");636 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 }
637 case BuiltinFnIdCmpExchange:644 case BuiltinFnIdCmpExchange:
638 return gen_cmp_exchange(g, node);645 return gen_cmp_exchange(g, node);
639 case BuiltinFnIdFence:646 case BuiltinFnIdFence:
...@@ -4330,6 +4337,26 @@ static void define_builtin_fns(CodeGen *g) {...@@ -4330,6 +4337,26 @@ static void define_builtin_fns(CodeGen *g) {
43304337
4331 g->trap_fn_val = builtin_fn->fn_val;4338 g->trap_fn_val = builtin_fn->fn_val;
4332 }4339 }
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 }
4333 {4360 {
4334 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");4361 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
4335 builtin_fn->return_type = g->builtin_types.entry_void;4362 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_...@@ -787,6 +787,8 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
787 zig_panic("TODO");787 zig_panic("TODO");
788 case BuiltinFnIdBreakpoint:788 case BuiltinFnIdBreakpoint:
789 case BuiltinFnIdInvalid:789 case BuiltinFnIdInvalid:
790 case BuiltinFnIdFrameAddress:
791 case BuiltinFnIdReturnAddress:
790 zig_unreachable();792 zig_unreachable();
791 }793 }
792794