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/codegen.cpp | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 7e7c1432e9..fd7134362f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4126,11 +4126,19 @@ 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[] = { - get_llvm_type(g, int_type), - LLVMInt1Type(), - }; - LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, int_type), param_types, n_args, false); + 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); LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type); assert(LLVMGetIntrinsicID(fn_val)); @@ -4140,9 +4148,9 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI } static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstructionClz *instruction) { - ZigType *int_type = instruction->value->value.type; + ZigType *int_type = instruction->op->value.type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz); - LLVMValueRef operand = ir_llvm_value(g, instruction->value); + LLVMValueRef operand = ir_llvm_value(g, instruction->op); LLVMValueRef params[] { operand, LLVMConstNull(LLVMInt1Type()), @@ -4152,9 +4160,9 @@ static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstru } static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstructionCtz *instruction) { - ZigType *int_type = instruction->value->value.type; + ZigType *int_type = instruction->op->value.type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz); - LLVMValueRef operand = ir_llvm_value(g, instruction->value); + LLVMValueRef operand = ir_llvm_value(g, instruction->op); LLVMValueRef params[] { operand, LLVMConstNull(LLVMInt1Type()), @@ -4164,9 +4172,9 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru } static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) { - ZigType *int_type = instruction->value->value.type; + ZigType *int_type = instruction->op->value.type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); - LLVMValueRef operand = ir_llvm_value(g, instruction->value); + LLVMValueRef operand = ir_llvm_value(g, instruction->op); LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value.type, wrong_size_int); } @@ -5650,6 +5658,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_pop_count(g, executable, (IrInstructionPopCount *)instruction); case IrInstructionIdSwitchBr: return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction); + case IrInstructionIdBswap: + return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); + case IrInstructionIdBitReverse: + return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction); case IrInstructionIdPhi: return ir_render_phi(g, executable, (IrInstructionPhi *)instruction); case IrInstructionIdRef: @@ -5766,10 +5778,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction); case IrInstructionIdSqrt: return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction); - case IrInstructionIdBswap: - return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); - case IrInstructionIdBitReverse: - return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction); case IrInstructionIdArrayToVector: return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction); case IrInstructionIdVectorToArray: @@ -7332,9 +7340,11 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdCInclude, "cInclude", 1); create_builtin_fn(g, BuiltinFnIdCDefine, "cDefine", 2); create_builtin_fn(g, BuiltinFnIdCUndef, "cUndef", 1); - create_builtin_fn(g, BuiltinFnIdCtz, "ctz", 1); - create_builtin_fn(g, BuiltinFnIdClz, "clz", 1); - create_builtin_fn(g, BuiltinFnIdPopCount, "popCount", 1); + create_builtin_fn(g, BuiltinFnIdCtz, "ctz", 2); + create_builtin_fn(g, BuiltinFnIdClz, "clz", 2); + create_builtin_fn(g, BuiltinFnIdPopCount, "popCount", 2); + create_builtin_fn(g, BuiltinFnIdBswap, "byteSwap", 2); + create_builtin_fn(g, BuiltinFnIdBitReverse, "bitReverse", 2); create_builtin_fn(g, BuiltinFnIdImport, "import", 1); create_builtin_fn(g, BuiltinFnIdCImport, "cImport", 1); create_builtin_fn(g, BuiltinFnIdErrName, "errorName", 1); @@ -7395,8 +7405,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); create_builtin_fn(g, BuiltinFnIdThis, "This", 0); - create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2); - create_builtin_fn(g, BuiltinFnIdBitReverse, "bitreverse", 2); } static const char *bool_to_str(bool b) { -- 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/codegen.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