authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-02 00:42:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-02 00:42:06-07:00
log6f1a7a0d70d53e7402380ce23a7b1e9c55aefa5c
treef568794f5e83b6840afcd37812a6652ed21a93c8
parentfc5ffd32e99bfac6bbf6f5f77804c3c5ebe9ae88

add abort function and "cold" fn attribute


4 files changed, 149 insertions(+), 18 deletions(-)

src/all_types.hpp+1
......@@ -792,6 +792,7 @@ struct FnTypeId {
792792 int param_count;
793793 bool is_var_args;
794794 bool is_naked;
795 bool is_cold;
795796 bool is_extern;
796797};
797798
src/analyze.cpp+23-5
......@@ -457,7 +457,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
457457
458458 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
459459 fn_type->data.fn.fn_type_id = fn_type_id;
460 fn_type->data.fn.calling_convention = fn_type_id.is_extern ? LLVMCCallConv : LLVMFastCallConv;
460
461 if (fn_type_id.is_cold) {
462 fn_type->data.fn.calling_convention = LLVMColdCallConv;
463 } else if (fn_type_id.is_extern) {
464 fn_type->data.fn.calling_convention = LLVMCCallConv;
465 } else {
466 fn_type->data.fn.calling_convention = LLVMFastCallConv;
467 }
461468
462469 fn_type->size_in_bits = g->pointer_size_bytes * 8;
463470 fn_type->align_in_bits = g->pointer_size_bytes * 8;
......@@ -466,7 +473,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
466473 buf_resize(&fn_type->name, 0);
467474 const char *extern_str = fn_type_id.is_extern ? "extern " : "";
468475 const char *naked_str = fn_type_id.is_naked ? "naked " : "";
469 buf_appendf(&fn_type->name, "%s%sfn(", extern_str, naked_str);
476 const char *cold_str = fn_type_id.is_cold ? "cold " : "";
477 buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str);
470478 for (int i = 0; i < fn_type_id.param_count; i += 1) {
471479 FnTypeParamInfo *param_info = &fn_type_id.param_info[i];
472480
......@@ -634,7 +642,7 @@ static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, B
634642}
635643
636644static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
637 TypeTableEntry *expected_type, AstNode *node, bool is_naked)
645 TypeTableEntry *expected_type, AstNode *node, bool is_naked, bool is_cold)
638646{
639647 assert(node->type == NodeTypeFnProto);
640648 AstNodeFnProto *fn_proto = &node->data.fn_proto;
......@@ -646,6 +654,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
646654 FnTypeId fn_type_id;
647655 fn_type_id.is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);
648656 fn_type_id.is_naked = is_naked;
657 fn_type_id.is_cold = is_cold;
649658 fn_type_id.param_count = node->data.fn_proto.params.length;
650659 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);
651660 fn_type_id.is_var_args = fn_proto->is_var_args;
......@@ -716,6 +725,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
716725
717726 fn_table_entry->is_inline = fn_proto->is_inline;
718727
728 bool is_cold = false;
719729 bool is_naked = false;
720730
721731 if (fn_proto->directives) {
......@@ -728,6 +738,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
728738 if (fn_table_entry->fn_def_node) {
729739 if (buf_eql_str(attr_name, "naked")) {
730740 is_naked = true;
741 } else if (buf_eql_str(attr_name, "cold")) {
742 is_cold = true;
731743 } else {
732744 add_node_error(g, directive_node,
733745 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
......@@ -743,7 +755,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
743755 }
744756 }
745757
746 TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, import->block_context, nullptr, node, is_naked);
758 TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, import->block_context, nullptr, node,
759 is_naked, is_cold);
747760
748761 fn_table_entry->type_entry = fn_type;
749762
......@@ -1549,6 +1562,9 @@ static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTable
15491562 if (expected_type->data.fn.fn_type_id.is_naked != actual_type->data.fn.fn_type_id.is_naked) {
15501563 return false;
15511564 }
1565 if (expected_type->data.fn.fn_type_id.is_cold != actual_type->data.fn.fn_type_id.is_cold) {
1566 return false;
1567 }
15521568 if (!types_match_const_cast_only(expected_type->data.fn.fn_type_id.return_type,
15531569 actual_type->data.fn.fn_type_id.return_type))
15541570 {
......@@ -3121,7 +3137,7 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
31213137static TypeTableEntry *analyze_fn_proto_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
31223138 TypeTableEntry *expected_type, AstNode *node)
31233139{
3124 TypeTableEntry *type_entry = analyze_fn_proto_type(g, import, context, expected_type, node, false);
3140 TypeTableEntry *type_entry = analyze_fn_proto_type(g, import, context, expected_type, node, false, false);
31253141
31263142 if (type_entry->id == TypeTableEntryIdInvalid) {
31273143 return type_entry;
......@@ -5498,6 +5514,7 @@ uint32_t fn_type_id_hash(FnTypeId id) {
54985514 uint32_t result = 0;
54995515 result += id.is_extern ? 3349388391 : 0;
55005516 result += id.is_naked ? 608688877 : 0;
5517 result += id.is_cold ? 3605523458 : 0;
55015518 result += id.is_var_args ? 1931444534 : 0;
55025519 result += hash_ptr(id.return_type);
55035520 result += id.param_count;
......@@ -5512,6 +5529,7 @@ uint32_t fn_type_id_hash(FnTypeId id) {
55125529bool fn_type_id_eql(FnTypeId a, FnTypeId b) {
55135530 if (a.is_extern != b.is_extern ||
55145531 a.is_naked != b.is_naked ||
5532 a.is_cold != b.is_cold ||
55155533 a.return_type != b.return_type ||
55165534 a.is_var_args != b.is_var_args ||
55175535 a.param_count != b.param_count)
std/std.zig+6
......@@ -172,6 +172,12 @@ pub fn os_get_random_bytes(buf: []u8) -> %void {
172172 }
173173}
174174
175#attribute("cold")
176pub fn abort() -> unreachable {
177 raise(SIGABRT);
178 raise(SIGKILL);
179 while (true) {}
180}
175181
176182pub error InvalidChar;
177183pub error Overflow;
std/syscall.zig+119-13
......@@ -1,11 +1,18 @@
1const SYS_read = 0;
2const SYS_write = 1;
3const SYS_mmap = 9;
4const SYS_munmap = 11;
5const SYS_exit = 60;
6const SYS_getrandom = 318;
7
8// mmap constants
1// this file is specific to x86_64
2
3const SYS_read = 0;
4const SYS_write = 1;
5const SYS_mmap = 9;
6const SYS_munmap = 11;
7const SYS_rt_sigprocmask = 14;
8const SYS_exit = 60;
9const SYS_kill = 62;
10const SYS_getgid = 104;
11const SYS_gettid = 186;
12const SYS_tkill = 200;
13const SYS_tgkill = 234;
14const SYS_getrandom = 318;
15
916pub const MMAP_PROT_NONE = 0;
1017pub const MMAP_PROT_READ = 1;
1118pub const MMAP_PROT_WRITE = 2;
......@@ -17,31 +24,100 @@ pub const MMAP_MAP_PRIVATE = 2;
1724pub const MMAP_MAP_FIXED = 16;
1825pub const MMAP_MAP_ANON = 32;
1926
27pub const SIGHUP = 1;
28pub const SIGINT = 2;
29pub const SIGQUIT = 3;
30pub const SIGILL = 4;
31pub const SIGTRAP = 5;
32pub const SIGABRT = 6;
33pub const SIGIOT = SIGABRT;
34pub const SIGBUS = 7;
35pub const SIGFPE = 8;
36pub const SIGKILL = 9;
37pub const SIGUSR1 = 10;
38pub const SIGSEGV = 11;
39pub const SIGUSR2 = 12;
40pub const SIGPIPE = 13;
41pub const SIGALRM = 14;
42pub const SIGTERM = 15;
43pub const SIGSTKFLT = 16;
44pub const SIGCHLD = 17;
45pub const SIGCONT = 18;
46pub const SIGSTOP = 19;
47pub const SIGTSTP = 20;
48pub const SIGTTIN = 21;
49pub const SIGTTOU = 22;
50pub const SIGURG = 23;
51pub const SIGXCPU = 24;
52pub const SIGXFSZ = 25;
53pub const SIGVTALRM = 26;
54pub const SIGPROF = 27;
55pub const SIGWINCH = 28;
56pub const SIGIO = 29;
57pub const SIGPOLL = 29;
58pub const SIGPWR = 30;
59pub const SIGSYS = 31;
60pub const SIGUNUSED = SIGSYS;
61
62const SIG_BLOCK = 0;
63const SIG_UNBLOCK = 1;
64const SIG_SETMASK = 2;
65
66fn syscall0(number: isize) -> isize {
67 asm volatile ("syscall"
68 : [ret] "={rax}" (-> isize)
69 : [number] "{rax}" (number)
70 : "rcx", "r11")
71}
72
2073fn syscall1(number: isize, arg1: isize) -> isize {
2174 asm volatile ("syscall"
2275 : [ret] "={rax}" (-> isize)
23 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1)
76 : [number] "{rax}" (number),
77 [arg1] "{rdi}" (arg1)
78 : "rcx", "r11")
79}
80
81fn syscall2(number: isize, arg1: isize, arg2: isize) -> isize {
82 asm volatile ("syscall"
83 : [ret] "={rax}" (-> isize)
84 : [number] "{rax}" (number),
85 [arg1] "{rdi}" (arg1),
86 [arg2] "{rsi}" (arg2)
2487 : "rcx", "r11")
2588}
2689
2790fn syscall3(number: isize, arg1: isize, arg2: isize, arg3: isize) -> isize {
2891 asm volatile ("syscall"
2992 : [ret] "={rax}" (-> isize)
30 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3)
93 : [number] "{rax}" (number),
94 [arg1] "{rdi}" (arg1),
95 [arg2] "{rsi}" (arg2),
96 [arg3] "{rdx}" (arg3)
3197 : "rcx", "r11")
3298}
3399
34fn syscall2(number: isize, arg1: isize, arg2: isize) -> isize {
100fn syscall4(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize) -> isize {
35101 asm volatile ("syscall"
36102 : [ret] "={rax}" (-> isize)
37 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2)
103 : [number] "{rax}" (number),
104 [arg1] "{rdi}" (arg1),
105 [arg2] "{rsi}" (arg2),
106 [arg3] "{rdx}" (arg3),
107 [arg4] "{r10}" (arg4)
38108 : "rcx", "r11")
39109}
40110
41111fn syscall6(number: isize, arg1: isize, arg2: isize, arg3: isize, arg4: isize, arg5: isize, arg6: isize) -> isize {
42112 asm volatile ("syscall"
43113 : [ret] "={rax}" (-> isize)
44 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3), [arg4] "{r10}" (arg4), [arg5] "{r8}" (arg5), [arg6] "{r9}" (arg6)
114 : [number] "{rax}" (number),
115 [arg1] "{rdi}" (arg1),
116 [arg2] "{rsi}" (arg2),
117 [arg3] "{rdx}" (arg3),
118 [arg4] "{r10}" (arg4),
119 [arg5] "{r8}" (arg5),
120 [arg6] "{r9}" (arg6)
45121 : "rcx", "r11")
46122}
47123
......@@ -69,3 +145,33 @@ pub fn exit(status: i32) -> unreachable {
69145pub fn getrandom(buf: &u8, count: isize, flags: u32) -> isize {
70146 syscall3(SYS_getrandom, isize(buf), count, isize(flags))
71147}
148
149pub fn kill(pid: i32, sig: i32) -> i32 {
150 i32(syscall2(SYS_kill, pid, sig))
151}
152
153const NSIG = 65;
154const sigset_t = [128]u8;
155const all_mask = []u8 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
156const app_mask = []u8 { 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, };
157
158pub fn raise(sig: i32) -> i32 {
159 var set: sigset_t = undefined;
160 block_app_signals(&set);
161 const tid = i32(syscall0(SYS_gettid));
162 const ret = i32(syscall2(SYS_tkill, tid, sig));
163 restore_signals(&set);
164 return ret;
165}
166
167fn block_all_signals(set: &sigset_t) {
168 syscall4(SYS_rt_sigprocmask, SIG_BLOCK, isize(&all_mask), isize(set), NSIG/8);
169}
170
171fn block_app_signals(set: &sigset_t) {
172 syscall4(SYS_rt_sigprocmask, SIG_BLOCK, isize(&app_mask), isize(set), NSIG/8);
173}
174
175fn restore_signals(set: &sigset_t) {
176 syscall4(SYS_rt_sigprocmask, SIG_SETMASK, isize(set), 0, NSIG/8);
177}