authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-09 00:15:23-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-09 00:26:26-04:00
log6edd81109d16178f1dc688dacee4b38964b617c4
tree7ca6c9b9b183846af311245176d40927076f9304
parent1a9d2f3aae780873eefedaf3fdf095b3cd87b55f

nullable pointers follow const-casting rules

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 still144 // 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}
45804580
4581static 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
4581static uint32_t hash_const_val(ConstExprValue *const_val) {4627static 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 algorithm4697 // 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 algorithm4710 // 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 algorithm4723 // 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;
48134819
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);
48184826
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}
53425350
5351bool 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
5343bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {5397bool 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}
55275541
5542void 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
5528void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {5577void 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}
50225022
5023static 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
5023static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {5096static 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());
50855154
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};
6667
67struct ConstCastErrSetMismatch {68struct 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;
76627664
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 const7680 // 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
91899207
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 }
91979219
...@@ -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);
93479369
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}
93549381
...@@ -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 }
1006310090
1006410091
10065 // explicit cast from child type of maybe type to maybe type10092 // 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 }
1011510143
10116 // explicit cast from [N]T to %[]const T10144 // 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 }
1014510173
10146 // explicit cast from T to %?T10174 // 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 }
1016810196
10169 // explicit cast from number literal to another type10197 // explicit cast from number literal to another type
10170 // explicit cast from number literal to &const integer10198 // 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}
1071010739
10740static 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
10711static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {10750static 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
1420714248
14208static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {14249static 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;
1477414818
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 }
1477914823
...@@ -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);
1483814882
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: type16264 // 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
1666416713
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");
1666616715
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];
1667116719
...@@ -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);
1667816726
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 else16729 } 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 }
1668616733
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
1673716784
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);
1673916786
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];
1674416790
...@@ -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);
1675116797
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 else16800 } 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 }
1676216807
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
19936static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) {19978static 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 @@
1const assert = @import("std").debug.assert;1const std = @import("std");
2const mem = @import("std").mem;2const assert = std.debug.assert;
3const mem = std.mem;
34
4test "int to ptr cast" {5test "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}
402403
404test "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}