authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-26 23:31:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-27 00:54:14-04:00
log2dfb1ebee2bc215271e5416b723d746af319621b
tree9b859eebd0926cb82c7370362baafec617e763dc
parentd6b01931ef8a04777ae198af323c2b6ba998f7b1

const global values can reference each other

Before, if you did something like: ``` const hi1 = "hi"; const hi2 = hi1; ``` This would create the "hi" data twice in the built object. But since the value is const we don't have to duplicate the data, now we take advantage of this fact. closes #336

8 files changed, 160 insertions(+), 84 deletions(-)

src/all_types.hpp+7-2
......@@ -210,11 +210,15 @@ struct ConstFn {
210210 FnTableEntry *fn_entry;
211211};
212212
213struct ConstGlobalRefs {
214 LLVMValueRef llvm_value;
215 LLVMValueRef llvm_global;
216};
217
213218struct ConstExprValue {
214219 TypeTableEntry *type;
215220 ConstValSpecial special;
216 LLVMValueRef llvm_value;
217 LLVMValueRef llvm_global;
221 ConstGlobalRefs *global_refs;
218222
219223 union {
220224 // populated if special == ConstValSpecialStatic
......@@ -527,6 +531,7 @@ enum CastOp {
527531 CastOpBoolToInt,
528532 CastOpResizeSlice,
529533 CastOpBytesToSlice,
534 CastOpNumLitToConcrete,
530535};
531536
532537struct AstNodeFnCallExpr {
src/analyze.cpp+39-22
......@@ -3457,7 +3457,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
34573457void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
34583458 const_val->special = ConstValSpecialStatic;
34593459 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
3460 const_val->data.x_array.s_none.elements = allocate<ConstExprValue>(buf_len(str));
3460 const_val->data.x_array.s_none.elements = create_const_vals(buf_len(str));
34613461
34623462 for (size_t i = 0; i < buf_len(str); i += 1) {
34633463 ConstExprValue *this_char = &const_val->data.x_array.s_none.elements[i];
......@@ -3468,7 +3468,7 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
34683468}
34693469
34703470ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
3471 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3471 ConstExprValue *const_val = create_const_vals(1);
34723472 init_const_str_lit(g, const_val, str);
34733473 return const_val;
34743474}
......@@ -3476,10 +3476,10 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
34763476void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
34773477 // first we build the underlying array
34783478 size_t len_with_null = buf_len(str) + 1;
3479 ConstExprValue *array_val = allocate<ConstExprValue>(1);
3479 ConstExprValue *array_val = create_const_vals(1);
34803480 array_val->special = ConstValSpecialStatic;
34813481 array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);
3482 array_val->data.x_array.s_none.elements = allocate<ConstExprValue>(len_with_null);
3482 array_val->data.x_array.s_none.elements = create_const_vals(len_with_null);
34833483 for (size_t i = 0; i < buf_len(str); i += 1) {
34843484 ConstExprValue *this_char = &array_val->data.x_array.s_none.elements[i];
34853485 this_char->special = ConstValSpecialStatic;
......@@ -3500,7 +3500,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
35003500 const_val->data.x_ptr.data.base_array.is_cstr = true;
35013501}
35023502ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
3503 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3503 ConstExprValue *const_val = create_const_vals(1);
35043504 init_const_c_str_lit(g, const_val, str);
35053505 return const_val;
35063506}
......@@ -3513,7 +3513,7 @@ void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *typ
35133513}
35143514
35153515ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative) {
3516 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3516 ConstExprValue *const_val = create_const_vals(1);
35173517 init_const_unsigned_negative(const_val, type, x, negative);
35183518 return const_val;
35193519}
......@@ -3533,7 +3533,7 @@ void init_const_signed(ConstExprValue *const_val, TypeTableEntry *type, int64_t
35333533}
35343534
35353535ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
3536 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3536 ConstExprValue *const_val = create_const_vals(1);
35373537 init_const_signed(const_val, type, x);
35383538 return const_val;
35393539}
......@@ -3545,7 +3545,7 @@ void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double va
35453545}
35463546
35473547ConstExprValue *create_const_float(TypeTableEntry *type, double value) {
3548 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3548 ConstExprValue *const_val = create_const_vals(1);
35493549 init_const_float(const_val, type, value);
35503550 return const_val;
35513551}
......@@ -3557,7 +3557,7 @@ void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64
35573557}
35583558
35593559ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag) {
3560 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3560 ConstExprValue *const_val = create_const_vals(1);
35613561 init_const_enum_tag(const_val, type, tag);
35623562 return const_val;
35633563}
......@@ -3569,7 +3569,7 @@ void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value) {
35693569}
35703570
35713571ConstExprValue *create_const_bool(CodeGen *g, bool value) {
3572 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3572 ConstExprValue *const_val = create_const_vals(1);
35733573 init_const_bool(g, const_val, value);
35743574 return const_val;
35753575}
......@@ -3580,7 +3580,7 @@ void init_const_runtime(ConstExprValue *const_val, TypeTableEntry *type) {
35803580}
35813581
35823582ConstExprValue *create_const_runtime(TypeTableEntry *type) {
3583 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3583 ConstExprValue *const_val = create_const_vals(1);
35843584 init_const_runtime(const_val, type);
35853585 return const_val;
35863586}
......@@ -3592,7 +3592,7 @@ void init_const_type(CodeGen *g, ConstExprValue *const_val, TypeTableEntry *type
35923592}
35933593
35943594ConstExprValue *create_const_type(CodeGen *g, TypeTableEntry *type_value) {
3595 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3595 ConstExprValue *const_val = create_const_vals(1);
35963596 init_const_type(g, const_val, type_value);
35973597 return const_val;
35983598}
......@@ -3604,14 +3604,14 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
36043604
36053605 const_val->special = ConstValSpecialStatic;
36063606 const_val->type = get_slice_type(g, array_val->type->data.array.child_type, is_const);
3607 const_val->data.x_struct.fields = allocate<ConstExprValue>(2);
3607 const_val->data.x_struct.fields = create_const_vals(2);
36083608
36093609 init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const);
36103610 init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len);
36113611}
36123612
36133613ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t start, size_t len, bool is_const) {
3614 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3614 ConstExprValue *const_val = create_const_vals(1);
36153615 init_const_slice(g, const_val, array_val, start, len, is_const);
36163616 return const_val;
36173617}
......@@ -3630,7 +3630,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue
36303630}
36313631
36323632ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const) {
3633 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3633 ConstExprValue *const_val = create_const_vals(1);
36343634 init_const_ptr_array(g, const_val, array_val, elem_index, is_const);
36353635 return const_val;
36363636}
......@@ -3643,7 +3643,7 @@ void init_const_ptr_ref(CodeGen *g, ConstExprValue *const_val, ConstExprValue *p
36433643}
36443644
36453645ConstExprValue *create_const_ptr_ref(CodeGen *g, ConstExprValue *pointee_val, bool is_const) {
3646 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3646 ConstExprValue *const_val = create_const_vals(1);
36473647 init_const_ptr_ref(g, const_val, pointee_val, is_const);
36483648 return const_val;
36493649}
......@@ -3660,7 +3660,7 @@ void init_const_ptr_hard_coded_addr(CodeGen *g, ConstExprValue *const_val, TypeT
36603660ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *pointee_type,
36613661 size_t addr, bool is_const)
36623662{
3663 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3663 ConstExprValue *const_val = create_const_vals(1);
36643664 init_const_ptr_hard_coded_addr(g, const_val, pointee_type, addr, is_const);
36653665 return const_val;
36663666}
......@@ -3673,7 +3673,7 @@ void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_inde
36733673}
36743674
36753675ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end) {
3676 ConstExprValue *const_val = allocate<ConstExprValue>(1);
3676 ConstExprValue *const_val = create_const_vals(1);
36773677 init_const_arg_tuple(g, const_val, arg_index_start, arg_index_end);
36783678 return const_val;
36793679}
......@@ -3689,7 +3689,7 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
36893689
36903690 const_val->special = ConstValSpecialStatic;
36913691 size_t field_count = wanted_type->data.structure.src_field_count;
3692 const_val->data.x_struct.fields = allocate<ConstExprValue>(field_count);
3692 const_val->data.x_struct.fields = create_const_vals(field_count);
36933693 for (size_t i = 0; i < field_count; i += 1) {
36943694 ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
36953695 field_val->type = wanted_type->data.structure.fields[i].type_entry;
......@@ -3707,6 +3707,15 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
37073707 }
37083708}
37093709
3710ConstExprValue *create_const_vals(size_t count) {
3711 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count);
3712 ConstExprValue *vals = allocate<ConstExprValue>(count);
3713 for (size_t i = 0; i < count; i += 1) {
3714 vals[i].global_refs = &global_refs[i];
3715 }
3716 return vals;
3717}
3718
37103719void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry) {
37113720 if (type_entry->id == TypeTableEntryIdStruct) {
37123721 if (!type_entry->data.structure.complete)
......@@ -3788,16 +3797,24 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
37883797 return false;
37893798 return true;
37903799 case ConstPtrSpecialBaseArray:
3791 if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val)
3800 if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val &&
3801 a->data.x_ptr.data.base_array.array_val->global_refs !=
3802 b->data.x_ptr.data.base_array.array_val->global_refs)
3803 {
37923804 return false;
3805 }
37933806 if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
37943807 return false;
37953808 if (a->data.x_ptr.data.base_array.is_cstr != b->data.x_ptr.data.base_array.is_cstr)
37963809 return false;
37973810 return true;
37983811 case ConstPtrSpecialBaseStruct:
3799 if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val)
3812 if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val &&
3813 a->data.x_ptr.data.base_struct.struct_val->global_refs !=
3814 b->data.x_ptr.data.base_struct.struct_val->global_refs)
3815 {
38003816 return false;
3817 }
38013818 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
38023819 return false;
38033820 return true;
......@@ -4293,7 +4310,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
42934310 if (const_val->data.x_array.special == ConstArraySpecialUndef) {
42944311 const_val->data.x_array.special = ConstArraySpecialNone;
42954312 size_t elem_count = const_val->type->data.array.len;
4296 const_val->data.x_array.s_none.elements = allocate<ConstExprValue>(elem_count);
4313 const_val->data.x_array.s_none.elements = create_const_vals(elem_count);
42974314 for (size_t i = 0; i < elem_count; i += 1) {
42984315 ConstExprValue *element_val = &const_val->data.x_array.s_none.elements[i];
42994316 element_val->type = const_val->type->data.array.child_type;
src/analyze.hpp+2
......@@ -153,6 +153,8 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
153153
154154void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
155155
156ConstExprValue *create_const_vals(size_t count);
157
156158TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
157159ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
158160FnTableEntry *get_extern_panic_fn(CodeGen *g);
src/codegen.cpp+47-32
......@@ -682,8 +682,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
682682
683683static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
684684 ConstExprValue *val = &g->panic_msg_vals[msg_id];
685 if (val->llvm_global)
686 return val->llvm_global;
685 if (val->global_refs->llvm_global)
686 return val->global_refs->llvm_global;
687687
688688 Buf *buf_msg = panic_msg_buf(msg_id);
689689 ConstExprValue *array_val = create_const_str_lit(g, buf_msg);
......@@ -692,8 +692,8 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
692692 render_const_val_global(g, val, "");
693693 render_const_val(g, val);
694694
695 assert(val->llvm_global);
696 return val->llvm_global;
695 assert(val->global_refs->llvm_global);
696 return val->global_refs->llvm_global;
697697}
698698
699699static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len) {
......@@ -1086,11 +1086,11 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
10861086 if (handle_is_ptr(instruction->value.type)) {
10871087 render_const_val_global(g, &instruction->value, "");
10881088 TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
1089 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");
1089 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, ptr_type->type_ref, "");
10901090 } else if (instruction->value.type->id == TypeTableEntryIdPointer) {
1091 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_value, instruction->value.type->type_ref, "");
1091 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value, instruction->value.type->type_ref, "");
10921092 } else {
1093 instruction->llvm_value = instruction->value.llvm_value;
1093 instruction->llvm_value = instruction->value.global_refs->llvm_value;
10941094 }
10951095 assert(instruction->llvm_value);
10961096 }
......@@ -1535,6 +1535,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
15351535
15361536 switch (cast_instruction->cast_op) {
15371537 case CastOpNoCast:
1538 case CastOpNumLitToConcrete:
15381539 zig_unreachable();
15391540 case CastOpNoop:
15401541 return expr_val;
......@@ -3197,7 +3198,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
31973198 case ConstParentIdNone:
31983199 render_const_val(g, val);
31993200 render_const_val_global(g, val, "");
3200 return val->llvm_global;
3201 return val->global_refs->llvm_global;
32013202 case ConstParentIdStruct:
32023203 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
32033204 parent->data.p_struct.field_index);
......@@ -3506,9 +3507,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
35063507 render_const_val(g, pointee);
35073508 render_const_val_global(g, pointee, "");
35083509 ConstExprValue *other_val = pointee;
3509 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
3510 const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref);
35103511 render_const_val_global(g, const_val, "");
3511 return const_val->llvm_value;
3512 return const_val->global_refs->llvm_value;
35123513 }
35133514 case ConstPtrSpecialBaseArray:
35143515 {
......@@ -3518,15 +3519,15 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
35183519 if (array_const_val->type->zero_bits) {
35193520 // make this a null pointer
35203521 TypeTableEntry *usize = g->builtin_types.entry_usize;
3521 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
3522 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
35223523 const_val->type->type_ref);
35233524 render_const_val_global(g, const_val, "");
3524 return const_val->llvm_value;
3525 return const_val->global_refs->llvm_value;
35253526 }
35263527 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,
35273528 elem_index);
35283529 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
3529 const_val->llvm_value = ptr_val;
3530 const_val->global_refs->llvm_value = ptr_val;
35303531 render_const_val_global(g, const_val, "");
35313532 return ptr_val;
35323533 }
......@@ -3537,10 +3538,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
35373538 if (struct_const_val->type->zero_bits) {
35383539 // make this a null pointer
35393540 TypeTableEntry *usize = g->builtin_types.entry_usize;
3540 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
3541 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
35413542 const_val->type->type_ref);
35423543 render_const_val_global(g, const_val, "");
3543 return const_val->llvm_value;
3544 return const_val->global_refs->llvm_value;
35443545 }
35453546 size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
35463547 size_t gen_field_index =
......@@ -3548,7 +3549,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
35483549 LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
35493550 gen_field_index);
35503551 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
3551 const_val->llvm_value = ptr_val;
3552 const_val->global_refs->llvm_value = ptr_val;
35523553 render_const_val_global(g, const_val, "");
35533554 return ptr_val;
35543555 }
......@@ -3556,10 +3557,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
35563557 {
35573558 uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
35583559 TypeTableEntry *usize = g->builtin_types.entry_usize;
3559 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
3560 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
35603561 const_val->type->type_ref);
35613562 render_const_val_global(g, const_val, "");
3562 return const_val->llvm_value;
3563 return const_val->global_refs->llvm_value;
35633564 }
35643565 }
35653566 }
......@@ -3608,27 +3609,32 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
36083609}
36093610
36103611static void render_const_val(CodeGen *g, ConstExprValue *const_val) {
3611 if (!const_val->llvm_value)
3612 const_val->llvm_value = gen_const_val(g, const_val);
3612 if (!const_val->global_refs)
3613 const_val->global_refs = allocate<ConstGlobalRefs>(1);
3614 if (!const_val->global_refs->llvm_value)
3615 const_val->global_refs->llvm_value = gen_const_val(g, const_val);
36133616
3614 if (const_val->llvm_global)
3615 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
3617 if (const_val->global_refs->llvm_global)
3618 LLVMSetInitializer(const_val->global_refs->llvm_global, const_val->global_refs->llvm_value);
36163619}
36173620
36183621static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name) {
3619 if (!const_val->llvm_global) {
3620 LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;
3622 if (!const_val->global_refs)
3623 const_val->global_refs = allocate<ConstGlobalRefs>(1);
3624
3625 if (!const_val->global_refs->llvm_global) {
3626 LLVMTypeRef type_ref = const_val->global_refs->llvm_value ? LLVMTypeOf(const_val->global_refs->llvm_value) : const_val->type->type_ref;
36213627 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, name);
36223628 LLVMSetLinkage(global_value, LLVMInternalLinkage);
36233629 LLVMSetGlobalConstant(global_value, true);
36243630 LLVMSetUnnamedAddr(global_value, true);
36253631 LLVMSetAlignment(global_value, get_type_alignment(g, const_val->type));
36263632
3627 const_val->llvm_global = global_value;
3633 const_val->global_refs->llvm_global = global_value;
36283634 }
36293635
3630 if (const_val->llvm_value)
3631 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
3636 if (const_val->global_refs->llvm_value)
3637 LLVMSetInitializer(const_val->global_refs->llvm_global, const_val->global_refs->llvm_value);
36323638}
36333639
36343640static void delete_unused_builtin_fns(CodeGen *g) {
......@@ -3849,7 +3855,7 @@ static void do_code_gen(CodeGen *g) {
38493855 bool exported = (var->linkage == VarLinkageExport);
38503856 render_const_val(g, var->value);
38513857 render_const_val_global(g, var->value, buf_ptr(get_mangled_name(g, &var->name, exported)));
3852 global_value = var->value->llvm_global;
3858 global_value = var->value->global_refs->llvm_global;
38533859
38543860 if (exported) {
38553861 LLVMSetLinkage(global_value, LLVMExternalLinkage);
......@@ -3862,7 +3868,7 @@ static void do_code_gen(CodeGen *g) {
38623868
38633869 // TODO debug info for function pointers
38643870 if (var->gen_is_const && var->value->type->id != TypeTableEntryIdFn) {
3865 gen_global_var(g, var, var->value->llvm_value, var->value->type);
3871 gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
38663872 }
38673873 }
38683874
......@@ -4737,9 +4743,18 @@ static void init(CodeGen *g) {
47374743
47384744 g->invalid_instruction = allocate<IrInstruction>(1);
47394745 g->invalid_instruction->value.type = g->builtin_types.entry_invalid;
4746 g->invalid_instruction->value.global_refs = allocate<ConstGlobalRefs>(1);
47404747
47414748 g->const_void_val.special = ConstValSpecialStatic;
47424749 g->const_void_val.type = g->builtin_types.entry_void;
4750 g->const_void_val.global_refs = allocate<ConstGlobalRefs>(1);
4751
4752 {
4753 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(PanicMsgIdCount);
4754 for (size_t i = 0; i < PanicMsgIdCount; i += 1) {
4755 g->panic_msg_vals[i].global_refs = &global_refs[i];
4756 }
4757 }
47434758
47444759 define_builtin_fns(g);
47454760 define_builtin_compile_vars(g);
......@@ -4826,10 +4841,10 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
48264841 TypeTableEntry *field_types[] = { str_type, fn_type, };
48274842 TypeTableEntry *struct_type = get_struct_type(g, "ZigTestFn", field_names, field_types, 2);
48284843
4829 ConstExprValue *test_fn_array = allocate<ConstExprValue>(1);
4844 ConstExprValue *test_fn_array = create_const_vals(1);
48304845 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length);
48314846 test_fn_array->special = ConstValSpecialStatic;
4832 test_fn_array->data.x_array.s_none.elements = allocate<ConstExprValue>(g->test_fns.length);
4847 test_fn_array->data.x_array.s_none.elements = create_const_vals(g->test_fns.length);
48334848
48344849 for (size_t i = 0; i < g->test_fns.length; i += 1) {
48354850 FnTableEntry *test_fn_entry = g->test_fns.at(i);
......@@ -4840,7 +4855,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
48404855 this_val->data.x_struct.parent.id = ConstParentIdArray;
48414856 this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;
48424857 this_val->data.x_struct.parent.data.p_array.elem_index = i;
4843 this_val->data.x_struct.fields = allocate<ConstExprValue>(2);
4858 this_val->data.x_struct.fields = create_const_vals(2);
48444859
48454860 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
48464861 ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name);
src/ir.cpp+39-24
......@@ -553,6 +553,7 @@ static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_no
553553 special_instruction->base.source_node = source_node;
554554 special_instruction->base.debug_id = exec_next_debug_id(irb->exec);
555555 special_instruction->base.owner_bb = irb->current_basic_block;
556 special_instruction->base.value.global_refs = allocate<ConstGlobalRefs>(1);
556557 return special_instruction;
557558}
558559
......@@ -3210,7 +3211,7 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco
32103211 variable_entry->mem_slot_index = SIZE_MAX;
32113212 variable_entry->is_comptime = is_comptime;
32123213 variable_entry->src_arg_index = SIZE_MAX;
3213 variable_entry->value = allocate<ConstExprValue>(1);
3214 variable_entry->value = create_const_vals(1);
32143215
32153216 if (name) {
32163217 buf_init_from_buf(&variable_entry->name, name);
......@@ -6565,6 +6566,14 @@ static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, TypeTableE
65656566 }
65666567}
65676568
6569static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs) {
6570 ConstGlobalRefs *global_refs = dest->global_refs;
6571 *dest = *src;
6572 if (!same_global_refs) {
6573 dest->global_refs = global_refs;
6574 }
6575}
6576
65686577static void eval_const_expr_implicit_cast(CastOp cast_op,
65696578 ConstExprValue *other_val, TypeTableEntry *other_type,
65706579 ConstExprValue *const_val, TypeTableEntry *new_type)
......@@ -6576,7 +6585,13 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
65766585 case CastOpNoCast:
65776586 zig_unreachable();
65786587 case CastOpNoop:
6579 *const_val = *other_val;
6588 {
6589 copy_const_val(const_val, other_val, other_val->special == ConstValSpecialStatic);
6590 const_val->type = new_type;
6591 break;
6592 }
6593 case CastOpNumLitToConcrete:
6594 const_val->data.x_bignum = other_val->data.x_bignum;
65806595 const_val->type = new_type;
65816596 break;
65826597 case CastOpResizeSlice:
......@@ -7188,7 +7203,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
71887203 }
71897204 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
71907205 source_instr->source_node, wanted_type);
7191 result->value = *val;
7206 result->value.data.x_bignum = val->data.x_bignum;
71927207 result->value.type = wanted_type;
71937208 return result;
71947209 }
......@@ -7613,7 +7628,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
76137628 (actual_type->id == TypeTableEntryIdNumLitInt &&
76147629 wanted_type->id == TypeTableEntryIdInt))
76157630 {
7616 op = CastOpNoop;
7631 op = CastOpNumLitToConcrete;
76177632 } else if (wanted_type->id == TypeTableEntryIdInt) {
76187633 op = CastOpFloatToInt;
76197634 } else if (wanted_type->id == TypeTableEntryIdFloat) {
......@@ -7741,7 +7756,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
77417756 if (pointee->special != ConstValSpecialRuntime) {
77427757 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
77437758 source_instruction->source_node, child_type);
7744 result->value = *pointee;
7759 copy_const_val(&result->value, pointee, ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst);
77457760 return result;
77467761 }
77477762 }
......@@ -8584,7 +8599,7 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
85848599
85858600 result_type = get_pointer_to_type(ira->codegen, child_type, true);
85868601
8587 out_array_val = allocate<ConstExprValue>(1);
8602 out_array_val = create_const_vals(1);
85888603 out_array_val->special = ConstValSpecialStatic;
85898604 out_array_val->type = get_array_type(ira->codegen, child_type, new_len);
85908605 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
......@@ -8592,7 +8607,7 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
85928607 out_val->data.x_ptr.data.base_array.array_val = out_array_val;
85938608 out_val->data.x_ptr.data.base_array.elem_index = 0;
85948609 }
8595 out_array_val->data.x_array.s_none.elements = allocate<ConstExprValue>(new_len);
8610 out_array_val->data.x_array.s_none.elements = create_const_vals(new_len);
85968611
85978612 expand_undef_array(ira->codegen, op1_array_val);
85988613
......@@ -8648,7 +8663,7 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp
86488663 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
86498664
86508665 uint64_t new_array_len = array_len.data.x_uint;
8651 out_val->data.x_array.s_none.elements = allocate<ConstExprValue>(new_array_len);
8666 out_val->data.x_array.s_none.elements = create_const_vals(new_array_len);
86528667
86538668 expand_undef_array(ira->codegen, array_val);
86548669
......@@ -9139,7 +9154,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
91399154 GenericFnTypeId *generic_id = allocate<GenericFnTypeId>(1);
91409155 generic_id->fn_entry = fn_entry;
91419156 generic_id->param_count = 0;
9142 generic_id->params = allocate<ConstExprValue>(new_fn_arg_count);
9157 generic_id->params = create_const_vals(new_fn_arg_count);
91439158 size_t next_proto_i = 0;
91449159
91459160 if (first_arg_ptr) {
......@@ -9451,7 +9466,7 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp
94519466 ConstExprValue *pointee = const_ptr_pointee(ira->codegen, &value->value);
94529467 if (pointee->type == child_type) {
94539468 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
9454 *out_val = *pointee;
9469 copy_const_val(out_val, pointee, value->value.data.x_ptr.mut == ConstPtrMutComptimeConst);
94559470 return child_type;
94569471 }
94579472 }
......@@ -10118,7 +10133,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
1011810133
1011910134 // TODO instead of allocating this every time, put it in the tld value and we can reference
1012010135 // the same one every time
10121 ConstExprValue *const_val = allocate<ConstExprValue>(1);
10136 ConstExprValue *const_val = create_const_vals(1);
1012210137 const_val->special = ConstValSpecialStatic;
1012310138 const_val->type = fn_entry->type_entry;
1012410139 const_val->data.x_fn.fn_entry = fn_entry;
......@@ -10162,7 +10177,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1016210177 }
1016310178 } else if (container_type->id == TypeTableEntryIdArray) {
1016410179 if (buf_eql_str(field_name, "len")) {
10165 ConstExprValue *len_val = allocate<ConstExprValue>(1);
10180 ConstExprValue *len_val = create_const_vals(1);
1016610181 init_const_usize(ira->codegen, len_val, container_type->data.array.len);
1016710182
1016810183 TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize;
......@@ -10185,7 +10200,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1018510200 ConstExprValue *child_val = const_ptr_pointee(ira->codegen, container_ptr_val);
1018610201
1018710202 if (buf_eql_str(field_name, "len")) {
10188 ConstExprValue *len_val = allocate<ConstExprValue>(1);
10203 ConstExprValue *len_val = create_const_vals(1);
1018910204 size_t len = child_val->data.x_arg_tuple.end_index - child_val->data.x_arg_tuple.start_index;
1019010205 init_const_usize(ira->codegen, len_val, len);
1019110206
......@@ -10258,7 +10273,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1025810273 } else if (child_type->id == TypeTableEntryIdPureError) {
1025910274 auto err_table_entry = ira->codegen->error_table.maybe_get(field_name);
1026010275 if (err_table_entry) {
10261 ConstExprValue *const_val = allocate<ConstExprValue>(1);
10276 ConstExprValue *const_val = create_const_vals(1);
1026210277 const_val->special = ConstValSpecialStatic;
1026310278 const_val->type = child_type;
1026410279 const_val->data.x_pure_err = err_table_entry->value;
......@@ -11346,7 +11361,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1134611361 case TypeTableEntryIdPureError:
1134711362 if (pointee_val) {
1134811363 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
11349 *out_val = *pointee_val;
11364 copy_const_val(out_val, pointee_val, true);
1135011365 out_val->type = target_type;
1135111366 return target_type;
1135211367 }
......@@ -11583,7 +11598,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
1158311598 ConstExprValue const_val = {};
1158411599 const_val.special = ConstValSpecialStatic;
1158511600 const_val.type = container_type;
11586 const_val.data.x_struct.fields = allocate<ConstExprValue>(actual_field_count);
11601 const_val.data.x_struct.fields = create_const_vals(actual_field_count);
1158711602 for (size_t i = 0; i < instr_field_count; i += 1) {
1158811603 IrInstructionContainerInitFieldsField *field = &fields[i];
1158911604
......@@ -11624,7 +11639,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
1162411639 if (!field_val)
1162511640 return ira->codegen->builtin_types.entry_invalid;
1162611641
11627 const_val.data.x_struct.fields[field_index] = *field_val;
11642 copy_const_val(&const_val.data.x_struct.fields[field_index], field_val, true);
1162811643 } else {
1162911644 first_non_const_instruction = casted_field_value;
1163011645 const_val.special = ConstValSpecialRuntime;
......@@ -11698,7 +11713,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
1169811713 ConstExprValue const_val = {};
1169911714 const_val.special = ConstValSpecialStatic;
1170011715 const_val.type = fixed_size_array_type;
11701 const_val.data.x_array.s_none.elements = allocate<ConstExprValue>(elem_count);
11716 const_val.data.x_array.s_none.elements = create_const_vals(elem_count);
1170211717
1170311718 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
1170411719
......@@ -11723,7 +11738,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
1172311738 if (!elem_val)
1172411739 return ira->codegen->builtin_types.entry_invalid;
1172511740
11726 const_val.data.x_array.s_none.elements[i] = *elem_val;
11741 copy_const_val(&const_val.data.x_array.s_none.elements[i], elem_val, true);
1172711742 } else {
1172811743 first_non_const_instruction = casted_arg;
1172911744 const_val.special = ConstValSpecialRuntime;
......@@ -11950,7 +11965,7 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc
1195011965 err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true);
1195111966 }
1195211967 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
11953 *out_val = *err->cached_error_name_val;
11968 copy_const_val(out_val, err->cached_error_name_val, true);
1195411969 return str_type;
1195511970 }
1195611971
......@@ -12133,7 +12148,7 @@ static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstru
1213312148 type_entry->cached_const_name_val = create_const_str_lit(ira->codegen, &type_entry->name);
1213412149 }
1213512150 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
12136 *out_val = *type_entry->cached_const_name_val;
12151 copy_const_val(out_val, type_entry->cached_const_name_val, true);
1213712152 return out_val->type;
1213812153}
1213912154
......@@ -12809,7 +12824,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1280912824 }
1281012825
1281112826 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
12812 out_val->data.x_struct.fields = allocate<ConstExprValue>(2);
12827 out_val->data.x_struct.fields = create_const_vals(2);
1281312828
1281412829 ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index];
1281512830
......@@ -13370,7 +13385,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc
1337013385 return ira->codegen->builtin_types.entry_invalid;
1337113386
1337213387 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13373 *out_val = *val;
13388 copy_const_val(out_val, val, false);
1337413389 out_val->type = dest_type;
1337513390 return dest_type;
1337613391 }
......@@ -13696,7 +13711,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
1369613711 ira->new_irb.exec = new_exec;
1369713712
1369813713 ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count;
13699 ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count);
13714 ira->exec_context.mem_slot_list = create_const_vals(ira->exec_context.mem_slot_count);
1370013715
1370113716 IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0);
1370213717 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr);
test/cases/eval.zig+10
......@@ -332,3 +332,13 @@ test "compile-time downcast when the bits fit" {
332332 assert(byte == 255);
333333 }
334334}
335
336const hi1 = "hi";
337const hi2 = hi1;
338test "const global shares pointer with other same one" {
339 assertEqualPtrs(&hi1[0], &hi2[0]);
340 comptime assert(&hi1[0] == &hi2[0]);
341}
342fn assertEqualPtrs(ptr1: &const u8, ptr2: &const u8) {
343 assert(ptr1 == ptr2);
344}
test/cases/var_args.zig+14
......@@ -65,3 +65,17 @@ test "array of var args functions" {
6565 assert(foos[0]());
6666 assert(!foos[1]());
6767}
68
69
70test "pass array and slice of same array to var args should have same pointers" {
71 const array = "hi";
72 const slice: []const u8 = array;
73 return assertSlicePtrsEql(array, slice);
74}
75
76fn assertSlicePtrsEql(args: ...) {
77 const s1 = ([]const u8)(args[0]);
78 const s2 = args[1];
79 assert(s1.ptr == s2.ptr);
80}
81
test/tests.zig+2-4
......@@ -591,8 +591,7 @@ pub const CompileErrorContext = struct {
591591 tc.addSourceFile(".tmp_source.zig", source);
592592 comptime var arg_i = 0;
593593 inline while (arg_i < expected_lines.len) : (arg_i += 1) {
594 // TODO mem.dupe is because of issue #336
595 tc.addExpectedError(%%mem.dupe(self.b.allocator, u8, expected_lines[arg_i]));
594 tc.addExpectedError(expected_lines[arg_i]);
596595 }
597596 return tc;
598597 }
......@@ -854,8 +853,7 @@ pub const ParseHContext = struct {
854853 tc.addSourceFile("source.h", source);
855854 comptime var arg_i = 0;
856855 inline while (arg_i < expected_lines.len) : (arg_i += 1) {
857 // TODO mem.dupe is because of issue #336
858 tc.addExpectedError(%%mem.dupe(self.b.allocator, u8, expected_lines[arg_i]));
856 tc.addExpectedError(expected_lines[arg_i]);
859857 }
860858 return tc;
861859 }