| author | |
| committer | |
| log | 6edd81109d16178f1dc688dacee4b38964b617c4 |
| tree | 7ca6c9b9b183846af311245176d40927076f9304 |
| parent | 1a9d2f3aae780873eefedaf3fdf095b3cd87b55f |
any *T -> ?*T cast is allowed implicitly, even
when it occurs deep inside the type, and the cast
is a no-op at runtime.
in order to add this I had to make the comptime value
representation of nullable pointers the same as the
comptime value representation of normal pointers,
so that we don't have to do any recursive transformation
of values when doing this kind of cast.5 files changed, 322 insertions(+), 252 deletions(-)
src/all_types.hpp+4-1| ... | @@ -144,6 +144,9 @@ enum ConstPtrSpecial { | ... | @@ -144,6 +144,9 @@ enum ConstPtrSpecial { |
| 144 | // understand the value of pointee at compile time. However, we will still | 144 | // understand the value of pointee at compile time. However, we will still |
| 145 | // emit a binary with a compile time known address. | 145 | // emit a binary with a compile time known address. |
| 146 | // In this case index is the numeric address value. | 146 | // In this case index is the numeric address value. |
| 147 | // We also use this for null pointer. We need the data layout for ConstCastOnly == true | ||
| 148 | // types to be the same, so all nullables of pointer types use x_ptr | ||
| 149 | // instead of x_nullable | ||
| 147 | ConstPtrSpecialHardCodedAddr, | 150 | ConstPtrSpecialHardCodedAddr, |
| 148 | // This means that the pointer represents memory of assigning to _. | 151 | // This means that the pointer represents memory of assigning to _. |
| 149 | // That is, storing discards the data, and loading is invalid. | 152 | // That is, storing discards the data, and loading is invalid. |
| ... | @@ -251,7 +254,7 @@ struct ConstExprValue { | ... | @@ -251,7 +254,7 @@ struct ConstExprValue { |
| 251 | bool x_bool; | 254 | bool x_bool; |
| 252 | ConstBoundFnValue x_bound_fn; | 255 | ConstBoundFnValue x_bound_fn; |
| 253 | TypeTableEntry *x_type; | 256 | TypeTableEntry *x_type; |
| 254 | ConstExprValue *x_maybe; | 257 | ConstExprValue *x_nullable; |
| 255 | ConstErrValue x_err_union; | 258 | ConstErrValue x_err_union; |
| 256 | ErrorTableEntry *x_err_set; | 259 | ErrorTableEntry *x_err_set; |
| 257 | BigInt x_enum_tag; | 260 | BigInt x_enum_tag; |
src/analyze.cpp+150-130| ... | @@ -4578,6 +4578,52 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { | ... | @@ -4578,6 +4578,52 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { |
| 4578 | return true; | 4578 | return true; |
| 4579 | } | 4579 | } |
| 4580 | 4580 | ||
| 4581 | static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { | ||
| 4582 | uint32_t hash_val = 0; | ||
| 4583 | switch (const_val->data.x_ptr.mut) { | ||
| 4584 | case ConstPtrMutRuntimeVar: | ||
| 4585 | hash_val += (uint32_t)3500721036; | ||
| 4586 | break; | ||
| 4587 | case ConstPtrMutComptimeConst: | ||
| 4588 | hash_val += (uint32_t)4214318515; | ||
| 4589 | break; | ||
| 4590 | case ConstPtrMutComptimeVar: | ||
| 4591 | hash_val += (uint32_t)1103195694; | ||
| 4592 | break; | ||
| 4593 | } | ||
| 4594 | switch (const_val->data.x_ptr.special) { | ||
| 4595 | case ConstPtrSpecialInvalid: | ||
| 4596 | zig_unreachable(); | ||
| 4597 | case ConstPtrSpecialRef: | ||
| 4598 | hash_val += (uint32_t)2478261866; | ||
| 4599 | hash_val += hash_ptr(const_val->data.x_ptr.data.ref.pointee); | ||
| 4600 | return hash_val; | ||
| 4601 | case ConstPtrSpecialBaseArray: | ||
| 4602 | hash_val += (uint32_t)1764906839; | ||
| 4603 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val); | ||
| 4604 | hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index); | ||
| 4605 | hash_val += const_val->data.x_ptr.data.base_array.is_cstr ? 1297263887 : 200363492; | ||
| 4606 | return hash_val; | ||
| 4607 | case ConstPtrSpecialBaseStruct: | ||
| 4608 | hash_val += (uint32_t)3518317043; | ||
| 4609 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); | ||
| 4610 | hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index); | ||
| 4611 | return hash_val; | ||
| 4612 | case ConstPtrSpecialHardCodedAddr: | ||
| 4613 | hash_val += (uint32_t)4048518294; | ||
| 4614 | hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr); | ||
| 4615 | return hash_val; | ||
| 4616 | case ConstPtrSpecialDiscard: | ||
| 4617 | hash_val += 2010123162; | ||
| 4618 | return hash_val; | ||
| 4619 | case ConstPtrSpecialFunction: | ||
| 4620 | hash_val += (uint32_t)2590901619; | ||
| 4621 | hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); | ||
| 4622 | return hash_val; | ||
| 4623 | } | ||
| 4624 | zig_unreachable(); | ||
| 4625 | } | ||
| 4626 | |||
| 4581 | static uint32_t hash_const_val(ConstExprValue *const_val) { | 4627 | static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4582 | assert(const_val->special == ConstValSpecialStatic); | 4628 | assert(const_val->special == ConstValSpecialStatic); |
| 4583 | switch (const_val->type->id) { | 4629 | switch (const_val->type->id) { |
| ... | @@ -4646,51 +4692,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -4646,51 +4692,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4646 | assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); | 4692 | assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); |
| 4647 | return 3677364617 ^ hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); | 4693 | return 3677364617 ^ hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); |
| 4648 | case TypeTableEntryIdPointer: | 4694 | case TypeTableEntryIdPointer: |
| 4649 | { | 4695 | return hash_const_val_ptr(const_val); |
| 4650 | uint32_t hash_val = 0; | ||
| 4651 | switch (const_val->data.x_ptr.mut) { | ||
| 4652 | case ConstPtrMutRuntimeVar: | ||
| 4653 | hash_val += (uint32_t)3500721036; | ||
| 4654 | break; | ||
| 4655 | case ConstPtrMutComptimeConst: | ||
| 4656 | hash_val += (uint32_t)4214318515; | ||
| 4657 | break; | ||
| 4658 | case ConstPtrMutComptimeVar: | ||
| 4659 | hash_val += (uint32_t)1103195694; | ||
| 4660 | break; | ||
| 4661 | } | ||
| 4662 | switch (const_val->data.x_ptr.special) { | ||
| 4663 | case ConstPtrSpecialInvalid: | ||
| 4664 | zig_unreachable(); | ||
| 4665 | case ConstPtrSpecialRef: | ||
| 4666 | hash_val += (uint32_t)2478261866; | ||
| 4667 | hash_val += hash_ptr(const_val->data.x_ptr.data.ref.pointee); | ||
| 4668 | return hash_val; | ||
| 4669 | case ConstPtrSpecialBaseArray: | ||
| 4670 | hash_val += (uint32_t)1764906839; | ||
| 4671 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val); | ||
| 4672 | hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index); | ||
| 4673 | hash_val += const_val->data.x_ptr.data.base_array.is_cstr ? 1297263887 : 200363492; | ||
| 4674 | return hash_val; | ||
| 4675 | case ConstPtrSpecialBaseStruct: | ||
| 4676 | hash_val += (uint32_t)3518317043; | ||
| 4677 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); | ||
| 4678 | hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index); | ||
| 4679 | return hash_val; | ||
| 4680 | case ConstPtrSpecialHardCodedAddr: | ||
| 4681 | hash_val += (uint32_t)4048518294; | ||
| 4682 | hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr); | ||
| 4683 | return hash_val; | ||
| 4684 | case ConstPtrSpecialDiscard: | ||
| 4685 | hash_val += 2010123162; | ||
| 4686 | return hash_val; | ||
| 4687 | case ConstPtrSpecialFunction: | ||
| 4688 | hash_val += (uint32_t)2590901619; | ||
| 4689 | hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); | ||
| 4690 | return hash_val; | ||
| 4691 | } | ||
| 4692 | zig_unreachable(); | ||
| 4693 | } | ||
| 4694 | case TypeTableEntryIdPromise: | 4696 | case TypeTableEntryIdPromise: |
| 4695 | // TODO better hashing algorithm | 4697 | // TODO better hashing algorithm |
| 4696 | return 223048345; | 4698 | return 223048345; |
| ... | @@ -4708,10 +4710,14 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -4708,10 +4710,14 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4708 | // TODO better hashing algorithm | 4710 | // TODO better hashing algorithm |
| 4709 | return 2709806591; | 4711 | return 2709806591; |
| 4710 | case TypeTableEntryIdMaybe: | 4712 | case TypeTableEntryIdMaybe: |
| 4711 | if (const_val->data.x_maybe) { | 4713 | if (get_codegen_ptr_type(const_val->type) != nullptr) { |
| 4712 | return hash_const_val(const_val->data.x_maybe) * 1992916303; | 4714 | return hash_const_val(const_val) * 1992916303; |
| 4713 | } else { | 4715 | } else { |
| 4714 | return 4016830364; | 4716 | if (const_val->data.x_nullable) { |
| 4717 | return hash_const_val(const_val->data.x_nullable) * 1992916303; | ||
| 4718 | } else { | ||
| 4719 | return 4016830364; | ||
| 4720 | } | ||
| 4715 | } | 4721 | } |
| 4716 | case TypeTableEntryIdErrorUnion: | 4722 | case TypeTableEntryIdErrorUnion: |
| 4717 | // TODO better hashing algorithm | 4723 | // TODO better hashing algorithm |
| ... | @@ -4812,9 +4818,11 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { | ... | @@ -4812,9 +4818,11 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4812 | return false; | 4818 | return false; |
| 4813 | 4819 | ||
| 4814 | case TypeTableEntryIdMaybe: | 4820 | case TypeTableEntryIdMaybe: |
| 4815 | if (value->data.x_maybe == nullptr) | 4821 | if (get_codegen_ptr_type(value->type) != nullptr) |
| 4822 | return value->data.x_ptr.mut == ConstPtrMutComptimeVar; | ||
| 4823 | if (value->data.x_nullable == nullptr) | ||
| 4816 | return false; | 4824 | return false; |
| 4817 | return can_mutate_comptime_var_state(value->data.x_maybe); | 4825 | return can_mutate_comptime_var_state(value->data.x_nullable); |
| 4818 | 4826 | ||
| 4819 | case TypeTableEntryIdErrorUnion: | 4827 | case TypeTableEntryIdErrorUnion: |
| 4820 | if (value->data.x_err_union.err != nullptr) | 4828 | if (value->data.x_err_union.err != nullptr) |
| ... | @@ -5340,6 +5348,52 @@ bool ir_get_var_is_comptime(VariableTableEntry *var) { | ... | @@ -5340,6 +5348,52 @@ bool ir_get_var_is_comptime(VariableTableEntry *var) { |
| 5340 | return var->is_comptime->value.data.x_bool; | 5348 | return var->is_comptime->value.data.x_bool; |
| 5341 | } | 5349 | } |
| 5342 | 5350 | ||
| 5351 | bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { | ||
| 5352 | if (a->data.x_ptr.special != b->data.x_ptr.special) | ||
| 5353 | return false; | ||
| 5354 | if (a->data.x_ptr.mut != b->data.x_ptr.mut) | ||
| 5355 | return false; | ||
| 5356 | switch (a->data.x_ptr.special) { | ||
| 5357 | case ConstPtrSpecialInvalid: | ||
| 5358 | zig_unreachable(); | ||
| 5359 | case ConstPtrSpecialRef: | ||
| 5360 | if (a->data.x_ptr.data.ref.pointee != b->data.x_ptr.data.ref.pointee) | ||
| 5361 | return false; | ||
| 5362 | return true; | ||
| 5363 | case ConstPtrSpecialBaseArray: | ||
| 5364 | if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val && | ||
| 5365 | a->data.x_ptr.data.base_array.array_val->global_refs != | ||
| 5366 | b->data.x_ptr.data.base_array.array_val->global_refs) | ||
| 5367 | { | ||
| 5368 | return false; | ||
| 5369 | } | ||
| 5370 | if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index) | ||
| 5371 | return false; | ||
| 5372 | if (a->data.x_ptr.data.base_array.is_cstr != b->data.x_ptr.data.base_array.is_cstr) | ||
| 5373 | return false; | ||
| 5374 | return true; | ||
| 5375 | case ConstPtrSpecialBaseStruct: | ||
| 5376 | if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val && | ||
| 5377 | a->data.x_ptr.data.base_struct.struct_val->global_refs != | ||
| 5378 | b->data.x_ptr.data.base_struct.struct_val->global_refs) | ||
| 5379 | { | ||
| 5380 | return false; | ||
| 5381 | } | ||
| 5382 | if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index) | ||
| 5383 | return false; | ||
| 5384 | return true; | ||
| 5385 | case ConstPtrSpecialHardCodedAddr: | ||
| 5386 | if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) | ||
| 5387 | return false; | ||
| 5388 | return true; | ||
| 5389 | case ConstPtrSpecialDiscard: | ||
| 5390 | return true; | ||
| 5391 | case ConstPtrSpecialFunction: | ||
| 5392 | return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; | ||
| 5393 | } | ||
| 5394 | zig_unreachable(); | ||
| 5395 | } | ||
| 5396 | |||
| 5343 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | 5397 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5344 | assert(a->type->id == b->type->id); | 5398 | assert(a->type->id == b->type->id); |
| 5345 | assert(a->special == ConstValSpecialStatic); | 5399 | assert(a->special == ConstValSpecialStatic); |
| ... | @@ -5391,49 +5445,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5391,49 +5445,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5391 | return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ; | 5445 | return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ; |
| 5392 | case TypeTableEntryIdPointer: | 5446 | case TypeTableEntryIdPointer: |
| 5393 | case TypeTableEntryIdFn: | 5447 | case TypeTableEntryIdFn: |
| 5394 | if (a->data.x_ptr.special != b->data.x_ptr.special) | 5448 | return const_values_equal_ptr(a, b); |
| 5395 | return false; | ||
| 5396 | if (a->data.x_ptr.mut != b->data.x_ptr.mut) | ||
| 5397 | return false; | ||
| 5398 | switch (a->data.x_ptr.special) { | ||
| 5399 | case ConstPtrSpecialInvalid: | ||
| 5400 | zig_unreachable(); | ||
| 5401 | case ConstPtrSpecialRef: | ||
| 5402 | if (a->data.x_ptr.data.ref.pointee != b->data.x_ptr.data.ref.pointee) | ||
| 5403 | return false; | ||
| 5404 | return true; | ||
| 5405 | case ConstPtrSpecialBaseArray: | ||
| 5406 | if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val && | ||
| 5407 | a->data.x_ptr.data.base_array.array_val->global_refs != | ||
| 5408 | b->data.x_ptr.data.base_array.array_val->global_refs) | ||
| 5409 | { | ||
| 5410 | return false; | ||
| 5411 | } | ||
| 5412 | if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index) | ||
| 5413 | return false; | ||
| 5414 | if (a->data.x_ptr.data.base_array.is_cstr != b->data.x_ptr.data.base_array.is_cstr) | ||
| 5415 | return false; | ||
| 5416 | return true; | ||
| 5417 | case ConstPtrSpecialBaseStruct: | ||
| 5418 | if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val && | ||
| 5419 | a->data.x_ptr.data.base_struct.struct_val->global_refs != | ||
| 5420 | b->data.x_ptr.data.base_struct.struct_val->global_refs) | ||
| 5421 | { | ||
| 5422 | return false; | ||
| 5423 | } | ||
| 5424 | if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index) | ||
| 5425 | return false; | ||
| 5426 | return true; | ||
| 5427 | case ConstPtrSpecialHardCodedAddr: | ||
| 5428 | if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) | ||
| 5429 | return false; | ||
| 5430 | return true; | ||
| 5431 | case ConstPtrSpecialDiscard: | ||
| 5432 | return true; | ||
| 5433 | case ConstPtrSpecialFunction: | ||
| 5434 | return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; | ||
| 5435 | } | ||
| 5436 | zig_unreachable(); | ||
| 5437 | case TypeTableEntryIdArray: | 5449 | case TypeTableEntryIdArray: |
| 5438 | zig_panic("TODO"); | 5450 | zig_panic("TODO"); |
| 5439 | case TypeTableEntryIdStruct: | 5451 | case TypeTableEntryIdStruct: |
| ... | @@ -5449,10 +5461,12 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5449,10 +5461,12 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5449 | case TypeTableEntryIdNull: | 5461 | case TypeTableEntryIdNull: |
| 5450 | zig_panic("TODO"); | 5462 | zig_panic("TODO"); |
| 5451 | case TypeTableEntryIdMaybe: | 5463 | case TypeTableEntryIdMaybe: |
| 5452 | if (a->data.x_maybe == nullptr || b->data.x_maybe == nullptr) { | 5464 | if (get_codegen_ptr_type(a->type) != nullptr) |
| 5453 | return (a->data.x_maybe == nullptr && b->data.x_maybe == nullptr); | 5465 | return const_values_equal_ptr(a, b); |
| 5466 | if (a->data.x_nullable == nullptr || b->data.x_nullable == nullptr) { | ||
| 5467 | return (a->data.x_nullable == nullptr && b->data.x_nullable == nullptr); | ||
| 5454 | } else { | 5468 | } else { |
| 5455 | return const_values_equal(a->data.x_maybe, b->data.x_maybe); | 5469 | return const_values_equal(a->data.x_nullable, b->data.x_nullable); |
| 5456 | } | 5470 | } |
| 5457 | case TypeTableEntryIdErrorUnion: | 5471 | case TypeTableEntryIdErrorUnion: |
| 5458 | zig_panic("TODO"); | 5472 | zig_panic("TODO"); |
| ... | @@ -5525,6 +5539,41 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue * | ... | @@ -5525,6 +5539,41 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue * |
| 5525 | } | 5539 | } |
| 5526 | } | 5540 | } |
| 5527 | 5541 | ||
| 5542 | void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, TypeTableEntry *type_entry) { | ||
| 5543 | switch (const_val->data.x_ptr.special) { | ||
| 5544 | case ConstPtrSpecialInvalid: | ||
| 5545 | zig_unreachable(); | ||
| 5546 | case ConstPtrSpecialRef: | ||
| 5547 | case ConstPtrSpecialBaseStruct: | ||
| 5548 | buf_appendf(buf, "*"); | ||
| 5549 | render_const_value(g, buf, const_ptr_pointee(g, const_val)); | ||
| 5550 | return; | ||
| 5551 | case ConstPtrSpecialBaseArray: | ||
| 5552 | if (const_val->data.x_ptr.data.base_array.is_cstr) { | ||
| 5553 | buf_appendf(buf, "*(c str lit)"); | ||
| 5554 | return; | ||
| 5555 | } else { | ||
| 5556 | buf_appendf(buf, "*"); | ||
| 5557 | render_const_value(g, buf, const_ptr_pointee(g, const_val)); | ||
| 5558 | return; | ||
| 5559 | } | ||
| 5560 | case ConstPtrSpecialHardCodedAddr: | ||
| 5561 | buf_appendf(buf, "(*%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->data.pointer.child_type->name), | ||
| 5562 | const_val->data.x_ptr.data.hard_coded_addr.addr); | ||
| 5563 | return; | ||
| 5564 | case ConstPtrSpecialDiscard: | ||
| 5565 | buf_append_str(buf, "*_"); | ||
| 5566 | return; | ||
| 5567 | case ConstPtrSpecialFunction: | ||
| 5568 | { | ||
| 5569 | FnTableEntry *fn_entry = const_val->data.x_ptr.data.fn.fn_entry; | ||
| 5570 | buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); | ||
| 5571 | return; | ||
| 5572 | } | ||
| 5573 | } | ||
| 5574 | zig_unreachable(); | ||
| 5575 | } | ||
| 5576 | |||
| 5528 | void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | 5577 | void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5529 | switch (const_val->special) { | 5578 | switch (const_val->special) { |
| 5530 | case ConstValSpecialRuntime: | 5579 | case ConstValSpecialRuntime: |
| ... | @@ -5601,38 +5650,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5601,38 +5650,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5601 | return; | 5650 | return; |
| 5602 | } | 5651 | } |
| 5603 | case TypeTableEntryIdPointer: | 5652 | case TypeTableEntryIdPointer: |
| 5604 | switch (const_val->data.x_ptr.special) { | 5653 | return render_const_val_ptr(g, buf, const_val, type_entry); |
| 5605 | case ConstPtrSpecialInvalid: | ||
| 5606 | zig_unreachable(); | ||
| 5607 | case ConstPtrSpecialRef: | ||
| 5608 | case ConstPtrSpecialBaseStruct: | ||
| 5609 | buf_appendf(buf, "&"); | ||
| 5610 | render_const_value(g, buf, const_ptr_pointee(g, const_val)); | ||
| 5611 | return; | ||
| 5612 | case ConstPtrSpecialBaseArray: | ||
| 5613 | if (const_val->data.x_ptr.data.base_array.is_cstr) { | ||
| 5614 | buf_appendf(buf, "&(c str lit)"); | ||
| 5615 | return; | ||
| 5616 | } else { | ||
| 5617 | buf_appendf(buf, "&"); | ||
| 5618 | render_const_value(g, buf, const_ptr_pointee(g, const_val)); | ||
| 5619 | return; | ||
| 5620 | } | ||
| 5621 | case ConstPtrSpecialHardCodedAddr: | ||
| 5622 | buf_appendf(buf, "(&%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->data.pointer.child_type->name), | ||
| 5623 | const_val->data.x_ptr.data.hard_coded_addr.addr); | ||
| 5624 | return; | ||
| 5625 | case ConstPtrSpecialDiscard: | ||
| 5626 | buf_append_str(buf, "&_"); | ||
| 5627 | return; | ||
| 5628 | case ConstPtrSpecialFunction: | ||
| 5629 | { | ||
| 5630 | FnTableEntry *fn_entry = const_val->data.x_ptr.data.fn.fn_entry; | ||
| 5631 | buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); | ||
| 5632 | return; | ||
| 5633 | } | ||
| 5634 | } | ||
| 5635 | zig_unreachable(); | ||
| 5636 | case TypeTableEntryIdBlock: | 5654 | case TypeTableEntryIdBlock: |
| 5637 | { | 5655 | { |
| 5638 | AstNode *node = const_val->data.x_block->source_node; | 5656 | AstNode *node = const_val->data.x_block->source_node; |
| ... | @@ -5692,8 +5710,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5692,8 +5710,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5692 | } | 5710 | } |
| 5693 | case TypeTableEntryIdMaybe: | 5711 | case TypeTableEntryIdMaybe: |
| 5694 | { | 5712 | { |
| 5695 | if (const_val->data.x_maybe) { | 5713 | if (get_codegen_ptr_type(const_val->type) != nullptr) |
| 5696 | render_const_value(g, buf, const_val->data.x_maybe); | 5714 | return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type); |
| 5715 | if (const_val->data.x_nullable) { | ||
| 5716 | render_const_value(g, buf, const_val->data.x_nullable); | ||
| 5697 | } else { | 5717 | } else { |
| 5698 | buf_appendf(buf, "null"); | 5718 | buf_appendf(buf, "null"); |
| 5699 | } | 5719 | } |
src/codegen.cpp+78-80| ... | @@ -5020,6 +5020,79 @@ static bool is_llvm_value_unnamed_type(TypeTableEntry *type_entry, LLVMValueRef | ... | @@ -5020,6 +5020,79 @@ static bool is_llvm_value_unnamed_type(TypeTableEntry *type_entry, LLVMValueRef |
| 5020 | return LLVMTypeOf(val) != type_entry->type_ref; | 5020 | return LLVMTypeOf(val) != type_entry->type_ref; |
| 5021 | } | 5021 | } |
| 5022 | 5022 | ||
| 5023 | static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, const char *name) { | ||
| 5024 | render_const_val_global(g, const_val, name); | ||
| 5025 | switch (const_val->data.x_ptr.special) { | ||
| 5026 | case ConstPtrSpecialInvalid: | ||
| 5027 | case ConstPtrSpecialDiscard: | ||
| 5028 | zig_unreachable(); | ||
| 5029 | case ConstPtrSpecialRef: | ||
| 5030 | { | ||
| 5031 | ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee; | ||
| 5032 | render_const_val(g, pointee, ""); | ||
| 5033 | render_const_val_global(g, pointee, ""); | ||
| 5034 | ConstExprValue *other_val = pointee; | ||
| 5035 | const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref); | ||
| 5036 | render_const_val_global(g, const_val, ""); | ||
| 5037 | return const_val->global_refs->llvm_value; | ||
| 5038 | } | ||
| 5039 | case ConstPtrSpecialBaseArray: | ||
| 5040 | { | ||
| 5041 | ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; | ||
| 5042 | size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; | ||
| 5043 | assert(array_const_val->type->id == TypeTableEntryIdArray); | ||
| 5044 | if (array_const_val->type->zero_bits) { | ||
| 5045 | // make this a null pointer | ||
| 5046 | TypeTableEntry *usize = g->builtin_types.entry_usize; | ||
| 5047 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | ||
| 5048 | const_val->type->type_ref); | ||
| 5049 | render_const_val_global(g, const_val, ""); | ||
| 5050 | return const_val->global_refs->llvm_value; | ||
| 5051 | } | ||
| 5052 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, | ||
| 5053 | elem_index); | ||
| 5054 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | ||
| 5055 | const_val->global_refs->llvm_value = ptr_val; | ||
| 5056 | render_const_val_global(g, const_val, ""); | ||
| 5057 | return ptr_val; | ||
| 5058 | } | ||
| 5059 | case ConstPtrSpecialBaseStruct: | ||
| 5060 | { | ||
| 5061 | ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val; | ||
| 5062 | assert(struct_const_val->type->id == TypeTableEntryIdStruct); | ||
| 5063 | if (struct_const_val->type->zero_bits) { | ||
| 5064 | // make this a null pointer | ||
| 5065 | TypeTableEntry *usize = g->builtin_types.entry_usize; | ||
| 5066 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | ||
| 5067 | const_val->type->type_ref); | ||
| 5068 | render_const_val_global(g, const_val, ""); | ||
| 5069 | return const_val->global_refs->llvm_value; | ||
| 5070 | } | ||
| 5071 | size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index; | ||
| 5072 | size_t gen_field_index = | ||
| 5073 | struct_const_val->type->data.structure.fields[src_field_index].gen_index; | ||
| 5074 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val, | ||
| 5075 | gen_field_index); | ||
| 5076 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | ||
| 5077 | const_val->global_refs->llvm_value = ptr_val; | ||
| 5078 | render_const_val_global(g, const_val, ""); | ||
| 5079 | return ptr_val; | ||
| 5080 | } | ||
| 5081 | case ConstPtrSpecialHardCodedAddr: | ||
| 5082 | { | ||
| 5083 | uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr; | ||
| 5084 | TypeTableEntry *usize = g->builtin_types.entry_usize; | ||
| 5085 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false), | ||
| 5086 | const_val->type->type_ref); | ||
| 5087 | render_const_val_global(g, const_val, ""); | ||
| 5088 | return const_val->global_refs->llvm_value; | ||
| 5089 | } | ||
| 5090 | case ConstPtrSpecialFunction: | ||
| 5091 | return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); | ||
| 5092 | } | ||
| 5093 | zig_unreachable(); | ||
| 5094 | } | ||
| 5095 | |||
| 5023 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) { | 5096 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) { |
| 5024 | TypeTableEntry *type_entry = const_val->type; | 5097 | TypeTableEntry *type_entry = const_val->type; |
| 5025 | assert(!type_entry->zero_bits); | 5098 | assert(!type_entry->zero_bits); |
| ... | @@ -5068,19 +5141,15 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5068,19 +5141,15 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5068 | { | 5141 | { |
| 5069 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | 5142 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 5070 | if (child_type->zero_bits) { | 5143 | if (child_type->zero_bits) { |
| 5071 | return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false); | 5144 | return LLVMConstInt(LLVMInt1Type(), const_val->data.x_nullable ? 1 : 0, false); |
| 5072 | } else if (type_is_codegen_pointer(child_type)) { | 5145 | } else if (type_is_codegen_pointer(child_type)) { |
| 5073 | if (const_val->data.x_maybe) { | 5146 | return gen_const_val_ptr(g, const_val, name); |
| 5074 | return gen_const_val(g, const_val->data.x_maybe, ""); | ||
| 5075 | } else { | ||
| 5076 | return LLVMConstNull(child_type->type_ref); | ||
| 5077 | } | ||
| 5078 | } else { | 5147 | } else { |
| 5079 | LLVMValueRef child_val; | 5148 | LLVMValueRef child_val; |
| 5080 | LLVMValueRef maybe_val; | 5149 | LLVMValueRef maybe_val; |
| 5081 | bool make_unnamed_struct; | 5150 | bool make_unnamed_struct; |
| 5082 | if (const_val->data.x_maybe) { | 5151 | if (const_val->data.x_nullable) { |
| 5083 | child_val = gen_const_val(g, const_val->data.x_maybe, ""); | 5152 | child_val = gen_const_val(g, const_val->data.x_nullable, ""); |
| 5084 | maybe_val = LLVMConstAllOnes(LLVMInt1Type()); | 5153 | maybe_val = LLVMConstAllOnes(LLVMInt1Type()); |
| 5085 | 5154 | ||
| 5086 | make_unnamed_struct = is_llvm_value_unnamed_type(const_val->type, child_val); | 5155 | make_unnamed_struct = is_llvm_value_unnamed_type(const_val->type, child_val); |
| ... | @@ -5270,78 +5339,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -5270,78 +5339,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5270 | assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | 5339 | assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); |
| 5271 | return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry); | 5340 | return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry); |
| 5272 | case TypeTableEntryIdPointer: | 5341 | case TypeTableEntryIdPointer: |
| 5273 | { | 5342 | return gen_const_val_ptr(g, const_val, name); |
| 5274 | render_const_val_global(g, const_val, name); | ||
| 5275 | switch (const_val->data.x_ptr.special) { | ||
| 5276 | case ConstPtrSpecialInvalid: | ||
| 5277 | case ConstPtrSpecialDiscard: | ||
| 5278 | zig_unreachable(); | ||
| 5279 | case ConstPtrSpecialRef: | ||
| 5280 | { | ||
| 5281 | ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee; | ||
| 5282 | render_const_val(g, pointee, ""); | ||
| 5283 | render_const_val_global(g, pointee, ""); | ||
| 5284 | ConstExprValue *other_val = pointee; | ||
| 5285 | const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref); | ||
| 5286 | render_const_val_global(g, const_val, ""); | ||
| 5287 | return const_val->global_refs->llvm_value; | ||
| 5288 | } | ||
| 5289 | case ConstPtrSpecialBaseArray: | ||
| 5290 | { | ||
| 5291 | ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val; | ||
| 5292 | size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; | ||
| 5293 | assert(array_const_val->type->id == TypeTableEntryIdArray); | ||
| 5294 | if (array_const_val->type->zero_bits) { | ||
| 5295 | // make this a null pointer | ||
| 5296 | TypeTableEntry *usize = g->builtin_types.entry_usize; | ||
| 5297 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | ||
| 5298 | const_val->type->type_ref); | ||
| 5299 | render_const_val_global(g, const_val, ""); | ||
| 5300 | return const_val->global_refs->llvm_value; | ||
| 5301 | } | ||
| 5302 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, | ||
| 5303 | elem_index); | ||
| 5304 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | ||
| 5305 | const_val->global_refs->llvm_value = ptr_val; | ||
| 5306 | render_const_val_global(g, const_val, ""); | ||
| 5307 | return ptr_val; | ||
| 5308 | } | ||
| 5309 | case ConstPtrSpecialBaseStruct: | ||
| 5310 | { | ||
| 5311 | ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val; | ||
| 5312 | assert(struct_const_val->type->id == TypeTableEntryIdStruct); | ||
| 5313 | if (struct_const_val->type->zero_bits) { | ||
| 5314 | // make this a null pointer | ||
| 5315 | TypeTableEntry *usize = g->builtin_types.entry_usize; | ||
| 5316 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | ||
| 5317 | const_val->type->type_ref); | ||
| 5318 | render_const_val_global(g, const_val, ""); | ||
| 5319 | return const_val->global_refs->llvm_value; | ||
| 5320 | } | ||
| 5321 | size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index; | ||
| 5322 | size_t gen_field_index = | ||
| 5323 | struct_const_val->type->data.structure.fields[src_field_index].gen_index; | ||
| 5324 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val, | ||
| 5325 | gen_field_index); | ||
| 5326 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | ||
| 5327 | const_val->global_refs->llvm_value = ptr_val; | ||
| 5328 | render_const_val_global(g, const_val, ""); | ||
| 5329 | return ptr_val; | ||
| 5330 | } | ||
| 5331 | case ConstPtrSpecialHardCodedAddr: | ||
| 5332 | { | ||
| 5333 | uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr; | ||
| 5334 | TypeTableEntry *usize = g->builtin_types.entry_usize; | ||
| 5335 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false), | ||
| 5336 | const_val->type->type_ref); | ||
| 5337 | render_const_val_global(g, const_val, ""); | ||
| 5338 | return const_val->global_refs->llvm_value; | ||
| 5339 | } | ||
| 5340 | case ConstPtrSpecialFunction: | ||
| 5341 | return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); | ||
| 5342 | } | ||
| 5343 | } | ||
| 5344 | zig_unreachable(); | ||
| 5345 | case TypeTableEntryIdErrorUnion: | 5343 | case TypeTableEntryIdErrorUnion: |
| 5346 | { | 5344 | { |
| 5347 | TypeTableEntry *payload_type = type_entry->data.error_union.payload_type; | 5345 | TypeTableEntry *payload_type = type_entry->data.error_union.payload_type; |
src/ir.cpp+82-39| ... | @@ -62,6 +62,7 @@ enum ConstCastResultId { | ... | @@ -62,6 +62,7 @@ enum ConstCastResultId { |
| 62 | ConstCastResultIdType, | 62 | ConstCastResultIdType, |
| 63 | ConstCastResultIdUnresolvedInferredErrSet, | 63 | ConstCastResultIdUnresolvedInferredErrSet, |
| 64 | ConstCastResultIdAsyncAllocatorType, | 64 | ConstCastResultIdAsyncAllocatorType, |
| 65 | ConstCastResultIdNullWrapPtr, | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | struct ConstCastErrSetMismatch { | 68 | struct ConstCastErrSetMismatch { |
| ... | @@ -90,6 +91,7 @@ struct ConstCastOnly { | ... | @@ -90,6 +91,7 @@ struct ConstCastOnly { |
| 90 | ConstCastOnly *error_union_error_set; | 91 | ConstCastOnly *error_union_error_set; |
| 91 | ConstCastOnly *return_type; | 92 | ConstCastOnly *return_type; |
| 92 | ConstCastOnly *async_allocator_type; | 93 | ConstCastOnly *async_allocator_type; |
| 94 | ConstCastOnly *null_wrap_ptr_child; | ||
| 93 | ConstCastArg fn_arg; | 95 | ConstCastArg fn_arg; |
| 94 | ConstCastArgNoAlias arg_no_alias; | 96 | ConstCastArgNoAlias arg_no_alias; |
| 95 | } data; | 97 | } data; |
| ... | @@ -7660,6 +7662,21 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry | ... | @@ -7660,6 +7662,21 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry |
| 7660 | if (expected_type == actual_type) | 7662 | if (expected_type == actual_type) |
| 7661 | return result; | 7663 | return result; |
| 7662 | 7664 | ||
| 7665 | // * and [*] can do a const-cast-only to ?* and ?[*], respectively | ||
| 7666 | if (expected_type->id == TypeTableEntryIdMaybe && | ||
| 7667 | expected_type->data.maybe.child_type->id == TypeTableEntryIdPointer && | ||
| 7668 | actual_type->id == TypeTableEntryIdPointer) | ||
| 7669 | { | ||
| 7670 | ConstCastOnly child = types_match_const_cast_only(ira, | ||
| 7671 | expected_type->data.maybe.child_type, actual_type, source_node); | ||
| 7672 | if (child.id != ConstCastResultIdOk) { | ||
| 7673 | result.id = ConstCastResultIdNullWrapPtr; | ||
| 7674 | result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1); | ||
| 7675 | *result.data.null_wrap_ptr_child = child; | ||
| 7676 | } | ||
| 7677 | return result; | ||
| 7678 | } | ||
| 7679 | |||
| 7663 | // pointer const | 7680 | // pointer const |
| 7664 | if (expected_type->id == TypeTableEntryIdPointer && | 7681 | if (expected_type->id == TypeTableEntryIdPointer && |
| 7665 | actual_type->id == TypeTableEntryIdPointer && | 7682 | actual_type->id == TypeTableEntryIdPointer && |
| ... | @@ -8741,7 +8758,8 @@ static void eval_const_expr_implicit_cast(CastOp cast_op, | ... | @@ -8741,7 +8758,8 @@ static void eval_const_expr_implicit_cast(CastOp cast_op, |
| 8741 | zig_panic("TODO"); | 8758 | zig_panic("TODO"); |
| 8742 | case CastOpNoop: | 8759 | case CastOpNoop: |
| 8743 | { | 8760 | { |
| 8744 | copy_const_val(const_val, other_val, other_val->special == ConstValSpecialStatic); | 8761 | bool same_global_refs = other_val->special == ConstValSpecialStatic; |
| 8762 | copy_const_val(const_val, other_val, same_global_refs); | ||
| 8745 | const_val->type = new_type; | 8763 | const_val->type = new_type; |
| 8746 | break; | 8764 | break; |
| 8747 | } | 8765 | } |
| ... | @@ -9189,9 +9207,13 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -9189,9 +9207,13 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc |
| 9189 | 9207 | ||
| 9190 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | 9208 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9191 | source_instr->scope, source_instr->source_node); | 9209 | source_instr->scope, source_instr->source_node); |
| 9192 | const_instruction->base.value.type = wanted_type; | ||
| 9193 | const_instruction->base.value.special = ConstValSpecialStatic; | 9210 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9194 | const_instruction->base.value.data.x_maybe = val; | 9211 | if (get_codegen_ptr_type(wanted_type) != nullptr) { |
| 9212 | copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst); | ||
| 9213 | } else { | ||
| 9214 | const_instruction->base.value.data.x_nullable = val; | ||
| 9215 | } | ||
| 9216 | const_instruction->base.value.type = wanted_type; | ||
| 9195 | return &const_instruction->base; | 9217 | return &const_instruction->base; |
| 9196 | } | 9218 | } |
| 9197 | 9219 | ||
| ... | @@ -9346,9 +9368,14 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so | ... | @@ -9346,9 +9368,14 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so |
| 9346 | assert(val); | 9368 | assert(val); |
| 9347 | 9369 | ||
| 9348 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node); | 9370 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 9349 | const_instruction->base.value.type = wanted_type; | ||
| 9350 | const_instruction->base.value.special = ConstValSpecialStatic; | 9371 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9351 | const_instruction->base.value.data.x_maybe = nullptr; | 9372 | if (get_codegen_ptr_type(wanted_type) != nullptr) { |
| 9373 | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | ||
| 9374 | const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0; | ||
| 9375 | } else { | ||
| 9376 | const_instruction->base.value.data.x_nullable = nullptr; | ||
| 9377 | } | ||
| 9378 | const_instruction->base.value.type = wanted_type; | ||
| 9352 | return &const_instruction->base; | 9379 | return &const_instruction->base; |
| 9353 | } | 9380 | } |
| 9354 | 9381 | ||
| ... | @@ -10062,7 +10089,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10062,7 +10089,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10062 | } | 10089 | } |
| 10063 | 10090 | ||
| 10064 | 10091 | ||
| 10065 | // explicit cast from child type of maybe type to maybe type | 10092 | // explicit cast from T to ?T |
| 10093 | // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism | ||
| 10066 | if (wanted_type->id == TypeTableEntryIdMaybe) { | 10094 | if (wanted_type->id == TypeTableEntryIdMaybe) { |
| 10067 | TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type; | 10095 | TypeTableEntry *wanted_child_type = wanted_type->data.maybe.child_type; |
| 10068 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk) { | 10096 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node).id == ConstCastResultIdOk) { |
| ... | @@ -10113,7 +10141,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10113,7 +10141,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10113 | } | 10141 | } |
| 10114 | } | 10142 | } |
| 10115 | 10143 | ||
| 10116 | // explicit cast from [N]T to %[]const T | 10144 | // explicit cast from [N]T to E![]const T |
| 10117 | if (wanted_type->id == TypeTableEntryIdErrorUnion && | 10145 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 10118 | is_slice(wanted_type->data.error_union.payload_type) && | 10146 | is_slice(wanted_type->data.error_union.payload_type) && |
| 10119 | actual_type->id == TypeTableEntryIdArray) | 10147 | actual_type->id == TypeTableEntryIdArray) |
| ... | @@ -10143,7 +10171,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10143,7 +10171,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10143 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); | 10171 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); |
| 10144 | } | 10172 | } |
| 10145 | 10173 | ||
| 10146 | // explicit cast from T to %?T | 10174 | // explicit cast from T to E!?T |
| 10147 | if (wanted_type->id == TypeTableEntryIdErrorUnion && | 10175 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 10148 | wanted_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe && | 10176 | wanted_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe && |
| 10149 | actual_type->id != TypeTableEntryIdMaybe) | 10177 | actual_type->id != TypeTableEntryIdMaybe) |
| ... | @@ -10167,7 +10195,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -10167,7 +10195,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10167 | } | 10195 | } |
| 10168 | 10196 | ||
| 10169 | // explicit cast from number literal to another type | 10197 | // explicit cast from number literal to another type |
| 10170 | // explicit cast from number literal to &const integer | 10198 | // explicit cast from number literal to *const integer |
| 10171 | if (actual_type->id == TypeTableEntryIdComptimeFloat || | 10199 | if (actual_type->id == TypeTableEntryIdComptimeFloat || |
| 10172 | actual_type->id == TypeTableEntryIdComptimeInt) | 10200 | actual_type->id == TypeTableEntryIdComptimeInt) |
| 10173 | { | 10201 | { |
| ... | @@ -10391,6 +10419,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -10391,6 +10419,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 10391 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | 10419 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, |
| 10392 | source_instruction->source_node, child_type); | 10420 | source_instruction->source_node, child_type); |
| 10393 | copy_const_val(&result->value, pointee, ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst); | 10421 | copy_const_val(&result->value, pointee, ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst); |
| 10422 | result->value.type = child_type; | ||
| 10394 | return result; | 10423 | return result; |
| 10395 | } | 10424 | } |
| 10396 | } | 10425 | } |
| ... | @@ -10708,6 +10737,16 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { | ... | @@ -10708,6 +10737,16 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { |
| 10708 | } | 10737 | } |
| 10709 | } | 10738 | } |
| 10710 | 10739 | ||
| 10740 | static bool nullable_value_is_null(ConstExprValue *val) { | ||
| 10741 | assert(val->special == ConstValSpecialStatic); | ||
| 10742 | if (get_codegen_ptr_type(val->type) != nullptr) { | ||
| 10743 | return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | ||
| 10744 | val->data.x_ptr.data.hard_coded_addr.addr == 0; | ||
| 10745 | } else { | ||
| 10746 | return val->data.x_nullable == nullptr; | ||
| 10747 | } | ||
| 10748 | } | ||
| 10749 | |||
| 10711 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 10750 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 10712 | IrInstruction *op1 = bin_op_instruction->op1->other; | 10751 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 10713 | IrInstruction *op2 = bin_op_instruction->op2->other; | 10752 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| ... | @@ -10737,7 +10776,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -10737,7 +10776,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 10737 | ConstExprValue *maybe_val = ir_resolve_const(ira, maybe_op, UndefBad); | 10776 | ConstExprValue *maybe_val = ir_resolve_const(ira, maybe_op, UndefBad); |
| 10738 | if (!maybe_val) | 10777 | if (!maybe_val) |
| 10739 | return ira->codegen->builtin_types.entry_invalid; | 10778 | return ira->codegen->builtin_types.entry_invalid; |
| 10740 | bool is_null = (maybe_val->data.x_maybe == nullptr); | 10779 | bool is_null = nullable_value_is_null(maybe_val); |
| 10741 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base); | 10780 | ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base); |
| 10742 | out_val->data.x_bool = (op_id == IrBinOpCmpEq) ? is_null : !is_null; | 10781 | out_val->data.x_bool = (op_id == IrBinOpCmpEq) ? is_null : !is_null; |
| 10743 | return ira->codegen->builtin_types.entry_bool; | 10782 | return ira->codegen->builtin_types.entry_bool; |
| ... | @@ -12015,7 +12054,9 @@ static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, | ... | @@ -12015,7 +12054,9 @@ static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 12015 | TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type); | 12054 | TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type); |
| 12016 | if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) { | 12055 | if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) { |
| 12017 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 12056 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 12018 | out_val->data.x_maybe = nullptr; | 12057 | assert(get_codegen_ptr_type(nullable_type) != nullptr); |
| 12058 | out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | ||
| 12059 | out_val->data.x_ptr.data.hard_coded_addr.addr = 0; | ||
| 12019 | return nullable_type; | 12060 | return nullable_type; |
| 12020 | } | 12061 | } |
| 12021 | IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope, | 12062 | IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope, |
| ... | @@ -14207,6 +14248,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -14207,6 +14248,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 14207 | 14248 | ||
| 14208 | static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { | 14249 | static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { |
| 14209 | IrInstruction *ptr = load_ptr_instruction->ptr->other; | 14250 | IrInstruction *ptr = load_ptr_instruction->ptr->other; |
| 14251 | if (type_is_invalid(ptr->value.type)) | ||
| 14252 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14253 | |||
| 14210 | IrInstruction *result = ir_get_deref(ira, &load_ptr_instruction->base, ptr); | 14254 | IrInstruction *result = ir_get_deref(ira, &load_ptr_instruction->base, ptr); |
| 14211 | ir_link_new_instruction(result, &load_ptr_instruction->base); | 14255 | ir_link_new_instruction(result, &load_ptr_instruction->base); |
| 14212 | assert(result->value.type); | 14256 | assert(result->value.type); |
| ... | @@ -14773,7 +14817,7 @@ static TypeTableEntry *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIn | ... | @@ -14773,7 +14817,7 @@ static TypeTableEntry *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIn |
| 14773 | return ira->codegen->builtin_types.entry_invalid; | 14817 | return ira->codegen->builtin_types.entry_invalid; |
| 14774 | 14818 | ||
| 14775 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 14819 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14776 | out_val->data.x_bool = (maybe_val->data.x_maybe != nullptr); | 14820 | out_val->data.x_bool = !nullable_value_is_null(maybe_val); |
| 14777 | return ira->codegen->builtin_types.entry_bool; | 14821 | return ira->codegen->builtin_types.entry_bool; |
| 14778 | } | 14822 | } |
| 14779 | 14823 | ||
| ... | @@ -14837,13 +14881,18 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | ... | @@ -14837,13 +14881,18 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 14837 | ConstExprValue *maybe_val = const_ptr_pointee(ira->codegen, val); | 14881 | ConstExprValue *maybe_val = const_ptr_pointee(ira->codegen, val); |
| 14838 | 14882 | ||
| 14839 | if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { | 14883 | if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 14840 | if (!maybe_val->data.x_maybe) { | 14884 | if (nullable_value_is_null(maybe_val)) { |
| 14841 | ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null")); | 14885 | ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null")); |
| 14842 | return ira->codegen->builtin_types.entry_invalid; | 14886 | return ira->codegen->builtin_types.entry_invalid; |
| 14843 | } | 14887 | } |
| 14844 | ConstExprValue *out_val = ir_build_const_from(ira, &unwrap_maybe_instruction->base); | 14888 | ConstExprValue *out_val = ir_build_const_from(ira, &unwrap_maybe_instruction->base); |
| 14845 | out_val->data.x_ptr.special = ConstPtrSpecialRef; | 14889 | out_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 14846 | out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_maybe; | 14890 | out_val->data.x_ptr.mut = val->data.x_ptr.mut; |
| 14891 | if (type_is_codegen_pointer(child_type)) { | ||
| 14892 | out_val->data.x_ptr.data.ref.pointee = maybe_val; | ||
| 14893 | } else { | ||
| 14894 | out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_nullable; | ||
| 14895 | } | ||
| 14847 | return result_type; | 14896 | return result_type; |
| 14848 | } | 14897 | } |
| 14849 | } | 14898 | } |
| ... | @@ -16206,12 +16255,12 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop | ... | @@ -16206,12 +16255,12 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop |
| 16206 | 0, 0); | 16255 | 0, 0); |
| 16207 | fn_def_fields[6].type = get_maybe_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); | 16256 | fn_def_fields[6].type = get_maybe_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); |
| 16208 | if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) { | 16257 | if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) { |
| 16209 | fn_def_fields[6].data.x_maybe = create_const_vals(1); | 16258 | fn_def_fields[6].data.x_nullable = create_const_vals(1); |
| 16210 | ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name); | 16259 | ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name); |
| 16211 | init_const_slice(ira->codegen, fn_def_fields[6].data.x_maybe, lib_name, 0, buf_len(fn_node->lib_name), true); | 16260 | init_const_slice(ira->codegen, fn_def_fields[6].data.x_nullable, lib_name, 0, buf_len(fn_node->lib_name), true); |
| 16261 | } else { | ||
| 16262 | fn_def_fields[6].data.x_nullable = nullptr; | ||
| 16212 | } | 16263 | } |
| 16213 | else | ||
| 16214 | fn_def_fields[6].data.x_maybe = nullptr; | ||
| 16215 | // return_type: type | 16264 | // return_type: type |
| 16216 | ensure_field_index(fn_def_val->type, "return_type", 7); | 16265 | ensure_field_index(fn_def_val->type, "return_type", 7); |
| 16217 | fn_def_fields[7].special = ConstValSpecialStatic; | 16266 | fn_def_fields[7].special = ConstValSpecialStatic; |
| ... | @@ -16664,8 +16713,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t | ... | @@ -16664,8 +16713,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16664 | 16713 | ||
| 16665 | TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField"); | 16714 | TypeTableEntry *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField"); |
| 16666 | 16715 | ||
| 16667 | for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) | 16716 | for (uint32_t union_field_index = 0; union_field_index < union_field_count; union_field_index++) { |
| 16668 | { | ||
| 16669 | TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index]; | 16717 | TypeUnionField *union_field = &type_entry->data.unionation.fields[union_field_index]; |
| 16670 | ConstExprValue *union_field_val = &union_field_array->data.x_array.s_none.elements[union_field_index]; | 16718 | ConstExprValue *union_field_val = &union_field_array->data.x_array.s_none.elements[union_field_index]; |
| 16671 | 16719 | ||
| ... | @@ -16676,12 +16724,11 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t | ... | @@ -16676,12 +16724,11 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16676 | inner_fields[1].special = ConstValSpecialStatic; | 16724 | inner_fields[1].special = ConstValSpecialStatic; |
| 16677 | inner_fields[1].type = get_maybe_type(ira->codegen, type_info_enum_field_type); | 16725 | inner_fields[1].type = get_maybe_type(ira->codegen, type_info_enum_field_type); |
| 16678 | 16726 | ||
| 16679 | if (fields[1].data.x_type == ira->codegen->builtin_types.entry_undef) | 16727 | if (fields[1].data.x_type == ira->codegen->builtin_types.entry_undef) { |
| 16680 | inner_fields[1].data.x_maybe = nullptr; | 16728 | inner_fields[1].data.x_nullable = nullptr; |
| 16681 | else | 16729 | } else { |
| 16682 | { | 16730 | inner_fields[1].data.x_nullable = create_const_vals(1); |
| 16683 | inner_fields[1].data.x_maybe = create_const_vals(1); | 16731 | make_enum_field_val(inner_fields[1].data.x_nullable, union_field->enum_field, type_info_enum_field_type); |
| 16684 | make_enum_field_val(inner_fields[1].data.x_maybe, union_field->enum_field, type_info_enum_field_type); | ||
| 16685 | } | 16732 | } |
| 16686 | 16733 | ||
| 16687 | inner_fields[2].special = ConstValSpecialStatic; | 16734 | inner_fields[2].special = ConstValSpecialStatic; |
| ... | @@ -16737,8 +16784,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t | ... | @@ -16737,8 +16784,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16737 | 16784 | ||
| 16738 | init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); | 16785 | init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); |
| 16739 | 16786 | ||
| 16740 | for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) | 16787 | for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) { |
| 16741 | { | ||
| 16742 | TypeStructField *struct_field = &type_entry->data.structure.fields[struct_field_index]; | 16788 | TypeStructField *struct_field = &type_entry->data.structure.fields[struct_field_index]; |
| 16743 | ConstExprValue *struct_field_val = &struct_field_array->data.x_array.s_none.elements[struct_field_index]; | 16789 | ConstExprValue *struct_field_val = &struct_field_array->data.x_array.s_none.elements[struct_field_index]; |
| 16744 | 16790 | ||
| ... | @@ -16749,15 +16795,14 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t | ... | @@ -16749,15 +16795,14 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16749 | inner_fields[1].special = ConstValSpecialStatic; | 16795 | inner_fields[1].special = ConstValSpecialStatic; |
| 16750 | inner_fields[1].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_usize); | 16796 | inner_fields[1].type = get_maybe_type(ira->codegen, ira->codegen->builtin_types.entry_usize); |
| 16751 | 16797 | ||
| 16752 | if (!type_has_bits(struct_field->type_entry)) | 16798 | if (!type_has_bits(struct_field->type_entry)) { |
| 16753 | inner_fields[1].data.x_maybe = nullptr; | 16799 | inner_fields[1].data.x_nullable = nullptr; |
| 16754 | else | 16800 | } else { |
| 16755 | { | ||
| 16756 | size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index); | 16801 | size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index); |
| 16757 | inner_fields[1].data.x_maybe = create_const_vals(1); | 16802 | inner_fields[1].data.x_nullable = create_const_vals(1); |
| 16758 | inner_fields[1].data.x_maybe->special = ConstValSpecialStatic; | 16803 | inner_fields[1].data.x_nullable->special = ConstValSpecialStatic; |
| 16759 | inner_fields[1].data.x_maybe->type = ira->codegen->builtin_types.entry_usize; | 16804 | inner_fields[1].data.x_nullable->type = ira->codegen->builtin_types.entry_usize; |
| 16760 | bigint_init_unsigned(&inner_fields[1].data.x_maybe->data.x_bigint, byte_offset); | 16805 | bigint_init_unsigned(&inner_fields[1].data.x_nullable->data.x_bigint, byte_offset); |
| 16761 | } | 16806 | } |
| 16762 | 16807 | ||
| 16763 | inner_fields[2].special = ConstValSpecialStatic; | 16808 | inner_fields[2].special = ConstValSpecialStatic; |
| ... | @@ -19008,9 +19053,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr | ... | @@ -19008,9 +19053,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr |
| 19008 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 19053 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 19009 | if (!val) | 19054 | if (!val) |
| 19010 | return ira->codegen->builtin_types.entry_invalid; | 19055 | return ira->codegen->builtin_types.entry_invalid; |
| 19011 | if (target->value.type->id == TypeTableEntryIdMaybe) { | ||
| 19012 | val = val->data.x_maybe; | ||
| 19013 | } | ||
| 19014 | if (val->type->id == TypeTableEntryIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { | 19056 | if (val->type->id == TypeTableEntryIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { |
| 19015 | IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope, | 19057 | IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope, |
| 19016 | instruction->base.source_node, usize); | 19058 | instruction->base.source_node, usize); |
| ... | @@ -19936,6 +19978,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -19936,6 +19978,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 19936 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) { | 19978 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) { |
| 19937 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); | 19979 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); |
| 19938 | instruction->value.type = instruction_type; | 19980 | instruction->value.type = instruction_type; |
| 19981 | |||
| 19939 | if (instruction->other) { | 19982 | if (instruction->other) { |
| 19940 | instruction->other->value.type = instruction_type; | 19983 | instruction->other->value.type = instruction_type; |
| 19941 | } else { | 19984 | } else { |
test/cases/cast.zig+8-2| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const std = @import("std"); |
| 2 | const mem = @import("std").mem; | 2 | const assert = std.debug.assert; |
| 3 | const mem = std.mem; | ||
| 3 | 4 | ||
| 4 | test "int to ptr cast" { | 5 | test "int to ptr cast" { |
| 5 | const x = usize(13); | 6 | const x = usize(13); |
| ... | @@ -400,3 +401,8 @@ fn testCastPtrOfArrayToSliceAndPtr() void { | ... | @@ -400,3 +401,8 @@ fn testCastPtrOfArrayToSliceAndPtr() void { |
| 400 | assert(mem.eql(u8, array[0..], "coeu")); | 401 | assert(mem.eql(u8, array[0..], "coeu")); |
| 401 | } | 402 | } |
| 402 | 403 | ||
| 404 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | ||
| 405 | const window_name = [1][*]const u8{c"window name"}; | ||
| 406 | const x: [*]const ?[*]const u8 = &window_name; | ||
| 407 | assert(mem.eql(u8, std.cstr.toSliceConst(??x[0]), "window name")); | ||
| 408 | } |