authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-21 15:36:25-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-21 15:36:25-05:00
loga2257e4b81764f8603a39b74eae3622651ec7d6b
tree6e046fee9d846528f4259926d49e4c1ec8208df4
parent052cd44588a94550a431adc6d1ff5af7e4439c88

IR: implement setFnVisible builtin


6 files changed, 371 insertions(+), 305 deletions(-)

src/all_types.hpp+8
......@@ -1448,6 +1448,7 @@ enum IrInstructionId {
14481448 IrInstructionIdToPtrType,
14491449 IrInstructionIdPtrTypeChild,
14501450 IrInstructionIdSetFnTest,
1451 IrInstructionIdSetFnVisible,
14511452 IrInstructionIdSetDebugSafety,
14521453 IrInstructionIdArrayType,
14531454 IrInstructionIdSliceType,
......@@ -1712,6 +1713,13 @@ struct IrInstructionSetFnTest {
17121713 IrInstruction *is_test;
17131714};
17141715
1716struct IrInstructionSetFnVisible {
1717 IrInstruction base;
1718
1719 IrInstruction *fn_value;
1720 IrInstruction *is_visible;
1721};
1722
17151723struct IrInstructionSetDebugSafety {
17161724 IrInstruction base;
17171725
src/codegen.cpp+1
......@@ -1649,6 +1649,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
16491649 case IrInstructionIdPtrTypeChild:
16501650 case IrInstructionIdFieldPtr:
16511651 case IrInstructionIdSetFnTest:
1652 case IrInstructionIdSetFnVisible:
16521653 case IrInstructionIdSetDebugSafety:
16531654 case IrInstructionIdArrayType:
16541655 case IrInstructionIdSliceType:
src/ir.cpp+71-42
......@@ -202,6 +202,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
202202 return IrInstructionIdSetFnTest;
203203}
204204
205static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnVisible *) {
206 return IrInstructionIdSetFnVisible;
207}
208
205209static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) {
206210 return IrInstructionIdSetDebugSafety;
207211}
......@@ -808,6 +812,19 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node,
808812 return &instruction->base;
809813}
810814
815static IrInstruction *ir_build_set_fn_visible(IrBuilder *irb, AstNode *source_node, IrInstruction *fn_value,
816 IrInstruction *is_visible)
817{
818 IrInstructionSetFnVisible *instruction = ir_build_instruction<IrInstructionSetFnVisible>(irb, source_node);
819 instruction->fn_value = fn_value;
820 instruction->is_visible = is_visible;
821
822 ir_ref_instruction(fn_value);
823 ir_ref_instruction(is_visible);
824
825 return &instruction->base;
826}
827
811828static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, AstNode *source_node,
812829 IrInstruction *scope_value, IrInstruction *debug_safety_on)
813830{
......@@ -1432,6 +1449,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
14321449
14331450 return ir_build_set_fn_test(irb, node, arg0_value, arg1_value);
14341451 }
1452 case BuiltinFnIdSetFnVisible:
1453 {
1454 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1455 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context);
1456 if (arg0_value == irb->codegen->invalid_instruction)
1457 return arg0_value;
1458
1459 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
1460 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, node->block_context);
1461 if (arg1_value == irb->codegen->invalid_instruction)
1462 return arg1_value;
1463
1464 return ir_build_set_fn_visible(irb, node, arg0_value, arg1_value);
1465 }
14351466 case BuiltinFnIdSetDebugSafety:
14361467 {
14371468 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
......@@ -1509,7 +1540,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
15091540 case BuiltinFnIdDivExact:
15101541 case BuiltinFnIdTruncate:
15111542 case BuiltinFnIdIntType:
1512 case BuiltinFnIdSetFnVisible:
15131543 case BuiltinFnIdSetFnStaticEval:
15141544 case BuiltinFnIdSetFnNoInline:
15151545 zig_panic("TODO IR gen more builtin functions");
......@@ -4394,6 +4424,43 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
43944424 return ira->codegen->builtin_types.entry_void;
43954425}
43964426
4427static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira,
4428 IrInstructionSetFnVisible *set_fn_visible_instruction)
4429{
4430 IrInstruction *fn_value = set_fn_visible_instruction->fn_value->other;
4431 IrInstruction *is_visible_value = set_fn_visible_instruction->is_visible->other;
4432
4433 FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value);
4434 if (!fn_entry)
4435 return ira->codegen->builtin_types.entry_invalid;
4436
4437 bool want_export;
4438 if (!ir_resolve_bool(ira, is_visible_value, &want_export))
4439 return ira->codegen->builtin_types.entry_invalid;
4440
4441 AstNode *source_node = set_fn_visible_instruction->base.source_node;
4442 if (fn_entry->fn_export_set_node) {
4443 ErrorMsg *msg = add_node_error(ira->codegen, source_node,
4444 buf_sprintf("function visibility set twice"));
4445 add_error_note(ira->codegen, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
4446 return ira->codegen->builtin_types.entry_invalid;
4447 }
4448 fn_entry->fn_export_set_node = source_node;
4449
4450 AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
4451 if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
4452 ErrorMsg *msg = add_node_error(ira->codegen, source_node,
4453 buf_sprintf("function must be marked export to set function visibility"));
4454 add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
4455 return ira->codegen->builtin_types.entry_invalid;
4456 }
4457 if (!want_export)
4458 LLVMSetLinkage(fn_entry->fn_value, LLVMInternalLinkage);
4459
4460 ir_build_const_from(ira, &set_fn_visible_instruction->base, false);
4461 return ira->codegen->builtin_types.entry_void;
4462}
4463
43974464static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
43984465 IrInstructionSetDebugSafety *set_debug_safety_instruction)
43994466{
......@@ -4847,6 +4914,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
48474914 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
48484915 case IrInstructionIdSetFnTest:
48494916 return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
4917 case IrInstructionIdSetFnVisible:
4918 return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction);
48504919 case IrInstructionIdSetDebugSafety:
48514920 return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);
48524921 case IrInstructionIdSliceType:
......@@ -4957,6 +5026,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
49575026 case IrInstructionIdReturn:
49585027 case IrInstructionIdUnreachable:
49595028 case IrInstructionIdSetFnTest:
5029 case IrInstructionIdSetFnVisible:
49605030 case IrInstructionIdSetDebugSafety:
49615031 return true;
49625032 case IrInstructionIdPhi:
......@@ -5523,44 +5593,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
55235593// return g->builtin_types.entry_void;
55245594//}
55255595//
5526//static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import,
5527// BlockContext *context, AstNode *node)
5528//{
5529// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
5530// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
5531//
5532// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
5533// if (!fn_entry) {
5534// return g->builtin_types.entry_invalid;
5535// }
5536//
5537// bool want_export;
5538// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export);
5539// if (!ok) {
5540// return g->builtin_types.entry_invalid;
5541// }
5542//
5543// if (fn_entry->fn_export_set_node) {
5544// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice"));
5545// add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
5546// return g->builtin_types.entry_invalid;
5547// }
5548// fn_entry->fn_export_set_node = node;
5549//
5550// AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
5551// if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
5552// ErrorMsg *msg = add_node_error(g, node,
5553// buf_sprintf("function must be marked export to set function visibility"));
5554// add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
5555// return g->builtin_types.entry_void;
5556// }
5557// if (!want_export) {
5558// fn_proto->top_level_decl.visib_mod = VisibModPub;
5559// }
5560//
5561// return g->builtin_types.entry_void;
5562//}
5563//
55645596//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
55655597// TypeTableEntry *expected_type, AstNode *node)
55665598//{
......@@ -5784,8 +5816,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
57845816// return analyze_set_fn_no_inline(g, import, context, node);
57855817// case BuiltinFnIdSetFnStaticEval:
57865818// return analyze_set_fn_static_eval(g, import, context, node);
5787// case BuiltinFnIdSetFnVisible:
5788// return analyze_set_fn_visible(g, import, context, node);
57895819// }
57905820// zig_unreachable();
57915821//}
......@@ -8310,7 +8340,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
83108340// case BuiltinFnIdUnreachable:
83118341// zig_panic("moved to ir render");
83128342// case BuiltinFnIdSetFnTest:
8313// case BuiltinFnIdSetFnVisible:
83148343// case BuiltinFnIdSetFnStaticEval:
83158344// case BuiltinFnIdSetFnNoInline:
83168345// case BuiltinFnIdSetDebugSafety:
src/ir_print.cpp+11
......@@ -425,6 +425,14 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi
425425 fprintf(irp->f, ")");
426426}
427427
428static void ir_print_set_fn_visible(IrPrint *irp, IrInstructionSetFnVisible *instruction) {
429 fprintf(irp->f, "@setFnVisible(");
430 ir_print_other_instruction(irp, instruction->fn_value);
431 fprintf(irp->f, ", ");
432 ir_print_other_instruction(irp, instruction->is_visible);
433 fprintf(irp->f, ")");
434}
435
428436static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) {
429437 fprintf(irp->f, "@setDebugSafety(");
430438 ir_print_other_instruction(irp, instruction->scope_value);
......@@ -603,6 +611,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
603611 case IrInstructionIdSetFnTest:
604612 ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
605613 break;
614 case IrInstructionIdSetFnVisible:
615 ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction);
616 break;
606617 case IrInstructionIdSetDebugSafety:
607618 ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
608619 break;
std/compiler_rt.zig+263-262
......@@ -1,262 +1,263 @@
1const CHAR_BIT = 8;
2const du_int = u64;
3const di_int = i64;
4const si_int = c_int;
5const su_int = c_uint;
6
7const udwords = [2]su_int;
8const low = if (@compileVar("is_big_endian")) 1 else 0;
9const high = 1 - low;
10
11export fn __udivdi3(a: du_int, b: du_int) -> du_int {
12 @setDebugSafety(this, false);
13 return __udivmoddi4(a, b, null);
14}
15
16fn du_int_to_udwords(x: du_int) -> udwords {
17 @setDebugSafety(this, false);
18 return *(&udwords)(&x);
19}
20
21export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
22 @setDebugSafety(this, false);
23
24 const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;
25 const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;
26 var n = du_int_to_udwords(a);
27 var d = du_int_to_udwords(b);
28 var q: udwords = undefined;
29 var r: udwords = undefined;
30 var sr: c_uint = undefined;
31 // special cases, X is unknown, K != 0
32 if (n[high] == 0) {
33 if (d[high] == 0) {
34 // 0 X
35 // ---
36 // 0 X
37 if (const rem ?= maybe_rem) {
38 *rem = n[low] % d[low];
39 }
40 return n[low] / d[low];
41 }
42 // 0 X
43 // ---
44 // K X
45 if (const rem ?= maybe_rem) {
46 *rem = n[low];
47 }
48 return 0;
49 }
50 // n[high] != 0
51 if (d[low] == 0) {
52 if (d[high] == 0) {
53 // K X
54 // ---
55 // 0 0
56 if (var rem ?= maybe_rem) {
57 *rem = n[high] % d[low];
58 }
59 return n[high] / d[low];
60 }
61 // d[high] != 0
62 if (n[low] == 0) {
63 // K 0
64 // ---
65 // K 0
66 if (var rem ?= maybe_rem) {
67 r[high] = n[high] % d[high];
68 r[low] = 0;
69 *rem = *(&du_int)(&r[0]);
70 }
71 return n[high] / d[high];
72 }
73 // K K
74 // ---
75 // K 0
76 // if d is a power of 2
77 if ((d[high] & (d[high] - 1)) == 0) {
78 if (var rem ?= maybe_rem) {
79 r[low] = n[low];
80 r[high] = n[high] & (d[high] - 1);
81 *rem = *(&du_int)(&r[0]);
82 }
83 return n[high] >> @ctz(@typeOf(d[high]), d[high]);
84 }
85 // K K
86 // ---
87 // K 0
88 sr = @clz(su_int, d[high]) - @clz(su_int, n[high]);
89 // 0 <= sr <= n_uword_bits - 2 or sr large
90 if (sr > n_uword_bits - 2) {
91 if (var rem ?= maybe_rem) {
92 *rem = *(&du_int)(&n[0]);
93 }
94 return 0;
95 }
96 sr += 1;
97 // 1 <= sr <= n_uword_bits - 1
98 // q.all = n.all << (n_udword_bits - sr);
99 q[low] = 0;
100 q[high] = n[low] << (n_uword_bits - sr);
101 // r.all = n.all >> sr;
102 r[high] = n[high] >> sr;
103 r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
104 } else {
105 // d[low] != 0
106 if (d[high] == 0) {
107 // K X
108 // ---
109 // 0 K
110 // if d is a power of 2
111 if ((d[low] & (d[low] - 1)) == 0) {
112 if (var rem ?= maybe_rem) {
113 *rem = n[low] & (d[low] - 1);
114 }
115 if (d[low] == 1) {
116 return *(&du_int)(&n[0]);
117 }
118 sr = @ctz(@typeOf(d[low]), d[low]);
119 q[high] = n[high] >> sr;
120 q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
121 return *(&du_int)(&q[0]);
122 }
123 // K X
124 // ---
125 // 0 K
126 sr = 1 + n_uword_bits + @clz(su_int, d[low]) - @clz(su_int, n[high]);
127 // 2 <= sr <= n_udword_bits - 1
128 // q.all = n.all << (n_udword_bits - sr);
129 // r.all = n.all >> sr;
130 if (sr == n_uword_bits) {
131 q[low] = 0;
132 q[high] = n[low];
133 r[high] = 0;
134 r[low] = n[high];
135 } else if (sr < n_uword_bits) {
136 // 2 <= sr <= n_uword_bits - 1
137 q[low] = 0;
138 q[high] = n[low] << (n_uword_bits - sr);
139 r[high] = n[high] >> sr;
140 r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
141 } else {
142 // n_uword_bits + 1 <= sr <= n_udword_bits - 1
143 q[low] = n[low] << (n_udword_bits - sr);
144 q[high] = (n[high] << (n_udword_bits - sr)) |
145 (n[low] >> (sr - n_uword_bits));
146 r[high] = 0;
147 r[low] = n[high] >> (sr - n_uword_bits);
148 }
149 } else {
150 // K X
151 // ---
152 // K K
153 sr = @clz(su_int, d[high]) - @clz(su_int, n[high]);
154 // 0 <= sr <= n_uword_bits - 1 or sr large
155 if (sr > n_uword_bits - 1) {
156 if (var rem ?= maybe_rem) {
157 *rem = *(&du_int)(&n[0]);
158 }
159 return 0;
160 }
161 sr += 1;
162 // 1 <= sr <= n_uword_bits
163 // q.all = n.all << (n_udword_bits - sr);
164 q[low] = 0;
165 if (sr == n_uword_bits) {
166 q[high] = n[low];
167 r[high] = 0;
168 r[low] = n[high];
169 } else {
170 q[high] = n[low] << (n_uword_bits - sr);
171 r[high] = n[high] >> sr;
172 r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
173 }
174 }
175 }
176 // Not a special case
177 // q and r are initialized with:
178 // q.all = n.all << (n_udword_bits - sr);
179 // r.all = n.all >> sr;
180 // 1 <= sr <= n_udword_bits - 1
181 var carry: su_int = 0;
182 while (sr > 0) {
183 // r:q = ((r:q) << 1) | carry
184 r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1));
185 r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1));
186 q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1));
187 q[low] = (q[low] << 1) | carry;
188 // carry = 0;
189 // if (r.all >= d.all)
190 // {
191 // r.all -= d.all;
192 // carry = 1;
193 // }
194 const s: di_int = (di_int)(*(&du_int)(&d[0]) - *(&du_int)(&r[0]) - 1) >> (n_udword_bits - 1);
195 carry = su_int(s & 1);
196 *(&du_int)(&r[0]) -= *(&du_int)(&d[0]) & u64(s);
197
198 sr -= 1;
199 }
200 *(&du_int)(&q[0]) = (*(&du_int)(&q[0]) << 1) | u64(carry);
201 if (var rem ?= maybe_rem) {
202 *rem = *(&du_int)(&r[0]);
203 }
204 return *(&du_int)(&q[0]);
205}
206
207export fn __umoddi3(a: du_int, b: du_int) -> du_int {
208 @setDebugSafety(this, false);
209
210 var r: du_int = undefined;
211 __udivmoddi4(a, b, &r);
212 return r;
213}
214
215fn test_umoddi3() {
216 @setFnTest(this, true);
217
218 test_one_umoddi3(0, 1, 0);
219 test_one_umoddi3(2, 1, 0);
220 test_one_umoddi3(0x8000000000000000, 1, 0x0);
221 test_one_umoddi3(0x8000000000000000, 2, 0x0);
222 test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1);
223}
224
225fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {
226 const r = __umoddi3(a, b);
227 assert(r == expected_r);
228}
229
230fn test_udivmoddi4() {
231 @setFnTest(this, true);
232
233 const cases = [][4]du_int {
234 []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
235 []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},
236 []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000},
237 []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF},
238 []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002},
239 []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD},
240 []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010},
241 []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF},
242 []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14},
243 []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001},
244 []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0},
245 []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000},
246 };
247
248 for (cases) |case| {
249 test_one_udivmoddi4(case[0], case[1], case[2], case[3]);
250 }
251}
252
253fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) {
254 var r: du_int = undefined;
255 const q = __udivmoddi4(a, b, &r);
256 assert(q == expected_q);
257 assert(r == expected_r);
258}
259
260fn assert(b: bool) {
261 if (!b) @unreachable();
262}
1// TODO
2//const CHAR_BIT = 8;
3//const du_int = u64;
4//const di_int = i64;
5//const si_int = c_int;
6//const su_int = c_uint;
7//
8//const udwords = [2]su_int;
9//const low = if (@compileVar("is_big_endian")) 1 else 0;
10//const high = 1 - low;
11//
12//export fn __udivdi3(a: du_int, b: du_int) -> du_int {
13// @setDebugSafety(this, false);
14// return __udivmoddi4(a, b, null);
15//}
16//
17//fn du_int_to_udwords(x: du_int) -> udwords {
18// @setDebugSafety(this, false);
19// return *(&udwords)(&x);
20//}
21//
22//export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
23// @setDebugSafety(this, false);
24//
25// const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;
26// const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;
27// var n = du_int_to_udwords(a);
28// var d = du_int_to_udwords(b);
29// var q: udwords = undefined;
30// var r: udwords = undefined;
31// var sr: c_uint = undefined;
32// // special cases, X is unknown, K != 0
33// if (n[high] == 0) {
34// if (d[high] == 0) {
35// // 0 X
36// // ---
37// // 0 X
38// if (const rem ?= maybe_rem) {
39// *rem = n[low] % d[low];
40// }
41// return n[low] / d[low];
42// }
43// // 0 X
44// // ---
45// // K X
46// if (const rem ?= maybe_rem) {
47// *rem = n[low];
48// }
49// return 0;
50// }
51// // n[high] != 0
52// if (d[low] == 0) {
53// if (d[high] == 0) {
54// // K X
55// // ---
56// // 0 0
57// if (var rem ?= maybe_rem) {
58// *rem = n[high] % d[low];
59// }
60// return n[high] / d[low];
61// }
62// // d[high] != 0
63// if (n[low] == 0) {
64// // K 0
65// // ---
66// // K 0
67// if (var rem ?= maybe_rem) {
68// r[high] = n[high] % d[high];
69// r[low] = 0;
70// *rem = *(&du_int)(&r[0]);
71// }
72// return n[high] / d[high];
73// }
74// // K K
75// // ---
76// // K 0
77// // if d is a power of 2
78// if ((d[high] & (d[high] - 1)) == 0) {
79// if (var rem ?= maybe_rem) {
80// r[low] = n[low];
81// r[high] = n[high] & (d[high] - 1);
82// *rem = *(&du_int)(&r[0]);
83// }
84// return n[high] >> @ctz(@typeOf(d[high]), d[high]);
85// }
86// // K K
87// // ---
88// // K 0
89// sr = @clz(su_int, d[high]) - @clz(su_int, n[high]);
90// // 0 <= sr <= n_uword_bits - 2 or sr large
91// if (sr > n_uword_bits - 2) {
92// if (var rem ?= maybe_rem) {
93// *rem = *(&du_int)(&n[0]);
94// }
95// return 0;
96// }
97// sr += 1;
98// // 1 <= sr <= n_uword_bits - 1
99// // q.all = n.all << (n_udword_bits - sr);
100// q[low] = 0;
101// q[high] = n[low] << (n_uword_bits - sr);
102// // r.all = n.all >> sr;
103// r[high] = n[high] >> sr;
104// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
105// } else {
106// // d[low] != 0
107// if (d[high] == 0) {
108// // K X
109// // ---
110// // 0 K
111// // if d is a power of 2
112// if ((d[low] & (d[low] - 1)) == 0) {
113// if (var rem ?= maybe_rem) {
114// *rem = n[low] & (d[low] - 1);
115// }
116// if (d[low] == 1) {
117// return *(&du_int)(&n[0]);
118// }
119// sr = @ctz(@typeOf(d[low]), d[low]);
120// q[high] = n[high] >> sr;
121// q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
122// return *(&du_int)(&q[0]);
123// }
124// // K X
125// // ---
126// // 0 K
127// sr = 1 + n_uword_bits + @clz(su_int, d[low]) - @clz(su_int, n[high]);
128// // 2 <= sr <= n_udword_bits - 1
129// // q.all = n.all << (n_udword_bits - sr);
130// // r.all = n.all >> sr;
131// if (sr == n_uword_bits) {
132// q[low] = 0;
133// q[high] = n[low];
134// r[high] = 0;
135// r[low] = n[high];
136// } else if (sr < n_uword_bits) {
137// // 2 <= sr <= n_uword_bits - 1
138// q[low] = 0;
139// q[high] = n[low] << (n_uword_bits - sr);
140// r[high] = n[high] >> sr;
141// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
142// } else {
143// // n_uword_bits + 1 <= sr <= n_udword_bits - 1
144// q[low] = n[low] << (n_udword_bits - sr);
145// q[high] = (n[high] << (n_udword_bits - sr)) |
146// (n[low] >> (sr - n_uword_bits));
147// r[high] = 0;
148// r[low] = n[high] >> (sr - n_uword_bits);
149// }
150// } else {
151// // K X
152// // ---
153// // K K
154// sr = @clz(su_int, d[high]) - @clz(su_int, n[high]);
155// // 0 <= sr <= n_uword_bits - 1 or sr large
156// if (sr > n_uword_bits - 1) {
157// if (var rem ?= maybe_rem) {
158// *rem = *(&du_int)(&n[0]);
159// }
160// return 0;
161// }
162// sr += 1;
163// // 1 <= sr <= n_uword_bits
164// // q.all = n.all << (n_udword_bits - sr);
165// q[low] = 0;
166// if (sr == n_uword_bits) {
167// q[high] = n[low];
168// r[high] = 0;
169// r[low] = n[high];
170// } else {
171// q[high] = n[low] << (n_uword_bits - sr);
172// r[high] = n[high] >> sr;
173// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
174// }
175// }
176// }
177// // Not a special case
178// // q and r are initialized with:
179// // q.all = n.all << (n_udword_bits - sr);
180// // r.all = n.all >> sr;
181// // 1 <= sr <= n_udword_bits - 1
182// var carry: su_int = 0;
183// while (sr > 0) {
184// // r:q = ((r:q) << 1) | carry
185// r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1));
186// r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1));
187// q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1));
188// q[low] = (q[low] << 1) | carry;
189// // carry = 0;
190// // if (r.all >= d.all)
191// // {
192// // r.all -= d.all;
193// // carry = 1;
194// // }
195// const s: di_int = (di_int)(*(&du_int)(&d[0]) - *(&du_int)(&r[0]) - 1) >> (n_udword_bits - 1);
196// carry = su_int(s & 1);
197// *(&du_int)(&r[0]) -= *(&du_int)(&d[0]) & u64(s);
198//
199// sr -= 1;
200// }
201// *(&du_int)(&q[0]) = (*(&du_int)(&q[0]) << 1) | u64(carry);
202// if (var rem ?= maybe_rem) {
203// *rem = *(&du_int)(&r[0]);
204// }
205// return *(&du_int)(&q[0]);
206//}
207//
208//export fn __umoddi3(a: du_int, b: du_int) -> du_int {
209// @setDebugSafety(this, false);
210//
211// var r: du_int = undefined;
212// __udivmoddi4(a, b, &r);
213// return r;
214//}
215//
216//fn test_umoddi3() {
217// @setFnTest(this, true);
218//
219// test_one_umoddi3(0, 1, 0);
220// test_one_umoddi3(2, 1, 0);
221// test_one_umoddi3(0x8000000000000000, 1, 0x0);
222// test_one_umoddi3(0x8000000000000000, 2, 0x0);
223// test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1);
224//}
225//
226//fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {
227// const r = __umoddi3(a, b);
228// assert(r == expected_r);
229//}
230//
231//fn test_udivmoddi4() {
232// @setFnTest(this, true);
233//
234// const cases = [][4]du_int {
235// []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
236// []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},
237// []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000},
238// []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF},
239// []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002},
240// []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD},
241// []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010},
242// []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF},
243// []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14},
244// []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001},
245// []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0},
246// []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000},
247// };
248//
249// for (cases) |case| {
250// test_one_udivmoddi4(case[0], case[1], case[2], case[3]);
251// }
252//}
253//
254//fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) {
255// var r: du_int = undefined;
256// const q = __udivmoddi4(a, b, &r);
257// assert(q == expected_q);
258// assert(r == expected_r);
259//}
260//
261//fn assert(b: bool) {
262// if (!b) @unreachable();
263//}
test/self_hosted2.zig+17-1
......@@ -1,13 +1,29 @@
11pub const SYS_write = 1;
22pub const SYS_exit = 60;
33pub const stdout_fileno = 1;
4const text = "hello\n";
4
5// normal comment
6/// this is a documentation comment
7/// doc comment line 2
8fn emptyFunctionWithComments() {
9}
10
11export fn disabledExternFn() {
12 @setFnVisible(this, false);
13}
14
15fn runAllTests() {
16 emptyFunctionWithComments();
17 disabledExternFn();
18}
519
620export nakedcc fn _start() -> unreachable {
721 myMain();
822}
923
1024fn myMain() -> unreachable {
25 runAllTests();
26 const text = "OK\n";
1127 write(stdout_fileno, &text[0], text.len);
1228 exit(0);
1329}