Skip to content

Commit 6edd811

Browse files
committedJun 9, 2018
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.
·
0.15.20.3.0
1 parent 1a9d2f3 commit 6edd811

File tree

5 files changed

+322
-252
lines changed

5 files changed

+322
-252
lines changed
 

‎src/all_types.hpp‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ enum ConstPtrSpecial {
144144
// understand the value of pointee at compile time. However, we will still
145145
// emit a binary with a compile time known address.
146146
// 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
147150
ConstPtrSpecialHardCodedAddr,
148151
// This means that the pointer represents memory of assigning to _.
149152
// That is, storing discards the data, and loading is invalid.
@@ -251,7 +254,7 @@ struct ConstExprValue {
251254
bool x_bool;
252255
ConstBoundFnValue x_bound_fn;
253256
TypeTableEntry *x_type;
254-
ConstExprValue *x_maybe;
257+
ConstExprValue *x_nullable;
255258
ConstErrValue x_err_union;
256259
ErrorTableEntry *x_err_set;
257260
BigInt x_enum_tag;

‎src/analyze.cpp‎

Lines changed: 150 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -4578,6 +4578,52 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
45784578
return true;
45794579
}
45804580

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+
45814627
static uint32_t hash_const_val(ConstExprValue *const_val) {
45824628
assert(const_val->special == ConstValSpecialStatic);
45834629
switch (const_val->type->id) {
@@ -4646,51 +4692,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
46464692
assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction);
46474693
return 3677364617 ^ hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
46484694
case TypeTableEntryIdPointer:
4649-
{
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-
}
4695+
return hash_const_val_ptr(const_val);
46944696
case TypeTableEntryIdPromise:
46954697
// TODO better hashing algorithm
46964698
return 223048345;
@@ -4708,10 +4710,14 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
47084710
// TODO better hashing algorithm
47094711
return 2709806591;
47104712
case TypeTableEntryIdMaybe:
4711-
if (const_val->data.x_maybe) {
4712-
return hash_const_val(const_val->data.x_maybe) * 1992916303;
4713+
if (get_codegen_ptr_type(const_val->type) != nullptr) {
4714+
return hash_const_val(const_val) * 1992916303;
47134715
} 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+
}
47154721
}
47164722
case TypeTableEntryIdErrorUnion:
47174723
// TODO better hashing algorithm
@@ -4812,9 +4818,11 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
48124818
return false;
48134819

48144820
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)
48164824
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

48194827
case TypeTableEntryIdErrorUnion:
48204828
if (value->data.x_err_union.err != nullptr)
@@ -5340,6 +5348,52 @@ bool ir_get_var_is_comptime(VariableTableEntry *var) {
53405348
return var->is_comptime->value.data.x_bool;
53415349
}
53425350

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+
53435397
bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
53445398
assert(a->type->id == b->type->id);
53455399
assert(a->special == ConstValSpecialStatic);
@@ -5391,49 +5445,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
53915445
return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
53925446
case TypeTableEntryIdPointer:
53935447
case TypeTableEntryIdFn:
5394-
if (a->data.x_ptr.special != b->data.x_ptr.special)
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();
5448+
return const_values_equal_ptr(a, b);
54375449
case TypeTableEntryIdArray:
54385450
zig_panic("TODO");
54395451
case TypeTableEntryIdStruct:
@@ -5449,10 +5461,12 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
54495461
case TypeTableEntryIdNull:
54505462
zig_panic("TODO");
54515463
case TypeTableEntryIdMaybe:
5452-
if (a->data.x_maybe == nullptr || b->data.x_maybe == nullptr) {
5453-
return (a->data.x_maybe == nullptr && b->data.x_maybe == nullptr);
5464+
if (get_codegen_ptr_type(a->type) != 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);
54545468
} 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);
54565470
}
54575471
case TypeTableEntryIdErrorUnion:
54585472
zig_panic("TODO");
@@ -5525,6 +5539,41 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
55255539
}
55265540
}
55275541

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+
55285577
void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
55295578
switch (const_val->special) {
55305579
case ConstValSpecialRuntime:
@@ -5601,38 +5650,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
56015650
return;
56025651
}
56035652
case TypeTableEntryIdPointer:
5604-
switch (const_val->data.x_ptr.special) {
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();
5653+
return render_const_val_ptr(g, buf, const_val, type_entry);
56365654
case TypeTableEntryIdBlock:
56375655
{
56385656
AstNode *node = const_val->data.x_block->source_node;
@@ -5692,8 +5710,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
56925710
}
56935711
case TypeTableEntryIdMaybe:
56945712
{
5695-
if (const_val->data.x_maybe) {
5696-
render_const_value(g, buf, const_val->data.x_maybe);
5713+
if (get_codegen_ptr_type(const_val->type) != nullptr)
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);
56975717
} else {
56985718
buf_appendf(buf, "null");
56995719
}

0 commit comments

Comments
 (0)
Please sign in to comment.