authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-21 13:27:44-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-21 13:27:44-05:00
log67d565136abd904b67792ae61f195a4054463b00
tree9d2628a827deae7688e595a69b0e30215e1714a4
parent71d95c6597bbca6ef44ba8a2a401c28c19a32bbb

IR: implement ctz and clz builtins


7 files changed, 270 insertions(+), 100 deletions(-)

doc/langref.md+2-2
......@@ -538,12 +538,12 @@ expression is not known at compile time.
538538
539539The result of the function is the result of the expression.
540540
541### @ctz(inline T: type, x: T) -> T
541### @ctz(x: T) -> T
542542
543543This function counts the number of trailing zeroes in x which is an integer
544544type T.
545545
546### @clz(inline T: type, x: T) -> T
546### @clz(x: T) -> T
547547
548548This function counts the number of leading zeroes in x which is an integer
549549type T.
src/all_types.hpp+14
......@@ -1455,6 +1455,8 @@ enum IrInstructionId {
14551455 IrInstructionIdSizeOf,
14561456 IrInstructionIdTestNull,
14571457 IrInstructionIdUnwrapMaybe,
1458 IrInstructionIdClz,
1459 IrInstructionIdCtz,
14581460};
14591461
14601462struct IrInstruction {
......@@ -1766,6 +1768,18 @@ struct IrInstructionUnwrapMaybe {
17661768 bool safety_check_on;
17671769};
17681770
1771struct IrInstructionCtz {
1772 IrInstruction base;
1773
1774 IrInstruction *value;
1775};
1776
1777struct IrInstructionClz {
1778 IrInstruction base;
1779
1780 IrInstruction *value;
1781};
1782
17691783enum LValPurpose {
17701784 LValPurposeNone,
17711785 LValPurposeAssign,
src/bignum.cpp+34
......@@ -360,3 +360,37 @@ bool bignum_multiply_by_scalar(BigNum *bignum, uint64_t scalar) {
360360 assert(!bignum->is_negative);
361361 return __builtin_umulll_overflow(bignum->data.x_uint, scalar, &bignum->data.x_uint);
362362}
363
364uint32_t bignum_ctz(BigNum *bignum, uint32_t bit_count) {
365 assert(bignum->kind == BigNumKindInt);
366
367 uint64_t x = bignum_to_twos_complement(bignum);
368 uint32_t result = 0;
369 for (uint32_t i = 0; i < bit_count; i += 1) {
370 if ((x & 0x1) != 0)
371 break;
372
373 result += 1;
374 x = x >> 1;
375 }
376 return result;
377}
378
379uint32_t bignum_clz(BigNum *bignum, uint32_t bit_count) {
380 assert(bignum->kind == BigNumKindInt);
381
382 if (bit_count == 0)
383 return 0;
384
385 uint64_t x = bignum_to_twos_complement(bignum);
386 uint64_t mask = ((uint64_t)1) << ((uint64_t)bit_count - 1);
387 uint32_t result = 0;
388 for (uint32_t i = 0; i < bit_count; i += 1) {
389 if ((x & mask) != 0)
390 break;
391
392 result += 1;
393 x = x << 1;
394 }
395 return result;
396}
src/bignum.hpp+3
......@@ -66,4 +66,7 @@ bool bignum_multiply_by_scalar(BigNum *bignum, uint64_t scalar);
6666struct Buf;
6767Buf *bignum_to_buf(BigNum *bn);
6868
69uint32_t bignum_ctz(BigNum *bignum, uint32_t bit_count);
70uint32_t bignum_clz(BigNum *bignum, uint32_t bit_count);
71
6972#endif
src/codegen.cpp+46-2
......@@ -1478,6 +1478,46 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
14781478 }
14791479}
14801480
1481static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, BuiltinFnId fn_id) {
1482 // [0-ctz,1-clz][0-8,1-16,2-32,3-64]
1483 size_t index0 = (fn_id == BuiltinFnIdCtz) ? 0 : 1;
1484 size_t index1 = bits_index(int_type->data.integral.bit_count);
1485 LLVMValueRef *fn = &g->int_builtin_fns[index0][index1];
1486 if (!*fn) {
1487 const char *fn_name = (fn_id == BuiltinFnIdCtz) ? "cttz" : "ctlz";
1488 Buf *llvm_name = buf_sprintf("llvm.%s.i%zu", fn_name, int_type->data.integral.bit_count);
1489 LLVMTypeRef param_types[] = {
1490 int_type->type_ref,
1491 LLVMInt1Type(),
1492 };
1493 LLVMTypeRef fn_type = LLVMFunctionType(int_type->type_ref, param_types, 2, false);
1494 *fn = LLVMAddFunction(g->module, buf_ptr(llvm_name), fn_type);
1495 }
1496 return *fn;
1497}
1498
1499static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstructionClz *instruction) {
1500 TypeTableEntry *int_type = instruction->base.type_entry;
1501 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz);
1502 LLVMValueRef operand = ir_llvm_value(g, instruction->value);
1503 LLVMValueRef params[] {
1504 operand,
1505 LLVMConstNull(LLVMInt1Type()),
1506 };
1507 return LLVMBuildCall(g->builder, fn_val, params, 2, "");
1508}
1509
1510static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstructionCtz *instruction) {
1511 TypeTableEntry *int_type = instruction->base.type_entry;
1512 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz);
1513 LLVMValueRef operand = ir_llvm_value(g, instruction->value);
1514 LLVMValueRef params[] {
1515 operand,
1516 LLVMConstNull(LLVMInt1Type()),
1517 };
1518 return LLVMBuildCall(g->builder, fn_val, params, 2, "");
1519}
1520
14811521static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
14821522 set_debug_source_node(g, instruction->source_node);
14831523
......@@ -1529,6 +1569,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
15291569 return ir_render_test_null(g, executable, (IrInstructionTestNull *)instruction);
15301570 case IrInstructionIdUnwrapMaybe:
15311571 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapMaybe *)instruction);
1572 case IrInstructionIdClz:
1573 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
1574 case IrInstructionIdCtz:
1575 return ir_render_ctz(g, executable, (IrInstructionCtz *)instruction);
15321576 case IrInstructionIdSwitchBr:
15331577 case IrInstructionIdPhi:
15341578 case IrInstructionIdContainerInitList:
......@@ -2774,8 +2818,8 @@ static void define_builtin_fns(CodeGen *g) {
27742818 create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "cUndef", 1);
27752819 create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileVar, "compileVar", 1);
27762820 create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "constEval", 1);
2777 create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 2);
2778 create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 2);
2821 create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 1);
2822 create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 1);
27792823 create_builtin_fn_with_arg_count(g, BuiltinFnIdImport, "import", 1);
27802824 create_builtin_fn_with_arg_count(g, BuiltinFnIdCImport, "cImport", 1);
27812825 create_builtin_fn_with_arg_count(g, BuiltinFnIdErrName, "errorName", 1);
src/ir.cpp+153-96
......@@ -234,6 +234,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapMaybe *) {
234234 return IrInstructionIdUnwrapMaybe;
235235}
236236
237static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
238 return IrInstructionIdClz;
239}
240
241static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) {
242 return IrInstructionIdCtz;
243}
244
237245template<typename T>
238246static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
239247 T *special_instruction = allocate<T>(1);
......@@ -924,6 +932,36 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction *
924932 return new_instruction;
925933}
926934
935static IrInstruction *ir_build_clz(IrBuilder *irb, AstNode *source_node, IrInstruction *value) {
936 IrInstructionClz *instruction = ir_build_instruction<IrInstructionClz>(irb, source_node);
937 instruction->value = value;
938
939 ir_ref_instruction(value);
940
941 return &instruction->base;
942}
943
944static IrInstruction *ir_build_clz_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
945 IrInstruction *new_instruction = ir_build_clz(irb, old_instruction->source_node, value);
946 ir_link_new_instruction(new_instruction, old_instruction);
947 return new_instruction;
948}
949
950static IrInstruction *ir_build_ctz(IrBuilder *irb, AstNode *source_node, IrInstruction *value) {
951 IrInstructionCtz *instruction = ir_build_instruction<IrInstructionCtz>(irb, source_node);
952 instruction->value = value;
953
954 ir_ref_instruction(value);
955
956 return &instruction->base;
957}
958
959static IrInstruction *ir_build_ctz_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value) {
960 IrInstruction *new_instruction = ir_build_ctz(irb, old_instruction->source_node, value);
961 ir_link_new_instruction(new_instruction, old_instruction);
962 return new_instruction;
963}
964
927965static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
928966 bool gen_error_defers, bool gen_maybe_defers)
929967{
......@@ -964,9 +1002,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) {
9641002 return ir_build_return(irb, node, return_value);
9651003 }
9661004 case ReturnKindError:
967 zig_panic("TODO %%return");
1005 zig_panic("TODO gen IR for %%return");
9681006 case ReturnKindMaybe:
969 zig_panic("TODO ?return");
1007 zig_panic("TODO gen IR for ?return");
9701008 }
9711009 zig_unreachable();
9721010}
......@@ -1188,7 +1226,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {
11881226 case BinOpTypeArrayMult:
11891227 return ir_gen_bin_op_id(irb, node, IrBinOpArrayMult);
11901228 case BinOpTypeUnwrapMaybe:
1191 zig_panic("TODO gen IR for unwrap maybe");
1229 zig_panic("TODO gen IR for unwrap maybe binary operation");
11921230 }
11931231 zig_unreachable();
11941232}
......@@ -1357,7 +1395,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
13571395
13581396 if (builtin_fn->param_count != actual_param_count) {
13591397 add_node_error(irb->codegen, node,
1360 buf_sprintf("expected %zu arguments, got %zu",
1398 buf_sprintf("expected %zu arguments, found %zu",
13611399 builtin_fn->param_count, actual_param_count));
13621400 return irb->codegen->invalid_instruction;
13631401 }
......@@ -1423,6 +1461,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
14231461
14241462 return ir_build_size_of(irb, node, arg0_value);
14251463 }
1464 case BuiltinFnIdCtz:
1465 {
1466 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1467 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context);
1468 if (arg0_value == irb->codegen->invalid_instruction)
1469 return arg0_value;
1470
1471 return ir_build_ctz(irb, node, arg0_value);
1472 }
1473 case BuiltinFnIdClz:
1474 {
1475 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1476 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context);
1477 if (arg0_value == irb->codegen->invalid_instruction)
1478 return arg0_value;
1479
1480 return ir_build_clz(irb, node, arg0_value);
1481 }
14261482 case BuiltinFnIdMemcpy:
14271483 case BuiltinFnIdMemset:
14281484 case BuiltinFnIdAlignof:
......@@ -1438,8 +1494,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
14381494 case BuiltinFnIdCUndef:
14391495 case BuiltinFnIdCompileErr:
14401496 case BuiltinFnIdConstEval:
1441 case BuiltinFnIdCtz:
1442 case BuiltinFnIdClz:
14431497 case BuiltinFnIdImport:
14441498 case BuiltinFnIdCImport:
14451499 case BuiltinFnIdErrName:
......@@ -1547,13 +1601,17 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp
15471601 return ir_gen_prefix_op_id_lval(irb, node, op_id, LValPurposeNone);
15481602}
15491603
1550static IrInstruction *ir_gen_prefix_op_unwrap_maybe(IrBuilder *irb, AstNode *node) {
1604static IrInstruction *ir_gen_prefix_op_unwrap_maybe(IrBuilder *irb, AstNode *node, LValPurpose lval) {
15511605 AstNode *expr = node->data.prefix_op_expr.primary_expr;
1552 IrInstruction *value = ir_gen_node(irb, expr, node->block_context);
1606 IrInstruction *value = ir_gen_node_extra(irb, expr, node->block_context, LValPurposeAddressOf);
15531607 if (value == irb->codegen->invalid_instruction)
15541608 return value;
15551609
1556 return ir_build_unwrap_maybe(irb, node, value, true);
1610 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, node, value, true);
1611 if (lval == LValPurposeNone)
1612 return ir_build_load_ptr(irb, node, unwrapped_ptr);
1613 else
1614 return unwrapped_ptr;
15571615}
15581616
15591617static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node, LValPurpose lval) {
......@@ -1585,7 +1643,7 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node, LValP
15851643 case PrefixOpUnwrapError:
15861644 return ir_gen_prefix_op_id(irb, node, IrUnOpUnwrapError);
15871645 case PrefixOpUnwrapMaybe:
1588 return ir_gen_prefix_op_unwrap_maybe(irb, node);
1646 return ir_gen_prefix_op_unwrap_maybe(irb, node, lval);
15891647 }
15901648 zig_unreachable();
15911649}
......@@ -2349,7 +2407,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
23492407 return result;
23502408 } else {
23512409 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node,
2352 dest_type->other, value->other, cast_op);
2410 dest_type, value, cast_op);
23532411 result->type_entry = wanted_type;
23542412 if (need_alloca && source_instr->source_node->block_context->fn_entry) {
23552413 IrInstructionCast *cast_instruction = (IrInstructionCast *)result;
......@@ -2776,7 +2834,7 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,
27762834 switch (result) {
27772835 case ImplicitCastMatchResultNo:
27782836 add_node_error(ira->codegen, first_executing_node(value->source_node),
2779 buf_sprintf("expected type '%s', got '%s'",
2837 buf_sprintf("expected type '%s', found '%s'",
27802838 buf_ptr(&expected_type->name),
27812839 buf_ptr(&value->type_entry->name)));
27822840 return ira->codegen->invalid_instruction;
......@@ -3346,7 +3404,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
33463404 return ira->codegen->builtin_types.entry_invalid;
33473405 }
33483406
3349 IrInstruction *arg = call_instruction->args[0];
3407 IrInstruction *arg = call_instruction->args[0]->other;
33503408 IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, fn_ref, arg);
33513409 if (cast_instruction == ira->codegen->invalid_instruction)
33523410 return ira->codegen->builtin_types.entry_invalid;
......@@ -3701,7 +3759,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
37013759 // return type_entry->data.error.child_type;
37023760 // } else {
37033761 // add_node_error(g, *expr_node,
3704 // buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
3762 // buf_sprintf("expected error type, found '%s'", buf_ptr(&type_entry->name)));
37053763 // return g->builtin_types.entry_invalid;
37063764 // }
37073765 //}
......@@ -4175,6 +4233,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
41754233 if (ptr->static_value.special != ConstValSpecialRuntime) {
41764234 // This memory location is transforming from known at compile time to known at runtime.
41774235 // We must emit our own var ptr instruction.
4236 // TODO can we delete this code now that we have inline var?
41784237 ptr->static_value.special = ConstValSpecialRuntime;
41794238 IrInstruction *new_ptr_inst;
41804239 if (ptr->id == IrInstructionIdVarPtr) {
......@@ -4347,12 +4406,12 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
43474406 target_context = type_arg->data.unionation.block_context;
43484407 } else {
43494408 add_node_error(ira->codegen, target_instruction->source_node,
4350 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
4409 buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name)));
43514410 return ira->codegen->builtin_types.entry_invalid;
43524411 }
43534412 } else {
43544413 add_node_error(ira->codegen, target_instruction->source_node,
4355 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
4414 buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&target_type->name)));
43564415 return ira->codegen->builtin_types.entry_invalid;
43574416 }
43584417
......@@ -4682,6 +4741,54 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
46824741 return result_type;
46834742}
46844743
4744static TypeTableEntry *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
4745 IrInstruction *value = ctz_instruction->value->other;
4746 if (value->type_entry->id == TypeTableEntryIdInvalid) {
4747 return ira->codegen->builtin_types.entry_invalid;
4748 } else if (value->type_entry->id == TypeTableEntryIdInt) {
4749 if (value->static_value.special != ConstValSpecialRuntime) {
4750 uint32_t result = bignum_ctz(&value->static_value.data.x_bignum,
4751 value->type_entry->data.integral.bit_count);
4752 bool depends_on_compile_var = value->static_value.depends_on_compile_var;
4753 ConstExprValue *out_val = ir_build_const_from(ira, &ctz_instruction->base,
4754 depends_on_compile_var);
4755 bignum_init_unsigned(&out_val->data.x_bignum, result);
4756 return value->type_entry;
4757 }
4758
4759 ir_build_ctz_from(&ira->new_irb, &ctz_instruction->base, value);
4760 return value->type_entry;
4761 } else {
4762 add_node_error(ira->codegen, ctz_instruction->base.source_node,
4763 buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->type_entry->name)));
4764 return ira->codegen->builtin_types.entry_invalid;
4765 }
4766}
4767
4768static TypeTableEntry *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *clz_instruction) {
4769 IrInstruction *value = clz_instruction->value->other;
4770 if (value->type_entry->id == TypeTableEntryIdInvalid) {
4771 return ira->codegen->builtin_types.entry_invalid;
4772 } else if (value->type_entry->id == TypeTableEntryIdInt) {
4773 if (value->static_value.special != ConstValSpecialRuntime) {
4774 uint32_t result = bignum_clz(&value->static_value.data.x_bignum,
4775 value->type_entry->data.integral.bit_count);
4776 bool depends_on_compile_var = value->static_value.depends_on_compile_var;
4777 ConstExprValue *out_val = ir_build_const_from(ira, &clz_instruction->base,
4778 depends_on_compile_var);
4779 bignum_init_unsigned(&out_val->data.x_bignum, result);
4780 return value->type_entry;
4781 }
4782
4783 ir_build_clz_from(&ira->new_irb, &clz_instruction->base, value);
4784 return value->type_entry;
4785 } else {
4786 add_node_error(ira->codegen, clz_instruction->base.source_node,
4787 buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->type_entry->name)));
4788 return ira->codegen->builtin_types.entry_invalid;
4789 }
4790}
4791
46854792static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
46864793 switch (instruction->id) {
46874794 case IrInstructionIdInvalid:
......@@ -4742,6 +4849,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
47424849 return ir_analyze_instruction_test_null(ira, (IrInstructionTestNull *)instruction);
47434850 case IrInstructionIdUnwrapMaybe:
47444851 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapMaybe *)instruction);
4852 case IrInstructionIdClz:
4853 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
4854 case IrInstructionIdCtz:
4855 return ir_analyze_instruction_ctz(ira, (IrInstructionCtz *)instruction);
47454856 case IrInstructionIdSwitchBr:
47464857 case IrInstructionIdCast:
47474858 case IrInstructionIdContainerInitList:
......@@ -4854,6 +4965,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
48544965 case IrInstructionIdSizeOf:
48554966 case IrInstructionIdTestNull:
48564967 case IrInstructionIdUnwrapMaybe:
4968 case IrInstructionIdClz:
4969 case IrInstructionIdCtz:
48574970 return false;
48584971 case IrInstructionIdAsm:
48594972 {
......@@ -5117,7 +5230,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
51175230// return g->builtin_types.entry_invalid;
51185231// } else if (ptr_type->id != TypeTableEntryIdPointer) {
51195232// add_node_error(g, *ptr_arg,
5120// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name)));
5233// buf_sprintf("expected pointer argument, found '%s'", buf_ptr(&ptr_type->name)));
51215234// return g->builtin_types.entry_invalid;
51225235// }
51235236//
......@@ -5223,7 +5336,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
52235336// zig_panic("TODO");
52245337// } else {
52255338// add_node_error(g, node,
5226// buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name)));
5339// buf_sprintf("expected integer type, found '%s'", buf_ptr(&result_type->name)));
52275340// return g->builtin_types.entry_invalid;
52285341// }
52295342//}
......@@ -5243,16 +5356,16 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
52435356// return g->builtin_types.entry_invalid;
52445357// } else if (dest_type->id != TypeTableEntryIdInt) {
52455358// add_node_error(g, *op1,
5246// buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name)));
5359// buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
52475360// return g->builtin_types.entry_invalid;
52485361// } else if (src_type->id != TypeTableEntryIdInt) {
52495362// add_node_error(g, *op2,
5250// buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name)));
5363// buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_type->name)));
52515364// return g->builtin_types.entry_invalid;
52525365// } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
52535366// const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
52545367// add_node_error(g, *op2,
5255// buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name)));
5368// buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
52565369// return g->builtin_types.entry_invalid;
52575370// } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) {
52585371// add_node_error(g, *op2,
......@@ -5459,7 +5572,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
54595572// result_node);
54605573// } else {
54615574// add_node_error(g, type_node,
5462// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
5575// buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
54635576// }
54645577//
54655578// // TODO constant expression evaluation
......@@ -5479,14 +5592,14 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
54795592// dest_type->id != TypeTableEntryIdPointer)
54805593// {
54815594// add_node_error(g, dest_node,
5482// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
5595// buf_sprintf("expected pointer argument, found '%s'", buf_ptr(&dest_type->name)));
54835596// }
54845597//
54855598// if (src_type->id != TypeTableEntryIdInvalid &&
54865599// src_type->id != TypeTableEntryIdPointer)
54875600// {
54885601// add_node_error(g, src_node,
5489// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
5602// buf_sprintf("expected pointer argument, found '%s'", buf_ptr(&src_type->name)));
54905603// }
54915604//
54925605// if (dest_type->id == TypeTableEntryIdPointer &&
......@@ -5517,7 +5630,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
55175630// dest_type->id != TypeTableEntryIdPointer)
55185631// {
55195632// add_node_error(g, dest_node,
5520// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
5633// buf_sprintf("expected pointer argument, found '%s'", buf_ptr(&dest_type->name)));
55215634// }
55225635//
55235636// return builtin_fn->return_type;
......@@ -5622,29 +5735,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
56225735//
56235736// return resolved_type;
56245737// }
5625// case BuiltinFnIdCtz:
5626// case BuiltinFnIdClz:
5627// {
5628// AstNode *type_node = node->data.fn_call_expr.params.at(0);
5629// TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
5630// if (int_type->id == TypeTableEntryIdInvalid) {
5631// return int_type;
5632// } else if (int_type->id == TypeTableEntryIdInt) {
5633// AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field;
5634// TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node);
5635// if (resolved_type->id == TypeTableEntryIdInvalid) {
5636// return resolved_type;
5637// }
5638//
5639// // TODO const expr eval
5640//
5641// return resolved_type;
5642// } else {
5643// add_node_error(g, type_node,
5644// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
5645// return g->builtin_types.entry_invalid;
5646// }
5647// }
56485738// case BuiltinFnIdImport:
56495739// return analyze_import(g, import, context, node);
56505740// case BuiltinFnIdCImport:
......@@ -6192,7 +6282,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
61926282// return child_type;
61936283// } else {
61946284// add_node_error(g, op1,
6195// buf_sprintf("expected maybe type, got '%s'",
6285// buf_sprintf("expected maybe type, found '%s'",
61966286// buf_ptr(&lhs_type->name)));
61976287// return g->builtin_types.entry_invalid;
61986288// }
......@@ -6212,7 +6302,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
62126302// op1_type->data.pointer.child_type == g->builtin_types.entry_u8) {
62136303// child_type = op1_type->data.pointer.child_type;
62146304// } else {
6215// add_node_error(g, *op1, buf_sprintf("expected array or C string literal, got '%s'",
6305// add_node_error(g, *op1, buf_sprintf("expected array or C string literal, found '%s'",
62166306// buf_ptr(&op1_type->name)));
62176307// return g->builtin_types.entry_invalid;
62186308// }
......@@ -6223,7 +6313,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
62236313// return g->builtin_types.entry_invalid;
62246314// } else if (op2_type->id == TypeTableEntryIdArray) {
62256315// if (op2_type->data.array.child_type != child_type) {
6226// add_node_error(g, *op2, buf_sprintf("expected array of type '%s', got '%s'",
6316// add_node_error(g, *op2, buf_sprintf("expected array of type '%s', found '%s'",
62276317// buf_ptr(&child_type->name),
62286318// buf_ptr(&op2_type->name)));
62296319// return g->builtin_types.entry_invalid;
......@@ -6231,7 +6321,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
62316321// } else if (op2_type->id == TypeTableEntryIdPointer &&
62326322// op2_type->data.pointer.child_type == g->builtin_types.entry_u8) {
62336323// } else {
6234// add_node_error(g, *op2, buf_sprintf("expected array or C string literal, got '%s'",
6324// add_node_error(g, *op2, buf_sprintf("expected array or C string literal, found '%s'",
62356325// buf_ptr(&op2_type->name)));
62366326// return g->builtin_types.entry_invalid;
62376327// }
......@@ -6271,12 +6361,12 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
62716361// } else if (op1_type->id == TypeTableEntryIdPointer) {
62726362// if (!op1_val->data.x_ptr.is_c_str) {
62736363// add_node_error(g, *op1,
6274// buf_sprintf("expected array or C string literal, got '%s'",
6364// buf_sprintf("expected array or C string literal, found '%s'",
62756365// buf_ptr(&op1_type->name)));
62766366// return g->builtin_types.entry_invalid;
62776367// } else if (!op2_val->data.x_ptr.is_c_str) {
62786368// add_node_error(g, *op2,
6279// buf_sprintf("expected array or C string literal, got '%s'",
6369// buf_sprintf("expected array or C string literal, found '%s'",
62806370// buf_ptr(&op2_type->name)));
62816371// return g->builtin_types.entry_invalid;
62826372// }
......@@ -6510,12 +6600,12 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
65106600// if (call_param_count < expect_arg_count) {
65116601// ok_invocation = false;
65126602// add_node_error(g, node,
6513// buf_sprintf("expected at least %zu arguments, got %zu", src_param_count, call_param_count));
6603// buf_sprintf("expected at least %zu arguments, found %zu", src_param_count, call_param_count));
65146604// }
65156605// } else if (expect_arg_count != call_param_count) {
65166606// ok_invocation = false;
65176607// add_node_error(g, node,
6518// buf_sprintf("expected %zu arguments, got %zu", expect_arg_count, call_param_count));
6608// buf_sprintf("expected %zu arguments, found %zu", expect_arg_count, call_param_count));
65196609// }
65206610//
65216611// bool all_args_const_expr = true;
......@@ -6631,7 +6721,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
66316721//
66326722// if (src_param_count != call_param_count + struct_node_1_or_0) {
66336723// add_node_error(g, call_node,
6634// buf_sprintf("expected %zu arguments, got %zu", src_param_count - struct_node_1_or_0, call_param_count));
6724// buf_sprintf("expected %zu arguments, found %zu", src_param_count - struct_node_1_or_0, call_param_count));
66356725// return g->builtin_types.entry_invalid;
66366726// }
66376727//
......@@ -6759,7 +6849,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
67596849//
67606850// if (actual_param_count != expected_param_count) {
67616851// add_node_error(g, first_executing_node(node),
6762// buf_sprintf("expected %zu arguments, got %zu", expected_param_count, actual_param_count));
6852// buf_sprintf("expected %zu arguments, found %zu", expected_param_count, actual_param_count));
67636853// return g->builtin_types.entry_invalid;
67646854// }
67656855//
......@@ -7180,7 +7270,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
71807270// return resolved_type->data.error.child_type;
71817271// } else {
71827272// add_node_error(g, node->data.return_expr.expr,
7183// buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name)));
7273// buf_sprintf("expected error type, found '%s'", buf_ptr(&resolved_type->name)));
71847274// return g->builtin_types.entry_invalid;
71857275// }
71867276// }
......@@ -7208,7 +7298,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
72087298// return resolved_type->data.maybe.child_type;
72097299// } else {
72107300// add_node_error(g, node->data.return_expr.expr,
7211// buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));
7301// buf_sprintf("expected maybe type, found '%s'", buf_ptr(&resolved_type->name)));
72127302// return g->builtin_types.entry_invalid;
72137303// }
72147304// }
......@@ -7502,14 +7592,14 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
75027592//
75037593// if (op1_type->id != TypeTableEntryIdArray) {
75047594// add_node_error(g, *op1,
7505// buf_sprintf("expected array type, got '%s'", buf_ptr(&op1_type->name)));
7595// buf_sprintf("expected array type, found '%s'", buf_ptr(&op1_type->name)));
75067596// return g->builtin_types.entry_invalid;
75077597// }
75087598//
75097599// if (op2_type->id != TypeTableEntryIdNumLitInt &&
75107600// op2_type->id != TypeTableEntryIdInt)
75117601// {
7512// add_node_error(g, *op2, buf_sprintf("expected integer type, got '%s'", buf_ptr(&op2_type->name)));
7602// add_node_error(g, *op2, buf_sprintf("expected integer type, found '%s'", buf_ptr(&op2_type->name)));
75137603// return g->builtin_types.entry_invalid;
75147604// }
75157605//
......@@ -7576,7 +7666,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
75767666// return child_type;
75777667// } else {
75787668// add_node_error(g, op1,
7579// buf_sprintf("expected error type, got '%s'", buf_ptr(&lhs_type->name)));
7669// buf_sprintf("expected error type, found '%s'", buf_ptr(&lhs_type->name)));
75807670// return g->builtin_types.entry_invalid;
75817671// }
75827672//}
......@@ -8076,21 +8166,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
80768166// case BuiltinFnIdCompileErr:
80778167// case BuiltinFnIdIntType:
80788168// zig_unreachable();
8079// case BuiltinFnIdCtz:
8080// case BuiltinFnIdClz:
8081// {
8082// size_t fn_call_param_count = node->data.fn_call_expr.params.length;
8083// assert(fn_call_param_count == 2);
8084// TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
8085// assert(int_type->id == TypeTableEntryIdInt);
8086// LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, builtin_fn->id);
8087// LLVMValueRef operand = gen_expr(g, node->data.fn_call_expr.params.at(1));
8088// LLVMValueRef params[] {
8089// operand,
8090// LLVMConstNull(LLVMInt1Type()),
8091// };
8092// return LLVMBuildCall(g->builder, fn_val, params, 2, "");
8093// }
80948169// case BuiltinFnIdAddWithOverflow:
80958170// case BuiltinFnIdSubWithOverflow:
80968171// case BuiltinFnIdMulWithOverflow:
......@@ -9539,24 +9614,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
95399614// return gen_var_decl_raw(g, node, &node->data.variable_declaration, false, &init_val, &init_val_type, false);
95409615//}
95419616//
9542//static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, BuiltinFnId fn_id) {
9543// // [0-ctz,1-clz][0-8,1-16,2-32,3-64]
9544// size_t index0 = (fn_id == BuiltinFnIdCtz) ? 0 : 1;
9545// size_t index1 = bits_index(int_type->data.integral.bit_count);
9546// LLVMValueRef *fn = &g->int_builtin_fns[index0][index1];
9547// if (!*fn) {
9548// const char *fn_name = (fn_id == BuiltinFnIdCtz) ? "cttz" : "ctlz";
9549// Buf *llvm_name = buf_sprintf("llvm.%s.i%zu", fn_name, int_type->data.integral.bit_count);
9550// LLVMTypeRef param_types[] = {
9551// int_type->type_ref,
9552// LLVMInt1Type(),
9553// };
9554// LLVMTypeRef fn_type = LLVMFunctionType(int_type->type_ref, param_types, 2, false);
9555// *fn = LLVMAddFunction(g->module, buf_ptr(llvm_name), fn_type);
9556// }
9557// return *fn;
9558//}
9559//
95609617//static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) {
95619618// assert(node->type == NodeTypeFnCallExpr);
95629619//
src/ir_print.cpp+18
......@@ -511,6 +511,18 @@ static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapMaybe *instru
511511 }
512512}
513513
514static void ir_print_clz(IrPrint *irp, IrInstructionClz *instruction) {
515 fprintf(irp->f, "@clz(");
516 ir_print_other_instruction(irp, instruction->value);
517 fprintf(irp->f, ")");
518}
519
520static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) {
521 fprintf(irp->f, "@ctz(");
522 ir_print_other_instruction(irp, instruction->value);
523 fprintf(irp->f, ")");
524}
525
514526static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
515527 ir_print_prefix(irp, instruction);
516528 switch (instruction->id) {
......@@ -612,6 +624,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
612624 case IrInstructionIdUnwrapMaybe:
613625 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapMaybe *)instruction);
614626 break;
627 case IrInstructionIdCtz:
628 ir_print_ctz(irp, (IrInstructionCtz *)instruction);
629 break;
630 case IrInstructionIdClz:
631 ir_print_clz(irp, (IrInstructionClz *)instruction);
632 break;
615633 case IrInstructionIdSwitchBr:
616634 zig_panic("TODO print more IR instructions");
617635 }