authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-11 13:13:45-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-11 13:13:45-05:00
log39287d7346436a87ce785866befa77351bf2fc85
tree0c3e20f4bd3c0dea8f42486177f88f49b71be09c
parent12049aa43b154f75445e616c2699aaff017d8228

rework compile-time known pointer values

See #257

6 files changed, 629 insertions(+), 298 deletions(-)

src/all_types.hpp+55-22
...@@ -67,6 +67,27 @@ enum OutType {...@@ -67,6 +67,27 @@ enum OutType {
67 OutTypeObj,67 OutTypeObj,
68};68};
6969
70enum ConstParentId {
71 ConstParentIdNone,
72 ConstParentIdStruct,
73 ConstParentIdArray,
74};
75
76struct ConstParent {
77 ConstParentId id;
78
79 union {
80 struct {
81 ConstExprValue *array_val;
82 size_t elem_index;
83 } p_array;
84 struct {
85 ConstExprValue *struct_val;
86 size_t field_index;
87 } p_struct;
88 } data;
89};
90
70struct ConstEnumValue {91struct ConstEnumValue {
71 uint64_t tag;92 uint64_t tag;
72 ConstExprValue *payload;93 ConstExprValue *payload;
...@@ -74,43 +95,55 @@ struct ConstEnumValue {...@@ -74,43 +95,55 @@ struct ConstEnumValue {
7495
75struct ConstStructValue {96struct ConstStructValue {
76 ConstExprValue *fields;97 ConstExprValue *fields;
98 ConstParent parent;
77};99};
78100
79struct ConstArrayValue {101struct ConstArrayValue {
80 ConstExprValue *elements;102 ConstExprValue *elements;
81 // This will be the same as `len` from the type, but we duplicate the information103 ConstParent parent;
82 // in the constant value so that pointers pointing to arrays can see this size.
83 // TODO now that ConstExprValue has the type field we can use that instead of this.
84 size_t size;
85 // If the data for this array is supposed to be contained in a different constant
86 // value, we link to the parent here. This way getting a pointer to this constant
87 // value can return a pointer into the parent data structure.
88 ConstExprValue *parent_array;
89 size_t parent_array_index;
90};104};
91105
92enum ConstPtrSpecial {106enum ConstPtrSpecial {
93 ConstPtrSpecialNone,107 // Enforce explicitly setting this ID by making the zero value invalid.
94 // This helps us preserve the null byte when performing compile-time108 ConstPtrSpecialInvalid,
95 // concatenation on C strings.109 // The pointer is a reference to a single object.
96 ConstPtrSpecialCStr,110 ConstPtrSpecialRef,
97 // This means that the pointer points to inline memory, so attempting111 // The pointer points to an element in an underlying array.
98 // to write a non-compile-time known value is an error112 ConstPtrSpecialBaseArray,
99 ConstPtrSpecialInline,113 // The pointer points to a field in an underlying struct.
114 ConstPtrSpecialBaseStruct,
100 // This means that we did a compile-time pointer reinterpret and we cannot115 // This means that we did a compile-time pointer reinterpret and we cannot
101 // understand the value of pointee at compile time. However, we will still116 // understand the value of pointee at compile time. However, we will still
102 // emit a binary with a compile time known address.117 // emit a binary with a compile time known address.
103 // In this case index is the numeric address value.118 // In this case index is the numeric address value.
104 ConstPtrSpecialRuntime,119 ConstPtrSpecialHardCodedAddr,
105};120};
106121
107struct ConstPtrValue {122struct ConstPtrValue {
108 ConstExprValue *base_ptr;
109 // If index is SIZE_MAX, then base_ptr points directly to child type.
110 // Otherwise base_ptr points to an array const val and index is offset
111 // in object units from base_ptr into the block of memory pointed to
112 size_t index;
113 ConstPtrSpecial special;123 ConstPtrSpecial special;
124 // This means that the pointer points to memory used by a comptime variable,
125 // so attempting to write a non-compile-time known value is an error
126 bool comptime_var_mem;
127
128 union {
129 struct {
130 ConstExprValue *pointee;
131 } ref;
132 struct {
133 ConstExprValue *array_val;
134 size_t elem_index;
135 // This helps us preserve the null byte when performing compile-time
136 // concatenation on C strings.
137 bool is_cstr;
138 } base_array;
139 struct {
140 ConstExprValue *struct_val;
141 size_t field_index;
142 } base_struct;
143 struct {
144 uint64_t addr;
145 } hard_coded_addr;
146 } data;
114};147};
115148
116struct ConstErrValue {149struct ConstErrValue {
src/analyze.cpp+110-32
...@@ -2832,7 +2832,33 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -2832,7 +2832,33 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
2832 return const_val->data.x_arg_tuple.start_index * 281907309 +2832 return const_val->data.x_arg_tuple.start_index * 281907309 +
2833 const_val->data.x_arg_tuple.end_index * 2290442768;2833 const_val->data.x_arg_tuple.end_index * 2290442768;
2834 case TypeTableEntryIdPointer:2834 case TypeTableEntryIdPointer:
2835 return hash_ptr(const_val->data.x_ptr.base_ptr) + hash_size(const_val->data.x_ptr.index);2835 {
2836 uint32_t hash_val = const_val->data.x_ptr.comptime_var_mem ? 2216297012 : 170810250;
2837 switch (const_val->data.x_ptr.special) {
2838 case ConstPtrSpecialInvalid:
2839 zig_unreachable();
2840 case ConstPtrSpecialRef:
2841 hash_val += 2478261866;
2842 hash_val += hash_ptr(const_val->data.x_ptr.data.ref.pointee);
2843 return hash_val;
2844 case ConstPtrSpecialBaseArray:
2845 hash_val += 1764906839;
2846 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
2847 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
2848 hash_val += const_val->data.x_ptr.data.base_array.is_cstr ? 1297263887 : 200363492;
2849 return hash_val;
2850 case ConstPtrSpecialBaseStruct:
2851 hash_val += 3518317043;
2852 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
2853 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
2854 return hash_val;
2855 case ConstPtrSpecialHardCodedAddr:
2856 hash_val += 4048518294;
2857 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
2858 return hash_val;
2859 }
2860 zig_unreachable();
2861 }
2836 case TypeTableEntryIdUndefLit:2862 case TypeTableEntryIdUndefLit:
2837 return 162837799;2863 return 162837799;
2838 case TypeTableEntryIdNullLit:2864 case TypeTableEntryIdNullLit:
...@@ -3007,7 +3033,6 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -3007,7 +3033,6 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
3007 const_val->special = ConstValSpecialStatic;3033 const_val->special = ConstValSpecialStatic;
3008 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));3034 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
3009 const_val->data.x_array.elements = allocate<ConstExprValue>(buf_len(str));3035 const_val->data.x_array.elements = allocate<ConstExprValue>(buf_len(str));
3010 const_val->data.x_array.size = buf_len(str);
30113036
3012 for (size_t i = 0; i < buf_len(str); i += 1) {3037 for (size_t i = 0; i < buf_len(str); i += 1) {
3013 ConstExprValue *this_char = &const_val->data.x_array.elements[i];3038 ConstExprValue *this_char = &const_val->data.x_array.elements[i];
...@@ -3030,7 +3055,6 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -3030,7 +3055,6 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
3030 array_val->special = ConstValSpecialStatic;3055 array_val->special = ConstValSpecialStatic;
3031 array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);3056 array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);
3032 array_val->data.x_array.elements = allocate<ConstExprValue>(len_with_null);3057 array_val->data.x_array.elements = allocate<ConstExprValue>(len_with_null);
3033 array_val->data.x_array.size = len_with_null;
3034 for (size_t i = 0; i < buf_len(str); i += 1) {3058 for (size_t i = 0; i < buf_len(str); i += 1) {
3035 ConstExprValue *this_char = &array_val->data.x_array.elements[i];3059 ConstExprValue *this_char = &array_val->data.x_array.elements[i];
3036 this_char->special = ConstValSpecialStatic;3060 this_char->special = ConstValSpecialStatic;
...@@ -3045,9 +3069,10 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -3045,9 +3069,10 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
3045 // then make the pointer point to it3069 // then make the pointer point to it
3046 const_val->special = ConstValSpecialStatic;3070 const_val->special = ConstValSpecialStatic;
3047 const_val->type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);3071 const_val->type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
3048 const_val->data.x_ptr.base_ptr = array_val;3072 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
3049 const_val->data.x_ptr.index = 0;3073 const_val->data.x_ptr.data.base_array.array_val = array_val;
3050 const_val->data.x_ptr.special = ConstPtrSpecialCStr;3074 const_val->data.x_ptr.data.base_array.elem_index = 0;
3075 const_val->data.x_ptr.data.base_array.is_cstr = true;
3051}3076}
3052ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {3077ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
3053 ConstExprValue *const_val = allocate<ConstExprValue>(1);3078 ConstExprValue *const_val = allocate<ConstExprValue>(1);
...@@ -3156,7 +3181,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr...@@ -3156,7 +3181,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
3156 const_val->type = get_slice_type(g, array_val->type->data.array.child_type, is_const);3181 const_val->type = get_slice_type(g, array_val->type->data.array.child_type, is_const);
3157 const_val->data.x_struct.fields = allocate<ConstExprValue>(2);3182 const_val->data.x_struct.fields = allocate<ConstExprValue>(2);
31583183
3159 init_const_ptr(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const);3184 init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const);
3160 init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len);3185 init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len);
3161}3186}
31623187
...@@ -3166,24 +3191,35 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t...@@ -3166,24 +3191,35 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
3166 return const_val;3191 return const_val;
3167}3192}
31683193
3169void init_const_ptr(CodeGen *g, ConstExprValue *const_val, ConstExprValue *base_ptr, size_t index, bool is_const) {3194void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
3170 TypeTableEntry *child_type;3195 size_t elem_index, bool is_const)
3171 if (index == SIZE_MAX) {3196{
3172 child_type = base_ptr->type;3197 assert(array_val->type->id == TypeTableEntryIdArray);
3173 } else {3198 TypeTableEntry *child_type = array_val->type->data.array.child_type;
3174 assert(base_ptr->type->id == TypeTableEntryIdArray);
3175 child_type = base_ptr->type->data.array.child_type;
3176 }
31773199
3178 const_val->special = ConstValSpecialStatic;3200 const_val->special = ConstValSpecialStatic;
3179 const_val->type = get_pointer_to_type(g, child_type, is_const);3201 const_val->type = get_pointer_to_type(g, child_type, is_const);
3180 const_val->data.x_ptr.base_ptr = base_ptr;3202 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
3181 const_val->data.x_ptr.index = index;3203 const_val->data.x_ptr.data.base_array.array_val = array_val;
3204 const_val->data.x_ptr.data.base_array.elem_index = elem_index;
3205}
3206
3207ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const) {
3208 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3209 init_const_ptr_array(g, const_val, array_val, elem_index, is_const);
3210 return const_val;
3211}
3212
3213void init_const_ptr_ref(CodeGen *g, ConstExprValue *const_val, ConstExprValue *pointee_val, bool is_const) {
3214 const_val->special = ConstValSpecialStatic;
3215 const_val->type = get_pointer_to_type(g, pointee_val->type, is_const);
3216 const_val->data.x_ptr.special = ConstPtrSpecialRef;
3217 const_val->data.x_ptr.data.ref.pointee = pointee_val;
3182}3218}
31833219
3184ConstExprValue *create_const_ptr(CodeGen *g, ConstExprValue *base_ptr, size_t index, bool is_const) {3220ConstExprValue *create_const_ptr_ref(CodeGen *g, ConstExprValue *pointee_val, bool is_const) {
3185 ConstExprValue *const_val = allocate<ConstExprValue>(1);3221 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3186 init_const_ptr(g, const_val, base_ptr, index, is_const);3222 init_const_ptr_ref(g, const_val, pointee_val, is_const);
3187 return const_val;3223 return const_val;
3188}3224}
31893225
...@@ -3207,14 +3243,14 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {...@@ -3207,14 +3243,14 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
3207 const_val->special = ConstValSpecialStatic;3243 const_val->special = ConstValSpecialStatic;
3208 size_t elem_count = canon_wanted_type->data.array.len;3244 size_t elem_count = canon_wanted_type->data.array.len;
3209 const_val->data.x_array.elements = allocate<ConstExprValue>(elem_count);3245 const_val->data.x_array.elements = allocate<ConstExprValue>(elem_count);
3210 const_val->data.x_array.size = elem_count;
3211 for (size_t i = 0; i < elem_count; i += 1) {3246 for (size_t i = 0; i < elem_count; i += 1) {
3212 ConstExprValue *element_val = &const_val->data.x_array.elements[i];3247 ConstExprValue *element_val = &const_val->data.x_array.elements[i];
3213 element_val->type = canon_wanted_type->data.array.child_type;3248 element_val->type = canon_wanted_type->data.array.child_type;
3214 init_const_undefined(g, element_val);3249 init_const_undefined(g, element_val);
3215 if (get_underlying_type(element_val->type)->id == TypeTableEntryIdArray) {3250 if (get_underlying_type(element_val->type)->id == TypeTableEntryIdArray) {
3216 element_val->data.x_array.parent_array = const_val;3251 element_val->data.x_array.parent.id = ConstParentIdArray;
3217 element_val->data.x_array.parent_array_index = i;3252 element_val->data.x_array.parent.data.p_array.array_val = const_val;
3253 element_val->data.x_array.parent.data.p_array.elem_index = i;
3218 }3254 }
3219 }3255 }
3220 } else if (canon_wanted_type->id == TypeTableEntryIdStruct) {3256 } else if (canon_wanted_type->id == TypeTableEntryIdStruct) {
...@@ -3301,9 +3337,37 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -3301,9 +3337,37 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
3301 case TypeTableEntryIdEnumTag:3337 case TypeTableEntryIdEnumTag:
3302 return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);3338 return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);
3303 case TypeTableEntryIdPointer:3339 case TypeTableEntryIdPointer:
3304 if (a->data.x_ptr.index != b->data.x_ptr.index)3340 if (a->data.x_ptr.special != b->data.x_ptr.special)
3341 return false;
3342 if (a->data.x_ptr.comptime_var_mem != b->data.x_ptr.comptime_var_mem)
3305 return false;3343 return false;
3306 return a->data.x_ptr.base_ptr == b->data.x_ptr.base_ptr;3344 switch (a->data.x_ptr.special) {
3345 case ConstPtrSpecialInvalid:
3346 zig_unreachable();
3347 case ConstPtrSpecialRef:
3348 if (a->data.x_ptr.data.ref.pointee != b->data.x_ptr.data.ref.pointee)
3349 return false;
3350 return true;
3351 case ConstPtrSpecialBaseArray:
3352 if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val)
3353 return false;
3354 if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
3355 return false;
3356 if (a->data.x_ptr.data.base_array.is_cstr != b->data.x_ptr.data.base_array.is_cstr)
3357 return false;
3358 return true;
3359 case ConstPtrSpecialBaseStruct:
3360 if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val)
3361 return false;
3362 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
3363 return false;
3364 return true;
3365 case ConstPtrSpecialHardCodedAddr:
3366 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
3367 return false;
3368 return true;
3369 }
3370 zig_unreachable();
3307 case TypeTableEntryIdArray:3371 case TypeTableEntryIdArray:
3308 zig_panic("TODO");3372 zig_panic("TODO");
3309 case TypeTableEntryIdStruct:3373 case TypeTableEntryIdStruct:
...@@ -3482,15 +3546,29 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {...@@ -3482,15 +3546,29 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
3482 return;3546 return;
3483 }3547 }
3484 case TypeTableEntryIdPointer:3548 case TypeTableEntryIdPointer:
3485 buf_appendf(buf, "&");3549 switch (const_val->data.x_ptr.special) {
3486 if (const_val->data.x_ptr.special == ConstPtrSpecialRuntime) {3550 case ConstPtrSpecialInvalid:
3487 buf_appendf(buf, "(runtime pointer value)");3551 zig_unreachable();
3488 } else if (const_val->data.x_ptr.special == ConstPtrSpecialCStr) {3552 case ConstPtrSpecialRef:
3489 buf_appendf(buf, "(c str lit)");3553 case ConstPtrSpecialBaseStruct:
3490 } else {3554 buf_appendf(buf, "&");
3491 render_const_value(buf, const_ptr_pointee(const_val));3555 render_const_value(buf, const_ptr_pointee(const_val));
3556 return;
3557 case ConstPtrSpecialBaseArray:
3558 if (const_val->data.x_ptr.data.base_array.is_cstr) {
3559 buf_appendf(buf, "&(c str lit)");
3560 return;
3561 } else {
3562 buf_appendf(buf, "&");
3563 render_const_value(buf, const_ptr_pointee(const_val));
3564 return;
3565 }
3566 case ConstPtrSpecialHardCodedAddr:
3567 buf_appendf(buf, "(&%s)(%" PRIx64 ")", buf_ptr(&canon_type->data.pointer.child_type->name),
3568 const_val->data.x_ptr.data.hard_coded_addr.addr);
3569 return;
3492 }3570 }
3493 return;3571 zig_unreachable();
3494 case TypeTableEntryIdFn:3572 case TypeTableEntryIdFn:
3495 {3573 {
3496 FnTableEntry *fn_entry = const_val->data.x_fn;3574 FnTableEntry *fn_entry = const_val->data.x_fn;
src/analyze.hpp+6-3
...@@ -126,9 +126,12 @@ ConstExprValue *create_const_type(CodeGen *g, TypeTableEntry *type_value);...@@ -126,9 +126,12 @@ ConstExprValue *create_const_type(CodeGen *g, TypeTableEntry *type_value);
126void init_const_runtime(ConstExprValue *const_val, TypeTableEntry *type);126void init_const_runtime(ConstExprValue *const_val, TypeTableEntry *type);
127ConstExprValue *create_const_runtime(TypeTableEntry *type);127ConstExprValue *create_const_runtime(TypeTableEntry *type);
128128
129void init_const_ptr(CodeGen *g, ConstExprValue *const_val, ConstExprValue *base_ptr, size_t index, bool is_const);129void init_const_ptr_ref(CodeGen *g, ConstExprValue *const_val, ConstExprValue *pointee_val, bool is_const);
130ConstExprValue *create_const_ptr(CodeGen *g, ConstExprValue *const_val, ConstExprValue *base_ptr,130ConstExprValue *create_const_ptr_ref(CodeGen *g, ConstExprValue *pointee_val, bool is_const);
131 size_t index, bool is_const);131
132void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
133 size_t elem_index, bool is_const);
134ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const);
132135
133void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,136void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
134 size_t start, size_t len, bool is_const);137 size_t start, size_t len, bool is_const);
src/codegen.cpp+94-37
...@@ -2527,17 +2527,29 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {...@@ -2527,17 +2527,29 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
2527 }2527 }
2528}2528}
25292529
2530static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {2530static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
2531 ConstExprValue *parent_array = array_const_val->data.x_array.parent_array;2531static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
2532 LLVMValueRef base_ptr;2532
2533 if (parent_array) {2533static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
2534 size_t parent_array_index = array_const_val->data.x_array.parent_array_index;2534 switch (parent->id) {
2535 base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index);2535 case ConstParentIdNone:
2536 } else {2536 render_const_val(g, val);
2537 render_const_val(g, array_const_val);2537 render_const_val_global(g, val, "");
2538 render_const_val_global(g, array_const_val, "");2538 return val->llvm_global;
2539 base_ptr = array_const_val->llvm_global;2539 case ConstParentIdStruct:
2540 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
2541 parent->data.p_struct.field_index);
2542 case ConstParentIdArray:
2543 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
2544 parent->data.p_array.elem_index);
2540 }2545 }
2546 zig_unreachable();
2547}
2548
2549static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
2550 ConstParent *parent = &array_const_val->data.x_array.parent;
2551 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
2552
2541 TypeTableEntry *usize = g->builtin_types.entry_usize;2553 TypeTableEntry *usize = g->builtin_types.entry_usize;
2542 LLVMValueRef indices[] = {2554 LLVMValueRef indices[] = {
2543 LLVMConstNull(usize->type_ref),2555 LLVMConstNull(usize->type_ref),
...@@ -2546,6 +2558,19 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar...@@ -2546,6 +2558,19 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
2546 return LLVMConstInBoundsGEP(base_ptr, indices, 2);2558 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
2547}2559}
25482560
2561static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
2562 ConstParent *parent = &struct_const_val->data.x_struct.parent;
2563 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
2564
2565 TypeTableEntry *u32 = g->builtin_types.entry_u32;
2566 LLVMValueRef indices[] = {
2567 LLVMConstNull(u32->type_ref),
2568 LLVMConstInt(u32->type_ref, field_index, false),
2569 };
2570 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
2571}
2572
2573
2549static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {2574static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2550 TypeTableEntry *canon_type = get_underlying_type(const_val->type);2575 TypeTableEntry *canon_type = get_underlying_type(const_val->type);
2551 assert(!canon_type->zero_bits);2576 assert(!canon_type->zero_bits);
...@@ -2684,38 +2709,70 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -2684,38 +2709,70 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2684 case TypeTableEntryIdPointer:2709 case TypeTableEntryIdPointer:
2685 {2710 {
2686 render_const_val_global(g, const_val, "");2711 render_const_val_global(g, const_val, "");
2687 size_t index = const_val->data.x_ptr.index;2712 switch (const_val->data.x_ptr.special) {
2688 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;2713 case ConstPtrSpecialInvalid:
2689 if (base_ptr) {2714 zig_unreachable();
2690 if (index == SIZE_MAX) {2715 case ConstPtrSpecialRef:
2691 render_const_val(g, base_ptr);2716 {
2692 render_const_val_global(g, base_ptr, "");2717 ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;
2693 ConstExprValue *other_val = base_ptr;2718 render_const_val(g, pointee);
2694 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);2719 render_const_val_global(g, pointee, "");
2695 render_const_val_global(g, const_val, "");2720 ConstExprValue *other_val = pointee;
2696 return const_val->llvm_value;2721 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
2697 } else {2722 render_const_val_global(g, const_val, "");
2698 ConstExprValue *array_const_val = base_ptr;2723 return const_val->llvm_value;
2699 assert(array_const_val->type->id == TypeTableEntryIdArray);2724 }
2700 if (array_const_val->type->zero_bits) {2725 case ConstPtrSpecialBaseArray:
2701 // make this a null pointer2726 {
2727 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
2728 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
2729 assert(array_const_val->type->id == TypeTableEntryIdArray);
2730 if (array_const_val->type->zero_bits) {
2731 // make this a null pointer
2732 TypeTableEntry *usize = g->builtin_types.entry_usize;
2733 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
2734 const_val->type->type_ref);
2735 render_const_val_global(g, const_val, "");
2736 return const_val->llvm_value;
2737 }
2738 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,
2739 elem_index);
2740 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
2741 const_val->llvm_value = ptr_val;
2742 render_const_val_global(g, const_val, "");
2743 return ptr_val;
2744 }
2745 case ConstPtrSpecialBaseStruct:
2746 {
2747 ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
2748 assert(struct_const_val->type->id == TypeTableEntryIdStruct);
2749 if (struct_const_val->type->zero_bits) {
2750 // make this a null pointer
2751 TypeTableEntry *usize = g->builtin_types.entry_usize;
2752 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
2753 const_val->type->type_ref);
2754 render_const_val_global(g, const_val, "");
2755 return const_val->llvm_value;
2756 }
2757 size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
2758 size_t gen_field_index =
2759 struct_const_val->type->data.structure.fields[src_field_index].gen_index;
2760 LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
2761 gen_field_index);
2762 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
2763 const_val->llvm_value = ptr_val;
2764 render_const_val_global(g, const_val, "");
2765 return ptr_val;
2766 }
2767 case ConstPtrSpecialHardCodedAddr:
2768 {
2769 uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
2702 TypeTableEntry *usize = g->builtin_types.entry_usize;2770 TypeTableEntry *usize = g->builtin_types.entry_usize;
2703 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),2771 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
2704 const_val->type->type_ref);2772 const_val->type->type_ref);
2705 render_const_val_global(g, const_val, "");2773 render_const_val_global(g, const_val, "");
2706 return const_val->llvm_value;2774 return const_val->llvm_value;
2707 }2775 }
2708 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index);
2709 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
2710 const_val->llvm_value = ptr_val;
2711 render_const_val_global(g, const_val, "");
2712 return ptr_val;
2713 }
2714 } else {
2715 TypeTableEntry *usize = g->builtin_types.entry_usize;
2716 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, index, false), const_val->type->type_ref);
2717 render_const_val_global(g, const_val, "");
2718 return const_val->llvm_value;
2719 }2776 }
2720 }2777 }
2721 case TypeTableEntryIdErrorUnion:2778 case TypeTableEntryIdErrorUnion:
src/ir.cpp+344-204
...@@ -64,16 +64,21 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ...@@ -64,16 +64,21 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
6464
65ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {65ConstExprValue *const_ptr_pointee(ConstExprValue *const_val) {
66 assert(const_val->special == ConstValSpecialStatic);66 assert(const_val->special == ConstValSpecialStatic);
67 assert(const_val->data.x_ptr.special != ConstPtrSpecialRuntime);67 switch (const_val->data.x_ptr.special) {
68 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;68 case ConstPtrSpecialInvalid:
69 size_t index = const_val->data.x_ptr.index;69 zig_unreachable();
7070 case ConstPtrSpecialRef:
71 if (index == SIZE_MAX) {71 return const_val->data.x_ptr.data.ref.pointee;
72 return base_ptr;72 case ConstPtrSpecialBaseArray:
73 } else {73 return &const_val->data.x_ptr.data.base_array.array_val->data.x_array.elements[
74 assert(index < base_ptr->data.x_array.size);74 const_val->data.x_ptr.data.base_array.elem_index];
75 return &base_ptr->data.x_array.elements[index];75 case ConstPtrSpecialBaseStruct:
76 return &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
77 const_val->data.x_ptr.data.base_struct.field_index];
78 case ConstPtrSpecialHardCodedAddr:
79 zig_unreachable();
76 }80 }
81 zig_unreachable();
77}82}
7883
79static bool ir_should_inline(IrExecutable *exec, Scope *scope) {84static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
...@@ -6209,7 +6214,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio...@@ -6209,7 +6214,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio
62096214
6210static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,6215static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,
6211 ConstExprValue *pointee, TypeTableEntry *pointee_type,6216 ConstExprValue *pointee, TypeTableEntry *pointee_type,
6212 ConstPtrSpecial special, bool ptr_is_const, bool ptr_is_volatile)6217 bool comptime_var_mem, bool ptr_is_const, bool ptr_is_volatile)
6213{6218{
6214 if (pointee_type->id == TypeTableEntryIdMetaType) {6219 if (pointee_type->id == TypeTableEntryIdMetaType) {
6215 TypeTableEntry *type_entry = pointee->data.x_type;6220 TypeTableEntry *type_entry = pointee->data.x_type;
...@@ -6227,9 +6232,9 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr...@@ -6227,9 +6232,9 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr
6227 TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, pointee_type,6232 TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, pointee_type,
6228 ptr_is_const, ptr_is_volatile);6233 ptr_is_const, ptr_is_volatile);
6229 ConstExprValue *const_val = ir_build_const_from(ira, instruction);6234 ConstExprValue *const_val = ir_build_const_from(ira, instruction);
6230 const_val->data.x_ptr.base_ptr = pointee;6235 const_val->data.x_ptr.special = ConstPtrSpecialRef;
6231 const_val->data.x_ptr.index = SIZE_MAX;6236 const_val->data.x_ptr.comptime_var_mem = comptime_var_mem;
6232 const_val->data.x_ptr.special = special;6237 const_val->data.x_ptr.data.ref.pointee = pointee;
6233 return ptr_type;6238 return ptr_type;
6234 }6239 }
6235}6240}
...@@ -6471,8 +6476,8 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_...@@ -6471,8 +6476,8 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
6471 source_instr->scope, source_instr->source_node);6476 source_instr->scope, source_instr->source_node);
6472 const_instruction->base.value.type = wanted_type;6477 const_instruction->base.value.type = wanted_type;
6473 const_instruction->base.value.special = ConstValSpecialStatic;6478 const_instruction->base.value.special = ConstValSpecialStatic;
6474 const_instruction->base.value.data.x_ptr.base_ptr = val;6479 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialRef;
6475 const_instruction->base.value.data.x_ptr.index = SIZE_MAX;6480 const_instruction->base.value.data.x_ptr.data.ref.pointee = val;
6476 return &const_instruction->base;6481 return &const_instruction->base;
6477 }6482 }
64786483
...@@ -6608,10 +6613,10 @@ static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -6608,10 +6613,10 @@ static IrInstruction *ir_analyze_ptr_to_int(IrAnalyze *ira, IrInstruction *sourc
6608 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);6613 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
6609 if (!val)6614 if (!val)
6610 return ira->codegen->invalid_instruction;6615 return ira->codegen->invalid_instruction;
6611 if (val->data.x_ptr.special == ConstPtrSpecialRuntime) {6616 if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
6612 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,6617 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
6613 source_instr->source_node, wanted_type);6618 source_instr->source_node, wanted_type);
6614 bignum_init_unsigned(&result->value.data.x_bignum, val->data.x_ptr.index);6619 bignum_init_unsigned(&result->value.data.x_bignum, val->data.x_ptr.data.hard_coded_addr.addr);
6615 return result;6620 return result;
6616 }6621 }
6617 }6622 }
...@@ -6633,9 +6638,8 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc...@@ -6633,9 +6638,8 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc
6633 return ira->codegen->invalid_instruction;6638 return ira->codegen->invalid_instruction;
6634 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,6639 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
6635 source_instr->source_node, wanted_type);6640 source_instr->source_node, wanted_type);
6636 result->value.data.x_ptr.base_ptr = nullptr;6641 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
6637 result->value.data.x_ptr.index = bignum_to_twos_complement(&val->data.x_bignum);6642 result->value.data.x_ptr.data.hard_coded_addr.addr = bignum_to_twos_complement(&val->data.x_bignum);
6638 result->value.data.x_ptr.special = ConstPtrSpecialRuntime;
6639 return result;6643 return result;
6640 }6644 }
66416645
...@@ -6660,9 +6664,8 @@ static IrInstruction *ir_analyze_int_lit_to_ptr(IrAnalyze *ira, IrInstruction *s...@@ -6660,9 +6664,8 @@ static IrInstruction *ir_analyze_int_lit_to_ptr(IrAnalyze *ira, IrInstruction *s
66606664
6661 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,6665 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
6662 source_instr->source_node, wanted_type);6666 source_instr->source_node, wanted_type);
6663 result->value.data.x_ptr.base_ptr = nullptr;6667 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
6664 result->value.data.x_ptr.index = bignum_to_twos_complement(&val->data.x_bignum);6668 result->value.data.x_ptr.data.hard_coded_addr.addr = bignum_to_twos_complement(&val->data.x_bignum);
6665 result->value.data.x_ptr.special = ConstPtrSpecialRuntime;
6666 return result;6669 return result;
6667}6670}
66686671
...@@ -7006,17 +7009,22 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -7006,17 +7009,22 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
7006 return ira->codegen->invalid_instruction;7009 return ira->codegen->invalid_instruction;
7007 } else if (type_entry->id == TypeTableEntryIdPointer) {7010 } else if (type_entry->id == TypeTableEntryIdPointer) {
7008 TypeTableEntry *child_type = type_entry->data.pointer.child_type;7011 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
7009 if (ptr->value.special != ConstValSpecialRuntime) {7012 if (instr_is_comptime(ptr)) {
7010 ConstExprValue *pointee = const_ptr_pointee(&ptr->value);7013 // Dereferencing a mutable pointer at compile time is not allowed
7011 if (pointee->special != ConstValSpecialRuntime) {7014 // unless that pointer is from a comptime variable
7012 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,7015 if (type_entry->data.pointer.is_const || ptr->value.data.x_ptr.comptime_var_mem) {
7013 source_instruction->source_node, child_type);7016 ConstExprValue *pointee = const_ptr_pointee(&ptr->value);
7014 result->value = *pointee;7017 if (pointee->special != ConstValSpecialRuntime) {
7015 return result;7018 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
7019 source_instruction->source_node, child_type);
7020 result->value = *pointee;
7021 return result;
7022 }
7016 }7023 }
7017 }7024 }
7018 // TODO if the instruction is a get pointer instruction we can skip it7025 // TODO if the instruction is a const ref instruction we can skip it
7019 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr);7026 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
7027 source_instruction->source_node, ptr);
7020 load_ptr_instruction->value.type = child_type;7028 load_ptr_instruction->value.type = child_type;
7021 return load_ptr_instruction;7029 return load_ptr_instruction;
7022 } else if (type_entry->id == TypeTableEntryIdMetaType) {7030 } else if (type_entry->id == TypeTableEntryIdMetaType) {
...@@ -7052,8 +7060,7 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst...@@ -7052,8 +7060,7 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst
7052 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);7060 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
7053 if (!val)7061 if (!val)
7054 return ira->codegen->builtin_types.entry_invalid;7062 return ira->codegen->builtin_types.entry_invalid;
7055 return ir_analyze_const_ptr(ira, source_instruction, val, value->value.type,7063 return ir_analyze_const_ptr(ira, source_instruction, val, value->value.type, false, is_const, is_volatile);
7056 ConstPtrSpecialNone, is_const, is_volatile);
7057 }7064 }
70587065
7059 TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, value->value.type, is_const, is_volatile);7066 TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, value->value.type, is_const, is_volatile);
...@@ -7136,13 +7143,14 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {...@@ -7136,13 +7143,14 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
71367143
7137 ConstExprValue *ptr_field = &const_val->data.x_struct.fields[slice_ptr_index];7144 ConstExprValue *ptr_field = &const_val->data.x_struct.fields[slice_ptr_index];
7138 ConstExprValue *len_field = &const_val->data.x_struct.fields[slice_len_index];7145 ConstExprValue *len_field = &const_val->data.x_struct.fields[slice_len_index];
7139 ConstExprValue *array_val = ptr_field->data.x_ptr.base_ptr;7146
7140 assert(ptr_field->data.x_ptr.index != SIZE_MAX);7147 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
7148 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
7141 size_t len = len_field->data.x_bignum.data.x_uint;7149 size_t len = len_field->data.x_bignum.data.x_uint;
7142 Buf *result = buf_alloc();7150 Buf *result = buf_alloc();
7143 buf_resize(result, len);7151 buf_resize(result, len);
7144 for (size_t i = 0; i < len; i += 1) {7152 for (size_t i = 0; i < len; i += 1) {
7145 size_t new_index = ptr_field->data.x_ptr.index + i;7153 size_t new_index = ptr_field->data.x_ptr.data.base_array.elem_index + i;
7146 ConstExprValue *char_val = &array_val->data.x_array.elements[new_index];7154 ConstExprValue *char_val = &array_val->data.x_array.elements[new_index];
7147 uint64_t big_c = char_val->data.x_bignum.data.x_uint;7155 uint64_t big_c = char_val->data.x_bignum.data.x_uint;
7148 assert(big_c <= UINT8_MAX);7156 assert(big_c <= UINT8_MAX);
...@@ -7591,22 +7599,24 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *...@@ -7591,22 +7599,24 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
7591 child_type = op1_canon_type->data.array.child_type;7599 child_type = op1_canon_type->data.array.child_type;
7592 op1_array_val = op1_val;7600 op1_array_val = op1_val;
7593 op1_array_index = 0;7601 op1_array_index = 0;
7594 op1_array_end = op1_val->data.x_array.size;7602 op1_array_end = op1_canon_type->data.array.len;
7595 } else if (op1_canon_type->id == TypeTableEntryIdPointer &&7603 } else if (op1_canon_type->id == TypeTableEntryIdPointer &&
7596 op1_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&7604 op1_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
7597 op1_val->data.x_ptr.special == ConstPtrSpecialCStr)7605 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
7606 op1_val->data.x_ptr.data.base_array.is_cstr)
7598 {7607 {
7599 child_type = op1_canon_type->data.pointer.child_type;7608 child_type = op1_canon_type->data.pointer.child_type;
7600 op1_array_val = op1_val->data.x_ptr.base_ptr;7609 op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;
7601 op1_array_index = op1_val->data.x_ptr.index;7610 op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;
7602 op1_array_end = op1_array_val->data.x_array.size - 1;7611 op1_array_end = op1_array_val->type->data.array.len - 1;
7603 } else if (is_slice(op1_canon_type)) {7612 } else if (is_slice(op1_canon_type)) {
7604 TypeTableEntry *ptr_type = op1_canon_type->data.structure.fields[slice_ptr_index].type_entry;7613 TypeTableEntry *ptr_type = op1_canon_type->data.structure.fields[slice_ptr_index].type_entry;
7605 child_type = ptr_type->data.pointer.child_type;7614 child_type = ptr_type->data.pointer.child_type;
7606 ConstExprValue *ptr_val = &op1_val->data.x_struct.fields[slice_ptr_index];7615 ConstExprValue *ptr_val = &op1_val->data.x_struct.fields[slice_ptr_index];
7607 op1_array_val = ptr_val->data.x_ptr.base_ptr;7616 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
7608 op1_array_index = ptr_val->data.x_ptr.index;7617 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
7609 op1_array_end = op1_array_val->data.x_array.size;7618 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
7619 op1_array_end = op1_array_val->type->data.array.len;
7610 } else {7620 } else {
7611 ir_add_error(ira, op1,7621 ir_add_error(ira, op1,
7612 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));7622 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
...@@ -7626,10 +7636,11 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *...@@ -7626,10 +7636,11 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
7626 }7636 }
7627 op2_array_val = op2_val;7637 op2_array_val = op2_val;
7628 op2_array_index = 0;7638 op2_array_index = 0;
7629 op2_array_end = op2_array_val->data.x_array.size;7639 op2_array_end = op2_array_val->type->data.array.len;
7630 } else if (op2_canon_type->id == TypeTableEntryIdPointer &&7640 } else if (op2_canon_type->id == TypeTableEntryIdPointer &&
7631 op2_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&7641 op2_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
7632 op2_val->data.x_ptr.special == ConstPtrSpecialCStr)7642 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
7643 op2_val->data.x_ptr.data.base_array.is_cstr)
7633 {7644 {
7634 if (child_type != ira->codegen->builtin_types.entry_u8) {7645 if (child_type != ira->codegen->builtin_types.entry_u8) {
7635 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",7646 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
...@@ -7637,9 +7648,9 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *...@@ -7637,9 +7648,9 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
7637 buf_ptr(&op2->value.type->name)));7648 buf_ptr(&op2->value.type->name)));
7638 return ira->codegen->builtin_types.entry_invalid;7649 return ira->codegen->builtin_types.entry_invalid;
7639 }7650 }
7640 op2_array_val = op2_val->data.x_ptr.base_ptr;7651 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
7641 op2_array_index = op2_val->data.x_ptr.index;7652 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
7642 op2_array_end = op2_array_val->data.x_array.size - 1;7653 op2_array_end = op2_array_val->type->data.array.len - 1;
7643 } else if (is_slice(op2_canon_type)) {7654 } else if (is_slice(op2_canon_type)) {
7644 TypeTableEntry *ptr_type = op2_canon_type->data.structure.fields[slice_ptr_index].type_entry;7655 TypeTableEntry *ptr_type = op2_canon_type->data.structure.fields[slice_ptr_index].type_entry;
7645 if (ptr_type->data.pointer.child_type != child_type) {7656 if (ptr_type->data.pointer.child_type != child_type) {
...@@ -7649,9 +7660,10 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *...@@ -7649,9 +7660,10 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
7649 return ira->codegen->builtin_types.entry_invalid;7660 return ira->codegen->builtin_types.entry_invalid;
7650 }7661 }
7651 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];7662 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
7652 op2_array_val = ptr_val->data.x_ptr.base_ptr;7663 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
7653 op2_array_index = ptr_val->data.x_ptr.index;7664 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
7654 op2_array_end = op2_array_val->data.x_array.size;7665 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
7666 op2_array_end = op2_array_val->type->data.array.len;
7655 } else {7667 } else {
7656 ir_add_error(ira, op2,7668 ir_add_error(ira, op2,
7657 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));7669 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
...@@ -7676,12 +7688,12 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *...@@ -7676,12 +7688,12 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
7676 out_array_val = allocate<ConstExprValue>(1);7688 out_array_val = allocate<ConstExprValue>(1);
7677 out_array_val->special = ConstValSpecialStatic;7689 out_array_val->special = ConstValSpecialStatic;
7678 out_array_val->type = get_array_type(ira->codegen, child_type, new_len);7690 out_array_val->type = get_array_type(ira->codegen, child_type, new_len);
7679 out_val->data.x_ptr.base_ptr = out_array_val;7691 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
7680 out_val->data.x_ptr.index = 0;7692 out_val->data.x_ptr.data.base_array.is_cstr = true;
7681 out_val->data.x_ptr.special = ConstPtrSpecialCStr;7693 out_val->data.x_ptr.data.base_array.array_val = out_array_val;
7694 out_val->data.x_ptr.data.base_array.elem_index = 0;
7682 }7695 }
7683 out_array_val->data.x_array.elements = allocate<ConstExprValue>(new_len);7696 out_array_val->data.x_array.elements = allocate<ConstExprValue>(new_len);
7684 out_array_val->data.x_array.size = new_len;
76857697
7686 size_t next_index = 0;7698 size_t next_index = 0;
7687 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {7699 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
...@@ -7736,7 +7748,6 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp...@@ -7736,7 +7748,6 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp
7736 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);7748 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
77377749
7738 uint64_t new_array_len = array_len.data.x_uint;7750 uint64_t new_array_len = array_len.data.x_uint;
7739 out_val->data.x_array.size = new_array_len;
7740 out_val->data.x_array.elements = allocate<ConstExprValue>(new_array_len);7751 out_val->data.x_array.elements = allocate<ConstExprValue>(new_array_len);
77417752
7742 uint64_t i = 0;7753 uint64_t i = 0;
...@@ -8721,24 +8732,23 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc...@@ -8721,24 +8732,23 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
8721 if (var->value.type->id == TypeTableEntryIdInvalid)8732 if (var->value.type->id == TypeTableEntryIdInvalid)
8722 return var->value.type;8733 return var->value.type;
87238734
8724 bool is_comptime = ir_get_var_is_comptime(var);8735 bool comptime_var_mem = ir_get_var_is_comptime(var);
87258736
8726 ConstExprValue *mem_slot = nullptr;8737 ConstExprValue *mem_slot = nullptr;
8727 FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope);8738 FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope);
8728 if (var->src_is_const && var->value.special == ConstValSpecialStatic) {8739 if (var->value.special == ConstValSpecialStatic) {
8729 mem_slot = &var->value;8740 mem_slot = &var->value;
8730 assert(mem_slot->special != ConstValSpecialRuntime);
8731 } else if (fn_entry) {8741 } else if (fn_entry) {
8732 // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing.8742 // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing.
8733 if (var->mem_slot_index != SIZE_MAX && (is_comptime || var->gen_is_const))8743 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const))
8734 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];8744 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
8735 }8745 }
87368746
8737 bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const;8747 bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const;
8738 bool is_volatile = (var->value.type->id == TypeTableEntryIdMetaType) ? is_volatile_ptr : false;8748 bool is_volatile = (var->value.type->id == TypeTableEntryIdMetaType) ? is_volatile_ptr : false;
8739 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {8749 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
8740 ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone;8750 return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type,
8741 return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, ptr_special, is_const, is_volatile);8751 comptime_var_mem, is_const, is_volatile);
8742 } else {8752 } else {
8743 ir_build_var_ptr_from(&ira->new_irb, instruction, var, is_const, is_volatile);8753 ir_build_var_ptr_from(&ira->new_irb, instruction, var, is_const, is_volatile);
8744 type_ensure_zero_bits_known(ira->codegen, var->value.type);8754 type_ensure_zero_bits_known(ira->codegen, var->value.type);
...@@ -8793,7 +8803,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -8793,7 +8803,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
8793 buf_sprintf("index 0 outside array of size 0"));8803 buf_sprintf("index 0 outside array of size 0"));
8794 }8804 }
8795 TypeTableEntry *child_type = array_type->data.array.child_type;8805 TypeTableEntry *child_type = array_type->data.array.child_type;
8796 return_type = get_pointer_to_type(ira->codegen, child_type, false);8806 return_type = get_pointer_to_type_volatile(ira->codegen, child_type,
8807 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile);
8797 } else if (array_type->id == TypeTableEntryIdPointer) {8808 } else if (array_type->id == TypeTableEntryIdPointer) {
8798 return_type = array_type;8809 return_type = array_type;
8799 } else if (is_slice(array_type)) {8810 } else if (is_slice(array_type)) {
...@@ -8826,8 +8837,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -8826,8 +8837,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
8826 is_const, is_volatile);8837 is_const, is_volatile);
8827 } else {8838 } else {
8828 return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,8839 return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val,
8829 ira->codegen->builtin_types.entry_void, ConstPtrSpecialNone,8840 ira->codegen->builtin_types.entry_void, false, is_const, is_volatile);
8830 is_const, is_volatile);
8831 }8841 }
8832 } else {8842 } else {
8833 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,8843 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
...@@ -8858,30 +8868,54 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -8858,30 +8868,54 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
8858 if (array_ptr->value.special != ConstValSpecialRuntime &&8868 if (array_ptr->value.special != ConstValSpecialRuntime &&
8859 (array_ptr_val = const_ptr_pointee(&array_ptr->value)) &&8869 (array_ptr_val = const_ptr_pointee(&array_ptr->value)) &&
8860 array_ptr_val->special != ConstValSpecialRuntime &&8870 array_ptr_val->special != ConstValSpecialRuntime &&
8861 (array_type->id != TypeTableEntryIdPointer || array_ptr_val->data.x_ptr.special != ConstPtrSpecialRuntime))8871 (array_type->id != TypeTableEntryIdPointer ||
8872 array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr))
8862 {8873 {
8863 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);8874 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base);
8875 out_val->data.x_ptr.comptime_var_mem = array_ptr->value.data.x_ptr.comptime_var_mem;
8864 if (array_type->id == TypeTableEntryIdPointer) {8876 if (array_type->id == TypeTableEntryIdPointer) {
8865 size_t offset = array_ptr_val->data.x_ptr.index;
8866 size_t new_index;8877 size_t new_index;
8867 size_t mem_size;8878 size_t mem_size;
8868 size_t old_size;8879 size_t old_size;
8869 if (offset == SIZE_MAX) {8880 switch (array_ptr_val->data.x_ptr.special) {
8870 new_index = SIZE_MAX;8881 case ConstPtrSpecialInvalid:
8871 mem_size = 1;8882 zig_unreachable();
8872 old_size = 1;8883 case ConstPtrSpecialRef:
8873 } else {8884 mem_size = 1;
8874 new_index = offset + index;8885 old_size = 1;
8875 mem_size = array_ptr_val->data.x_ptr.base_ptr->data.x_array.size;8886 new_index = index;
8876 old_size = mem_size - offset;8887
8888 out_val->data.x_ptr.special = ConstPtrSpecialRef;
8889 out_val->data.x_ptr.data.ref.pointee = array_ptr_val->data.x_ptr.data.ref.pointee;
8890 break;
8891 case ConstPtrSpecialBaseArray:
8892 {
8893 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
8894 new_index = offset + index;
8895 mem_size = array_ptr_val->data.x_ptr.data.base_array.array_val->type->data.array.len;
8896 old_size = mem_size - offset;
8897
8898 assert(array_ptr_val->data.x_ptr.data.base_array.array_val);
8899
8900 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
8901 out_val->data.x_ptr.data.base_array.array_val =
8902 array_ptr_val->data.x_ptr.data.base_array.array_val;
8903 out_val->data.x_ptr.data.base_array.elem_index = new_index;
8904 out_val->data.x_ptr.data.base_array.is_cstr =
8905 array_ptr_val->data.x_ptr.data.base_array.is_cstr;
8906
8907 break;
8908 }
8909 case ConstPtrSpecialBaseStruct:
8910 zig_panic("TODO elem ptr on a const inner struct");
8911 case ConstPtrSpecialHardCodedAddr:
8912 zig_unreachable();
8877 }8913 }
8878 if (new_index >= mem_size) {8914 if (new_index >= mem_size) {
8879 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,8915 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
8880 buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64, index, old_size));8916 buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64, index, old_size));
8881 return ira->codegen->builtin_types.entry_invalid;8917 return ira->codegen->builtin_types.entry_invalid;
8882 }8918 }
8883 out_val->data.x_ptr.base_ptr = array_ptr_val->data.x_ptr.base_ptr;
8884 out_val->data.x_ptr.index = new_index;
8885 } else if (is_slice(array_type)) {8919 } else if (is_slice(array_type)) {
8886 ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];8920 ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
8887 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];8921 ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index];
...@@ -8892,18 +8926,35 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -8892,18 +8926,35 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
8892 index, slice_len));8926 index, slice_len));
8893 return ira->codegen->builtin_types.entry_invalid;8927 return ira->codegen->builtin_types.entry_invalid;
8894 }8928 }
8895 out_val->data.x_ptr.base_ptr = ptr_field->data.x_ptr.base_ptr;8929 switch (ptr_field->data.x_ptr.special) {
8896 size_t offset = ptr_field->data.x_ptr.index;8930 case ConstPtrSpecialInvalid:
8897 if (offset == SIZE_MAX) {8931 zig_unreachable();
8898 out_val->data.x_ptr.index = SIZE_MAX;8932 case ConstPtrSpecialRef:
8899 } else {8933 out_val->data.x_ptr.special = ConstPtrSpecialRef;
8900 uint64_t new_index = offset + index;8934 out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;
8901 assert(new_index < ptr_field->data.x_ptr.base_ptr->data.x_array.size);8935 break;
8902 out_val->data.x_ptr.index = new_index;8936 case ConstPtrSpecialBaseArray:
8937 {
8938 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
8939 uint64_t new_index = offset + index;
8940 assert(new_index < ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len);
8941 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
8942 out_val->data.x_ptr.data.base_array.array_val =
8943 ptr_field->data.x_ptr.data.base_array.array_val;
8944 out_val->data.x_ptr.data.base_array.elem_index = new_index;
8945 out_val->data.x_ptr.data.base_array.is_cstr =
8946 ptr_field->data.x_ptr.data.base_array.is_cstr;
8947 break;
8948 }
8949 case ConstPtrSpecialBaseStruct:
8950 zig_panic("TODO elem ptr on a slice backed by const inner struct");
8951 case ConstPtrSpecialHardCodedAddr:
8952 zig_unreachable();
8903 }8953 }
8904 } else if (array_type->id == TypeTableEntryIdArray) {8954 } else if (array_type->id == TypeTableEntryIdArray) {
8905 out_val->data.x_ptr.base_ptr = array_ptr_val;8955 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
8906 out_val->data.x_ptr.index = index;8956 out_val->data.x_ptr.data.base_array.array_val = array_ptr_val;
8957 out_val->data.x_ptr.data.base_array.elem_index = index;
8907 } else {8958 } else {
8908 zig_unreachable();8959 zig_unreachable();
8909 }8960 }
...@@ -8931,6 +8982,9 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -8931,6 +8982,9 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
8931 return ira->codegen->builtin_types.entry_invalid;8982 return ira->codegen->builtin_types.entry_invalid;
8932 TldFn *tld_fn = (TldFn *)tld;8983 TldFn *tld_fn = (TldFn *)tld;
8933 FnTableEntry *fn_entry = tld_fn->fn_entry;8984 FnTableEntry *fn_entry = tld_fn->fn_entry;
8985 if (fn_entry->type_entry->id == TypeTableEntryIdInvalid)
8986 return ira->codegen->builtin_types.entry_invalid;
8987
8934 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope,8988 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope,
8935 field_ptr_instruction->base.source_node, fn_entry, container_ptr);8989 field_ptr_instruction->base.source_node, fn_entry, container_ptr);
8936 return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true, false);8990 return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true, false);
...@@ -8962,15 +9016,17 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field...@@ -8962,15 +9016,17 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
8962 if (!ptr_val)9016 if (!ptr_val)
8963 return ira->codegen->builtin_types.entry_invalid;9017 return ira->codegen->builtin_types.entry_invalid;
89649018
8965 if (ptr_val->data.x_ptr.special != ConstPtrSpecialRuntime) {9019 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
8966 ConstExprValue *struct_val = const_ptr_pointee(ptr_val);9020 ConstExprValue *struct_val = const_ptr_pointee(ptr_val);
8967 if (value_is_comptime(struct_val)) {9021 ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
8968 ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];9022 TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, field_val->type,
8969 if (value_is_comptime(field_val)) {9023 is_const, is_volatile);
8970 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, field_val,9024 ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base);
8971 field_val->type, ConstPtrSpecialNone, is_const, is_volatile);9025 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
8972 }9026 const_val->data.x_ptr.comptime_var_mem = container_ptr->value.data.x_ptr.comptime_var_mem;
8973 }9027 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
9028 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
9029 return ptr_type;
8974 }9030 }
8975 }9031 }
8976 ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);9032 ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);
...@@ -9032,7 +9088,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source...@@ -9032,7 +9088,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
9032 bool ptr_is_const = true;9088 bool ptr_is_const = true;
9033 bool ptr_is_volatile = false;9089 bool ptr_is_volatile = false;
9034 return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,9090 return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
9035 ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9091 false, ptr_is_const, ptr_is_volatile);
9036 }9092 }
9037 case TldIdTypeDef:9093 case TldIdTypeDef:
9038 {9094 {
...@@ -9049,7 +9105,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source...@@ -9049,7 +9105,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
9049 bool ptr_is_const = true;9105 bool ptr_is_const = true;
9050 bool ptr_is_volatile = false;9106 bool ptr_is_volatile = false;
9051 return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type,9107 return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type,
9052 ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9108 false, ptr_is_const, ptr_is_volatile);
9053 }9109 }
9054 }9110 }
9055 zig_unreachable();9111 zig_unreachable();
...@@ -9092,7 +9148,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -9092,7 +9148,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
9092 bool ptr_is_const = true;9148 bool ptr_is_const = true;
9093 bool ptr_is_volatile = false;9149 bool ptr_is_volatile = false;
9094 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,9150 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
9095 usize, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9151 usize, false, ptr_is_const, ptr_is_volatile);
9096 } else {9152 } else {
9097 ir_add_error_node(ira, source_node,9153 ir_add_error_node(ira, source_node,
9098 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),9154 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
...@@ -9116,7 +9172,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -9116,7 +9172,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
9116 bool ptr_is_const = true;9172 bool ptr_is_const = true;
9117 bool ptr_is_volatile = false;9173 bool ptr_is_volatile = false;
9118 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,9174 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
9119 usize, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9175 usize, false, ptr_is_const, ptr_is_volatile);
9120 } else {9176 } else {
9121 ir_add_error_node(ira, source_node,9177 ir_add_error_node(ira, source_node,
9122 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),9178 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
...@@ -9155,14 +9211,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -9155,14 +9211,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
9155 bool ptr_is_volatile = false;9211 bool ptr_is_volatile = false;
9156 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,9212 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
9157 create_const_enum_tag(child_type, field->value), child_type,9213 create_const_enum_tag(child_type, field->value), child_type,
9158 ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9214 false, ptr_is_const, ptr_is_volatile);
9159 } else {9215 } else {
9160 bool ptr_is_const = true;9216 bool ptr_is_const = true;
9161 bool ptr_is_volatile = false;9217 bool ptr_is_volatile = false;
9162 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,9218 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
9163 create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false),9219 create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false),
9164 child_type->data.enumeration.tag_type,9220 child_type->data.enumeration.tag_type,
9165 ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9221 false, ptr_is_const, ptr_is_volatile);
9166 }9222 }
9167 }9223 }
9168 }9224 }
...@@ -9187,7 +9243,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -9187,7 +9243,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
9187 bool ptr_is_const = true;9243 bool ptr_is_const = true;
9188 bool ptr_is_volatile = false;9244 bool ptr_is_volatile = false;
9189 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val,9245 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val,
9190 child_type, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9246 child_type, false, ptr_is_const, ptr_is_volatile);
9191 }9247 }
91929248
9193 ir_add_error(ira, &field_ptr_instruction->base,9249 ir_add_error(ira, &field_ptr_instruction->base,
...@@ -9201,14 +9257,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -9201,14 +9257,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
9201 create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,9257 create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,
9202 child_type->data.integral.bit_count, false),9258 child_type->data.integral.bit_count, false),
9203 ira->codegen->builtin_types.entry_num_lit_int,9259 ira->codegen->builtin_types.entry_num_lit_int,
9204 ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9260 false, ptr_is_const, ptr_is_volatile);
9205 } else if (buf_eql_str(field_name, "is_signed")) {9261 } else if (buf_eql_str(field_name, "is_signed")) {
9206 bool ptr_is_const = true;9262 bool ptr_is_const = true;
9207 bool ptr_is_volatile = false;9263 bool ptr_is_volatile = false;
9208 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,9264 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
9209 create_const_bool(ira->codegen, child_type->data.integral.is_signed),9265 create_const_bool(ira->codegen, child_type->data.integral.is_signed),
9210 ira->codegen->builtin_types.entry_bool,9266 ira->codegen->builtin_types.entry_bool,
9211 ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);9267 false, ptr_is_const, ptr_is_volatile);
9212 } else {9268 } else {
9213 ir_add_error(ira, &field_ptr_instruction->base,9269 ir_add_error(ira, &field_ptr_instruction->base,
9214 buf_sprintf("type '%s' has no member called '%s'",9270 buf_sprintf("type '%s' has no member called '%s'",
...@@ -9295,16 +9351,16 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru...@@ -9295,16 +9351,16 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
9295 if (casted_value == ira->codegen->invalid_instruction)9351 if (casted_value == ira->codegen->invalid_instruction)
9296 return ira->codegen->builtin_types.entry_invalid;9352 return ira->codegen->builtin_types.entry_invalid;
92979353
9298 if (ptr->value.special != ConstValSpecialRuntime && ptr->value.data.x_ptr.special != ConstPtrSpecialRuntime) {9354 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
9299 bool is_inline = (ptr->value.data.x_ptr.special == ConstPtrSpecialInline);9355 bool comptime_var_mem = ptr->value.data.x_ptr.comptime_var_mem;
9300 if (casted_value->value.special != ConstValSpecialRuntime) {9356 if (comptime_var_mem) {
9301 ConstExprValue *dest_val = const_ptr_pointee(&ptr->value);9357 if (instr_is_comptime(casted_value)) {
9302 if (dest_val->special != ConstValSpecialRuntime) {9358 ConstExprValue *dest_val = const_ptr_pointee(&ptr->value);
9303 *dest_val = casted_value->value;9359 if (dest_val->special != ConstValSpecialRuntime) {
9304 return ir_analyze_void(ira, &store_ptr_instruction->base);9360 *dest_val = casted_value->value;
9361 return ir_analyze_void(ira, &store_ptr_instruction->base);
9362 }
9305 }9363 }
9306 }
9307 if (is_inline) {
9308 ir_add_error(ira, &store_ptr_instruction->base,9364 ir_add_error(ira, &store_ptr_instruction->base,
9309 buf_sprintf("cannot store runtime value in compile time variable"));9365 buf_sprintf("cannot store runtime value in compile time variable"));
9310 return ira->codegen->builtin_types.entry_invalid;9366 return ira->codegen->builtin_types.entry_invalid;
...@@ -9906,14 +9962,15 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -9906,14 +9962,15 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
9906 return ira->codegen->builtin_types.entry_invalid;9962 return ira->codegen->builtin_types.entry_invalid;
9907 }9963 }
9908 TypeTableEntry *child_type = type_entry->data.maybe.child_type;9964 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
9909 TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false);9965 TypeTableEntry *result_type = get_pointer_to_type_volatile(ira->codegen, child_type,
9966 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile);
99109967
9911 if (instr_is_comptime(value)) {9968 if (instr_is_comptime(value)) {
9912 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);9969 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
9913 if (!val)9970 if (!val)
9914 return ira->codegen->builtin_types.entry_invalid;9971 return ira->codegen->builtin_types.entry_invalid;
9915 ConstExprValue *maybe_val = val->data.x_ptr.base_ptr;9972 assert(val->data.x_ptr.special == ConstPtrSpecialRef);
9916 assert(val->data.x_ptr.index == SIZE_MAX);9973 ConstExprValue *maybe_val = val->data.x_ptr.data.ref.pointee;
99179974
9918 if (maybe_val->special != ConstValSpecialRuntime) {9975 if (maybe_val->special != ConstValSpecialRuntime) {
9919 if (!maybe_val->data.x_maybe) {9976 if (!maybe_val->data.x_maybe) {
...@@ -9921,8 +9978,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -9921,8 +9978,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
9921 return ira->codegen->builtin_types.entry_invalid;9978 return ira->codegen->builtin_types.entry_invalid;
9922 }9979 }
9923 ConstExprValue *out_val = ir_build_const_from(ira, &unwrap_maybe_instruction->base);9980 ConstExprValue *out_val = ir_build_const_from(ira, &unwrap_maybe_instruction->base);
9924 out_val->data.x_ptr.base_ptr = maybe_val->data.x_maybe;9981 out_val->data.x_ptr.special = ConstPtrSpecialRef;
9925 out_val->data.x_ptr.index = SIZE_MAX;9982 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_maybe;
9926 return result_type;9983 return result_type;
9927 }9984 }
9928 }9985 }
...@@ -10215,9 +10272,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr...@@ -10215,9 +10272,10 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
10215 ConstExprValue *pointee_val = const_ptr_pointee(target_val_ptr);10272 ConstExprValue *pointee_val = const_ptr_pointee(target_val_ptr);
10216 if (pointee_val->type->id == TypeTableEntryIdEnum) {10273 if (pointee_val->type->id == TypeTableEntryIdEnum) {
10217 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);10274 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
10218 out_val->data.x_ptr.base_ptr = pointee_val->data.x_enum.payload;10275 out_val->data.x_ptr.special = ConstPtrSpecialRef;
10219 out_val->data.x_ptr.index = SIZE_MAX;10276 out_val->data.x_ptr.data.ref.pointee = pointee_val->data.x_enum.payload;
10220 return get_pointer_to_type(ira->codegen, pointee_val->type, target_value_ptr->value.type->data.pointer.is_const);10277 return get_pointer_to_type(ira->codegen, pointee_val->type,
10278 target_value_ptr->value.type->data.pointer.is_const);
10221 } else {10279 } else {
10222 zig_panic("TODO comptime switch var");10280 zig_panic("TODO comptime switch var");
10223 }10281 }
...@@ -10501,7 +10559,6 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -10501,7 +10559,6 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
10501 const_val.special = ConstValSpecialStatic;10559 const_val.special = ConstValSpecialStatic;
10502 const_val.type = fixed_size_array_type;10560 const_val.type = fixed_size_array_type;
10503 const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);10561 const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);
10504 const_val.data.x_array.size = elem_count;
1050510562
10506 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);10563 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
1050710564
...@@ -10540,8 +10597,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira...@@ -10540,8 +10597,9 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
10540 for (size_t i = 0; i < elem_count; i += 1) {10597 for (size_t i = 0; i < elem_count; i += 1) {
10541 ConstExprValue *elem_val = &out_val->data.x_array.elements[i];10598 ConstExprValue *elem_val = &out_val->data.x_array.elements[i];
10542 if (elem_val->type->id == TypeTableEntryIdArray) {10599 if (elem_val->type->id == TypeTableEntryIdArray) {
10543 elem_val->data.x_array.parent_array = out_val;10600 elem_val->data.x_array.parent.id = ConstParentIdArray;
10544 elem_val->data.x_array.parent_array_index = i;10601 elem_val->data.x_array.parent.data.p_array.array_val = out_val;
10602 elem_val->data.x_array.parent.data.p_array.elem_index = i;
10545 }10603 }
10546 }10604 }
10547 return fixed_size_array_type;10605 return fixed_size_array_type;
...@@ -11227,22 +11285,34 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi...@@ -11227,22 +11285,34 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi
1122711285
11228 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&11286 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
11229 casted_byte->value.special == ConstValSpecialStatic &&11287 casted_byte->value.special == ConstValSpecialStatic &&
11230 casted_count->value.special == ConstValSpecialStatic)11288 casted_count->value.special == ConstValSpecialStatic &&
11289 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
11231 {11290 {
11232 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;11291 ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;
1123311292
11234 ConstExprValue *dest_elements;11293 ConstExprValue *dest_elements;
11235 size_t start;11294 size_t start;
11236 size_t bound_end;11295 size_t bound_end;
11237 if (dest_ptr_val->data.x_ptr.index == SIZE_MAX) {11296 switch (dest_ptr_val->data.x_ptr.special) {
11238 dest_elements = dest_ptr_val->data.x_ptr.base_ptr;11297 case ConstPtrSpecialInvalid:
11239 start = 0;11298 zig_unreachable();
11240 bound_end = 1;11299 case ConstPtrSpecialRef:
11241 } else {11300 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
11242 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.base_ptr;11301 start = 0;
11243 dest_elements = array_val->data.x_array.elements;11302 bound_end = 1;
11244 start = dest_ptr_val->data.x_ptr.index;11303 break;
11245 bound_end = array_val->data.x_array.size;11304 case ConstPtrSpecialBaseArray:
11305 {
11306 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
11307 dest_elements = array_val->data.x_array.elements;
11308 start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
11309 bound_end = array_val->type->data.array.len;
11310 break;
11311 }
11312 case ConstPtrSpecialBaseStruct:
11313 zig_panic("TODO memset on const inner struct");
11314 case ConstPtrSpecialHardCodedAddr:
11315 zig_unreachable();
11246 }11316 }
1124711317
11248 size_t count = casted_count->value.data.x_bignum.data.x_uint;11318 size_t count = casted_count->value.data.x_bignum.data.x_uint;
...@@ -11304,7 +11374,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi...@@ -11304,7 +11374,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi
1130411374
11305 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&11375 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
11306 casted_src_ptr->value.special == ConstValSpecialStatic &&11376 casted_src_ptr->value.special == ConstValSpecialStatic &&
11307 casted_count->value.special == ConstValSpecialStatic)11377 casted_count->value.special == ConstValSpecialStatic &&
11378 casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
11308 {11379 {
11309 size_t count = casted_count->value.data.x_bignum.data.x_uint;11380 size_t count = casted_count->value.data.x_bignum.data.x_uint;
1131011381
...@@ -11312,15 +11383,26 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi...@@ -11312,15 +11383,26 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi
11312 ConstExprValue *dest_elements;11383 ConstExprValue *dest_elements;
11313 size_t dest_start;11384 size_t dest_start;
11314 size_t dest_end;11385 size_t dest_end;
11315 if (dest_ptr_val->data.x_ptr.index == SIZE_MAX) {11386 switch (dest_ptr_val->data.x_ptr.special) {
11316 dest_elements = dest_ptr_val->data.x_ptr.base_ptr;11387 case ConstPtrSpecialInvalid:
11317 dest_start = 0;11388 zig_unreachable();
11318 dest_end = 1;11389 case ConstPtrSpecialRef:
11319 } else {11390 dest_elements = dest_ptr_val->data.x_ptr.data.ref.pointee;
11320 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.base_ptr;11391 dest_start = 0;
11321 dest_elements = array_val->data.x_array.elements;11392 dest_end = 1;
11322 dest_start = dest_ptr_val->data.x_ptr.index;11393 break;
11323 dest_end = array_val->data.x_array.size;11394 case ConstPtrSpecialBaseArray:
11395 {
11396 ConstExprValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
11397 dest_elements = array_val->data.x_array.elements;
11398 dest_start = dest_ptr_val->data.x_ptr.data.base_array.elem_index;
11399 dest_end = array_val->type->data.array.len;
11400 break;
11401 }
11402 case ConstPtrSpecialBaseStruct:
11403 zig_panic("TODO memcpy on const inner struct");
11404 case ConstPtrSpecialHardCodedAddr:
11405 zig_unreachable();
11324 }11406 }
1132511407
11326 if (dest_start + count > dest_end) {11408 if (dest_start + count > dest_end) {
...@@ -11332,15 +11414,27 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi...@@ -11332,15 +11414,27 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi
11332 ConstExprValue *src_elements;11414 ConstExprValue *src_elements;
11333 size_t src_start;11415 size_t src_start;
11334 size_t src_end;11416 size_t src_end;
11335 if (src_ptr_val->data.x_ptr.index == SIZE_MAX) {11417
11336 src_elements = src_ptr_val->data.x_ptr.base_ptr;11418 switch (src_ptr_val->data.x_ptr.special) {
11337 src_start = 0;11419 case ConstPtrSpecialInvalid:
11338 src_end = 1;11420 zig_unreachable();
11339 } else {11421 case ConstPtrSpecialRef:
11340 ConstExprValue *array_val = src_ptr_val->data.x_ptr.base_ptr;11422 src_elements = src_ptr_val->data.x_ptr.data.ref.pointee;
11341 src_elements = array_val->data.x_array.elements;11423 src_start = 0;
11342 src_start = src_ptr_val->data.x_ptr.index;11424 src_end = 1;
11343 src_end = array_val->data.x_array.size;11425 break;
11426 case ConstPtrSpecialBaseArray:
11427 {
11428 ConstExprValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;
11429 src_elements = array_val->data.x_array.elements;
11430 src_start = src_ptr_val->data.x_ptr.data.base_array.elem_index;
11431 src_end = array_val->type->data.array.len;
11432 break;
11433 }
11434 case ConstPtrSpecialBaseStruct:
11435 zig_panic("TODO memcpy on const inner struct");
11436 case ConstPtrSpecialHardCodedAddr:
11437 zig_unreachable();
11344 }11438 }
1134511439
11346 if (src_start + count > src_end) {11440 if (src_start + count > src_end) {
...@@ -11415,68 +11509,115 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio...@@ -11415,68 +11509,115 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
11415 casted_start->value.special == ConstValSpecialStatic &&11509 casted_start->value.special == ConstValSpecialStatic &&
11416 (!end || end->value.special == ConstValSpecialStatic))11510 (!end || end->value.special == ConstValSpecialStatic))
11417 {11511 {
11418 ConstExprValue *base_ptr;11512 ConstExprValue *array_val;
11513 ConstExprValue *parent_ptr;
11419 size_t abs_offset;11514 size_t abs_offset;
11420 size_t rel_end;11515 size_t rel_end;
11421 if (array_type->id == TypeTableEntryIdArray) {11516 if (array_type->id == TypeTableEntryIdArray) {
11422 base_ptr = &ptr->value;11517 array_val = &ptr->value;
11423 abs_offset = 0;11518 abs_offset = 0;
11424 rel_end = array_type->data.array.len;11519 rel_end = array_type->data.array.len;
11520 parent_ptr = nullptr;
11425 } else if (array_type->id == TypeTableEntryIdPointer) {11521 } else if (array_type->id == TypeTableEntryIdPointer) {
11426 base_ptr = ptr->value.data.x_ptr.base_ptr;11522 parent_ptr = &ptr->value;
11427 abs_offset = ptr->value.data.x_ptr.index;11523 switch (parent_ptr->data.x_ptr.special) {
11428 if (abs_offset == SIZE_MAX) {11524 case ConstPtrSpecialInvalid:
11429 rel_end = 1;11525 zig_unreachable();
11430 } else {11526 case ConstPtrSpecialRef:
11431 rel_end = base_ptr->data.x_array.size - abs_offset;11527 array_val = nullptr;
11528 abs_offset = SIZE_MAX;
11529 rel_end = 1;
11530 break;
11531 case ConstPtrSpecialBaseArray:
11532 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
11533 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
11534 rel_end = array_val->type->data.array.len - abs_offset;
11535 break;
11536 case ConstPtrSpecialBaseStruct:
11537 zig_panic("TODO slice const inner struct");
11538 case ConstPtrSpecialHardCodedAddr:
11539 array_val = nullptr;
11540 break;
11432 }11541 }
11433 } else if (is_slice(array_type)) {11542 } else if (is_slice(array_type)) {
11434 ConstExprValue *ptr_val = &ptr->value.data.x_struct.fields[slice_ptr_index];11543 parent_ptr = &ptr->value.data.x_struct.fields[slice_ptr_index];
11435 ConstExprValue *len_val = &ptr->value.data.x_struct.fields[slice_len_index];11544 ConstExprValue *len_val = &ptr->value.data.x_struct.fields[slice_len_index];
11436 base_ptr = ptr_val->data.x_ptr.base_ptr;
11437 abs_offset = ptr_val->data.x_ptr.index;
1143811545
11439 if (ptr_val->data.x_ptr.index == SIZE_MAX) {11546 switch (parent_ptr->data.x_ptr.special) {
11440 rel_end = 1;11547 case ConstPtrSpecialInvalid:
11441 } else {11548 zig_unreachable();
11442 rel_end = len_val->data.x_bignum.data.x_uint;11549 case ConstPtrSpecialRef:
11550 array_val = nullptr;
11551 abs_offset = SIZE_MAX;
11552 rel_end = 1;
11553 break;
11554 case ConstPtrSpecialBaseArray:
11555 array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
11556 abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
11557 rel_end = len_val->data.x_bignum.data.x_uint;
11558 break;
11559 case ConstPtrSpecialBaseStruct:
11560 zig_panic("TODO slice const inner struct");
11561 case ConstPtrSpecialHardCodedAddr:
11562 array_val = nullptr;
11563 break;
11443 }11564 }
11444 } else {11565 } else {
11445 zig_unreachable();11566 zig_unreachable();
11446 }11567 }
1144711568
11448 uint64_t start_scalar = casted_start->value.data.x_bignum.data.x_uint;11569 if (array_val || parent_ptr->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
11449 if (start_scalar > rel_end) {11570 uint64_t start_scalar = casted_start->value.data.x_bignum.data.x_uint;
11450 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));11571 if (start_scalar > rel_end) {
11451 return ira->codegen->builtin_types.entry_invalid;11572 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
11452 }11573 return ira->codegen->builtin_types.entry_invalid;
11574 }
1145311575
11454 uint64_t end_scalar;11576 uint64_t end_scalar;
11455 if (end) {11577 if (end) {
11456 end_scalar = end->value.data.x_bignum.data.x_uint;11578 end_scalar = end->value.data.x_bignum.data.x_uint;
11457 } else {11579 } else {
11458 end_scalar = rel_end;11580 end_scalar = rel_end;
11459 }11581 }
11460 if (end_scalar > rel_end) {11582 if (end_scalar > rel_end) {
11461 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));11583 ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice"));
11462 return ira->codegen->builtin_types.entry_invalid;11584 return ira->codegen->builtin_types.entry_invalid;
11463 }11585 }
11464 if (start_scalar > end_scalar) {11586 if (start_scalar > end_scalar) {
11465 ir_add_error(ira, &instruction->base, buf_sprintf("slice start is greater than end"));11587 ir_add_error(ira, &instruction->base, buf_sprintf("slice start is greater than end"));
11466 return ira->codegen->builtin_types.entry_invalid;11588 return ira->codegen->builtin_types.entry_invalid;
11467 }11589 }
1146811590
11469 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);11591 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
11470 out_val->data.x_struct.fields = allocate<ConstExprValue>(2);11592 out_val->data.x_struct.fields = allocate<ConstExprValue>(2);
1147111593
11472 ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index];11594 ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index];
11473 size_t index = (abs_offset != SIZE_MAX) ? (abs_offset + start_scalar) : SIZE_MAX;11595
11474 init_const_ptr(ira->codegen, ptr_val, base_ptr, index, instruction->is_const);11596 if (array_val) {
11597 size_t index = abs_offset + start_scalar;
11598 init_const_ptr_array(ira->codegen, ptr_val, array_val, index, instruction->is_const);
11599 } else {
11600 switch (parent_ptr->data.x_ptr.special) {
11601 case ConstPtrSpecialInvalid:
11602 zig_unreachable();
11603 case ConstPtrSpecialRef:
11604 init_const_ptr_ref(ira->codegen, ptr_val,
11605 parent_ptr->data.x_ptr.data.ref.pointee, instruction->is_const);
11606 break;
11607 case ConstPtrSpecialBaseArray:
11608 zig_unreachable();
11609 case ConstPtrSpecialBaseStruct:
11610 zig_panic("TODO");
11611 case ConstPtrSpecialHardCodedAddr:
11612 zig_unreachable();
11613 }
11614 }
1147511615
11476 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];11616 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
11477 init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);11617 init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
1147811618
11479 return return_type;11619 return return_type;
11620 }
11480 }11621 }
1148111622
11482 IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr,11623 IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr,
...@@ -11688,8 +11829,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,...@@ -11688,8 +11829,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
11688 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);11829 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
11689 if (!ptr_val)11830 if (!ptr_val)
11690 return ira->codegen->builtin_types.entry_invalid;11831 return ira->codegen->builtin_types.entry_invalid;
11691 ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr;11832 ConstExprValue *err_union_val = const_ptr_pointee(ptr_val);
11692 assert(ptr_val->data.x_ptr.index == SIZE_MAX);
11693 if (err_union_val->special != ConstValSpecialRuntime) {11833 if (err_union_val->special != ConstValSpecialRuntime) {
11694 ErrorTableEntry *err = err_union_val->data.x_err_union.err;11834 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
11695 assert(err);11835 assert(err);
...@@ -11728,13 +11868,13 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -11728,13 +11868,13 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
11728 return ira->codegen->builtin_types.entry_invalid;11868 return ira->codegen->builtin_types.entry_invalid;
11729 } else if (canon_type->id == TypeTableEntryIdErrorUnion) {11869 } else if (canon_type->id == TypeTableEntryIdErrorUnion) {
11730 TypeTableEntry *child_type = canon_type->data.error.child_type;11870 TypeTableEntry *child_type = canon_type->data.error.child_type;
11731 TypeTableEntry *result_type = get_pointer_to_type(ira->codegen, child_type, false);11871 TypeTableEntry *result_type = get_pointer_to_type_volatile(ira->codegen, child_type,
11872 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile);
11732 if (instr_is_comptime(value)) {11873 if (instr_is_comptime(value)) {
11733 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);11874 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
11734 if (!ptr_val)11875 if (!ptr_val)
11735 return ira->codegen->builtin_types.entry_invalid;11876 return ira->codegen->builtin_types.entry_invalid;
11736 ConstExprValue *err_union_val = ptr_val->data.x_ptr.base_ptr;11877 ConstExprValue *err_union_val = const_ptr_pointee(ptr_val);
11737 assert(ptr_val->data.x_ptr.index == SIZE_MAX);
11738 if (err_union_val->special != ConstValSpecialRuntime) {11878 if (err_union_val->special != ConstValSpecialRuntime) {
11739 ErrorTableEntry *err = err_union_val->data.x_err_union.err;11879 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
11740 if (err != nullptr) {11880 if (err != nullptr) {
...@@ -11744,8 +11884,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -11744,8 +11884,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
11744 }11884 }
1174511885
11746 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);11886 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
11747 out_val->data.x_ptr.base_ptr = err_union_val->data.x_err_union.payload;11887 out_val->data.x_ptr.special = ConstPtrSpecialRef;
11748 out_val->data.x_ptr.index = SIZE_MAX;11888 out_val->data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
11749 return result_type;11889 return result_type;
11750 }11890 }
11751 }11891 }
test/cases/eval.zig+20
...@@ -263,3 +263,23 @@ fn fnWithSetDebugSafety() -> i32{...@@ -263,3 +263,23 @@ fn fnWithSetDebugSafety() -> i32{
263 @setDebugSafety(this, true);263 @setDebugSafety(this, true);
264 return 1234;264 return 1234;
265}265}
266
267
268
269const SimpleStruct = struct {
270 field: i32,
271
272 fn method(self: &const SimpleStruct) -> i32 {
273 return self.field + 3;
274 }
275};
276
277var simple_struct = SimpleStruct{ .field = 1234, };
278
279const bound_fn = simple_struct.method;
280
281fn callMethodOnBoundFnReferringToVarInstance() {
282 @setFnTest(this);
283
284 assert(bound_fn() == 1237);
285}