| ... | ... | @@ -9900,6 +9900,100 @@ static Stage1AirInst *ir_analyze_math_op(IrAnalyze *ira, Scope *scope, AstNode * |
| 9900 | 9900 | return ir_implicit_cast(ira, result_instruction, type_entry); |
| 9901 | 9901 | } |
| 9902 | 9902 | |
| 9903 | static Stage1AirInst *ir_analyze_truncate(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 9904 | ZigType *dest_scalar_type, AstNode *dest_type_node, |
| 9905 | Stage1AirInst *operand, AstNode *operand_node) |
| 9906 | { |
| 9907 | if (dest_scalar_type->id != ZigTypeIdInt && |
| 9908 | dest_scalar_type->id != ZigTypeIdComptimeInt) |
| 9909 | { |
| 9910 | ir_add_error_node(ira, dest_type_node, |
| 9911 | buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_scalar_type->name))); |
| 9912 | return ira->codegen->invalid_inst_gen; |
| 9913 | } |
| 9914 | |
| 9915 | ZigType *src_type = operand->value->type; |
| 9916 | bool is_vector = (src_type->id == ZigTypeIdVector); |
| 9917 | ZigType *src_scalar_type = is_vector ? |
| 9918 | src_type->data.vector.elem_type : src_type; |
| 9919 | |
| 9920 | ZigType *dest_type = is_vector ? |
| 9921 | get_vector_type(ira->codegen, src_type->data.vector.len, dest_scalar_type) : |
| 9922 | dest_scalar_type; |
| 9923 | |
| 9924 | if (src_scalar_type->id != ZigTypeIdInt && src_scalar_type->id != ZigTypeIdComptimeInt) { |
| 9925 | ir_add_error_node(ira, operand_node, |
| 9926 | buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_scalar_type->name))); |
| 9927 | return ira->codegen->invalid_inst_gen; |
| 9928 | } |
| 9929 | |
| 9930 | if (dest_scalar_type->id == ZigTypeIdComptimeInt) { |
| 9931 | return ir_implicit_cast2(ira, scope, operand_node, operand, dest_type); |
| 9932 | } |
| 9933 | |
| 9934 | if (src_scalar_type->id != ZigTypeIdComptimeInt) { |
| 9935 | if (src_scalar_type->data.integral.is_signed != dest_scalar_type->data.integral.is_signed) { |
| 9936 | const char *sign_str = dest_scalar_type->data.integral.is_signed ? "signed" : "unsigned"; |
| 9937 | ir_add_error_node(ira, operand_node, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_scalar_type->name))); |
| 9938 | return ira->codegen->invalid_inst_gen; |
| 9939 | } else if (src_scalar_type->data.integral.bit_count > 0 && src_scalar_type->data.integral.bit_count < dest_scalar_type->data.integral.bit_count) { |
| 9940 | ir_add_error_node(ira, operand_node, buf_sprintf("type '%s' has fewer bits than destination type '%s'", |
| 9941 | buf_ptr(&src_scalar_type->name), buf_ptr(&dest_scalar_type->name))); |
| 9942 | return ira->codegen->invalid_inst_gen; |
| 9943 | } |
| 9944 | } |
| 9945 | |
| 9946 | if (instr_is_comptime(operand)) { |
| 9947 | ZigValue *val = ir_resolve_const(ira, operand, UndefBad); |
| 9948 | if (val == nullptr) |
| 9949 | return ira->codegen->invalid_inst_gen; |
| 9950 | |
| 9951 | if (!is_vector) { |
| 9952 | Stage1AirInst *result = ir_const(ira, scope, source_node, dest_type); |
| 9953 | bigint_truncate(&result->value->data.x_bigint, &val->data.x_bigint, |
| 9954 | dest_scalar_type->data.integral.bit_count, |
| 9955 | dest_scalar_type->data.integral.is_signed); |
| 9956 | return result; |
| 9957 | } |
| 9958 | |
| 9959 | Stage1AirInst *result_instruction = ir_const(ira, scope, source_node, dest_type); |
| 9960 | ZigValue *out_val = result_instruction->value; |
| 9961 | expand_undef_array(ira->codegen, operand->value); |
| 9962 | out_val->special = ConstValSpecialUndef; |
| 9963 | expand_undef_array(ira->codegen, out_val); |
| 9964 | size_t len = dest_type->data.vector.len; |
| 9965 | for (size_t i = 0; i < len; i += 1) { |
| 9966 | ZigValue *scalar_operand_val = &operand->value->data.x_array.data.s_none.elements[i]; |
| 9967 | ZigValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i]; |
| 9968 | assert(scalar_operand_val->type == dest_scalar_type); |
| 9969 | assert(scalar_out_val->type == dest_scalar_type); |
| 9970 | |
| 9971 | bigint_truncate(&scalar_out_val->data.x_bigint, |
| 9972 | &scalar_operand_val->data.x_bigint, |
| 9973 | dest_scalar_type->data.integral.bit_count, |
| 9974 | dest_scalar_type->data.integral.is_signed); |
| 9975 | |
| 9976 | scalar_out_val->type = dest_scalar_type; |
| 9977 | scalar_out_val->special = ConstValSpecialStatic; |
| 9978 | } |
| 9979 | out_val->type = dest_type; |
| 9980 | out_val->special = ConstValSpecialStatic; |
| 9981 | return result_instruction; |
| 9982 | } |
| 9983 | |
| 9984 | if (src_scalar_type->data.integral.bit_count == 0 || |
| 9985 | dest_scalar_type->data.integral.bit_count == 0) |
| 9986 | { |
| 9987 | Stage1AirInst *result = ir_const(ira, scope, source_node, dest_type); |
| 9988 | if (!is_vector) { |
| 9989 | bigint_init_unsigned(&result->value->data.x_bigint, 0); |
| 9990 | } |
| 9991 | return result; |
| 9992 | } |
| 9993 | |
| 9994 | return ir_build_truncate_gen(ira, scope, source_node, dest_type, operand); |
| 9995 | } |
| 9996 | |
| 9903 | 9997 | static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *bin_op_instruction) { |
| 9904 | 9998 | Stage1AirInst *op1 = bin_op_instruction->op1->child; |
| 9905 | 9999 | if (type_is_invalid(op1->value->type)) |
| ... | ... | @@ -9951,6 +10045,12 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b |
| 9951 | 10045 | // comptime_int has no finite bit width |
| 9952 | 10046 | casted_op2 = op2; |
| 9953 | 10047 | |
| 10048 | if (op_id == IrBinOpShlSat) { |
| 10049 | ir_add_error_node(ira, bin_op_instruction->base.source_node, |
| 10050 | buf_sprintf("saturating shift on a comptime_int which has unlimited bits")); |
| 10051 | return ira->codegen->invalid_inst_gen; |
| 10052 | } |
| 10053 | |
| 9954 | 10054 | if (op_id == IrBinOpBitShiftLeftLossy) { |
| 9955 | 10055 | op_id = IrBinOpBitShiftLeftExact; |
| 9956 | 10056 | } |
| ... | ... | @@ -9972,6 +10072,13 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b |
| 9972 | 10072 | buf_sprintf("shift by negative value %s", buf_ptr(val_buf))); |
| 9973 | 10073 | return ira->codegen->invalid_inst_gen; |
| 9974 | 10074 | } |
| 10075 | } else if (op_id == IrBinOpShlSat) { |
| 10076 | casted_op2 = ir_analyze_truncate(ira, |
| 10077 | bin_op_instruction->base.scope, bin_op_instruction->base.source_node, |
| 10078 | op1_scalar_type, bin_op_instruction->op1->source_node, |
| 10079 | op2, bin_op_instruction->op2->source_node); |
| 10080 | if (type_is_invalid(casted_op2->value->type)) |
| 10081 | return ira->codegen->invalid_inst_gen; |
| 9975 | 10082 | } else { |
| 9976 | 10083 | const unsigned bit_count = op1_scalar_type->data.integral.bit_count; |
| 9977 | 10084 | ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen, |
| ... | ... | @@ -10030,8 +10137,9 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b |
| 10030 | 10137 | return ir_analyze_math_op(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op1_type, op1_val, op_id, op2_val); |
| 10031 | 10138 | } |
| 10032 | 10139 | |
| 10033 | | return ir_build_bin_op_gen(ira, bin_op_instruction->base.scope, bin_op_instruction->base.source_node, op1->value->type, |
| 10034 | | op_id, op1, casted_op2, bin_op_instruction->safety_check_on); |
| 10140 | return ir_build_bin_op_gen(ira, |
| 10141 | bin_op_instruction->base.scope, bin_op_instruction->base.source_node, |
| 10142 | op1->value->type, op_id, op1, casted_op2, bin_op_instruction->safety_check_on); |
| 10035 | 10143 | } |
| 10036 | 10144 | |
| 10037 | 10145 | static bool ok_float_op(IrBinOp op) { |
| ... | ... | @@ -11035,6 +11143,7 @@ static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirIns |
| 11035 | 11143 | case IrBinOpBitShiftLeftExact: |
| 11036 | 11144 | case IrBinOpBitShiftRightLossy: |
| 11037 | 11145 | case IrBinOpBitShiftRightExact: |
| 11146 | case IrBinOpShlSat: |
| 11038 | 11147 | return ir_analyze_bit_shift(ira, bin_op_instruction); |
| 11039 | 11148 | case IrBinOpBinOr: |
| 11040 | 11149 | case IrBinOpBinXor: |
| ... | ... | @@ -11057,7 +11166,6 @@ static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirIns |
| 11057 | 11166 | case IrBinOpAddSat: |
| 11058 | 11167 | case IrBinOpSubSat: |
| 11059 | 11168 | case IrBinOpMultSat: |
| 11060 | | case IrBinOpShlSat: |
| 11061 | 11169 | return ir_analyze_bin_op_math(ira, bin_op_instruction); |
| 11062 | 11170 | case IrBinOpArrayCat: |
| 11063 | 11171 | return ir_analyze_array_cat(ira, bin_op_instruction); |
| ... | ... | @@ -20017,59 +20125,13 @@ static Stage1AirInst *ir_analyze_instruction_truncate(IrAnalyze *ira, Stage1ZirI |
| 20017 | 20125 | if (type_is_invalid(dest_type)) |
| 20018 | 20126 | return ira->codegen->invalid_inst_gen; |
| 20019 | 20127 | |
| 20020 | | if (dest_type->id != ZigTypeIdInt && |
| 20021 | | dest_type->id != ZigTypeIdComptimeInt) |
| 20022 | | { |
| 20023 | | ir_add_error(ira, dest_type_value, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); |
| 20024 | | return ira->codegen->invalid_inst_gen; |
| 20025 | | } |
| 20026 | | |
| 20027 | | Stage1AirInst *target = instruction->target->child; |
| 20028 | | ZigType *src_type = target->value->type; |
| 20029 | | if (type_is_invalid(src_type)) |
| 20030 | | return ira->codegen->invalid_inst_gen; |
| 20031 | | |
| 20032 | | if (src_type->id != ZigTypeIdInt && |
| 20033 | | src_type->id != ZigTypeIdComptimeInt) |
| 20034 | | { |
| 20035 | | ir_add_error(ira, target, buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_type->name))); |
| 20128 | Stage1AirInst *operand = instruction->target->child; |
| 20129 | if (type_is_invalid(operand->value->type)) |
| 20036 | 20130 | return ira->codegen->invalid_inst_gen; |
| 20037 | | } |
| 20038 | | |
| 20039 | | if (dest_type->id == ZigTypeIdComptimeInt) { |
| 20040 | | return ir_implicit_cast2(ira, instruction->target->scope, instruction->target->source_node, target, dest_type); |
| 20041 | | } |
| 20042 | 20131 | |
| 20043 | | if (src_type->id != ZigTypeIdComptimeInt) { |
| 20044 | | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { |
| 20045 | | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; |
| 20046 | | ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); |
| 20047 | | return ira->codegen->invalid_inst_gen; |
| 20048 | | } else if (src_type->data.integral.bit_count > 0 && src_type->data.integral.bit_count < dest_type->data.integral.bit_count) { |
| 20049 | | ir_add_error(ira, target, buf_sprintf("type '%s' has fewer bits than destination type '%s'", |
| 20050 | | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); |
| 20051 | | return ira->codegen->invalid_inst_gen; |
| 20052 | | } |
| 20053 | | } |
| 20054 | | |
| 20055 | | if (instr_is_comptime(target)) { |
| 20056 | | ZigValue *val = ir_resolve_const(ira, target, UndefBad); |
| 20057 | | if (val == nullptr) |
| 20058 | | return ira->codegen->invalid_inst_gen; |
| 20059 | | |
| 20060 | | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, dest_type); |
| 20061 | | bigint_truncate(&result->value->data.x_bigint, &val->data.x_bigint, |
| 20062 | | dest_type->data.integral.bit_count, dest_type->data.integral.is_signed); |
| 20063 | | return result; |
| 20064 | | } |
| 20065 | | |
| 20066 | | if (src_type->data.integral.bit_count == 0 || dest_type->data.integral.bit_count == 0) { |
| 20067 | | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, dest_type); |
| 20068 | | bigint_init_unsigned(&result->value->data.x_bigint, 0); |
| 20069 | | return result; |
| 20070 | | } |
| 20071 | | |
| 20072 | | return ir_build_truncate_gen(ira, instruction->base.scope, instruction->base.source_node, dest_type, target); |
| 20132 | return ir_analyze_truncate(ira, instruction->base.scope, instruction->base.source_node, |
| 20133 | dest_type, instruction->dest_type->source_node, |
| 20134 | operand, instruction->target->source_node); |
| 20073 | 20135 | } |
| 20074 | 20136 | |
| 20075 | 20137 | static Stage1AirInst *ir_analyze_int_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, |