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....@@ -538,12 +538,12 @@ expression is not known at compile time.
538538
539The result of the function is the result of the expression.539The result of the function is the result of the expression.
540540
541### @ctz(inline T: type, x: T) -> T541### @ctz(x: T) -> T
542542
543This function counts the number of trailing zeroes in x which is an integer543This function counts the number of trailing zeroes in x which is an integer
544type T.544type T.
545545
546### @clz(inline T: type, x: T) -> T546### @clz(x: T) -> T
547547
548This function counts the number of leading zeroes in x which is an integer548This function counts the number of leading zeroes in x which is an integer
549type T.549type T.
src/all_types.hpp+14
...@@ -1455,6 +1455,8 @@ enum IrInstructionId {...@@ -1455,6 +1455,8 @@ enum IrInstructionId {
1455 IrInstructionIdSizeOf,1455 IrInstructionIdSizeOf,
1456 IrInstructionIdTestNull,1456 IrInstructionIdTestNull,
1457 IrInstructionIdUnwrapMaybe,1457 IrInstructionIdUnwrapMaybe,
1458 IrInstructionIdClz,
1459 IrInstructionIdCtz,
1458};1460};
14591461
1460struct IrInstruction {1462struct IrInstruction {
...@@ -1766,6 +1768,18 @@ struct IrInstructionUnwrapMaybe {...@@ -1766,6 +1768,18 @@ struct IrInstructionUnwrapMaybe {
1766 bool safety_check_on;1768 bool safety_check_on;
1767};1769};
17681770
1771struct IrInstructionCtz {
1772 IrInstruction base;
1773
1774 IrInstruction *value;
1775};
1776
1777struct IrInstructionClz {
1778 IrInstruction base;
1779
1780 IrInstruction *value;
1781};
1782
1769enum LValPurpose {1783enum LValPurpose {
1770 LValPurposeNone,1784 LValPurposeNone,
1771 LValPurposeAssign,1785 LValPurposeAssign,
src/bignum.cpp+34
...@@ -360,3 +360,37 @@ bool bignum_multiply_by_scalar(BigNum *bignum, uint64_t scalar) {...@@ -360,3 +360,37 @@ bool bignum_multiply_by_scalar(BigNum *bignum, uint64_t scalar) {
360 assert(!bignum->is_negative);360 assert(!bignum->is_negative);
361 return __builtin_umulll_overflow(bignum->data.x_uint, scalar, &bignum->data.x_uint);361 return __builtin_umulll_overflow(bignum->data.x_uint, scalar, &bignum->data.x_uint);
362}362}
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);...@@ -66,4 +66,7 @@ bool bignum_multiply_by_scalar(BigNum *bignum, uint64_t scalar);
66struct Buf;66struct Buf;
67Buf *bignum_to_buf(BigNum *bn);67Buf *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
69#endif72#endif
src/codegen.cpp+46-2
...@@ -1478,6 +1478,46 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,...@@ -1478,6 +1478,46 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
1478 }1478 }
1479}1479}
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
1481static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {1521static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
1482 set_debug_source_node(g, instruction->source_node);1522 set_debug_source_node(g, instruction->source_node);
14831523
...@@ -1529,6 +1569,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1529,6 +1569,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1529 return ir_render_test_null(g, executable, (IrInstructionTestNull *)instruction);1569 return ir_render_test_null(g, executable, (IrInstructionTestNull *)instruction);
1530 case IrInstructionIdUnwrapMaybe:1570 case IrInstructionIdUnwrapMaybe:
1531 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapMaybe *)instruction);1571 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);
1532 case IrInstructionIdSwitchBr:1576 case IrInstructionIdSwitchBr:
1533 case IrInstructionIdPhi:1577 case IrInstructionIdPhi:
1534 case IrInstructionIdContainerInitList:1578 case IrInstructionIdContainerInitList:
...@@ -2774,8 +2818,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -2774,8 +2818,8 @@ static void define_builtin_fns(CodeGen *g) {
2774 create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "cUndef", 1);2818 create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "cUndef", 1);
2775 create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileVar, "compileVar", 1);2819 create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileVar, "compileVar", 1);
2776 create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "constEval", 1);2820 create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "constEval", 1);
2777 create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 2);2821 create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 1);
2778 create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 2);2822 create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 1);
2779 create_builtin_fn_with_arg_count(g, BuiltinFnIdImport, "import", 1);2823 create_builtin_fn_with_arg_count(g, BuiltinFnIdImport, "import", 1);
2780 create_builtin_fn_with_arg_count(g, BuiltinFnIdCImport, "cImport", 1);2824 create_builtin_fn_with_arg_count(g, BuiltinFnIdCImport, "cImport", 1);
2781 create_builtin_fn_with_arg_count(g, BuiltinFnIdErrName, "errorName", 1);2825 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 *) {...@@ -234,6 +234,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapMaybe *) {
234 return IrInstructionIdUnwrapMaybe;234 return IrInstructionIdUnwrapMaybe;
235}235}
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
237template<typename T>245template<typename T>
238static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {246static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
239 T *special_instruction = allocate<T>(1);247 T *special_instruction = allocate<T>(1);
...@@ -924,6 +932,36 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction *...@@ -924,6 +932,36 @@ static IrInstruction *ir_build_unwrap_maybe_from(IrBuilder *irb, IrInstruction *
924 return new_instruction;932 return new_instruction;
925}933}
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
927static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,965static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
928 bool gen_error_defers, bool gen_maybe_defers)966 bool gen_error_defers, bool gen_maybe_defers)
929{967{
...@@ -964,9 +1002,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) {...@@ -964,9 +1002,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) {
964 return ir_build_return(irb, node, return_value);1002 return ir_build_return(irb, node, return_value);
965 }1003 }
966 case ReturnKindError:1004 case ReturnKindError:
967 zig_panic("TODO %%return");1005 zig_panic("TODO gen IR for %%return");
968 case ReturnKindMaybe:1006 case ReturnKindMaybe:
969 zig_panic("TODO ?return");1007 zig_panic("TODO gen IR for ?return");
970 }1008 }
971 zig_unreachable();1009 zig_unreachable();
972}1010}
...@@ -1188,7 +1226,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {...@@ -1188,7 +1226,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {
1188 case BinOpTypeArrayMult:1226 case BinOpTypeArrayMult:
1189 return ir_gen_bin_op_id(irb, node, IrBinOpArrayMult);1227 return ir_gen_bin_op_id(irb, node, IrBinOpArrayMult);
1190 case BinOpTypeUnwrapMaybe:1228 case BinOpTypeUnwrapMaybe:
1191 zig_panic("TODO gen IR for unwrap maybe");1229 zig_panic("TODO gen IR for unwrap maybe binary operation");
1192 }1230 }
1193 zig_unreachable();1231 zig_unreachable();
1194}1232}
...@@ -1357,7 +1395,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {...@@ -1357,7 +1395,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
13571395
1358 if (builtin_fn->param_count != actual_param_count) {1396 if (builtin_fn->param_count != actual_param_count) {
1359 add_node_error(irb->codegen, node,1397 add_node_error(irb->codegen, node,
1360 buf_sprintf("expected %zu arguments, got %zu",1398 buf_sprintf("expected %zu arguments, found %zu",
1361 builtin_fn->param_count, actual_param_count));1399 builtin_fn->param_count, actual_param_count));
1362 return irb->codegen->invalid_instruction;1400 return irb->codegen->invalid_instruction;
1363 }1401 }
...@@ -1423,6 +1461,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {...@@ -1423,6 +1461,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
14231461
1424 return ir_build_size_of(irb, node, arg0_value);1462 return ir_build_size_of(irb, node, arg0_value);
1425 }1463 }
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 }
1426 case BuiltinFnIdMemcpy:1482 case BuiltinFnIdMemcpy:
1427 case BuiltinFnIdMemset:1483 case BuiltinFnIdMemset:
1428 case BuiltinFnIdAlignof:1484 case BuiltinFnIdAlignof:
...@@ -1438,8 +1494,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {...@@ -1438,8 +1494,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
1438 case BuiltinFnIdCUndef:1494 case BuiltinFnIdCUndef:
1439 case BuiltinFnIdCompileErr:1495 case BuiltinFnIdCompileErr:
1440 case BuiltinFnIdConstEval:1496 case BuiltinFnIdConstEval:
1441 case BuiltinFnIdCtz:
1442 case BuiltinFnIdClz:
1443 case BuiltinFnIdImport:1497 case BuiltinFnIdImport:
1444 case BuiltinFnIdCImport:1498 case BuiltinFnIdCImport:
1445 case BuiltinFnIdErrName:1499 case BuiltinFnIdErrName:
...@@ -1547,13 +1601,17 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp...@@ -1547,13 +1601,17 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp
1547 return ir_gen_prefix_op_id_lval(irb, node, op_id, LValPurposeNone);1601 return ir_gen_prefix_op_id_lval(irb, node, op_id, LValPurposeNone);
1548}1602}
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) {
1551 AstNode *expr = node->data.prefix_op_expr.primary_expr;1605 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);
1553 if (value == irb->codegen->invalid_instruction)1607 if (value == irb->codegen->invalid_instruction)
1554 return value;1608 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;
1557}1615}
15581616
1559static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node, LValPurpose lval) {1617static 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...@@ -1585,7 +1643,7 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node, LValP
1585 case PrefixOpUnwrapError:1643 case PrefixOpUnwrapError:
1586 return ir_gen_prefix_op_id(irb, node, IrUnOpUnwrapError);1644 return ir_gen_prefix_op_id(irb, node, IrUnOpUnwrapError);
1587 case PrefixOpUnwrapMaybe:1645 case PrefixOpUnwrapMaybe:
1588 return ir_gen_prefix_op_unwrap_maybe(irb, node);1646 return ir_gen_prefix_op_unwrap_maybe(irb, node, lval);
1589 }1647 }
1590 zig_unreachable();1648 zig_unreachable();
1591}1649}
...@@ -2349,7 +2407,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -2349,7 +2407,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
2349 return result;2407 return result;
2350 } else {2408 } else {
2351 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node,2409 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);
2353 result->type_entry = wanted_type;2411 result->type_entry = wanted_type;
2354 if (need_alloca && source_instr->source_node->block_context->fn_entry) {2412 if (need_alloca && source_instr->source_node->block_context->fn_entry) {
2355 IrInstructionCast *cast_instruction = (IrInstructionCast *)result;2413 IrInstructionCast *cast_instruction = (IrInstructionCast *)result;
...@@ -2776,7 +2834,7 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,...@@ -2776,7 +2834,7 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,
2776 switch (result) {2834 switch (result) {
2777 case ImplicitCastMatchResultNo:2835 case ImplicitCastMatchResultNo:
2778 add_node_error(ira->codegen, first_executing_node(value->source_node),2836 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'",
2780 buf_ptr(&expected_type->name),2838 buf_ptr(&expected_type->name),
2781 buf_ptr(&value->type_entry->name)));2839 buf_ptr(&value->type_entry->name)));
2782 return ira->codegen->invalid_instruction;2840 return ira->codegen->invalid_instruction;
...@@ -3346,7 +3404,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -3346,7 +3404,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
3346 return ira->codegen->builtin_types.entry_invalid;3404 return ira->codegen->builtin_types.entry_invalid;
3347 }3405 }
33483406
3349 IrInstruction *arg = call_instruction->args[0];3407 IrInstruction *arg = call_instruction->args[0]->other;
3350 IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, fn_ref, arg);3408 IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, fn_ref, arg);
3351 if (cast_instruction == ira->codegen->invalid_instruction)3409 if (cast_instruction == ira->codegen->invalid_instruction)
3352 return ira->codegen->builtin_types.entry_invalid;3410 return ira->codegen->builtin_types.entry_invalid;
...@@ -3701,7 +3759,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -3701,7 +3759,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
3701 // return type_entry->data.error.child_type;3759 // return type_entry->data.error.child_type;
3702 // } else {3760 // } else {
3703 // add_node_error(g, *expr_node,3761 // 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)));
3705 // return g->builtin_types.entry_invalid;3763 // return g->builtin_types.entry_invalid;
3706 // }3764 // }
3707 //}3765 //}
...@@ -4175,6 +4233,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru...@@ -4175,6 +4233,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
4175 if (ptr->static_value.special != ConstValSpecialRuntime) {4233 if (ptr->static_value.special != ConstValSpecialRuntime) {
4176 // This memory location is transforming from known at compile time to known at runtime.4234 // This memory location is transforming from known at compile time to known at runtime.
4177 // We must emit our own var ptr instruction.4235 // We must emit our own var ptr instruction.
4236 // TODO can we delete this code now that we have inline var?
4178 ptr->static_value.special = ConstValSpecialRuntime;4237 ptr->static_value.special = ConstValSpecialRuntime;
4179 IrInstruction *new_ptr_inst;4238 IrInstruction *new_ptr_inst;
4180 if (ptr->id == IrInstructionIdVarPtr) {4239 if (ptr->id == IrInstructionIdVarPtr) {
...@@ -4347,12 +4406,12 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,...@@ -4347,12 +4406,12 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
4347 target_context = type_arg->data.unionation.block_context;4406 target_context = type_arg->data.unionation.block_context;
4348 } else {4407 } else {
4349 add_node_error(ira->codegen, target_instruction->source_node,4408 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)));
4351 return ira->codegen->builtin_types.entry_invalid;4410 return ira->codegen->builtin_types.entry_invalid;
4352 }4411 }
4353 } else {4412 } else {
4354 add_node_error(ira->codegen, target_instruction->source_node,4413 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)));
4356 return ira->codegen->builtin_types.entry_invalid;4415 return ira->codegen->builtin_types.entry_invalid;
4357 }4416 }
43584417
...@@ -4682,6 +4741,54 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -4682,6 +4741,54 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
4682 return result_type;4741 return result_type;
4683}4742}
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
4685static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {4792static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
4686 switch (instruction->id) {4793 switch (instruction->id) {
4687 case IrInstructionIdInvalid:4794 case IrInstructionIdInvalid:
...@@ -4742,6 +4849,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -4742,6 +4849,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
4742 return ir_analyze_instruction_test_null(ira, (IrInstructionTestNull *)instruction);4849 return ir_analyze_instruction_test_null(ira, (IrInstructionTestNull *)instruction);
4743 case IrInstructionIdUnwrapMaybe:4850 case IrInstructionIdUnwrapMaybe:
4744 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapMaybe *)instruction);4851 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);
4745 case IrInstructionIdSwitchBr:4856 case IrInstructionIdSwitchBr:
4746 case IrInstructionIdCast:4857 case IrInstructionIdCast:
4747 case IrInstructionIdContainerInitList:4858 case IrInstructionIdContainerInitList:
...@@ -4854,6 +4965,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -4854,6 +4965,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
4854 case IrInstructionIdSizeOf:4965 case IrInstructionIdSizeOf:
4855 case IrInstructionIdTestNull:4966 case IrInstructionIdTestNull:
4856 case IrInstructionIdUnwrapMaybe:4967 case IrInstructionIdUnwrapMaybe:
4968 case IrInstructionIdClz:
4969 case IrInstructionIdCtz:
4857 return false;4970 return false;
4858 case IrInstructionIdAsm:4971 case IrInstructionIdAsm:
4859 {4972 {
...@@ -5117,7 +5230,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5117,7 +5230,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5117// return g->builtin_types.entry_invalid;5230// return g->builtin_types.entry_invalid;
5118// } else if (ptr_type->id != TypeTableEntryIdPointer) {5231// } else if (ptr_type->id != TypeTableEntryIdPointer) {
5119// add_node_error(g, *ptr_arg,5232// 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)));
5121// return g->builtin_types.entry_invalid;5234// return g->builtin_types.entry_invalid;
5122// }5235// }
5123//5236//
...@@ -5223,7 +5336,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5223,7 +5336,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5223// zig_panic("TODO");5336// zig_panic("TODO");
5224// } else {5337// } else {
5225// add_node_error(g, node,5338// 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)));
5227// return g->builtin_types.entry_invalid;5340// return g->builtin_types.entry_invalid;
5228// }5341// }
5229//}5342//}
...@@ -5243,16 +5356,16 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5243,16 +5356,16 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5243// return g->builtin_types.entry_invalid;5356// return g->builtin_types.entry_invalid;
5244// } else if (dest_type->id != TypeTableEntryIdInt) {5357// } else if (dest_type->id != TypeTableEntryIdInt) {
5245// add_node_error(g, *op1,5358// 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)));
5247// return g->builtin_types.entry_invalid;5360// return g->builtin_types.entry_invalid;
5248// } else if (src_type->id != TypeTableEntryIdInt) {5361// } else if (src_type->id != TypeTableEntryIdInt) {
5249// add_node_error(g, *op2,5362// 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)));
5251// return g->builtin_types.entry_invalid;5364// return g->builtin_types.entry_invalid;
5252// } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {5365// } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
5253// const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";5366// const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
5254// add_node_error(g, *op2,5367// 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)));
5256// return g->builtin_types.entry_invalid;5369// return g->builtin_types.entry_invalid;
5257// } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) {5370// } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) {
5258// add_node_error(g, *op2,5371// add_node_error(g, *op2,
...@@ -5459,7 +5572,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5459,7 +5572,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5459// result_node);5572// result_node);
5460// } else {5573// } else {
5461// add_node_error(g, type_node,5574// 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)));
5463// }5576// }
5464//5577//
5465// // TODO constant expression evaluation5578// // TODO constant expression evaluation
...@@ -5479,14 +5592,14 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5479,14 +5592,14 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5479// dest_type->id != TypeTableEntryIdPointer)5592// dest_type->id != TypeTableEntryIdPointer)
5480// {5593// {
5481// add_node_error(g, dest_node,5594// 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)));
5483// }5596// }
5484//5597//
5485// if (src_type->id != TypeTableEntryIdInvalid &&5598// if (src_type->id != TypeTableEntryIdInvalid &&
5486// src_type->id != TypeTableEntryIdPointer)5599// src_type->id != TypeTableEntryIdPointer)
5487// {5600// {
5488// add_node_error(g, src_node,5601// 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)));
5490// }5603// }
5491//5604//
5492// if (dest_type->id == TypeTableEntryIdPointer &&5605// if (dest_type->id == TypeTableEntryIdPointer &&
...@@ -5517,7 +5630,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5517,7 +5630,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5517// dest_type->id != TypeTableEntryIdPointer)5630// dest_type->id != TypeTableEntryIdPointer)
5518// {5631// {
5519// add_node_error(g, dest_node,5632// 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)));
5521// }5634// }
5522//5635//
5523// return builtin_fn->return_type;5636// return builtin_fn->return_type;
...@@ -5622,29 +5735,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5622,29 +5735,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5622//5735//
5623// return resolved_type;5736// return resolved_type;
5624// }5737// }
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// }
5648// case BuiltinFnIdImport:5738// case BuiltinFnIdImport:
5649// return analyze_import(g, import, context, node);5739// return analyze_import(g, import, context, node);
5650// case BuiltinFnIdCImport:5740// case BuiltinFnIdCImport:
...@@ -6192,7 +6282,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6192,7 +6282,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6192// return child_type;6282// return child_type;
6193// } else {6283// } else {
6194// add_node_error(g, op1,6284// add_node_error(g, op1,
6195// buf_sprintf("expected maybe type, got '%s'",6285// buf_sprintf("expected maybe type, found '%s'",
6196// buf_ptr(&lhs_type->name)));6286// buf_ptr(&lhs_type->name)));
6197// return g->builtin_types.entry_invalid;6287// return g->builtin_types.entry_invalid;
6198// }6288// }
...@@ -6212,7 +6302,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6212,7 +6302,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6212// op1_type->data.pointer.child_type == g->builtin_types.entry_u8) {6302// op1_type->data.pointer.child_type == g->builtin_types.entry_u8) {
6213// child_type = op1_type->data.pointer.child_type;6303// child_type = op1_type->data.pointer.child_type;
6214// } else {6304// } 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'",
6216// buf_ptr(&op1_type->name)));6306// buf_ptr(&op1_type->name)));
6217// return g->builtin_types.entry_invalid;6307// return g->builtin_types.entry_invalid;
6218// }6308// }
...@@ -6223,7 +6313,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6223,7 +6313,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6223// return g->builtin_types.entry_invalid;6313// return g->builtin_types.entry_invalid;
6224// } else if (op2_type->id == TypeTableEntryIdArray) {6314// } else if (op2_type->id == TypeTableEntryIdArray) {
6225// if (op2_type->data.array.child_type != child_type) {6315// 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'",
6227// buf_ptr(&child_type->name),6317// buf_ptr(&child_type->name),
6228// buf_ptr(&op2_type->name)));6318// buf_ptr(&op2_type->name)));
6229// return g->builtin_types.entry_invalid;6319// return g->builtin_types.entry_invalid;
...@@ -6231,7 +6321,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6231,7 +6321,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6231// } else if (op2_type->id == TypeTableEntryIdPointer &&6321// } else if (op2_type->id == TypeTableEntryIdPointer &&
6232// op2_type->data.pointer.child_type == g->builtin_types.entry_u8) {6322// op2_type->data.pointer.child_type == g->builtin_types.entry_u8) {
6233// } else {6323// } 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'",
6235// buf_ptr(&op2_type->name)));6325// buf_ptr(&op2_type->name)));
6236// return g->builtin_types.entry_invalid;6326// return g->builtin_types.entry_invalid;
6237// }6327// }
...@@ -6271,12 +6361,12 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6271,12 +6361,12 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6271// } else if (op1_type->id == TypeTableEntryIdPointer) {6361// } else if (op1_type->id == TypeTableEntryIdPointer) {
6272// if (!op1_val->data.x_ptr.is_c_str) {6362// if (!op1_val->data.x_ptr.is_c_str) {
6273// add_node_error(g, *op1,6363// 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'",
6275// buf_ptr(&op1_type->name)));6365// buf_ptr(&op1_type->name)));
6276// return g->builtin_types.entry_invalid;6366// return g->builtin_types.entry_invalid;
6277// } else if (!op2_val->data.x_ptr.is_c_str) {6367// } else if (!op2_val->data.x_ptr.is_c_str) {
6278// add_node_error(g, *op2,6368// 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'",
6280// buf_ptr(&op2_type->name)));6370// buf_ptr(&op2_type->name)));
6281// return g->builtin_types.entry_invalid;6371// return g->builtin_types.entry_invalid;
6282// }6372// }
...@@ -6510,12 +6600,12 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6510,12 +6600,12 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6510// if (call_param_count < expect_arg_count) {6600// if (call_param_count < expect_arg_count) {
6511// ok_invocation = false;6601// ok_invocation = false;
6512// add_node_error(g, node,6602// 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));
6514// }6604// }
6515// } else if (expect_arg_count != call_param_count) {6605// } else if (expect_arg_count != call_param_count) {
6516// ok_invocation = false;6606// ok_invocation = false;
6517// add_node_error(g, node,6607// 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));
6519// }6609// }
6520//6610//
6521// bool all_args_const_expr = true;6611// bool all_args_const_expr = true;
...@@ -6631,7 +6721,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6631,7 +6721,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6631//6721//
6632// if (src_param_count != call_param_count + struct_node_1_or_0) {6722// if (src_param_count != call_param_count + struct_node_1_or_0) {
6633// add_node_error(g, call_node,6723// 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));
6635// return g->builtin_types.entry_invalid;6725// return g->builtin_types.entry_invalid;
6636// }6726// }
6637//6727//
...@@ -6759,7 +6849,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -6759,7 +6849,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6759//6849//
6760// if (actual_param_count != expected_param_count) {6850// if (actual_param_count != expected_param_count) {
6761// add_node_error(g, first_executing_node(node),6851// 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));
6763// return g->builtin_types.entry_invalid;6853// return g->builtin_types.entry_invalid;
6764// }6854// }
6765//6855//
...@@ -7180,7 +7270,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -7180,7 +7270,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
7180// return resolved_type->data.error.child_type;7270// return resolved_type->data.error.child_type;
7181// } else {7271// } else {
7182// add_node_error(g, node->data.return_expr.expr,7272// 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)));
7184// return g->builtin_types.entry_invalid;7274// return g->builtin_types.entry_invalid;
7185// }7275// }
7186// }7276// }
...@@ -7208,7 +7298,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -7208,7 +7298,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
7208// return resolved_type->data.maybe.child_type;7298// return resolved_type->data.maybe.child_type;
7209// } else {7299// } else {
7210// add_node_error(g, node->data.return_expr.expr,7300// 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)));
7212// return g->builtin_types.entry_invalid;7302// return g->builtin_types.entry_invalid;
7213// }7303// }
7214// }7304// }
...@@ -7502,14 +7592,14 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -7502,14 +7592,14 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
7502//7592//
7503// if (op1_type->id != TypeTableEntryIdArray) {7593// if (op1_type->id != TypeTableEntryIdArray) {
7504// add_node_error(g, *op1,7594// 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)));
7506// return g->builtin_types.entry_invalid;7596// return g->builtin_types.entry_invalid;
7507// }7597// }
7508//7598//
7509// if (op2_type->id != TypeTableEntryIdNumLitInt &&7599// if (op2_type->id != TypeTableEntryIdNumLitInt &&
7510// op2_type->id != TypeTableEntryIdInt)7600// op2_type->id != TypeTableEntryIdInt)
7511// {7601// {
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)));
7513// return g->builtin_types.entry_invalid;7603// return g->builtin_types.entry_invalid;
7514// }7604// }
7515//7605//
...@@ -7576,7 +7666,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -7576,7 +7666,7 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
7576// return child_type;7666// return child_type;
7577// } else {7667// } else {
7578// add_node_error(g, op1,7668// 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)));
7580// return g->builtin_types.entry_invalid;7670// return g->builtin_types.entry_invalid;
7581// }7671// }
7582//}7672//}
...@@ -8076,21 +8166,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no...@@ -8076,21 +8166,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
8076// case BuiltinFnIdCompileErr:8166// case BuiltinFnIdCompileErr:
8077// case BuiltinFnIdIntType:8167// case BuiltinFnIdIntType:
8078// zig_unreachable();8168// 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// }
8094// case BuiltinFnIdAddWithOverflow:8169// case BuiltinFnIdAddWithOverflow:
8095// case BuiltinFnIdSubWithOverflow:8170// case BuiltinFnIdSubWithOverflow:
8096// case BuiltinFnIdMulWithOverflow:8171// case BuiltinFnIdMulWithOverflow:
...@@ -9539,24 +9614,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no...@@ -9539,24 +9614,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
9539// return gen_var_decl_raw(g, node, &node->data.variable_declaration, false, &init_val, &init_val_type, false);9614// return gen_var_decl_raw(g, node, &node->data.variable_declaration, false, &init_val, &init_val_type, false);
9540//}9615//}
9541//9616//
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//
9560//static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) {9617//static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) {
9561// assert(node->type == NodeTypeFnCallExpr);9618// assert(node->type == NodeTypeFnCallExpr);
9562//9619//
src/ir_print.cpp+18
...@@ -511,6 +511,18 @@ static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapMaybe *instru...@@ -511,6 +511,18 @@ static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapMaybe *instru
511 }511 }
512}512}
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
514static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {526static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
515 ir_print_prefix(irp, instruction);527 ir_print_prefix(irp, instruction);
516 switch (instruction->id) {528 switch (instruction->id) {
...@@ -612,6 +624,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -612,6 +624,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
612 case IrInstructionIdUnwrapMaybe:624 case IrInstructionIdUnwrapMaybe:
613 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapMaybe *)instruction);625 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapMaybe *)instruction);
614 break;626 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;
615 case IrInstructionIdSwitchBr:633 case IrInstructionIdSwitchBr:
616 zig_panic("TODO print more IR instructions");634 zig_panic("TODO print more IR instructions");
617 }635 }