From 1fdb24827fb51351d5e31103069619668fae31c4 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Wed, 3 Apr 2019 09:00:39 -0500 Subject: breaking changes to all bit manipulation intrinsics * `@clz`, `@ctz`, `@popCount`, `@bswap`, `@bitreverse` now have a type parameter * rename @bitreverse to @bitReverse * rename @bswap to @byteSwap Closes #2119 Closes #2120 --- src/ir.cpp | 331 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 172 insertions(+), 159 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index f70d5d475c..afb032276c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -575,6 +575,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPopCount *) { return IrInstructionIdPopCount; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) { + return IrInstructionIdBswap; +} + +static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) { + return IrInstructionIdBitReverse; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) { return IrInstructionIdUnionTag; } @@ -983,14 +991,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { return IrInstructionIdSqrt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) { - return IrInstructionIdBswap; -} - -static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) { - return IrInstructionIdBitReverse; -} - static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { return IrInstructionIdCheckRuntimeScope; } @@ -1768,29 +1768,57 @@ static IrInstruction *ir_build_err_wrap_code(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } -static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { +static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { IrInstructionClz *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; + instruction->type = type; + instruction->op = op; - ir_ref_instruction(value, irb->current_basic_block); + if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_ctz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { +static IrInstruction *ir_build_ctz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { IrInstructionCtz *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; + instruction->type = type; + instruction->op = op; - ir_ref_instruction(value, irb->current_basic_block); + if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { +static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { IrInstructionPopCount *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; + instruction->type = type; + instruction->op = op; - ir_ref_instruction(value, irb->current_basic_block); + if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { + IrInstructionBswap *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { + IrInstructionBitReverse *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); return &instruction->base; } @@ -2986,28 +3014,6 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc return &instruction->base; } -static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { - IrInstructionBswap *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { - IrInstructionBitReverse *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { IrInstructionCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node); instruction->scope_is_comptime = scope_is_comptime; @@ -4082,36 +4088,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, size_of, lval); } - case BuiltinFnIdCtz: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) - return arg0_value; - - IrInstruction *ctz = ir_build_ctz(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, ctz, lval); - } - case BuiltinFnIdPopCount: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) - return arg0_value; - - IrInstruction *instr = ir_build_pop_count(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, instr, lval); - } - case BuiltinFnIdClz: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) - return arg0_value; - - IrInstruction *clz = ir_build_clz(irb, scope, node, arg0_value); - return ir_lval_wrap(irb, scope, clz, lval); - } case BuiltinFnIdImport: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5084,21 +5060,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, result, lval); } + case BuiltinFnIdCtz: + case BuiltinFnIdPopCount: + case BuiltinFnIdClz: case BuiltinFnIdBswap: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - 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, scope); - if (arg1_value == irb->codegen->invalid_instruction) - return arg1_value; - - IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); - return ir_lval_wrap(irb, scope, result, lval); - } case BuiltinFnIdBitReverse: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5111,7 +5076,26 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (arg1_value == irb->codegen->invalid_instruction) return arg1_value; - IrInstruction *result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value); + IrInstruction *result; + switch (builtin_fn->id) { + case BuiltinFnIdCtz: + result = ir_build_ctz(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdPopCount: + result = ir_build_pop_count(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdClz: + result = ir_build_clz(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdBswap: + result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); + break; + case BuiltinFnIdBitReverse: + result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value); + break; + default: + zig_unreachable(); + } return ir_lval_wrap(irb, scope, result, lval); } } @@ -17040,92 +17024,125 @@ static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on); } -static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) { - IrInstruction *value = ctz_instruction->value->child; - if (type_is_invalid(value->value.type)) { +static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) { + ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - } else if (value->value.type->id == ZigTypeIdInt) { - ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, - value->value.type->data.integral.bit_count); - if (value->value.special != ConstValSpecialRuntime) { - size_t result_usize = bigint_ctz(&value->value.data.x_bigint, - value->value.type->data.integral.bit_count); - IrInstruction *result = ir_const(ira, &ctz_instruction->base, return_type); - bigint_init_unsigned(&result->value.data.x_bigint, result_usize); - return result; - } - IrInstruction *result = ir_build_ctz(&ira->new_irb, - ctz_instruction->base.scope, ctz_instruction->base.source_node, value); - result->value.type = return_type; - return result; - } else { - ir_add_error_node(ira, ctz_instruction->base.source_node, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name))); + IrInstruction *op = instruction->op->child; + + if (int_type->id != ZigTypeIdInt) { + ir_add_error(ira, instruction->type, + buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); return ira->codegen->invalid_instruction; } -} -static IrInstruction *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *clz_instruction) { - IrInstruction *value = clz_instruction->value->child; - if (type_is_invalid(value->value.type)) { + IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); + if (type_is_invalid(casted_op->value.type)) return ira->codegen->invalid_instruction; - } else if (value->value.type->id == ZigTypeIdInt) { - ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, - value->value.type->data.integral.bit_count); - if (value->value.special != ConstValSpecialRuntime) { - size_t result_usize = bigint_clz(&value->value.data.x_bigint, - value->value.type->data.integral.bit_count); - IrInstruction *result = ir_const(ira, &clz_instruction->base, return_type); - bigint_init_unsigned(&result->value.data.x_bigint, result_usize); - return result; - } - IrInstruction *result = ir_build_clz(&ira->new_irb, - clz_instruction->base.scope, clz_instruction->base.source_node, value); - result->value.type = return_type; + ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); + + if (int_type->data.integral.bit_count == 0) { + IrInstruction *result = ir_const(ira, &instruction->base, return_type); + bigint_init_unsigned(&result->value.data.x_bigint, 0); return result; - } else { - ir_add_error_node(ira, clz_instruction->base.source_node, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name))); + } + + if (instr_is_comptime(casted_op)) { + size_t result_usize = bigint_ctz(&op->value.data.x_bigint, + op->value.type->data.integral.bit_count); + IrInstruction *result = ir_const(ira, &instruction->base, return_type); + bigint_init_unsigned(&result->value.data.x_bigint, result_usize); + return result; + } + + IrInstruction *result = ir_build_ctz(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr, casted_op); + result->value.type = return_type; + return result; +} + +static IrInstruction *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *instruction) { + ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + if (type_is_invalid(int_type)) + return ira->codegen->invalid_instruction; + + IrInstruction *op = instruction->op->child; + + if (int_type->id != ZigTypeIdInt) { + ir_add_error(ira, instruction->type, + buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); return ira->codegen->invalid_instruction; } + + IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); + if (type_is_invalid(casted_op->value.type)) + return ira->codegen->invalid_instruction; + + ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); + + if (int_type->data.integral.bit_count == 0) { + IrInstruction *result = ir_const(ira, &instruction->base, return_type); + bigint_init_unsigned(&result->value.data.x_bigint, 0); + return result; + } + + if (instr_is_comptime(casted_op)) { + size_t result_usize = bigint_clz(&op->value.data.x_bigint, + op->value.type->data.integral.bit_count); + IrInstruction *result = ir_const(ira, &instruction->base, return_type); + bigint_init_unsigned(&result->value.data.x_bigint, result_usize); + return result; + } + + IrInstruction *result = ir_build_clz(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr, casted_op); + result->value.type = return_type; + return result; } static IrInstruction *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPopCount *instruction) { - IrInstruction *value = instruction->value->child; - if (type_is_invalid(value->value.type)) + ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - if (value->value.type->id != ZigTypeIdInt && value->value.type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, value, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&value->value.type->name))); + IrInstruction *op = instruction->op->child; + + if (int_type->id != ZigTypeIdInt) { + ir_add_error(ira, instruction->type, + buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); return ira->codegen->invalid_instruction; } - if (instr_is_comptime(value)) { - ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); + IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); + if (type_is_invalid(casted_op->value.type)) + return ira->codegen->invalid_instruction; + + ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); + + if (int_type->data.integral.bit_count == 0) { + IrInstruction *result = ir_const(ira, &instruction->base, return_type); + bigint_init_unsigned(&result->value.data.x_bigint, 0); + return result; + } + + if (instr_is_comptime(casted_op)) { + ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); if (!val) return ira->codegen->invalid_instruction; + if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) { size_t result = bigint_popcount_unsigned(&val->data.x_bigint); return ir_const_unsigned(ira, &instruction->base, result); } - if (value->value.type->id == ZigTypeIdComptimeInt) { - Buf *val_buf = buf_alloc(); - bigint_append_buf(val_buf, &val->data.x_bigint, 10); - ir_add_error(ira, &instruction->base, - buf_sprintf("@popCount on negative %s value %s", - buf_ptr(&value->value.type->name), buf_ptr(val_buf))); - return ira->codegen->invalid_instruction; - } - size_t result = bigint_popcount_signed(&val->data.x_bigint, value->value.type->data.integral.bit_count); + size_t result = bigint_popcount_signed(&val->data.x_bigint, op->value.type->data.integral.bit_count); return ir_const_unsigned(ira, &instruction->base, result); } IrInstruction *result = ir_build_pop_count(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, value); - result->value.type = get_smallest_unsigned_int_type(ira->codegen, value->value.type->data.integral.bit_count); + instruction->base.source_node, nullptr, casted_op); + result->value.type = return_type; return result; } @@ -22990,8 +23007,6 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction return ira->codegen->invalid_instruction; IrInstruction *op = instruction->op->child; - if (type_is_invalid(op->value.type)) - return ira->codegen->invalid_instruction; if (int_type->id != ZigTypeIdInt) { ir_add_error(ira, instruction->type, @@ -22999,17 +23014,17 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction return ira->codegen->invalid_instruction; } + IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); + if (type_is_invalid(casted_op->value.type)) + return ira->codegen->invalid_instruction; + if (int_type->data.integral.bit_count % 8 != 0) { - ir_add_error(ira, instruction->type, - buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", + ir_add_error(ira, instruction->op, + buf_sprintf("@byteSwap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", buf_ptr(&int_type->name), int_type->data.integral.bit_count)); return ira->codegen->invalid_instruction; } - IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); - if (type_is_invalid(casted_op->value.type)) - return ira->codegen->invalid_instruction; - if (int_type->data.integral.bit_count == 0) { IrInstruction *result = ir_const(ira, &instruction->base, int_type); bigint_init_unsigned(&result->value.data.x_bigint, 0); @@ -23017,7 +23032,7 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction } if (int_type->data.integral.bit_count == 8) { - return casted_op; + return op; } if (instr_is_comptime(casted_op)) { @@ -23046,8 +23061,6 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr return ira->codegen->invalid_instruction; IrInstruction *op = instruction->op->child; - if (type_is_invalid(op->value.type)) - return ira->codegen->invalid_instruction; if (int_type->id != ZigTypeIdInt) { ir_add_error(ira, instruction->type, @@ -23251,6 +23264,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio return ir_analyze_instruction_ctz(ira, (IrInstructionCtz *)instruction); case IrInstructionIdPopCount: return ir_analyze_instruction_pop_count(ira, (IrInstructionPopCount *)instruction); + case IrInstructionIdBswap: + return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction); + case IrInstructionIdBitReverse: + return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction); case IrInstructionIdSwitchBr: return ir_analyze_instruction_switch_br(ira, (IrInstructionSwitchBr *)instruction); case IrInstructionIdSwitchTarget: @@ -23443,10 +23460,6 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction); case IrInstructionIdSqrt: return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction); - case IrInstructionIdBswap: - return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction); - case IrInstructionIdBitReverse: - return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction); case IrInstructionIdIntToErr: return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); case IrInstructionIdErrToInt: @@ -23621,6 +23634,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdClz: case IrInstructionIdCtz: case IrInstructionIdPopCount: + case IrInstructionIdBswap: + case IrInstructionIdBitReverse: case IrInstructionIdSwitchVar: case IrInstructionIdSwitchElseVar: case IrInstructionIdSwitchTarget: @@ -23679,8 +23694,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdCoroPromise: case IrInstructionIdPromiseResultType: case IrInstructionIdSqrt: - case IrInstructionIdBswap: - case IrInstructionIdBitReverse: case IrInstructionIdAtomicLoad: case IrInstructionIdIntCast: case IrInstructionIdFloatCast: -- cgit v1.2.3 From 80983ca1ca5cdcbd5ce7db017c1987d75cc8184b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 16 May 2019 16:32:24 -0400 Subject: fixups to the previous commit --- doc/langref.html.in | 27 ++--- src/analyze.cpp | 32 ++---- src/analyze.hpp | 1 - src/codegen.cpp | 18 +--- src/ir.cpp | 193 +++++++++++++++--------------------- test/stage1/behavior/bitreverse.zig | 22 ++-- test/stage1/behavior/bugs/2114.zig | 2 +- test/stage1/behavior/byteswap.zig | 20 ++-- test/stage1/behavior/math.zig | 31 ++---- test/stage1/behavior/popcount.zig | 2 +- 10 files changed, 144 insertions(+), 204 deletions(-) (limited to 'src/ir.cpp') diff --git a/doc/langref.html.in b/doc/langref.html.in index 0afbe11fc6..d578be4ba8 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6337,18 +6337,19 @@ comptime { {#header_close#} {#header_open|@clz#} -
{#syntax#}@clz(comptime T: type, integer: T) math.Log2Int(@intType(false, @typeInfo(T).Int.bits + 1)){#endsyntax#}
+
{#syntax#}@clz(comptime T: type, integer: T){#endsyntax#}

- This function counts the number of leading zeroes in {#syntax#}x{#endsyntax#} which is an integer - type {#syntax#}T{#endsyntax#}. + This function counts the number of leading zeroes in {#syntax#}integer{#endsyntax#}.

- If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, the return type is {#syntax#}comptime_int{#endsyntax#}. + If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, + the return type is {#syntax#}comptime_int{#endsyntax#}. Otherwise, the return type is an unsigned integer with the minimum number of bits that can represent the bit count of the integer type.

- If {#syntax#}x{#endsyntax#} is zero, {#syntax#}@clz{#endsyntax#} returns {#syntax#}T.bit_count{#endsyntax#}. + If {#syntax#}integer{#endsyntax#} is zero, {#syntax#}@clz{#endsyntax#} returns the bit width + of integer type {#syntax#}T{#endsyntax#}.

{#see_also|@ctz|@popCount#} {#header_close#} @@ -6478,18 +6479,19 @@ test "main" { {#header_close#} {#header_open|@ctz#} -
{#syntax#}@ctz(comptime T: type, integer: T) math.Log2Int(@intType(false, @typeInfo(T).Int.bits + 1)){#endsyntax#}
+
{#syntax#}@ctz(comptime T: type, integer: T){#endsyntax#}

- This function counts the number of trailing zeroes in {#syntax#}x{#endsyntax#} which is an integer - type {#syntax#}T{#endsyntax#}. + This function counts the number of trailing zeroes in {#syntax#}integer{#endsyntax#}.

- If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, the return type is {#syntax#}comptime_int{#endsyntax#}. + If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, + the return type is {#syntax#}comptime_int{#endsyntax#}. Otherwise, the return type is an unsigned integer with the minimum number of bits that can represent the bit count of the integer type.

- If {#syntax#}x{#endsyntax#} is zero, {#syntax#}@ctz{#endsyntax#} returns {#syntax#}T.bit_count{#endsyntax#}. + If {#syntax#}integer{#endsyntax#} is zero, {#syntax#}@ctz{#endsyntax#} returns + the bit width of integer type {#syntax#}T{#endsyntax#}.

{#see_also|@clz|@popCount#} {#header_close#} @@ -7036,10 +7038,11 @@ test "call foo" { {#header_close#} {#header_open|@popCount#} -
{#syntax#}@popCount(comptime T: type, integer: T) math.Log2Int(@intType(false, @typeInfo(T).Int.bits + 1)){#endsyntax#}
+
{#syntax#}@popCount(comptime T: type, integer: T){#endsyntax#}

Counts the number of bits set in an integer.

- If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, the return type is {#syntax#}comptime_int{#endsyntax#}. + If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, + the return type is {#syntax#}comptime_int{#endsyntax#}. Otherwise, the return type is an unsigned integer with the minimum number of bits that can represent the bit count of the integer type.

diff --git a/src/analyze.cpp b/src/analyze.cpp index f4e81ec042..57244aba6a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -213,6 +213,15 @@ static ZigType *new_container_type_entry(CodeGen *g, ZigTypeId id, AstNode *sour return entry; } +static uint8_t bits_needed_for_unsigned(uint64_t x) { + if (x == 0) { + return 0; + } + uint8_t base = log2_u64(x); + uint64_t upper = (((uint64_t)1) << base) - 1; + return (upper >= x) ? base : (base + 1); +} + AstNode *type_decl_node(ZigType *type_entry) { switch (type_entry->id) { case ZigTypeIdInvalid: @@ -326,33 +335,10 @@ static bool is_slice(ZigType *type) { return type->id == ZigTypeIdStruct && type->data.structure.is_slice; } -static uint8_t bits_needed_for_unsigned(uint64_t x) { - if (x == 0) { - return 0; - } - uint8_t base = log2_u64(x); - uint64_t upper = (((uint64_t)1) << base) - 1; - return (upper >= x) ? base : (base + 1); -} - -static uint8_t bits_needed_for_popcount_unsigned(uint64_t x) { - uint8_t count = 0; - for (uint64_t s = x;s != 0;s >>= 1) - count++; - - return count; -} - ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { return get_int_type(g, false, bits_needed_for_unsigned(x)); } -// This is not the same as above, because while shift by bit width is UB, @clz, @popCount, and @ctz -// can return bit width -ZigType *get_smallest_popcount_unsigned_int_type(CodeGen *g, uint64_t x) { - return get_int_type(g, false, bits_needed_for_popcount_unsigned(x)); -} - ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { if (result_type != nullptr && result_type->promise_parent != nullptr) { return result_type->promise_parent; diff --git a/src/analyze.hpp b/src/analyze.hpp index f92b1922f9..d55733482f 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -34,7 +34,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type); ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout); ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); -ZigType *get_smallest_popcount_unsigned_int_type(CodeGen *g, uint64_t x); ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type); ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry); ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name); diff --git a/src/codegen.cpp b/src/codegen.cpp index fd7134362f..c8903b7dbf 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4126,19 +4126,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI char llvm_name[64]; sprintf(llvm_name, "llvm.%s.i%" PRIu32, fn_name, int_type->data.integral.bit_count); - LLVMTypeRef param_types[3]; - switch (n_args) { - case 1: - param_types[0] = get_llvm_type(g, int_type); - break; - case 2: // clz and ctz - param_types[0] = get_llvm_type(g, int_type); - param_types[1] = LLVMInt1Type(); - break; - default: - zig_unreachable(); - } - LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, int_type), ¶m_types[0], n_args, false); + LLVMTypeRef param_types[] = { + get_llvm_type(g, int_type), + LLVMInt1Type(), + }; + LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, int_type), param_types, n_args, false); LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type); assert(LLVMGetIntrinsicID(fn_val)); diff --git a/src/ir.cpp b/src/ir.cpp index afb032276c..8a3fd55c7e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10472,6 +10472,20 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { return const_val->data.x_type; } +static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) { + ZigType *ty = ir_resolve_type(ira, type_value); + if (type_is_invalid(ty)) + return ira->codegen->builtin_types.entry_invalid; + + if (ty->id != ZigTypeIdInt) { + ir_add_error(ira, type_value, + buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name))); + return ira->codegen->builtin_types.entry_invalid; + } + + return ty; +} + static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) { if (type_is_invalid(type_value->value.type)) return ira->codegen->builtin_types.entry_invalid; @@ -17025,123 +17039,93 @@ static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, } static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) { - ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - IrInstruction *op = instruction->op->child; - - if (int_type->id != ZigTypeIdInt) { - ir_add_error(ira, instruction->type, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); - return ira->codegen->invalid_instruction; - } - - IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); - if (type_is_invalid(casted_op->value.type)) + IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + if (type_is_invalid(op->value.type)) return ira->codegen->invalid_instruction; - ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); + if (int_type->data.integral.bit_count == 0) + return ir_const_unsigned(ira, &instruction->base, 0); - if (int_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_const(ira, &instruction->base, return_type); - bigint_init_unsigned(&result->value.data.x_bigint, 0); - return result; - } - - if (instr_is_comptime(casted_op)) { - size_t result_usize = bigint_ctz(&op->value.data.x_bigint, - op->value.type->data.integral.bit_count); - IrInstruction *result = ir_const(ira, &instruction->base, return_type); - bigint_init_unsigned(&result->value.data.x_bigint, result_usize); - return result; + if (instr_is_comptime(op)) { + ConstExprValue *val = ir_resolve_const(ira, op, UndefOk); + if (val == nullptr) + return ira->codegen->invalid_instruction; + if (val->special == ConstValSpecialUndef) + return ir_const_undef(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); + size_t result_usize = bigint_ctz(&op->value.data.x_bigint, int_type->data.integral.bit_count); + return ir_const_unsigned(ira, &instruction->base, result_usize); } + ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); IrInstruction *result = ir_build_ctz(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_op); + instruction->base.source_node, nullptr, op); result->value.type = return_type; return result; } static IrInstruction *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *instruction) { - ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - IrInstruction *op = instruction->op->child; - - if (int_type->id != ZigTypeIdInt) { - ir_add_error(ira, instruction->type, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); - return ira->codegen->invalid_instruction; - } - - IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); - if (type_is_invalid(casted_op->value.type)) + IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + if (type_is_invalid(op->value.type)) return ira->codegen->invalid_instruction; - ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); + if (int_type->data.integral.bit_count == 0) + return ir_const_unsigned(ira, &instruction->base, 0); - if (int_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_const(ira, &instruction->base, return_type); - bigint_init_unsigned(&result->value.data.x_bigint, 0); - return result; - } - - if (instr_is_comptime(casted_op)) { - size_t result_usize = bigint_clz(&op->value.data.x_bigint, - op->value.type->data.integral.bit_count); - IrInstruction *result = ir_const(ira, &instruction->base, return_type); - bigint_init_unsigned(&result->value.data.x_bigint, result_usize); - return result; + if (instr_is_comptime(op)) { + ConstExprValue *val = ir_resolve_const(ira, op, UndefOk); + if (val == nullptr) + return ira->codegen->invalid_instruction; + if (val->special == ConstValSpecialUndef) + return ir_const_undef(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); + size_t result_usize = bigint_clz(&op->value.data.x_bigint, int_type->data.integral.bit_count); + return ir_const_unsigned(ira, &instruction->base, result_usize); } + ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); IrInstruction *result = ir_build_clz(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_op); + instruction->base.source_node, nullptr, op); result->value.type = return_type; return result; } static IrInstruction *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPopCount *instruction) { - ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - IrInstruction *op = instruction->op->child; - - if (int_type->id != ZigTypeIdInt) { - ir_add_error(ira, instruction->type, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); - return ira->codegen->invalid_instruction; - } - - IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); - if (type_is_invalid(casted_op->value.type)) + IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + if (type_is_invalid(op->value.type)) return ira->codegen->invalid_instruction; - ZigType *return_type = get_smallest_popcount_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); + if (int_type->data.integral.bit_count == 0) + return ir_const_unsigned(ira, &instruction->base, 0); - if (int_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_const(ira, &instruction->base, return_type); - bigint_init_unsigned(&result->value.data.x_bigint, 0); - return result; - } - - if (instr_is_comptime(casted_op)) { - ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); - if (!val) + if (instr_is_comptime(op)) { + ConstExprValue *val = ir_resolve_const(ira, op, UndefOk); + if (val == nullptr) return ira->codegen->invalid_instruction; + if (val->special == ConstValSpecialUndef) + return ir_const_undef(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) { size_t result = bigint_popcount_unsigned(&val->data.x_bigint); return ir_const_unsigned(ira, &instruction->base, result); } - size_t result = bigint_popcount_signed(&val->data.x_bigint, op->value.type->data.integral.bit_count); + size_t result = bigint_popcount_signed(&val->data.x_bigint, int_type->data.integral.bit_count); return ir_const_unsigned(ira, &instruction->base, result); } + ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); IrInstruction *result = ir_build_pop_count(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_op); + instruction->base.source_node, nullptr, op); result->value.type = return_type; return result; } @@ -23002,28 +22986,13 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS } static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { - ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - IrInstruction *op = instruction->op->child; - - if (int_type->id != ZigTypeIdInt) { - ir_add_error(ira, instruction->type, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); - return ira->codegen->invalid_instruction; - } - - IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); - if (type_is_invalid(casted_op->value.type)) - return ira->codegen->invalid_instruction; - - if (int_type->data.integral.bit_count % 8 != 0) { - ir_add_error(ira, instruction->op, - buf_sprintf("@byteSwap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", - buf_ptr(&int_type->name), int_type->data.integral.bit_count)); + IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + if (type_is_invalid(op->value.type)) return ira->codegen->invalid_instruction; - } if (int_type->data.integral.bit_count == 0) { IrInstruction *result = ir_const(ira, &instruction->base, int_type); @@ -23031,14 +23000,22 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction return result; } - if (int_type->data.integral.bit_count == 8) { + if (int_type->data.integral.bit_count == 8) return op; + + if (int_type->data.integral.bit_count % 8 != 0) { + ir_add_error(ira, instruction->op, + buf_sprintf("@byteSwap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", + buf_ptr(&int_type->name), int_type->data.integral.bit_count)); + return ira->codegen->invalid_instruction; } - if (instr_is_comptime(casted_op)) { - ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); - if (!val) + if (instr_is_comptime(op)) { + ConstExprValue *val = ir_resolve_const(ira, op, UndefOk); + if (val == nullptr) return ira->codegen->invalid_instruction; + if (val->special == ConstValSpecialUndef) + return ir_const_undef(ira, &instruction->base, int_type); IrInstruction *result = ir_const(ira, &instruction->base, int_type); size_t buf_size = int_type->data.integral.bit_count / 8; @@ -23050,26 +23027,18 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction } IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_op); + instruction->base.source_node, nullptr, op); result->value.type = int_type; return result; } static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstructionBitReverse *instruction) { - ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) return ira->codegen->invalid_instruction; - IrInstruction *op = instruction->op->child; - - if (int_type->id != ZigTypeIdInt) { - ir_add_error(ira, instruction->type, - buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); - return ira->codegen->invalid_instruction; - } - - IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); - if (type_is_invalid(casted_op->value.type)) + IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + if (type_is_invalid(op->value.type)) return ira->codegen->invalid_instruction; if (int_type->data.integral.bit_count == 0) { @@ -23078,10 +23047,12 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr return result; } - if (instr_is_comptime(casted_op)) { - ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); - if (!val) + if (instr_is_comptime(op)) { + ConstExprValue *val = ir_resolve_const(ira, op, UndefOk); + if (val == nullptr) return ira->codegen->invalid_instruction; + if (val->special == ConstValSpecialUndef) + return ir_const_undef(ira, &instruction->base, int_type); IrInstruction *result = ir_const(ira, &instruction->base, int_type); size_t num_bits = int_type->data.integral.bit_count; @@ -23111,7 +23082,7 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr } IrInstruction *result = ir_build_bit_reverse(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_op); + instruction->base.source_node, nullptr, op); result->value.type = int_type; return result; } diff --git a/test/stage1/behavior/bitreverse.zig b/test/stage1/behavior/bitreverse.zig index d1de3997fb..2b0eb71fb6 100644 --- a/test/stage1/behavior/bitreverse.zig +++ b/test/stage1/behavior/bitreverse.zig @@ -9,17 +9,17 @@ test "@bitReverse" { fn testBitReverse() void { // using comptime_ints, unsigned - expect(@bitReverse(u0, u0(0)) == 0); - expect(@bitReverse(u5, u5(0x12)) == 0x9); - expect(@bitReverse(u8, u8(0x12)) == 0x48); - expect(@bitReverse(u16, u16(0x1234)) == 0x2c48); - expect(@bitReverse(u24, u24(0x123456)) == 0x6a2c48); - expect(@bitReverse(u32, u32(0x12345678)) == 0x1e6a2c48); - expect(@bitReverse(u40, u40(0x123456789a)) == 0x591e6a2c48); - expect(@bitReverse(u48, u48(0x123456789abc)) == 0x3d591e6a2c48); - expect(@bitReverse(u56, u56(0x123456789abcde)) == 0x7b3d591e6a2c48); - expect(@bitReverse(u64, u64(0x123456789abcdef1)) == 0x8f7b3d591e6a2c48); - expect(@bitReverse(u128, u128(0x123456789abcdef11121314151617181)) == 0x818e868a828c84888f7b3d591e6a2c48); + expect(@bitReverse(u0, 0) == 0); + expect(@bitReverse(u5, 0x12) == 0x9); + expect(@bitReverse(u8, 0x12) == 0x48); + expect(@bitReverse(u16, 0x1234) == 0x2c48); + expect(@bitReverse(u24, 0x123456) == 0x6a2c48); + expect(@bitReverse(u32, 0x12345678) == 0x1e6a2c48); + expect(@bitReverse(u40, 0x123456789a) == 0x591e6a2c48); + expect(@bitReverse(u48, 0x123456789abc) == 0x3d591e6a2c48); + expect(@bitReverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48); + expect(@bitReverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48); + expect(@bitReverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48); // using runtime uints, unsigned var num0: u0 = 0; diff --git a/test/stage1/behavior/bugs/2114.zig b/test/stage1/behavior/bugs/2114.zig index f24899649b..e266279564 100644 --- a/test/stage1/behavior/bugs/2114.zig +++ b/test/stage1/behavior/bugs/2114.zig @@ -3,7 +3,7 @@ const expect = std.testing.expect; const math = std.math; fn ctz(x: var) usize { - return @ctz(u128, x); + return @ctz(@typeOf(x), x); } test "fixed" { diff --git a/test/stage1/behavior/byteswap.zig b/test/stage1/behavior/byteswap.zig index 408210f3e1..3e7c34cb85 100644 --- a/test/stage1/behavior/byteswap.zig +++ b/test/stage1/behavior/byteswap.zig @@ -7,16 +7,16 @@ test "@byteSwap" { } fn testByteSwap() void { - expect(@byteSwap(u0, u0(0)) == 0); - expect(@byteSwap(u8, u8(0x12)) == 0x12); - expect(@byteSwap(u16, u16(0x1234)) == 0x3412); - expect(@byteSwap(u24, u24(0x123456)) == 0x563412); - expect(@byteSwap(u32, u32(0x12345678)) == 0x78563412); - expect(@byteSwap(u40, u40(0x123456789a)) == 0x9a78563412); - expect(@byteSwap(i48, u48(0x123456789abc)) == @bitCast(i48, u48(0xbc9a78563412))); - expect(@byteSwap(u56, u56(0x123456789abcde)) == 0xdebc9a78563412); - expect(@byteSwap(u64, u64(0x123456789abcdef1)) == 0xf1debc9a78563412); - expect(@byteSwap(u128, u128(0x123456789abcdef11121314151617181)) == 0x8171615141312111f1debc9a78563412); + expect(@byteSwap(u0, 0) == 0); + expect(@byteSwap(u8, 0x12) == 0x12); + expect(@byteSwap(u16, 0x1234) == 0x3412); + expect(@byteSwap(u24, 0x123456) == 0x563412); + expect(@byteSwap(u32, 0x12345678) == 0x78563412); + expect(@byteSwap(u40, 0x123456789a) == 0x9a78563412); + expect(@byteSwap(i48, 0x123456789abc) == @bitCast(i48, u48(0xbc9a78563412))); + expect(@byteSwap(u56, 0x123456789abcde) == 0xdebc9a78563412); + expect(@byteSwap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); + expect(@byteSwap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); expect(@byteSwap(u0, u0(0)) == 0); expect(@byteSwap(i8, i8(-50)) == -50); diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig index 83f09fae41..18e7fc9dcb 100644 --- a/test/stage1/behavior/math.zig +++ b/test/stage1/behavior/math.zig @@ -114,12 +114,12 @@ test "@clz" { } fn testClz() void { - expect(clz(u8, u8(0b10001010)) == 0); - expect(clz(u8, u8(0b00001010)) == 4); - expect(clz(u8, u8(0b00011010)) == 3); - expect(clz(u8, u8(0b00000000)) == 8); - expect(clz(u128, u128(0xffffffffffffffff)) == 64); - expect(clz(u128, u128(0x10000000000000000)) == 63); + expect(clz(u8, 0b10001010) == 0); + expect(clz(u8, 0b00001010) == 4); + expect(clz(u8, 0b00011010) == 3); + expect(clz(u8, 0b00000000) == 8); + expect(clz(u128, 0xffffffffffffffff) == 64); + expect(clz(u128, 0x10000000000000000) == 63); } fn clz(comptime T: type, x: T) usize { @@ -132,27 +132,16 @@ test "@ctz" { } fn testCtz() void { - expect(ctz(u8, u8(0b10100000)) == 5); - expect(ctz(u8, u8(0b10001010)) == 1); - expect(ctz(u8, u8(0b00000000)) == 8); - expect(ctz(u16, u16(0b00000000)) == 16); + expect(ctz(u8, 0b10100000) == 5); + expect(ctz(u8, 0b10001010) == 1); + expect(ctz(u8, 0b00000000) == 8); + expect(ctz(u16, 0b00000000) == 16); } fn ctz(comptime T: type, x: T) usize { return @ctz(T, x); } -pub fn Log2Int(comptime T: type) type { - // comptime ceil log2 - comptime var count = 0; - comptime var s = T.bit_count - 1; - inline while (s != 0) : (s >>= 1) { - count += 1; - } - - return @IntType(false, count); -} - test "assignment operators" { var i: u32 = 0; i += 5; diff --git a/test/stage1/behavior/popcount.zig b/test/stage1/behavior/popcount.zig index 02d4531758..327bee62a1 100644 --- a/test/stage1/behavior/popcount.zig +++ b/test/stage1/behavior/popcount.zig @@ -38,7 +38,7 @@ fn testPopCount() void { expect(@popCount(u8, @bitCast(u8, i8(-120))) == 2); } comptime { - expect(@popCount(i128, u128(0b11111111000110001100010000100001000011000011100101010001)) == 24); + expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24); } } -- cgit v1.2.3