aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2018-06-09 00:15:23 -0400
committerAndrew Kelley <superjoe30@gmail.com>2018-06-09 00:26:26 -0400
commit6edd81109d16178f1dc688dacee4b38964b617c4 (patch)
tree7ca6c9b9b183846af311245176d40927076f9304 /src/codegen.cpp
parent1a9d2f3aae780873eefedaf3fdf095b3cd87b55f (diff)
downloadzig-6edd81109d16178f1dc688dacee4b38964b617c4.tar.gz
zig-6edd81109d16178f1dc688dacee4b38964b617c4.zip
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.
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp158
1 files changed, 78 insertions, 80 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index fab2ad659e..65b465a519 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -5020,6 +5020,79 @@ static bool is_llvm_value_unnamed_type(TypeTableEntry *type_entry, LLVMValueRef
return LLVMTypeOf(val) != type_entry->type_ref;
}
+static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, const char *name) {
+ render_const_val_global(g, const_val, name);
+ switch (const_val->data.x_ptr.special) {
+ case ConstPtrSpecialInvalid:
+ case ConstPtrSpecialDiscard:
+ zig_unreachable();
+ case ConstPtrSpecialRef:
+ {
+ ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;
+ render_const_val(g, pointee, "");
+ render_const_val_global(g, pointee, "");
+ ConstExprValue *other_val = pointee;
+ const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref);
+ render_const_val_global(g, const_val, "");
+ return const_val->global_refs->llvm_value;
+ }
+ case ConstPtrSpecialBaseArray:
+ {
+ ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
+ size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
+ assert(array_const_val->type->id == TypeTableEntryIdArray);
+ if (array_const_val->type->zero_bits) {
+ // make this a null pointer
+ TypeTableEntry *usize = g->builtin_types.entry_usize;
+ const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->type->type_ref);
+ render_const_val_global(g, const_val, "");
+ return const_val->global_refs->llvm_value;
+ }
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,
+ elem_index);
+ LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
+ const_val->global_refs->llvm_value = ptr_val;
+ render_const_val_global(g, const_val, "");
+ return ptr_val;
+ }
+ case ConstPtrSpecialBaseStruct:
+ {
+ ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
+ assert(struct_const_val->type->id == TypeTableEntryIdStruct);
+ if (struct_const_val->type->zero_bits) {
+ // make this a null pointer
+ TypeTableEntry *usize = g->builtin_types.entry_usize;
+ const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->type->type_ref);
+ render_const_val_global(g, const_val, "");
+ return const_val->global_refs->llvm_value;
+ }
+ size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
+ size_t gen_field_index =
+ struct_const_val->type->data.structure.fields[src_field_index].gen_index;
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
+ gen_field_index);
+ LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
+ const_val->global_refs->llvm_value = ptr_val;
+ render_const_val_global(g, const_val, "");
+ return ptr_val;
+ }
+ case ConstPtrSpecialHardCodedAddr:
+ {
+ uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
+ TypeTableEntry *usize = g->builtin_types.entry_usize;
+ const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
+ const_val->type->type_ref);
+ render_const_val_global(g, const_val, "");
+ return const_val->global_refs->llvm_value;
+ }
+ case ConstPtrSpecialFunction:
+ return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
+ }
+ zig_unreachable();
+}
+
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
TypeTableEntry *type_entry = const_val->type;
assert(!type_entry->zero_bits);
@@ -5068,19 +5141,15 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
{
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
if (child_type->zero_bits) {
- return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false);
+ return LLVMConstInt(LLVMInt1Type(), const_val->data.x_nullable ? 1 : 0, false);
} else if (type_is_codegen_pointer(child_type)) {
- if (const_val->data.x_maybe) {
- return gen_const_val(g, const_val->data.x_maybe, "");
- } else {
- return LLVMConstNull(child_type->type_ref);
- }
+ return gen_const_val_ptr(g, const_val, name);
} else {
LLVMValueRef child_val;
LLVMValueRef maybe_val;
bool make_unnamed_struct;
- if (const_val->data.x_maybe) {
- child_val = gen_const_val(g, const_val->data.x_maybe, "");
+ if (const_val->data.x_nullable) {
+ child_val = gen_const_val(g, const_val->data.x_nullable, "");
maybe_val = LLVMConstAllOnes(LLVMInt1Type());
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
assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry);
case TypeTableEntryIdPointer:
- {
- render_const_val_global(g, const_val, name);
- switch (const_val->data.x_ptr.special) {
- case ConstPtrSpecialInvalid:
- case ConstPtrSpecialDiscard:
- zig_unreachable();
- case ConstPtrSpecialRef:
- {
- ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;
- render_const_val(g, pointee, "");
- render_const_val_global(g, pointee, "");
- ConstExprValue *other_val = pointee;
- const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
- return const_val->global_refs->llvm_value;
- }
- case ConstPtrSpecialBaseArray:
- {
- ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
- size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
- assert(array_const_val->type->id == TypeTableEntryIdArray);
- if (array_const_val->type->zero_bits) {
- // make this a null pointer
- TypeTableEntry *usize = g->builtin_types.entry_usize;
- const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
- const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
- return const_val->global_refs->llvm_value;
- }
- LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,
- elem_index);
- LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
- const_val->global_refs->llvm_value = ptr_val;
- render_const_val_global(g, const_val, "");
- return ptr_val;
- }
- case ConstPtrSpecialBaseStruct:
- {
- ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
- assert(struct_const_val->type->id == TypeTableEntryIdStruct);
- if (struct_const_val->type->zero_bits) {
- // make this a null pointer
- TypeTableEntry *usize = g->builtin_types.entry_usize;
- const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
- const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
- return const_val->global_refs->llvm_value;
- }
- size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
- size_t gen_field_index =
- struct_const_val->type->data.structure.fields[src_field_index].gen_index;
- LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
- gen_field_index);
- LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
- const_val->global_refs->llvm_value = ptr_val;
- render_const_val_global(g, const_val, "");
- return ptr_val;
- }
- case ConstPtrSpecialHardCodedAddr:
- {
- uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
- TypeTableEntry *usize = g->builtin_types.entry_usize;
- const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
- const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
- return const_val->global_refs->llvm_value;
- }
- case ConstPtrSpecialFunction:
- return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
- }
- }
- zig_unreachable();
+ return gen_const_val_ptr(g, const_val, name);
case TypeTableEntryIdErrorUnion:
{
TypeTableEntry *payload_type = type_entry->data.error_union.payload_type;