From a2257e4b81764f8603a39b74eae3622651ec7d6b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 21 Nov 2016 15:36:25 -0500 Subject: [PATCH] IR: implement setFnVisible builtin --- src/all_types.hpp | 8 + src/codegen.cpp | 1 + src/ir.cpp | 113 +++++---- src/ir_print.cpp | 11 + std/compiler_rt.zig | 525 +++++++++++++++++++++--------------------- test/self_hosted2.zig | 18 +- 6 files changed, 371 insertions(+), 305 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index a1325a5fdd..882a4d5210 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1448,6 +1448,7 @@ enum IrInstructionId { IrInstructionIdToPtrType, IrInstructionIdPtrTypeChild, IrInstructionIdSetFnTest, + IrInstructionIdSetFnVisible, IrInstructionIdSetDebugSafety, IrInstructionIdArrayType, IrInstructionIdSliceType, @@ -1712,6 +1713,13 @@ struct IrInstructionSetFnTest { IrInstruction *is_test; }; +struct IrInstructionSetFnVisible { + IrInstruction base; + + IrInstruction *fn_value; + IrInstruction *is_visible; +}; + struct IrInstructionSetDebugSafety { IrInstruction base; diff --git a/src/codegen.cpp b/src/codegen.cpp index 45cdd400c4..541bb500eb 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1649,6 +1649,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdPtrTypeChild: case IrInstructionIdFieldPtr: case IrInstructionIdSetFnTest: + case IrInstructionIdSetFnVisible: case IrInstructionIdSetDebugSafety: case IrInstructionIdArrayType: case IrInstructionIdSliceType: diff --git a/src/ir.cpp b/src/ir.cpp index 47f0b9f233..7ed8d8388d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -202,6 +202,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) { return IrInstructionIdSetFnTest; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnVisible *) { + return IrInstructionIdSetFnVisible; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) { return IrInstructionIdSetDebugSafety; } @@ -808,6 +812,19 @@ static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node, return &instruction->base; } +static IrInstruction *ir_build_set_fn_visible(IrBuilder *irb, AstNode *source_node, IrInstruction *fn_value, + IrInstruction *is_visible) +{ + IrInstructionSetFnVisible *instruction = ir_build_instruction(irb, source_node); + instruction->fn_value = fn_value; + instruction->is_visible = is_visible; + + ir_ref_instruction(fn_value); + ir_ref_instruction(is_visible); + + return &instruction->base; +} + static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, AstNode *source_node, IrInstruction *scope_value, IrInstruction *debug_safety_on) { @@ -1432,6 +1449,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { return ir_build_set_fn_test(irb, node, arg0_value, arg1_value); } + case BuiltinFnIdSetFnVisible: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, node->block_context); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + return ir_build_set_fn_visible(irb, node, arg0_value, arg1_value); + } case BuiltinFnIdSetDebugSafety: { 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) { case BuiltinFnIdDivExact: case BuiltinFnIdTruncate: case BuiltinFnIdIntType: - case BuiltinFnIdSetFnVisible: case BuiltinFnIdSetFnStaticEval: case BuiltinFnIdSetFnNoInline: zig_panic("TODO IR gen more builtin functions"); @@ -4394,6 +4424,43 @@ static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira, return ira->codegen->builtin_types.entry_void; } +static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira, + IrInstructionSetFnVisible *set_fn_visible_instruction) +{ + IrInstruction *fn_value = set_fn_visible_instruction->fn_value->other; + IrInstruction *is_visible_value = set_fn_visible_instruction->is_visible->other; + + FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value); + if (!fn_entry) + return ira->codegen->builtin_types.entry_invalid; + + bool want_export; + if (!ir_resolve_bool(ira, is_visible_value, &want_export)) + return ira->codegen->builtin_types.entry_invalid; + + AstNode *source_node = set_fn_visible_instruction->base.source_node; + if (fn_entry->fn_export_set_node) { + ErrorMsg *msg = add_node_error(ira->codegen, source_node, + buf_sprintf("function visibility set twice")); + add_error_note(ira->codegen, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here")); + return ira->codegen->builtin_types.entry_invalid; + } + fn_entry->fn_export_set_node = source_node; + + AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto; + if (fn_proto->top_level_decl.visib_mod != VisibModExport) { + ErrorMsg *msg = add_node_error(ira->codegen, source_node, + buf_sprintf("function must be marked export to set function visibility")); + add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("function declared here")); + return ira->codegen->builtin_types.entry_invalid; + } + if (!want_export) + LLVMSetLinkage(fn_entry->fn_value, LLVMInternalLinkage); + + ir_build_const_from(ira, &set_fn_visible_instruction->base, false); + return ira->codegen->builtin_types.entry_void; +} + static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, IrInstructionSetDebugSafety *set_debug_safety_instruction) { @@ -4847,6 +4914,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); case IrInstructionIdSetFnTest: return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction); + case IrInstructionIdSetFnVisible: + return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction); case IrInstructionIdSetDebugSafety: return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); case IrInstructionIdSliceType: @@ -4957,6 +5026,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdReturn: case IrInstructionIdUnreachable: case IrInstructionIdSetFnTest: + case IrInstructionIdSetFnVisible: case IrInstructionIdSetDebugSafety: return true; case IrInstructionIdPhi: @@ -5523,44 +5593,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { // return g->builtin_types.entry_void; //} // -//static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import, -// BlockContext *context, AstNode *node) -//{ -// AstNode **fn_node = &node->data.fn_call_expr.params.at(0); -// AstNode **value_node = &node->data.fn_call_expr.params.at(1); -// -// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); -// if (!fn_entry) { -// return g->builtin_types.entry_invalid; -// } -// -// bool want_export; -// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export); -// if (!ok) { -// return g->builtin_types.entry_invalid; -// } -// -// if (fn_entry->fn_export_set_node) { -// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice")); -// add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here")); -// return g->builtin_types.entry_invalid; -// } -// fn_entry->fn_export_set_node = node; -// -// AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto; -// if (fn_proto->top_level_decl.visib_mod != VisibModExport) { -// ErrorMsg *msg = add_node_error(g, node, -// buf_sprintf("function must be marked export to set function visibility")); -// add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here")); -// return g->builtin_types.entry_void; -// } -// if (!want_export) { -// fn_proto->top_level_decl.visib_mod = VisibModPub; -// } -// -// return g->builtin_types.entry_void; -//} -// //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, // TypeTableEntry *expected_type, AstNode *node) //{ @@ -5784,8 +5816,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { // return analyze_set_fn_no_inline(g, import, context, node); // case BuiltinFnIdSetFnStaticEval: // return analyze_set_fn_static_eval(g, import, context, node); -// case BuiltinFnIdSetFnVisible: -// return analyze_set_fn_visible(g, import, context, node); // } // zig_unreachable(); //} @@ -8310,7 +8340,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no // case BuiltinFnIdUnreachable: // zig_panic("moved to ir render"); // case BuiltinFnIdSetFnTest: -// case BuiltinFnIdSetFnVisible: // case BuiltinFnIdSetFnStaticEval: // case BuiltinFnIdSetFnNoInline: // case BuiltinFnIdSetDebugSafety: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index b51adaf7d6..d48cc9fcab 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -425,6 +425,14 @@ static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instructi fprintf(irp->f, ")"); } +static void ir_print_set_fn_visible(IrPrint *irp, IrInstructionSetFnVisible *instruction) { + fprintf(irp->f, "@setFnVisible("); + ir_print_other_instruction(irp, instruction->fn_value); + fprintf(irp->f, ", "); + ir_print_other_instruction(irp, instruction->is_visible); + fprintf(irp->f, ")"); +} + static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) { fprintf(irp->f, "@setDebugSafety("); ir_print_other_instruction(irp, instruction->scope_value); @@ -603,6 +611,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdSetFnTest: ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction); break; + case IrInstructionIdSetFnVisible: + ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction); + break; case IrInstructionIdSetDebugSafety: ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction); break; diff --git a/std/compiler_rt.zig b/std/compiler_rt.zig index b27da3b3de..f94ccfe6b9 100644 --- a/std/compiler_rt.zig +++ b/std/compiler_rt.zig @@ -1,262 +1,263 @@ -const CHAR_BIT = 8; -const du_int = u64; -const di_int = i64; -const si_int = c_int; -const su_int = c_uint; - -const udwords = [2]su_int; -const low = if (@compileVar("is_big_endian")) 1 else 0; -const high = 1 - low; - -export fn __udivdi3(a: du_int, b: du_int) -> du_int { - @setDebugSafety(this, false); - return __udivmoddi4(a, b, null); -} - -fn du_int_to_udwords(x: du_int) -> udwords { - @setDebugSafety(this, false); - return *(&udwords)(&x); -} - -export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { - @setDebugSafety(this, false); - - const n_uword_bits = @sizeOf(su_int) * CHAR_BIT; - const n_udword_bits = @sizeOf(du_int) * CHAR_BIT; - var n = du_int_to_udwords(a); - var d = du_int_to_udwords(b); - var q: udwords = undefined; - var r: udwords = undefined; - var sr: c_uint = undefined; - // special cases, X is unknown, K != 0 - if (n[high] == 0) { - if (d[high] == 0) { - // 0 X - // --- - // 0 X - if (const rem ?= maybe_rem) { - *rem = n[low] % d[low]; - } - return n[low] / d[low]; - } - // 0 X - // --- - // K X - if (const rem ?= maybe_rem) { - *rem = n[low]; - } - return 0; - } - // n[high] != 0 - if (d[low] == 0) { - if (d[high] == 0) { - // K X - // --- - // 0 0 - if (var rem ?= maybe_rem) { - *rem = n[high] % d[low]; - } - return n[high] / d[low]; - } - // d[high] != 0 - if (n[low] == 0) { - // K 0 - // --- - // K 0 - if (var rem ?= maybe_rem) { - r[high] = n[high] % d[high]; - r[low] = 0; - *rem = *(&du_int)(&r[0]); - } - return n[high] / d[high]; - } - // K K - // --- - // K 0 - // if d is a power of 2 - if ((d[high] & (d[high] - 1)) == 0) { - if (var rem ?= maybe_rem) { - r[low] = n[low]; - r[high] = n[high] & (d[high] - 1); - *rem = *(&du_int)(&r[0]); - } - return n[high] >> @ctz(@typeOf(d[high]), d[high]); - } - // K K - // --- - // K 0 - sr = @clz(su_int, d[high]) - @clz(su_int, n[high]); - // 0 <= sr <= n_uword_bits - 2 or sr large - if (sr > n_uword_bits - 2) { - if (var rem ?= maybe_rem) { - *rem = *(&du_int)(&n[0]); - } - return 0; - } - sr += 1; - // 1 <= sr <= n_uword_bits - 1 - // q.all = n.all << (n_udword_bits - sr); - q[low] = 0; - q[high] = n[low] << (n_uword_bits - sr); - // r.all = n.all >> sr; - r[high] = n[high] >> sr; - r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); - } else { - // d[low] != 0 - if (d[high] == 0) { - // K X - // --- - // 0 K - // if d is a power of 2 - if ((d[low] & (d[low] - 1)) == 0) { - if (var rem ?= maybe_rem) { - *rem = n[low] & (d[low] - 1); - } - if (d[low] == 1) { - return *(&du_int)(&n[0]); - } - sr = @ctz(@typeOf(d[low]), d[low]); - q[high] = n[high] >> sr; - q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); - return *(&du_int)(&q[0]); - } - // K X - // --- - // 0 K - sr = 1 + n_uword_bits + @clz(su_int, d[low]) - @clz(su_int, n[high]); - // 2 <= sr <= n_udword_bits - 1 - // q.all = n.all << (n_udword_bits - sr); - // r.all = n.all >> sr; - if (sr == n_uword_bits) { - q[low] = 0; - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - } else if (sr < n_uword_bits) { - // 2 <= sr <= n_uword_bits - 1 - q[low] = 0; - q[high] = n[low] << (n_uword_bits - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); - } else { - // n_uword_bits + 1 <= sr <= n_udword_bits - 1 - q[low] = n[low] << (n_udword_bits - sr); - q[high] = (n[high] << (n_udword_bits - sr)) | - (n[low] >> (sr - n_uword_bits)); - r[high] = 0; - r[low] = n[high] >> (sr - n_uword_bits); - } - } else { - // K X - // --- - // K K - sr = @clz(su_int, d[high]) - @clz(su_int, n[high]); - // 0 <= sr <= n_uword_bits - 1 or sr large - if (sr > n_uword_bits - 1) { - if (var rem ?= maybe_rem) { - *rem = *(&du_int)(&n[0]); - } - return 0; - } - sr += 1; - // 1 <= sr <= n_uword_bits - // q.all = n.all << (n_udword_bits - sr); - q[low] = 0; - if (sr == n_uword_bits) { - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - } else { - q[high] = n[low] << (n_uword_bits - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); - } - } - } - // Not a special case - // q and r are initialized with: - // q.all = n.all << (n_udword_bits - sr); - // r.all = n.all >> sr; - // 1 <= sr <= n_udword_bits - 1 - var carry: su_int = 0; - while (sr > 0) { - // r:q = ((r:q) << 1) | carry - r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1)); - r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1)); - q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1)); - q[low] = (q[low] << 1) | carry; - // carry = 0; - // if (r.all >= d.all) - // { - // r.all -= d.all; - // carry = 1; - // } - const s: di_int = (di_int)(*(&du_int)(&d[0]) - *(&du_int)(&r[0]) - 1) >> (n_udword_bits - 1); - carry = su_int(s & 1); - *(&du_int)(&r[0]) -= *(&du_int)(&d[0]) & u64(s); - - sr -= 1; - } - *(&du_int)(&q[0]) = (*(&du_int)(&q[0]) << 1) | u64(carry); - if (var rem ?= maybe_rem) { - *rem = *(&du_int)(&r[0]); - } - return *(&du_int)(&q[0]); -} - -export fn __umoddi3(a: du_int, b: du_int) -> du_int { - @setDebugSafety(this, false); - - var r: du_int = undefined; - __udivmoddi4(a, b, &r); - return r; -} - -fn test_umoddi3() { - @setFnTest(this, true); - - test_one_umoddi3(0, 1, 0); - test_one_umoddi3(2, 1, 0); - test_one_umoddi3(0x8000000000000000, 1, 0x0); - test_one_umoddi3(0x8000000000000000, 2, 0x0); - test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1); -} - -fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) { - const r = __umoddi3(a, b); - assert(r == expected_r); -} - -fn test_udivmoddi4() { - @setFnTest(this, true); - - const cases = [][4]du_int { - []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000}, - []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000}, - []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000}, - []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF}, - []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002}, - []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD}, - []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010}, - []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF}, - []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14}, - []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001}, - []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0}, - []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000}, - }; - - for (cases) |case| { - test_one_udivmoddi4(case[0], case[1], case[2], case[3]); - } -} - -fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) { - var r: du_int = undefined; - const q = __udivmoddi4(a, b, &r); - assert(q == expected_q); - assert(r == expected_r); -} - -fn assert(b: bool) { - if (!b) @unreachable(); -} +// TODO +//const CHAR_BIT = 8; +//const du_int = u64; +//const di_int = i64; +//const si_int = c_int; +//const su_int = c_uint; +// +//const udwords = [2]su_int; +//const low = if (@compileVar("is_big_endian")) 1 else 0; +//const high = 1 - low; +// +//export fn __udivdi3(a: du_int, b: du_int) -> du_int { +// @setDebugSafety(this, false); +// return __udivmoddi4(a, b, null); +//} +// +//fn du_int_to_udwords(x: du_int) -> udwords { +// @setDebugSafety(this, false); +// return *(&udwords)(&x); +//} +// +//export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { +// @setDebugSafety(this, false); +// +// const n_uword_bits = @sizeOf(su_int) * CHAR_BIT; +// const n_udword_bits = @sizeOf(du_int) * CHAR_BIT; +// var n = du_int_to_udwords(a); +// var d = du_int_to_udwords(b); +// var q: udwords = undefined; +// var r: udwords = undefined; +// var sr: c_uint = undefined; +// // special cases, X is unknown, K != 0 +// if (n[high] == 0) { +// if (d[high] == 0) { +// // 0 X +// // --- +// // 0 X +// if (const rem ?= maybe_rem) { +// *rem = n[low] % d[low]; +// } +// return n[low] / d[low]; +// } +// // 0 X +// // --- +// // K X +// if (const rem ?= maybe_rem) { +// *rem = n[low]; +// } +// return 0; +// } +// // n[high] != 0 +// if (d[low] == 0) { +// if (d[high] == 0) { +// // K X +// // --- +// // 0 0 +// if (var rem ?= maybe_rem) { +// *rem = n[high] % d[low]; +// } +// return n[high] / d[low]; +// } +// // d[high] != 0 +// if (n[low] == 0) { +// // K 0 +// // --- +// // K 0 +// if (var rem ?= maybe_rem) { +// r[high] = n[high] % d[high]; +// r[low] = 0; +// *rem = *(&du_int)(&r[0]); +// } +// return n[high] / d[high]; +// } +// // K K +// // --- +// // K 0 +// // if d is a power of 2 +// if ((d[high] & (d[high] - 1)) == 0) { +// if (var rem ?= maybe_rem) { +// r[low] = n[low]; +// r[high] = n[high] & (d[high] - 1); +// *rem = *(&du_int)(&r[0]); +// } +// return n[high] >> @ctz(@typeOf(d[high]), d[high]); +// } +// // K K +// // --- +// // K 0 +// sr = @clz(su_int, d[high]) - @clz(su_int, n[high]); +// // 0 <= sr <= n_uword_bits - 2 or sr large +// if (sr > n_uword_bits - 2) { +// if (var rem ?= maybe_rem) { +// *rem = *(&du_int)(&n[0]); +// } +// return 0; +// } +// sr += 1; +// // 1 <= sr <= n_uword_bits - 1 +// // q.all = n.all << (n_udword_bits - sr); +// q[low] = 0; +// q[high] = n[low] << (n_uword_bits - sr); +// // r.all = n.all >> sr; +// r[high] = n[high] >> sr; +// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); +// } else { +// // d[low] != 0 +// if (d[high] == 0) { +// // K X +// // --- +// // 0 K +// // if d is a power of 2 +// if ((d[low] & (d[low] - 1)) == 0) { +// if (var rem ?= maybe_rem) { +// *rem = n[low] & (d[low] - 1); +// } +// if (d[low] == 1) { +// return *(&du_int)(&n[0]); +// } +// sr = @ctz(@typeOf(d[low]), d[low]); +// q[high] = n[high] >> sr; +// q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); +// return *(&du_int)(&q[0]); +// } +// // K X +// // --- +// // 0 K +// sr = 1 + n_uword_bits + @clz(su_int, d[low]) - @clz(su_int, n[high]); +// // 2 <= sr <= n_udword_bits - 1 +// // q.all = n.all << (n_udword_bits - sr); +// // r.all = n.all >> sr; +// if (sr == n_uword_bits) { +// q[low] = 0; +// q[high] = n[low]; +// r[high] = 0; +// r[low] = n[high]; +// } else if (sr < n_uword_bits) { +// // 2 <= sr <= n_uword_bits - 1 +// q[low] = 0; +// q[high] = n[low] << (n_uword_bits - sr); +// r[high] = n[high] >> sr; +// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); +// } else { +// // n_uword_bits + 1 <= sr <= n_udword_bits - 1 +// q[low] = n[low] << (n_udword_bits - sr); +// q[high] = (n[high] << (n_udword_bits - sr)) | +// (n[low] >> (sr - n_uword_bits)); +// r[high] = 0; +// r[low] = n[high] >> (sr - n_uword_bits); +// } +// } else { +// // K X +// // --- +// // K K +// sr = @clz(su_int, d[high]) - @clz(su_int, n[high]); +// // 0 <= sr <= n_uword_bits - 1 or sr large +// if (sr > n_uword_bits - 1) { +// if (var rem ?= maybe_rem) { +// *rem = *(&du_int)(&n[0]); +// } +// return 0; +// } +// sr += 1; +// // 1 <= sr <= n_uword_bits +// // q.all = n.all << (n_udword_bits - sr); +// q[low] = 0; +// if (sr == n_uword_bits) { +// q[high] = n[low]; +// r[high] = 0; +// r[low] = n[high]; +// } else { +// q[high] = n[low] << (n_uword_bits - sr); +// r[high] = n[high] >> sr; +// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); +// } +// } +// } +// // Not a special case +// // q and r are initialized with: +// // q.all = n.all << (n_udword_bits - sr); +// // r.all = n.all >> sr; +// // 1 <= sr <= n_udword_bits - 1 +// var carry: su_int = 0; +// while (sr > 0) { +// // r:q = ((r:q) << 1) | carry +// r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1)); +// r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1)); +// q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1)); +// q[low] = (q[low] << 1) | carry; +// // carry = 0; +// // if (r.all >= d.all) +// // { +// // r.all -= d.all; +// // carry = 1; +// // } +// const s: di_int = (di_int)(*(&du_int)(&d[0]) - *(&du_int)(&r[0]) - 1) >> (n_udword_bits - 1); +// carry = su_int(s & 1); +// *(&du_int)(&r[0]) -= *(&du_int)(&d[0]) & u64(s); +// +// sr -= 1; +// } +// *(&du_int)(&q[0]) = (*(&du_int)(&q[0]) << 1) | u64(carry); +// if (var rem ?= maybe_rem) { +// *rem = *(&du_int)(&r[0]); +// } +// return *(&du_int)(&q[0]); +//} +// +//export fn __umoddi3(a: du_int, b: du_int) -> du_int { +// @setDebugSafety(this, false); +// +// var r: du_int = undefined; +// __udivmoddi4(a, b, &r); +// return r; +//} +// +//fn test_umoddi3() { +// @setFnTest(this, true); +// +// test_one_umoddi3(0, 1, 0); +// test_one_umoddi3(2, 1, 0); +// test_one_umoddi3(0x8000000000000000, 1, 0x0); +// test_one_umoddi3(0x8000000000000000, 2, 0x0); +// test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1); +//} +// +//fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) { +// const r = __umoddi3(a, b); +// assert(r == expected_r); +//} +// +//fn test_udivmoddi4() { +// @setFnTest(this, true); +// +// const cases = [][4]du_int { +// []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000}, +// []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000}, +// []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000}, +// []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF}, +// []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002}, +// []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD}, +// []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010}, +// []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF}, +// []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14}, +// []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001}, +// []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0}, +// []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000}, +// }; +// +// for (cases) |case| { +// test_one_udivmoddi4(case[0], case[1], case[2], case[3]); +// } +//} +// +//fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) { +// var r: du_int = undefined; +// const q = __udivmoddi4(a, b, &r); +// assert(q == expected_q); +// assert(r == expected_r); +//} +// +//fn assert(b: bool) { +// if (!b) @unreachable(); +//} diff --git a/test/self_hosted2.zig b/test/self_hosted2.zig index 60b12bfac8..cafec36d1c 100644 --- a/test/self_hosted2.zig +++ b/test/self_hosted2.zig @@ -1,13 +1,29 @@ pub const SYS_write = 1; pub const SYS_exit = 60; pub const stdout_fileno = 1; -const text = "hello\n"; + +// normal comment +/// this is a documentation comment +/// doc comment line 2 +fn emptyFunctionWithComments() { +} + +export fn disabledExternFn() { + @setFnVisible(this, false); +} + +fn runAllTests() { + emptyFunctionWithComments(); + disabledExternFn(); +} export nakedcc fn _start() -> unreachable { myMain(); } fn myMain() -> unreachable { + runAllTests(); + const text = "OK\n"; write(stdout_fileno, &text[0], text.len); exit(0); }