authorgravatar for keyboard.operator@gmail.comRobert Scott <keyboard.operator@gmail.com> 2019-05-09 02:28:14-07:00
committergravatar for keyboard.operator@gmail.comRobert Scott <keyboard.operator@gmail.com> 2019-05-24 01:48:45-07:00
log9b7ad124810e4a3df964927ace449502daa167f9
tree62a6674b3a255fcc76f464029f5b5d2a6cb4d9f3
parent163a8e98bc04ea955ee54d5905436ffac34c93a2

Implement @unionInit


5 files changed, 148 insertions(+), 8 deletions(-)

src/all_types.hpp+13
......@@ -1471,6 +1471,7 @@ enum BuiltinFnId {
14711471 BuiltinFnIdErrorReturnTrace,
14721472 BuiltinFnIdAtomicRmw,
14731473 BuiltinFnIdAtomicLoad,
1474 BuiltinFnIdUnionInit,
14741475};
14751476
14761477struct BuiltinFnEntry {
......@@ -2297,6 +2298,7 @@ enum IrInstructionId {
22972298 IrInstructionIdArrayToVector,
22982299 IrInstructionIdAssertZero,
22992300 IrInstructionIdAssertNonNull,
2301 IrInstructionIdUnionInit2,
23002302};
23012303
23022304struct IrInstruction {
......@@ -3503,6 +3505,17 @@ struct IrInstructionAssertNonNull {
35033505 IrInstruction *target;
35043506};
35053507
3508// TODO, need a better name. Using 2 because there is currently a IrInstructionUnionInit
3509// It seems like the first one should only be used during the analyze phase, but still
3510// don't understand it all.
3511struct IrInstructionUnionInit2 {
3512 IrInstruction base;
3513
3514 IrInstruction *union_type_value;
3515 IrInstruction *field_name_expr;
3516 IrInstruction *value;
3517};
3518
35063519static const size_t slice_ptr_index = 0;
35073520static const size_t slice_len_index = 1;
35083521
src/codegen.cpp+2
......@@ -5616,6 +5616,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
56165616 case IrInstructionIdLoadPtr:
56175617 case IrInstructionIdBitCast:
56185618 case IrInstructionIdGlobalAsm:
5619 case IrInstructionIdUnionInit2:
56195620 zig_unreachable();
56205621
56215622 case IrInstructionIdDeclVarGen:
......@@ -7409,6 +7410,7 @@ static void define_builtin_fns(CodeGen *g) {
74097410 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
74107411 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
74117412 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
7413 create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3);
74127414}
74137415
74147416static const char *bool_to_str(bool b) {
src/ir.cpp+83-7
......@@ -188,7 +188,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
188188 assert(get_src_ptr_type(const_val->type) != nullptr);
189189 assert(const_val->special == ConstValSpecialStatic);
190190 ConstExprValue *result;
191
191
192192 switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
193193 case OnePossibleValueInvalid:
194194 zig_unreachable();
......@@ -200,7 +200,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
200200 case OnePossibleValueNo:
201201 break;
202202 }
203
203
204204 switch (const_val->data.x_ptr.special) {
205205 case ConstPtrSpecialInvalid:
206206 zig_unreachable();
......@@ -1011,6 +1011,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *)
10111011 return IrInstructionIdAssertNonNull;
10121012}
10131013
1014static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInit2 *) {
1015 return IrInstructionIdUnionInit2;
1016}
1017
10141018template<typename T>
10151019static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
10161020 T *special_instruction = allocate<T>(1);
......@@ -1312,6 +1316,7 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
13121316 return &instruction->base;
13131317}
13141318
1319
13151320static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
13161321 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
13171322 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,
......@@ -3025,6 +3030,21 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
30253030 return &instruction->base;
30263031}
30273032
3033static IrInstruction *ir_build_union_init_2(IrBuilder *irb, Scope *scope, AstNode *source_node,
3034 IrInstruction *union_type_value, IrInstruction *field_name_expr, IrInstruction *value) {
3035 IrInstructionUnionInit2 *instruction = ir_build_instruction<IrInstructionUnionInit2>(irb, scope, source_node);
3036 instruction->union_type_value = union_type_value;
3037 instruction->field_name_expr = field_name_expr;
3038 instruction->value = value;
3039
3040 ir_ref_instruction(union_type_value, irb->current_basic_block);
3041 ir_ref_instruction(field_name_expr, irb->current_basic_block);
3042 ir_ref_instruction(value, irb->current_basic_block);
3043
3044 return &instruction->base;
3045}
3046
3047
30283048static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
30293049 IrInstruction *vector, ZigType *result_type)
30303050{
......@@ -3868,7 +3888,7 @@ static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode
38683888 TldVar *tld_var = allocate<TldVar>(1);
38693889 init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base);
38703890 tld_var->base.resolution = TldResolutionInvalid;
3871 tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
3891 tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
38723892 &g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid);
38733893 scope_decls->decl_table.put(var_name, &tld_var->base);
38743894}
......@@ -5098,6 +5118,29 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
50985118 }
50995119 return ir_lval_wrap(irb, scope, result, lval);
51005120 }
5121 case BuiltinFnIdUnionInit:
5122 {
5123
5124 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5125 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5126 if (arg0_value == irb->codegen->invalid_instruction)
5127 return arg0_value;
5128
5129 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5130 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5131 if (arg1_value == irb->codegen->invalid_instruction)
5132 return arg1_value;
5133
5134 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
5135 IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
5136 if (arg2_value == irb->codegen->invalid_instruction)
5137 return arg2_value;
5138
5139 IrInstruction *result = ir_build_union_init_2(irb, scope, node, arg0_value, arg1_value, arg2_value);
5140
5141 // TODO: Not sure if we need ir_lval_wrap or not.
5142 return result;
5143 }
51015144 }
51025145 zig_unreachable();
51035146}
......@@ -6328,7 +6371,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
63286371 prong_values, prong_values_len);
63296372 var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, var_symbol_node, var_ptr_value);
63306373 } else {
6331 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node,
6374 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node,
63326375target_value_ptr);
63336376 }
63346377 IrInstruction *var_type = nullptr; // infer the type
......@@ -12372,7 +12415,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1237212415 } else {
1237312416 return is_non_null;
1237412417 }
12375 } else if (is_equality_cmp &&
12418 } else if (is_equality_cmp &&
1237612419 ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer &&
1237712420 op2->value.type->data.pointer.ptr_len == PtrLenC) ||
1237812421 (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer &&
......@@ -19383,7 +19426,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1938319426 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err)));
1938419427 return ira->codegen->invalid_instruction;
1938519428 }
19386
19429
1938719430 if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) {
1938819431 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err)));
1938919432 return ira->codegen->invalid_instruction;
......@@ -20333,7 +20376,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
2033320376 return ira->codegen->invalid_instruction;
2033420377
2033520378 // TODO test this at comptime with u8 and non-u8 types
20336 // TODO test with dest ptr being a global runtime variable
20379 // TODO test with dest ptr being a global runtime variable
2033720380 if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
2033820381 casted_src_ptr->value.special == ConstValSpecialStatic &&
2033920382 casted_count->value.special == ConstValSpecialStatic &&
......@@ -23151,6 +23194,35 @@ static IrInstruction *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira,
2315123194 return ir_const_void(ira, &instruction->base);
2315223195}
2315323196
23197static IrInstruction *ir_analyze_instruction_union_init_2(IrAnalyze *ira, IrInstructionUnionInit2 *union_init_instruction)
23198{
23199 Error err;
23200 IrInstruction *union_type_value = union_init_instruction->union_type_value->child;
23201 ZigType *union_type = ir_resolve_type(ira, union_type_value);
23202 if (type_is_invalid(union_type)) {
23203 return ira->codegen->invalid_instruction;
23204 }
23205
23206 if (union_type->id != ZigTypeIdUnion)
23207 return ira->codegen->invalid_instruction;
23208
23209 if ((err = ensure_complete_type(ira->codegen, union_type)))
23210 return ira->codegen->invalid_instruction;
23211
23212 IrInstruction *field_name_expr = union_init_instruction->field_name_expr->child;
23213 Buf *field_name = ir_resolve_str(ira, field_name_expr);
23214 if (!field_name)
23215 return ira->codegen->invalid_instruction;
23216
23217 IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(1);
23218
23219 fields[0].name = field_name;
23220 fields[0].value = union_init_instruction->value;
23221 fields[0].source_node = union_init_instruction->base.source_node;
23222
23223 return ir_analyze_container_init_fields_union(ira, &union_init_instruction->base, union_type, 1, fields);
23224}
23225
2315423226static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
2315523227 switch (instruction->id) {
2315623228 case IrInstructionIdInvalid:
......@@ -23445,6 +23517,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2344523517 return ir_analyze_instruction_enum_to_int(ira, (IrInstructionEnumToInt *)instruction);
2344623518 case IrInstructionIdCheckRuntimeScope:
2344723519 return ir_analyze_instruction_check_runtime_scope(ira, (IrInstructionCheckRuntimeScope *)instruction);
23520 case IrInstructionIdUnionInit2:
23521 return ir_analyze_instruction_union_init_2(ira, (IrInstructionUnionInit2 *)instruction);
2344823522 }
2344923523 zig_unreachable();
2345023524}
......@@ -23681,6 +23755,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2368123755 case IrInstructionIdEnumToInt:
2368223756 case IrInstructionIdVectorToArray:
2368323757 case IrInstructionIdArrayToVector:
23758 case IrInstructionIdUnionInit2:
23759
2368423760 return false;
2368523761
2368623762 case IrInstructionIdAsm:
src/ir_print.cpp+14
......@@ -1453,6 +1453,17 @@ static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_va
14531453 }
14541454}
14551455
1456
1457static void ir_print_uniont_init_2(IrPrint *irp, IrInstructionUnionInit2 *instruction) {
1458 fprintf(irp->f, "@unionInit(");
1459 ir_print_other_instruction(irp, instruction->union_type_value);
1460 fprintf(irp->f, ", ");
1461 ir_print_other_instruction(irp, instruction->field_name_expr);
1462 fprintf(irp->f, ", ");
1463 ir_print_other_instruction(irp, instruction->value);
1464 fprintf(irp->f, ")");
1465}
1466
14561467static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
14571468 ir_print_prefix(irp, instruction);
14581469 switch (instruction->id) {
......@@ -1920,6 +1931,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
19201931 case IrInstructionIdResizeSlice:
19211932 ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);
19221933 break;
1934 case IrInstructionIdUnionInit2:
1935 ir_print_uniont_init_2(irp, (IrInstructionUnionInit2 *)instruction);
1936 break;
19231937 }
19241938 fprintf(irp->f, "\n");
19251939}
test/stage1/behavior/union.zig+36-1
......@@ -374,7 +374,7 @@ const Attribute = union(enum) {
374374fn setAttribute(attr: Attribute) void {}
375375
376376fn Setter(attr: Attribute) type {
377 return struct{
377 return struct {
378378 fn set() void {
379379 setAttribute(attr);
380380 }
......@@ -402,3 +402,38 @@ test "comptime union field value equality" {
402402 expect(a0 != a1);
403403 expect(b0 != b1);
404404}
405
406test "unionInit can modify a union type" {
407 const UnionInitEnum = union(enum) {
408 Boolean: bool,
409 Byte: u8,
410 };
411
412 var value: UnionInitEnum = undefined;
413
414 value = @unionInit(UnionInitEnum, "Boolean", true);
415 expect(value.Boolean == true);
416 value.Boolean = false;
417 expect(value.Boolean == false);
418
419 value = @unionInit(UnionInitEnum, "Byte", 2);
420 expect(value.Byte == 2);
421 value.Byte = 3;
422 expect(value.Byte == 3);
423}
424
425test "unionInit can modify a pointer value" {
426 const UnionInitEnum = union(enum) {
427 Boolean: bool,
428 Byte: u8,
429 };
430
431 var value: UnionInitEnum = undefined;
432 var value_ptr = &value;
433
434 value_ptr.* = @unionInit(UnionInitEnum, "Boolean", true);
435 expect(value.Boolean == true);
436
437 value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2);
438 expect(value.Byte == 2);
439}