| ... | @@ -9900,6 +9900,100 @@ static Stage1AirInst *ir_analyze_math_op(IrAnalyze *ira, Scope *scope, AstNode * | ... | @@ -9900,6 +9900,100 @@ static Stage1AirInst *ir_analyze_math_op(IrAnalyze *ira, Scope *scope, AstNode * |
| 9900 | return ir_implicit_cast(ira, result_instruction, type_entry); | 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 | static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *bin_op_instruction) { | 9997 | static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *bin_op_instruction) { |
| 9904 | Stage1AirInst *op1 = bin_op_instruction->op1->child; | 9998 | Stage1AirInst *op1 = bin_op_instruction->op1->child; |
| 9905 | if (type_is_invalid(op1->value->type)) | 9999 | if (type_is_invalid(op1->value->type)) |
| ... | @@ -9951,6 +10045,12 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b | ... | @@ -9951,6 +10045,12 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b |
| 9951 | // comptime_int has no finite bit width | 10045 | // comptime_int has no finite bit width |
| 9952 | casted_op2 = op2; | 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 | if (op_id == IrBinOpBitShiftLeftLossy) { | 10054 | if (op_id == IrBinOpBitShiftLeftLossy) { |
| 9955 | op_id = IrBinOpBitShiftLeftExact; | 10055 | op_id = IrBinOpBitShiftLeftExact; |
| 9956 | } | 10056 | } |
| ... | @@ -9972,6 +10072,13 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b | ... | @@ -9972,6 +10072,13 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b |
| 9972 | buf_sprintf("shift by negative value %s", buf_ptr(val_buf))); | 10072 | buf_sprintf("shift by negative value %s", buf_ptr(val_buf))); |
| 9973 | return ira->codegen->invalid_inst_gen; | 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 | } else { | 10082 | } else { |
| 9976 | const unsigned bit_count = op1_scalar_type->data.integral.bit_count; | 10083 | const unsigned bit_count = op1_scalar_type->data.integral.bit_count; |
| 9977 | ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen, | 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,8 +10137,9 @@ static Stage1AirInst *ir_analyze_bit_shift(IrAnalyze *ira, Stage1ZirInstBinOp *b |
| 10030 | 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); | 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, | 10140 | return ir_build_bin_op_gen(ira, |
| 10034 | op_id, op1, casted_op2, bin_op_instruction->safety_check_on); | 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 | static bool ok_float_op(IrBinOp op) { | 10145 | static bool ok_float_op(IrBinOp op) { |
| ... | @@ -11035,6 +11143,7 @@ static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirIns | ... | @@ -11035,6 +11143,7 @@ static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirIns |
| 11035 | case IrBinOpBitShiftLeftExact: | 11143 | case IrBinOpBitShiftLeftExact: |
| 11036 | case IrBinOpBitShiftRightLossy: | 11144 | case IrBinOpBitShiftRightLossy: |
| 11037 | case IrBinOpBitShiftRightExact: | 11145 | case IrBinOpBitShiftRightExact: |
| | 11146 | case IrBinOpShlSat: |
| 11038 | return ir_analyze_bit_shift(ira, bin_op_instruction); | 11147 | return ir_analyze_bit_shift(ira, bin_op_instruction); |
| 11039 | case IrBinOpBinOr: | 11148 | case IrBinOpBinOr: |
| 11040 | case IrBinOpBinXor: | 11149 | case IrBinOpBinXor: |
| ... | @@ -11057,7 +11166,6 @@ static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirIns | ... | @@ -11057,7 +11166,6 @@ static Stage1AirInst *ir_analyze_instruction_bin_op(IrAnalyze *ira, Stage1ZirIns |
| 11057 | case IrBinOpAddSat: | 11166 | case IrBinOpAddSat: |
| 11058 | case IrBinOpSubSat: | 11167 | case IrBinOpSubSat: |
| 11059 | case IrBinOpMultSat: | 11168 | case IrBinOpMultSat: |
| 11060 | case IrBinOpShlSat: | | |
| 11061 | return ir_analyze_bin_op_math(ira, bin_op_instruction); | 11169 | return ir_analyze_bin_op_math(ira, bin_op_instruction); |
| 11062 | case IrBinOpArrayCat: | 11170 | case IrBinOpArrayCat: |
| 11063 | return ir_analyze_array_cat(ira, bin_op_instruction); | 11171 | return ir_analyze_array_cat(ira, bin_op_instruction); |
| ... | @@ -20017,59 +20125,13 @@ static Stage1AirInst *ir_analyze_instruction_truncate(IrAnalyze *ira, Stage1ZirI | ... | @@ -20017,59 +20125,13 @@ static Stage1AirInst *ir_analyze_instruction_truncate(IrAnalyze *ira, Stage1ZirI |
| 20017 | if (type_is_invalid(dest_type)) | 20125 | if (type_is_invalid(dest_type)) |
| 20018 | return ira->codegen->invalid_inst_gen; | 20126 | return ira->codegen->invalid_inst_gen; |
| 20019 | | 20127 | |
| 20020 | if (dest_type->id != ZigTypeIdInt && | 20128 | Stage1AirInst *operand = instruction->target->child; |
| 20021 | dest_type->id != ZigTypeIdComptimeInt) | 20129 | if (type_is_invalid(operand->value->type)) |
| 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))); | | |
| 20036 | return ira->codegen->invalid_inst_gen; | 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) { | 20132 | return ir_analyze_truncate(ira, instruction->base.scope, instruction->base.source_node, |
| 20044 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { | 20133 | dest_type, instruction->dest_type->source_node, |
| 20045 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; | 20134 | operand, instruction->target->source_node); |
| 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); | | |
| 20073 | } | 20135 | } |
| 20074 | | 20136 | |
| 20075 | static Stage1AirInst *ir_analyze_int_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, | 20137 | static Stage1AirInst *ir_analyze_int_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, |