authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-03 11:26:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-03 11:26:55-04:00
log9da054095cdc6d428c645c37189730c5e689964d
tree8d551e7c3c845154acfa5333a5c926bca9b39d13
parent9daf0140e5a78802fd294bce8a9019f59bd89b61
parent9b7ad124810e4a3df964927ace449502daa167f9
signature Commit is signed but in an unrecognized format.

Merge branch 'comptime-union-init' of https://github.com/rbscott/zig into rbscott-comptime-union-init


5 files changed, 136 insertions(+), 1 deletions(-)

src/all_types.hpp+10
...@@ -1509,6 +1509,7 @@ enum BuiltinFnId {...@@ -1509,6 +1509,7 @@ enum BuiltinFnId {
1509 BuiltinFnIdAtomicRmw,1509 BuiltinFnIdAtomicRmw,
1510 BuiltinFnIdAtomicLoad,1510 BuiltinFnIdAtomicLoad,
1511 BuiltinFnIdHasDecl,1511 BuiltinFnIdHasDecl,
1512 BuiltinFnIdUnionInit,
1512};1513};
15131514
1514struct BuiltinFnEntry {1515struct BuiltinFnEntry {
...@@ -2359,6 +2360,7 @@ enum IrInstructionId {...@@ -2359,6 +2360,7 @@ enum IrInstructionId {
2359 IrInstructionIdAllocaGen,2360 IrInstructionIdAllocaGen,
2360 IrInstructionIdEndExpr,2361 IrInstructionIdEndExpr,
2361 IrInstructionIdPtrOfArrayToSlice,2362 IrInstructionIdPtrOfArrayToSlice,
2363 IrInstructionIdUnionInitNamedField,
2362};2364};
23632365
2364struct IrInstruction {2366struct IrInstruction {
...@@ -3603,6 +3605,14 @@ struct IrInstructionAssertNonNull {...@@ -3603,6 +3605,14 @@ struct IrInstructionAssertNonNull {
3603 IrInstruction *target;3605 IrInstruction *target;
3604};3606};
36053607
3608struct IrInstructionUnionInitNamedField {
3609 IrInstruction base;
3610
3611 IrInstruction *union_type;
3612 IrInstruction *field_name;
3613 IrInstruction *value;
3614};
3615
3606struct IrInstructionHasDecl {3616struct IrInstructionHasDecl {
3607 IrInstruction base;3617 IrInstruction base;
36083618
src/codegen.cpp+2
...@@ -5635,6 +5635,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5635,6 +5635,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5635 case IrInstructionIdRef:5635 case IrInstructionIdRef:
5636 case IrInstructionIdBitCastSrc:5636 case IrInstructionIdBitCastSrc:
5637 case IrInstructionIdTestErrSrc:5637 case IrInstructionIdTestErrSrc:
5638 case IrInstructionIdUnionInitNamedField:
5638 zig_unreachable();5639 zig_unreachable();
56395640
5640 case IrInstructionIdDeclVarGen:5641 case IrInstructionIdDeclVarGen:
...@@ -7419,6 +7420,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -7419,6 +7420,7 @@ static void define_builtin_fns(CodeGen *g) {
7419 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);7420 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
7420 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);7421 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
7421 create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2);7422 create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2);
7423 create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3);
7422}7424}
74237425
7424static const char *bool_to_str(bool b) {7426static const char *bool_to_str(bool b) {
src/ir.cpp+75
...@@ -1069,6 +1069,7 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *)...@@ -1069,6 +1069,7 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *)
1069 return IrInstructionIdAssertNonNull;1069 return IrInstructionIdAssertNonNull;
1070}1070}
10711071
1072<<<<<<< HEAD
1072static constexpr IrInstructionId ir_instruction_id(IrInstructionHasDecl *) {1073static constexpr IrInstructionId ir_instruction_id(IrInstructionHasDecl *) {
1073 return IrInstructionIdHasDecl;1074 return IrInstructionIdHasDecl;
1074}1075}
...@@ -1089,6 +1090,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) {...@@ -1089,6 +1090,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) {
1089 return IrInstructionIdEndExpr;1090 return IrInstructionIdEndExpr;
1090}1091}
10911092
1093static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInitNamedField *) {
1094 return IrInstructionIdUnionInitNamedField;
1095}
1096
1092template<typename T>1097template<typename T>
1093static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {1098static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
1094 T *special_instruction = allocate<T>(1);1099 T *special_instruction = allocate<T>(1);
...@@ -3324,6 +3329,21 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,...@@ -3324,6 +3329,21 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
3324 return &instruction->base;3329 return &instruction->base;
3325}3330}
33263331
3332static IrInstruction *ir_build_union_init_2(IrBuilder *irb, Scope *scope, AstNode *source_node,
3333 IrInstruction *union_type_value, IrInstruction *field_name_expr, IrInstruction *value) {
3334 IrInstructionUnionInit2 *instruction = ir_build_instruction<IrInstructionUnionInit2>(irb, scope, source_node);
3335 instruction->union_type_value = union_type_value;
3336 instruction->field_name_expr = field_name_expr;
3337 instruction->value = value;
3338
3339 ir_ref_instruction(union_type_value, irb->current_basic_block);
3340 ir_ref_instruction(field_name_expr, irb->current_basic_block);
3341 ir_ref_instruction(value, irb->current_basic_block);
3342
3343 return &instruction->base;
3344}
3345
3346
3327static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,3347static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
3328 ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc)3348 ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc)
3329{3349{
...@@ -5651,6 +5671,29 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5651,6 +5671,29 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5651 IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value);5671 IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value);
5652 return ir_lval_wrap(irb, scope, has_decl, lval, result_loc);5672 return ir_lval_wrap(irb, scope, has_decl, lval, result_loc);
5653 }5673 }
5674 case BuiltinFnIdUnionInit:
5675 {
5676
5677 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5678 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5679 if (arg0_value == irb->codegen->invalid_instruction)
5680 return arg0_value;
5681
5682 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5683 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5684 if (arg1_value == irb->codegen->invalid_instruction)
5685 return arg1_value;
5686
5687 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5688 IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
5689 if (arg2_value == irb->codegen->invalid_instruction)
5690 return arg2_value;
5691
5692 IrInstruction *result = ir_build_union_init_2(irb, scope, node, arg0_value, arg1_value, arg2_value);
5693
5694 // TODO: Not sure if we need ir_lval_wrap or not.
5695 return result;
5696 }
5654 }5697 }
5655 zig_unreachable();5698 zig_unreachable();
5656}5699}
...@@ -25326,6 +25369,35 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst...@@ -25326,6 +25369,35 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst
25326 return instruction->result_loc_bit_cast->parent->gen_instruction;25369 return instruction->result_loc_bit_cast->parent->gen_instruction;
25327}25370}
2532825371
25372static IrInstruction *ir_analyze_instruction_union_init_2(IrAnalyze *ira, IrInstructionUnionInit2 *union_init_instruction)
25373{
25374 Error err;
25375 IrInstruction *union_type_value = union_init_instruction->union_type_value->child;
25376 ZigType *union_type = ir_resolve_type(ira, union_type_value);
25377 if (type_is_invalid(union_type)) {
25378 return ira->codegen->invalid_instruction;
25379 }
25380
25381 if (union_type->id != ZigTypeIdUnion)
25382 return ira->codegen->invalid_instruction;
25383
25384 if ((err = ensure_complete_type(ira->codegen, union_type)))
25385 return ira->codegen->invalid_instruction;
25386
25387 IrInstruction *field_name_expr = union_init_instruction->field_name_expr->child;
25388 Buf *field_name = ir_resolve_str(ira, field_name_expr);
25389 if (!field_name)
25390 return ira->codegen->invalid_instruction;
25391
25392 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(1);
25393
25394 fields[0].name = field_name;
25395 fields[0].value = union_init_instruction->value;
25396 fields[0].source_node = union_init_instruction->base.source_node;
25397
25398 return ir_analyze_container_init_fields_union(ira, &union_init_instruction->base, union_type, 1, fields);
25399}
25400
25329static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {25401static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
25330 switch (instruction->id) {25402 switch (instruction->id) {
25331 case IrInstructionIdInvalid:25403 case IrInstructionIdInvalid:
...@@ -25641,6 +25713,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25641,6 +25713,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25641 return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction);25713 return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction);
25642 case IrInstructionIdBitCastSrc:25714 case IrInstructionIdBitCastSrc:
25643 return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);25715 return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction);
25716 case IrInstructionIdUnionInitNamedField:
25717 return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction);
25644 }25718 }
25645 zig_unreachable();25719 zig_unreachable();
25646}25720}
...@@ -25794,6 +25868,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -25794,6 +25868,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
25794 case IrInstructionIdCast:25868 case IrInstructionIdCast:
25795 case IrInstructionIdContainerInitList:25869 case IrInstructionIdContainerInitList:
25796 case IrInstructionIdContainerInitFields:25870 case IrInstructionIdContainerInitFields:
25871 case IrInstructionIdUnionInitNamedField:
25797 case IrInstructionIdFieldPtr:25872 case IrInstructionIdFieldPtr:
25798 case IrInstructionIdElemPtr:25873 case IrInstructionIdElemPtr:
25799 case IrInstructionIdVarPtr:25874 case IrInstructionIdVarPtr:
src/ir_print.cpp+13
...@@ -1626,6 +1626,16 @@ static void ir_print_undeclared_ident(IrPrint *irp, IrInstructionUndeclaredIdent...@@ -1626,6 +1626,16 @@ static void ir_print_undeclared_ident(IrPrint *irp, IrInstructionUndeclaredIdent
1626 fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name));1626 fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name));
1627}1627}
16281628
1629static void ir_print_union_init_named_field(IrPrint *irp, IrInstructionUnionInitNamedField *instruction) {
1630 fprintf(irp->f, "@unionInit(");
1631 ir_print_other_instruction(irp, instruction->union_type);
1632 fprintf(irp->f, ", ");
1633 ir_print_other_instruction(irp, instruction->field_name);
1634 fprintf(irp->f, ", ");
1635 ir_print_other_instruction(irp, instruction->value);
1636 fprintf(irp->f, ")");
1637}
1638
1629static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1639static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1630 ir_print_prefix(irp, instruction);1640 ir_print_prefix(irp, instruction);
1631 switch (instruction->id) {1641 switch (instruction->id) {
...@@ -2132,6 +2142,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -2132,6 +2142,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
2132 case IrInstructionIdEndExpr:2142 case IrInstructionIdEndExpr:
2133 ir_print_end_expr(irp, (IrInstructionEndExpr *)instruction);2143 ir_print_end_expr(irp, (IrInstructionEndExpr *)instruction);
2134 break;2144 break;
2145 case IrInstructionIdUnionInitNamedField:
2146 ir_print_union_init_named_field(irp, (IrInstructionUnionInitNamedField *)instruction);
2147 break;
2135 }2148 }
2136 fprintf(irp->f, "\n");2149 fprintf(irp->f, "\n");
2137}2150}
test/stage1/behavior/union.zig+36-1
...@@ -416,9 +416,44 @@ test "return union init with void payload" {...@@ -416,9 +416,44 @@ test "return union init with void payload" {
416 two: u32,416 two: u32,
417 };417 };
418 fn func() Outer {418 fn func() Outer {
419 return Outer{ .state = State{ .one = {} }};419 return Outer{ .state = State{ .one = {} } };
420 }420 }
421 };421 };
422 S.entry();422 S.entry();
423 comptime S.entry();423 comptime S.entry();
424}424}
425
426test "@unionInit can modify a union type" {
427 const UnionInitEnum = union(enum) {
428 Boolean: bool,
429 Byte: u8,
430 };
431
432 var value: UnionInitEnum = undefined;
433
434 value = @unionInit(UnionInitEnum, "Boolean", true);
435 expect(value.Boolean == true);
436 value.Boolean = false;
437 expect(value.Boolean == false);
438
439 value = @unionInit(UnionInitEnum, "Byte", 2);
440 expect(value.Byte == 2);
441 value.Byte = 3;
442 expect(value.Byte == 3);
443}
444
445test "@unionInit can modify a pointer value" {
446 const UnionInitEnum = union(enum) {
447 Boolean: bool,
448 Byte: u8,
449 };
450
451 var value: UnionInitEnum = undefined;
452 var value_ptr = &value;
453
454 value_ptr.* = @unionInit(UnionInitEnum, "Boolean", true);
455 expect(value.Boolean == true);
456
457 value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2);
458 expect(value.Byte == 2);
459}