authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-17 16:27:45-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-17 16:27:45-04:00
log74250e434eb4ba0d752808e6a7b8d647e545c420
tree04506678184e682a57d837ff6caab7d67cab737b
parentb025193de5b951734e5108e4762e5dc40359431b
signature Commit is signed but in an unrecognized format.

inferred comptime union inits


3 files changed, 85 insertions(+), 74 deletions(-)

src/all_types.hpp-1
...@@ -2646,7 +2646,6 @@ struct IrInstructionContainerInitList {...@@ -2646,7 +2646,6 @@ struct IrInstructionContainerInitList {
26462646
2647struct IrInstructionContainerInitFieldsField {2647struct IrInstructionContainerInitFieldsField {
2648 Buf *name;2648 Buf *name;
2649 IrInstruction *value;
2650 AstNode *source_node;2649 AstNode *source_node;
2651 TypeStructField *type_struct_field;2650 TypeStructField *type_struct_field;
2652 IrInstruction *result_loc;2651 IrInstruction *result_loc;
src/ir.cpp+84-72
...@@ -1555,7 +1555,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop...@@ -1555,7 +1555,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop
15551555
1556 ir_ref_instruction(container_type, irb->current_basic_block);1556 ir_ref_instruction(container_type, irb->current_basic_block);
1557 for (size_t i = 0; i < field_count; i += 1) {1557 for (size_t i = 0; i < field_count; i += 1) {
1558 ir_ref_instruction(fields[i].value, irb->current_basic_block);1558 ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);
1559 }1559 }
1560 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);1560 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
15611561
...@@ -5783,7 +5783,6 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A...@@ -5783,7 +5783,6 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
5783 return expr_value;5783 return expr_value;
57845784
5785 fields[i].name = name;5785 fields[i].name = name;
5786 fields[i].value = expr_value;
5787 fields[i].source_node = entry_node;5786 fields[i].source_node = entry_node;
5788 fields[i].result_loc = field_ptr;5787 fields[i].result_loc = field_ptr;
5789 }5788 }
...@@ -17182,69 +17181,89 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -17182,69 +17181,89 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
17182 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,17181 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
17183 source_instr, container_ptr, container_type);17182 source_instr, container_ptr, container_type);
17184 }17183 }
17185 } else if (bare_type->id == ZigTypeIdEnum) {17184 }
17185
17186 if (bare_type->id == ZigTypeIdEnum) {
17186 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,17187 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
17187 source_instr, container_ptr, container_type);17188 source_instr, container_ptr, container_type);
17188 } else if (bare_type->id == ZigTypeIdUnion) {17189 }
17190
17191 if (bare_type->id == ZigTypeIdUnion) {
17189 bool is_const = container_ptr->value.type->data.pointer.is_const;17192 bool is_const = container_ptr->value.type->data.pointer.is_const;
17190 bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;17193 bool is_volatile = container_ptr->value.type->data.pointer.is_volatile;
1719117194
17192 TypeUnionField *field = find_union_type_field(bare_type, field_name);17195 TypeUnionField *field = find_union_type_field(bare_type, field_name);
17193 if (field) {17196 if (field == nullptr) {
17194 if (instr_is_comptime(container_ptr)) {17197 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
17195 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);17198 source_instr, container_ptr, container_type);
17196 if (!ptr_val)17199 }
17200 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
17201 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
17202 if (instr_is_comptime(container_ptr)) {
17203 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
17204 if (!ptr_val)
17205 return ira->codegen->invalid_instruction;
17206
17207 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
17208 ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
17209 if (union_val == nullptr)
17210 return ira->codegen->invalid_instruction;
17211 if (type_is_invalid(union_val->type))
17197 return ira->codegen->invalid_instruction;17212 return ira->codegen->invalid_instruction;
1719817213
17199 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {17214 if (initializing) {
17200 ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);17215 ConstExprValue *payload_val = create_const_vals(1);
17201 if (union_val == nullptr)17216 payload_val->special = ConstValSpecialUndef;
17202 return ira->codegen->invalid_instruction;17217 payload_val->type = field->type_entry;
17203 if (type_is_invalid(union_val->type))17218 ConstParent *parent = get_const_val_parent(ira->codegen, payload_val);
17204 return ira->codegen->invalid_instruction;17219 if (parent != nullptr) {
17220 parent->id = ConstParentIdUnion;
17221 parent->data.p_union.union_val = union_val;
17222 }
1720517223
17206 if (initializing) {17224 union_val->special = ConstValSpecialStatic;
17207 bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);17225 bigint_init_bigint(&union_val->data.x_union.tag, &field->enum_field->value);
17208 } else {17226 union_val->data.x_union.payload = payload_val;
17209 TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);17227 } else {
17210 if (actual_field == nullptr)17228 TypeUnionField *actual_field = find_union_field_by_tag(bare_type, &union_val->data.x_union.tag);
17211 zig_unreachable();17229 if (actual_field == nullptr)
17230 zig_unreachable();
1721217231
17213 if (field != actual_field) {17232 if (field != actual_field) {
17214 ir_add_error_node(ira, source_instr->source_node,17233 ir_add_error_node(ira, source_instr->source_node,
17215 buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name),17234 buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name),
17216 buf_ptr(actual_field->name)));17235 buf_ptr(actual_field->name)));
17217 return ira->codegen->invalid_instruction;17236 return ira->codegen->invalid_instruction;
17218 }
17219 }17237 }
17238 }
1722017239
17221 ConstExprValue *payload_val = union_val->data.x_union.payload;17240 ConstExprValue *payload_val = union_val->data.x_union.payload;
1722217241
17223 ZigType *field_type = field->type_entry;
17224 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
17225 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
1722617242
17227 IrInstruction *result = ir_const(ira, source_instr, ptr_type);17243 IrInstruction *result;
17228 ConstExprValue *const_val = &result->value;17244 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
17229 const_val->data.x_ptr.special = ConstPtrSpecialRef;17245 result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
17230 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;17246 source_instr->source_node, container_ptr, field, initializing);
17231 const_val->data.x_ptr.data.ref.pointee = payload_val;17247 result->value.type = ptr_type;
17232 return result;17248 result->value.special = ConstValSpecialStatic;
17249 } else {
17250 result = ir_const(ira, source_instr, ptr_type);
17233 }17251 }
17252 ConstExprValue *const_val = &result->value;
17253 const_val->data.x_ptr.special = ConstPtrSpecialRef;
17254 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
17255 const_val->data.x_ptr.data.ref.pointee = payload_val;
17256 return result;
17234 }17257 }
17235
17236 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
17237 source_instr->source_node, container_ptr, field, initializing);
17238 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
17239 PtrLenSingle, 0, 0, 0, false);
17240 return result;
17241 } else {
17242 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
17243 source_instr, container_ptr, container_type);
17244 }17258 }
17245 } else {17259
17246 zig_unreachable();17260 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope,
17261 source_instr->source_node, container_ptr, field, initializing);
17262 result->value.type = ptr_type;
17263 return result;
17247 }17264 }
17265
17266 zig_unreachable();
17248}17267}
1724917268
17250static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {17269static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {
...@@ -18891,12 +18910,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -18891,12 +18910,12 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
18891 }18910 }
1889218911
18893 IrInstructionContainerInitFieldsField *field = &fields[0];18912 IrInstructionContainerInitFieldsField *field = &fields[0];
18894 IrInstruction *field_value = field->value->child;18913 IrInstruction *field_result_loc = field->result_loc->child;
18895 if (type_is_invalid(field_value->value.type))18914 if (type_is_invalid(field_result_loc->value.type))
18896 return ira->codegen->invalid_instruction;18915 return ira->codegen->invalid_instruction;
1889718916
18898 TypeUnionField *type_field = find_union_type_field(container_type, field->name);18917 TypeUnionField *type_field = find_union_type_field(container_type, field->name);
18899 if (!type_field) {18918 if (type_field == nullptr) {
18900 ir_add_error_node(ira, field->source_node,18919 ir_add_error_node(ira, field->source_node,
18901 buf_sprintf("no member named '%s' in union '%s'",18920 buf_sprintf("no member named '%s' in union '%s'",
18902 buf_ptr(field->name), buf_ptr(&container_type->name)));18921 buf_ptr(field->name), buf_ptr(&container_type->name)));
...@@ -18906,33 +18925,26 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -18906,33 +18925,26 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
18906 if (type_is_invalid(type_field->type_entry))18925 if (type_is_invalid(type_field->type_entry))
18907 return ira->codegen->invalid_instruction;18926 return ira->codegen->invalid_instruction;
1890818927
18909 IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);18928 if (result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) {
18910 if (casted_field_value == ira->codegen->invalid_instruction)18929 if (instr_is_comptime(field_result_loc) &&
18911 return ira->codegen->invalid_instruction;18930 field_result_loc->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
1891218931 {
18913 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))18932 result_loc->value.data.x_ptr.mut = ConstPtrMutComptimeConst;
18914 return ira->codegen->invalid_instruction;18933 } else {
18934 result_loc->value.special = ConstValSpecialRuntime;
18935 }
18936 }
1891518937
18916 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)18938 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
18917 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;18939 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
18918 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
18919 !type_has_bits(casted_field_value->value.type))
18920 {
18921 ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
18922 if (!field_val)
18923 return ira->codegen->invalid_instruction;
18924
18925 IrInstruction *result = ir_const(ira, instruction, container_type);
18926 ConstExprValue *out_val = &result->value;
18927 out_val->data.x_union.payload = field_val;
18928 out_val->data.x_union.tag = type_field->enum_field->value;
18929 out_val->parent.id = ConstParentIdUnion;
18930 out_val->parent.data.p_union.union_val = out_val;
1893118940
18932 return result;18941 IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr);
18942 if (is_comptime && !instr_is_comptime(result)) {
18943 ir_add_error(ira, field->result_loc,
18944 buf_sprintf("unable to evaluate constant expression"));
18945 return ira->codegen->invalid_instruction;
18933 }18946 }
1893418947 return result;
18935 return ir_get_deref(ira, instruction, result_loc, nullptr);
18936}18948}
1893718949
18938static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,18950static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
src/ir_print.cpp+1-1
...@@ -364,7 +364,7 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI...@@ -364,7 +364,7 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
364 IrInstructionContainerInitFieldsField *field = &instruction->fields[i];364 IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
365 const char *comma = (i == 0) ? "" : ", ";365 const char *comma = (i == 0) ? "" : ", ";
366 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));366 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
367 ir_print_other_instruction(irp, field->value);367 ir_print_other_instruction(irp, field->result_loc);
368 }368 }
369 fprintf(irp->f, "} // container init");369 fprintf(irp->f, "} // container init");
370}370}