| ... | ... | @@ -86,6 +86,8 @@ enum ConstCastResultId { |
| 86 | 86 | ConstCastResultIdCV, |
| 87 | 87 | ConstCastResultIdPtrSentinel, |
| 88 | 88 | ConstCastResultIdIntShorten, |
| 89 | ConstCastResultIdVectorLength, |
| 90 | ConstCastResultIdVectorChild, |
| 89 | 91 | }; |
| 90 | 92 | |
| 91 | 93 | struct ConstCastOnly; |
| ... | ... | @@ -914,6 +916,7 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte |
| 914 | 916 | if (is_opt_err_set(expected) && is_opt_err_set(actual)) |
| 915 | 917 | return true; |
| 916 | 918 | |
| 919 | // XXX: Vectors and arrays are interchangeable at comptime |
| 917 | 920 | if (expected->id != actual->id) |
| 918 | 921 | return false; |
| 919 | 922 | |
| ... | ... | @@ -947,9 +950,11 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte |
| 947 | 950 | case ZigTypeIdErrorUnion: |
| 948 | 951 | case ZigTypeIdEnum: |
| 949 | 952 | case ZigTypeIdUnion: |
| 950 | | case ZigTypeIdVector: |
| 951 | 953 | case ZigTypeIdFnFrame: |
| 952 | 954 | return false; |
| 955 | case ZigTypeIdVector: |
| 956 | return expected->data.vector.len == actual->data.vector.len && |
| 957 | types_have_same_zig_comptime_repr(codegen, expected->data.vector.elem_type, actual->data.vector.elem_type); |
| 953 | 958 | case ZigTypeIdArray: |
| 954 | 959 | return expected->data.array.len == actual->data.array.len && |
| 955 | 960 | expected->data.array.child_type == actual->data.array.child_type && |
| ... | ... | @@ -12190,6 +12195,24 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted |
| 12190 | 12195 | return result; |
| 12191 | 12196 | } |
| 12192 | 12197 | |
| 12198 | if (wanted_type->id == ZigTypeIdVector && actual_type->id == ZigTypeIdVector) { |
| 12199 | if (actual_type->data.vector.len != wanted_type->data.vector.len) { |
| 12200 | result.id = ConstCastResultIdVectorLength; |
| 12201 | return result; |
| 12202 | } |
| 12203 | |
| 12204 | ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.vector.elem_type, |
| 12205 | actual_type->data.vector.elem_type, source_node, false); |
| 12206 | if (child.id == ConstCastResultIdInvalid) |
| 12207 | return child; |
| 12208 | if (child.id != ConstCastResultIdOk) { |
| 12209 | result.id = ConstCastResultIdVectorChild; |
| 12210 | return result; |
| 12211 | } |
| 12212 | |
| 12213 | return result; |
| 12214 | } |
| 12215 | |
| 12193 | 12216 | result.id = ConstCastResultIdType; |
| 12194 | 12217 | result.data.type_mismatch = heap::c_allocator.allocate_nonzero<ConstCastTypeMismatch>(1); |
| 12195 | 12218 | result.data.type_mismatch->wanted_type = wanted_type; |
| ... | ... | @@ -14306,37 +14329,62 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, |
| 14306 | 14329 | return ira->codegen->invalid_inst_gen; |
| 14307 | 14330 | } |
| 14308 | 14331 | |
| 14332 | static bool value_numeric_fits_in_type(ZigValue *value, ZigType *type_entry); |
| 14333 | |
| 14309 | 14334 | static IrInstGen *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInst* source_instr, |
| 14310 | 14335 | IrInstGen *target, ZigType *wanted_type) |
| 14311 | 14336 | { |
| 14312 | | assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdFloat); |
| 14337 | ZigType *wanted_scalar_type = (target->value->type->id == ZigTypeIdVector) ? |
| 14338 | wanted_type->data.vector.elem_type : wanted_type; |
| 14339 | |
| 14340 | assert(wanted_scalar_type->id == ZigTypeIdInt || wanted_scalar_type->id == ZigTypeIdFloat); |
| 14313 | 14341 | |
| 14314 | 14342 | if (instr_is_comptime(target)) { |
| 14315 | 14343 | ZigValue *val = ir_resolve_const(ira, target, UndefBad); |
| 14316 | 14344 | if (!val) |
| 14317 | 14345 | return ira->codegen->invalid_inst_gen; |
| 14318 | | if (wanted_type->id == ZigTypeIdInt) { |
| 14319 | | if (bigint_cmp_zero(&val->data.x_bigint) == CmpLT && !wanted_type->data.integral.is_signed) { |
| 14346 | |
| 14347 | if (wanted_scalar_type->id == ZigTypeIdInt) { |
| 14348 | if (!wanted_scalar_type->data.integral.is_signed && value_cmp_numeric_val_any(val, CmpLT, nullptr)) { |
| 14320 | 14349 | ir_add_error(ira, source_instr, |
| 14321 | 14350 | buf_sprintf("attempt to cast negative value to unsigned integer")); |
| 14322 | 14351 | return ira->codegen->invalid_inst_gen; |
| 14323 | 14352 | } |
| 14324 | | if (!bigint_fits_in_bits(&val->data.x_bigint, wanted_type->data.integral.bit_count, |
| 14325 | | wanted_type->data.integral.is_signed)) |
| 14326 | | { |
| 14353 | if (!value_numeric_fits_in_type(val, wanted_scalar_type)) { |
| 14327 | 14354 | ir_add_error(ira, source_instr, |
| 14328 | 14355 | buf_sprintf("cast from '%s' to '%s' truncates bits", |
| 14329 | | buf_ptr(&target->value->type->name), buf_ptr(&wanted_type->name))); |
| 14356 | buf_ptr(&target->value->type->name), buf_ptr(&wanted_scalar_type->name))); |
| 14330 | 14357 | return ira->codegen->invalid_inst_gen; |
| 14331 | 14358 | } |
| 14332 | 14359 | } |
| 14360 | |
| 14333 | 14361 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 14334 | 14362 | result->value->type = wanted_type; |
| 14335 | | if (wanted_type->id == ZigTypeIdInt) { |
| 14336 | | bigint_init_bigint(&result->value->data.x_bigint, &val->data.x_bigint); |
| 14363 | |
| 14364 | if (wanted_type->id == ZigTypeIdVector) { |
| 14365 | result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(wanted_type->data.vector.len); |
| 14366 | |
| 14367 | for (size_t i = 0; i < wanted_type->data.vector.len; i++) { |
| 14368 | ZigValue *scalar_dest_value = &result->value->data.x_array.data.s_none.elements[i]; |
| 14369 | ZigValue *scalar_src_value = &val->data.x_array.data.s_none.elements[i]; |
| 14370 | |
| 14371 | scalar_dest_value->type = wanted_scalar_type; |
| 14372 | scalar_dest_value->special = ConstValSpecialStatic; |
| 14373 | |
| 14374 | if (wanted_scalar_type->id == ZigTypeIdInt) { |
| 14375 | bigint_init_bigint(&scalar_dest_value->data.x_bigint, &scalar_src_value->data.x_bigint); |
| 14376 | } else { |
| 14377 | float_init_float(scalar_dest_value, scalar_src_value); |
| 14378 | } |
| 14379 | } |
| 14337 | 14380 | } else { |
| 14338 | | float_init_float(result->value, val); |
| 14381 | if (wanted_type->id == ZigTypeIdInt) { |
| 14382 | bigint_init_bigint(&result->value->data.x_bigint, &val->data.x_bigint); |
| 14383 | } else { |
| 14384 | float_init_float(result->value, val); |
| 14385 | } |
| 14339 | 14386 | } |
| 14387 | |
| 14340 | 14388 | return result; |
| 14341 | 14389 | } |
| 14342 | 14390 | |
| ... | ... | @@ -14779,6 +14827,8 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa |
| 14779 | 14827 | actual_signed, actual_type->data.integral.bit_count)); |
| 14780 | 14828 | break; |
| 14781 | 14829 | } |
| 14830 | case ConstCastResultIdVectorLength: // TODO |
| 14831 | case ConstCastResultIdVectorChild: // TODO |
| 14782 | 14832 | case ConstCastResultIdFnAlign: // TODO |
| 14783 | 14833 | case ConstCastResultIdFnVarArgs: // TODO |
| 14784 | 14834 | case ConstCastResultIdFnReturnType: // TODO |
| ... | ... | @@ -15462,12 +15512,35 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, |
| 15462 | 15512 | } |
| 15463 | 15513 | |
| 15464 | 15514 | // @Vector(N,T1) to @Vector(N,T2) |
| 15465 | | if (actual_type->id == ZigTypeIdVector && wanted_type->id == ZigTypeIdVector) { |
| 15466 | | if (actual_type->data.vector.len == wanted_type->data.vector.len && |
| 15467 | | types_match_const_cast_only(ira, wanted_type->data.vector.elem_type, |
| 15468 | | actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk) |
| 15515 | if (actual_type->id == ZigTypeIdVector && wanted_type->id == ZigTypeIdVector && |
| 15516 | actual_type->data.vector.len == wanted_type->data.vector.len) |
| 15517 | { |
| 15518 | ZigType *scalar_actual_type = actual_type->data.vector.elem_type; |
| 15519 | ZigType *scalar_wanted_type = wanted_type->data.vector.elem_type; |
| 15520 | |
| 15521 | // widening conversion |
| 15522 | if (scalar_wanted_type->id == ZigTypeIdInt && |
| 15523 | scalar_actual_type->id == ZigTypeIdInt && |
| 15524 | scalar_wanted_type->data.integral.is_signed == scalar_actual_type->data.integral.is_signed && |
| 15525 | scalar_wanted_type->data.integral.bit_count >= scalar_actual_type->data.integral.bit_count) |
| 15526 | { |
| 15527 | return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); |
| 15528 | } |
| 15529 | |
| 15530 | // small enough unsigned ints can get casted to large enough signed ints |
| 15531 | if (scalar_wanted_type->id == ZigTypeIdInt && scalar_wanted_type->data.integral.is_signed && |
| 15532 | scalar_actual_type->id == ZigTypeIdInt && !scalar_actual_type->data.integral.is_signed && |
| 15533 | scalar_wanted_type->data.integral.bit_count > scalar_actual_type->data.integral.bit_count) |
| 15534 | { |
| 15535 | return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); |
| 15536 | } |
| 15537 | |
| 15538 | // float widening conversion |
| 15539 | if (scalar_wanted_type->id == ZigTypeIdFloat && |
| 15540 | scalar_actual_type->id == ZigTypeIdFloat && |
| 15541 | scalar_wanted_type->data.floating.bit_count >= scalar_actual_type->data.floating.bit_count) |
| 15469 | 15542 | { |
| 15470 | | return ir_analyze_bit_cast(ira, source_instr, value, wanted_type); |
| 15543 | return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); |
| 15471 | 15544 | } |
| 15472 | 15545 | } |
| 15473 | 15546 | |
| ... | ... | @@ -17728,6 +17801,33 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { |
| 17728 | 17801 | zig_unreachable(); |
| 17729 | 17802 | } |
| 17730 | 17803 | |
| 17804 | // Returns true if integer `value` can be converted to `type_entry` without |
| 17805 | // losing data. |
| 17806 | // If `value` is a vector the function returns true if this is valid for every |
| 17807 | // element. |
| 17808 | static bool value_numeric_fits_in_type(ZigValue *value, ZigType *type_entry) { |
| 17809 | assert(value->special == ConstValSpecialStatic); |
| 17810 | assert(type_entry->id == ZigTypeIdInt); |
| 17811 | |
| 17812 | switch (value->type->id) { |
| 17813 | case ZigTypeIdComptimeInt: |
| 17814 | case ZigTypeIdInt: { |
| 17815 | return bigint_fits_in_bits(&value->data.x_bigint, type_entry->data.integral.bit_count, |
| 17816 | type_entry->data.integral.is_signed); |
| 17817 | } |
| 17818 | case ZigTypeIdVector: { |
| 17819 | for (size_t i = 0; i < value->type->data.vector.len; i++) { |
| 17820 | ZigValue *scalar_value = &value->data.x_array.data.s_none.elements[i]; |
| 17821 | const bool result = bigint_fits_in_bits(&scalar_value->data.x_bigint, |
| 17822 | type_entry->data.integral.bit_count, type_entry->data.integral.is_signed); |
| 17823 | if (!result) return false; |
| 17824 | } |
| 17825 | return true; |
| 17826 | } |
| 17827 | default: zig_unreachable(); |
| 17828 | } |
| 17829 | } |
| 17830 | |
| 17731 | 17831 | static bool value_cmp_numeric_val(ZigValue *left, Cmp predicate, ZigValue *right, bool any) { |
| 17732 | 17832 | assert(left->special == ConstValSpecialStatic); |
| 17733 | 17833 | assert(right == nullptr || right->special == ConstValSpecialStatic); |
| ... | ... | @@ -27154,8 +27254,12 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa |
| 27154 | 27254 | if (type_is_invalid(dest_type)) |
| 27155 | 27255 | return ira->codegen->invalid_inst_gen; |
| 27156 | 27256 | |
| 27157 | | if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) { |
| 27158 | | ir_add_error(ira, &instruction->dest_type->base, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); |
| 27257 | ZigType *scalar_dest_type = (dest_type->id == ZigTypeIdVector) ? |
| 27258 | dest_type->data.vector.elem_type : dest_type; |
| 27259 | |
| 27260 | if (scalar_dest_type->id != ZigTypeIdInt && scalar_dest_type->id != ZigTypeIdComptimeInt) { |
| 27261 | ir_add_error(ira, &instruction->dest_type->base, |
| 27262 | buf_sprintf("expected integer type, found '%s'", buf_ptr(&scalar_dest_type->name))); |
| 27159 | 27263 | return ira->codegen->invalid_inst_gen; |
| 27160 | 27264 | } |
| 27161 | 27265 | |
| ... | ... | @@ -27163,13 +27267,16 @@ static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCa |
| 27163 | 27267 | if (type_is_invalid(target->value->type)) |
| 27164 | 27268 | return ira->codegen->invalid_inst_gen; |
| 27165 | 27269 | |
| 27166 | | if (target->value->type->id != ZigTypeIdInt && target->value->type->id != ZigTypeIdComptimeInt) { |
| 27270 | ZigType *scalar_target_type = (target->value->type->id == ZigTypeIdVector) ? |
| 27271 | target->value->type->data.vector.elem_type : target->value->type; |
| 27272 | |
| 27273 | if (scalar_target_type->id != ZigTypeIdInt && scalar_target_type->id != ZigTypeIdComptimeInt) { |
| 27167 | 27274 | ir_add_error(ira, &instruction->target->base, buf_sprintf("expected integer type, found '%s'", |
| 27168 | | buf_ptr(&target->value->type->name))); |
| 27275 | buf_ptr(&scalar_target_type->name))); |
| 27169 | 27276 | return ira->codegen->invalid_inst_gen; |
| 27170 | 27277 | } |
| 27171 | 27278 | |
| 27172 | | if (instr_is_comptime(target) || dest_type->id == ZigTypeIdComptimeInt) { |
| 27279 | if (scalar_dest_type->id == ZigTypeIdComptimeInt) { |
| 27173 | 27280 | ZigValue *val = ir_resolve_const(ira, target, UndefBad); |
| 27174 | 27281 | if (val == nullptr) |
| 27175 | 27282 | return ira->codegen->invalid_inst_gen; |
| ... | ... | @@ -27222,6 +27329,7 @@ static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFlo |
| 27222 | 27329 | if (val == nullptr) |
| 27223 | 27330 | return ira->codegen->invalid_inst_gen; |
| 27224 | 27331 | |
| 27332 | // XXX: This will trigger an assertion failure if dest_type is comptime_float |
| 27225 | 27333 | return ir_analyze_widen_or_shorten(ira, &instruction->target->base, target, dest_type); |
| 27226 | 27334 | } |
| 27227 | 27335 | |