authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-26 20:59:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-26 20:59:36-07:00
log2687b8f7f4825c9018af6998e1de140e6185f9cd
tree4bbd5f609153618e883ad4cce09c7a8c920a22b0
parent32e89a98d82c0f4505a3f3d4cd72e7db2eadfbb9

stage2: implement `@unionInit`

The ZIR instruction `union_init_ptr` is renamed to `union_init`. I made it always use by-value semantics for now, not taking the time to invest in result location semantics, in case we decide to change the rules for unions. This way is much simpler. There is a new AIR instruction: union_init. This is for a comptime known tag, runtime-known field value. vector_init is renamed to aggregate_init, which solves a TODO comment.

16 files changed, 370 insertions(+), 110 deletions(-)

src/Air.zig+13-5
......@@ -561,13 +561,15 @@ pub const Inst = struct {
561561 /// Uses the `un_op` field.
562562 error_name,
563563
564 /// Constructs a vector, tuple, or array value out of runtime-known elements.
564 /// Constructs a vector, tuple, struct, or array value out of runtime-known elements.
565565 /// Some of the elements may be comptime-known.
566566 /// Uses the `ty_pl` field, payload is index of an array of elements, each of which
567567 /// is a `Ref`. Length of the array is given by the vector type.
568 /// TODO rename this to `aggregate_init` and make it support array values and
569 /// struct values too.
570 vector_init,
568 aggregate_init,
569
570 /// Constructs a union from a field index and a runtime-known init value.
571 /// Uses the `ty_pl` field with payload `UnionInit`.
572 union_init,
571573
572574 /// Communicates an intent to load memory.
573575 /// Result is always unused.
......@@ -768,6 +770,11 @@ pub const AtomicRmw = struct {
768770 }
769771};
770772
773pub const UnionInit = struct {
774 field_index: u32,
775 init: Inst.Ref,
776};
777
771778pub fn getMainBody(air: Air) []const Air.Inst.Index {
772779 const body_index = air.extra[@enumToInt(ExtraIndex.main_block)];
773780 const extra = air.extraData(Block, body_index);
......@@ -864,7 +871,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
864871 .cmpxchg_weak,
865872 .cmpxchg_strong,
866873 .slice,
867 .vector_init,
874 .aggregate_init,
875 .union_init,
868876 .field_parent_ptr,
869877 => return air.getRefType(datas[inst].ty_pl.ty),
870878
src/AstGen.zig+11-34
......@@ -2052,8 +2052,8 @@ fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Sc
20522052 _ = try unusedResultExpr(gz, expr_scope, expr_node);
20532053}
20542054
2055/// Returns AST source node of the thing that is noreturn if the statement is definitely `noreturn`.
2056/// Otherwise returns 0.
2055/// Returns AST source node of the thing that is noreturn if the statement is
2056/// definitely `noreturn`. Otherwise returns 0.
20572057fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index {
20582058 try emitDbgNode(gz, statement);
20592059 // We need to emit an error if the result is not `noreturn` or `void`, but
......@@ -2201,7 +2201,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
22012201 .array_init_anon,
22022202 .array_init_ref,
22032203 .array_init_anon_ref,
2204 .union_init_ptr,
2204 .union_init,
22052205 .field_type,
22062206 .field_type_ref,
22072207 .error_set_decl,
......@@ -6802,40 +6802,17 @@ fn unionInit(
68026802) InnerError!Zir.Inst.Ref {
68036803 const union_type = try typeExpr(gz, scope, params[0]);
68046804 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
6805 switch (rl) {
6806 .none, .discard, .ref, .ty, .coerced_ty, .inferred_ptr => {
6807 _ = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
6808 .container_type = union_type,
6809 .field_name = field_name,
6810 });
6811 const result = try expr(gz, scope, .{ .ty = union_type }, params[2]);
6812 return rvalue(gz, rl, result, node);
6813 },
6814 .ptr => |result_ptr| {
6815 return unionInitRlPtr(gz, scope, node, result_ptr, params[2], union_type, field_name);
6816 },
6817 .block_ptr => |block_scope| {
6818 return unionInitRlPtr(gz, scope, node, block_scope.rl_ptr, params[2], union_type, field_name);
6819 },
6820 }
6821}
6822
6823fn unionInitRlPtr(
6824 parent_gz: *GenZir,
6825 scope: *Scope,
6826 node: Ast.Node.Index,
6827 result_ptr: Zir.Inst.Ref,
6828 expr_node: Ast.Node.Index,
6829 union_type: Zir.Inst.Ref,
6830 field_name: Zir.Inst.Ref,
6831) InnerError!Zir.Inst.Ref {
6832 const union_init_ptr = try parent_gz.addPlNode(.union_init_ptr, node, Zir.Inst.UnionInitPtr{
6833 .result_ptr = result_ptr,
6805 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
6806 .container_type = union_type,
6807 .field_name = field_name,
6808 });
6809 const init = try reachableExpr(gz, scope, .{ .ty = field_type }, params[2], node);
6810 const result = try gz.addPlNode(.union_init, node, Zir.Inst.UnionInit{
68346811 .union_type = union_type,
6812 .init = init,
68356813 .field_name = field_name,
68366814 });
6837 // TODO check if we need to do the elision like below in asRlPtr
6838 return expr(parent_gz, scope, .{ .ptr = union_init_ptr }, expr_node);
6815 return rvalue(gz, rl, result, node);
68396816}
68406817
68416818fn asRlPtr(
src/Liveness.zig+8-4
......@@ -25,7 +25,7 @@ tomb_bits: []usize,
2525/// array. The meaning of the data depends on the AIR tag.
2626/// * `cond_br` - points to a `CondBr` in `extra` at this index.
2727/// * `switch_br` - points to a `SwitchBr` in `extra` at this index.
28/// * `asm`, `call`, `vector_init` - the value is a set of bits which are the extra tomb
28/// * `asm`, `call`, `aggregate_init` - the value is a set of bits which are the extra tomb
2929/// bits of operands.
3030/// The main tomb bits are still used and the extra ones are starting with the lsb of the
3131/// value here.
......@@ -420,10 +420,10 @@ fn analyzeInst(
420420 }
421421 return extra_tombs.finish();
422422 },
423 .vector_init => {
423 .aggregate_init => {
424424 const ty_pl = inst_datas[inst].ty_pl;
425 const vector_ty = a.air.getRefType(ty_pl.ty);
426 const len = @intCast(usize, vector_ty.arrayLen());
425 const aggregate_ty = a.air.getRefType(ty_pl.ty);
426 const len = @intCast(usize, aggregate_ty.arrayLen());
427427 const elements = @bitCast([]const Air.Inst.Ref, a.air.extra[ty_pl.payload..][0..len]);
428428
429429 if (elements.len <= bpi - 1) {
......@@ -442,6 +442,10 @@ fn analyzeInst(
442442 }
443443 return extra_tombs.finish();
444444 },
445 .union_init => {
446 const extra = a.air.extraData(Air.UnionInit, inst_datas[inst].ty_pl.payload).data;
447 return trackOperands(a, new_set, inst, main_tomb, .{ extra.init, .none, .none });
448 },
445449 .struct_field_ptr, .struct_field_val => {
446450 const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data;
447451 return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none });
src/Module.zig+9
......@@ -1123,6 +1123,15 @@ pub const Union = struct {
11231123 /// undefined until `status` is `have_field_types` or `have_layout`.
11241124 ty: Type,
11251125 abi_align: Value,
1126
1127 /// Returns the field alignment, assuming the union is not packed.
1128 pub fn normalAlignment(field: Field, target: Target) u32 {
1129 if (field.abi_align.tag() == .abi_align_default) {
1130 return field.ty.abiAlignment(target);
1131 } else {
1132 return @intCast(u32, field.abi_align.toUnsignedInt());
1133 }
1134 }
11261135 };
11271136
11281137 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
src/Sema.zig+84-29
......@@ -204,7 +204,7 @@ pub const Block = struct {
204204 return block.namespace.file_scope;
205205 }
206206
207 pub fn addTy(
207 fn addTy(
208208 block: *Block,
209209 tag: Air.Inst.Tag,
210210 ty: Type,
......@@ -215,7 +215,7 @@ pub const Block = struct {
215215 });
216216 }
217217
218 pub fn addTyOp(
218 fn addTyOp(
219219 block: *Block,
220220 tag: Air.Inst.Tag,
221221 ty: Type,
......@@ -230,7 +230,7 @@ pub const Block = struct {
230230 });
231231 }
232232
233 pub fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref {
233 fn addBitCast(block: *Block, ty: Type, operand: Air.Inst.Ref) Allocator.Error!Air.Inst.Ref {
234234 return block.addInst(.{
235235 .tag = .bitcast,
236236 .data = .{ .ty_op = .{
......@@ -240,14 +240,14 @@ pub const Block = struct {
240240 });
241241 }
242242
243 pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {
243 fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref {
244244 return block.addInst(.{
245245 .tag = tag,
246246 .data = .{ .no_op = {} },
247247 });
248248 }
249249
250 pub fn addUnOp(
250 fn addUnOp(
251251 block: *Block,
252252 tag: Air.Inst.Tag,
253253 operand: Air.Inst.Ref,
......@@ -258,7 +258,7 @@ pub const Block = struct {
258258 });
259259 }
260260
261 pub fn addBr(
261 fn addBr(
262262 block: *Block,
263263 target_block: Air.Inst.Index,
264264 operand: Air.Inst.Ref,
......@@ -328,7 +328,7 @@ pub const Block = struct {
328328 });
329329 }
330330
331 pub fn addStructFieldVal(
331 fn addStructFieldVal(
332332 block: *Block,
333333 struct_val: Air.Inst.Ref,
334334 field_index: u32,
......@@ -346,7 +346,7 @@ pub const Block = struct {
346346 });
347347 }
348348
349 pub fn addSliceElemPtr(
349 fn addSliceElemPtr(
350350 block: *Block,
351351 slice: Air.Inst.Ref,
352352 elem_index: Air.Inst.Ref,
......@@ -364,7 +364,7 @@ pub const Block = struct {
364364 });
365365 }
366366
367 pub fn addPtrElemPtr(
367 fn addPtrElemPtr(
368368 block: *Block,
369369 array_ptr: Air.Inst.Ref,
370370 elem_index: Air.Inst.Ref,
......@@ -374,7 +374,7 @@ pub const Block = struct {
374374 return block.addPtrElemPtrTypeRef(array_ptr, elem_index, ty_ref);
375375 }
376376
377 pub fn addPtrElemPtrTypeRef(
377 fn addPtrElemPtrTypeRef(
378378 block: *Block,
379379 array_ptr: Air.Inst.Ref,
380380 elem_index: Air.Inst.Ref,
......@@ -392,7 +392,7 @@ pub const Block = struct {
392392 });
393393 }
394394
395 pub fn addVectorInit(
395 fn addAggregateInit(
396396 block: *Block,
397397 vector_ty: Type,
398398 elements: []const Air.Inst.Ref,
......@@ -404,7 +404,7 @@ pub const Block = struct {
404404 sema.appendRefsAssumeCapacity(elements);
405405
406406 return block.addInst(.{
407 .tag = .vector_init,
407 .tag = .aggregate_init,
408408 .data = .{ .ty_pl = .{
409409 .ty = ty_ref,
410410 .payload = extra_index,
......@@ -412,6 +412,24 @@ pub const Block = struct {
412412 });
413413 }
414414
415 fn addUnionInit(
416 block: *Block,
417 union_ty: Type,
418 field_index: u32,
419 init: Air.Inst.Ref,
420 ) !Air.Inst.Ref {
421 return block.addInst(.{
422 .tag = .union_init,
423 .data = .{ .ty_pl = .{
424 .ty = try block.sema.addType(union_ty),
425 .payload = try block.sema.addExtra(Air.UnionInit{
426 .field_index = field_index,
427 .init = init,
428 }),
429 } },
430 });
431 }
432
415433 pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref {
416434 return Air.indexToRef(try block.addInstAsIndex(inst));
417435 }
......@@ -697,7 +715,7 @@ fn analyzeBodyInner(
697715 .array_init_ref => try sema.zirArrayInit(block, inst, true),
698716 .array_init_anon => try sema.zirArrayInitAnon(block, inst, false),
699717 .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),
700 .union_init_ptr => try sema.zirUnionInitPtr(block, inst),
718 .union_init => try sema.zirUnionInit(block, inst),
701719 .field_type => try sema.zirFieldType(block, inst),
702720 .field_type_ref => try sema.zirFieldTypeRef(block, inst),
703721 .ptr_to_int => try sema.zirPtrToInt(block, inst),
......@@ -11273,10 +11291,31 @@ fn arrayInitEmpty(sema: *Sema, obj_ty: Type) CompileError!Air.Inst.Ref {
1127311291 }
1127411292}
1127511293
11276fn zirUnionInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
11294fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1127711295 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11278 const src = inst_data.src();
11279 return sema.fail(block, src, "TODO: Sema.zirUnionInitPtr", .{});
11296 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
11297 const field_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
11298 const init_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
11299 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
11300 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);
11301 const field_name = try sema.resolveConstString(block, field_src, extra.field_name);
11302 const init = sema.resolveInst(extra.init);
11303 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
11304 const field_index_usize = union_obj.fields.getIndex(field_name) orelse
11305 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
11306 const field_index = @intCast(u32, field_index_usize);
11307
11308 if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| {
11309 const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index);
11310 return sema.addConstant(
11311 union_ty,
11312 try Value.Tag.@"union".create(sema.arena, .{ .tag = tag_val, .val = init_val }),
11313 );
11314 }
11315
11316 try sema.requireRuntimeBlock(block, init_src);
11317 try sema.resolveTypeLayout(block, ty_src, union_ty);
11318 return block.addUnionInit(union_ty, field_index, init);
1128011319}
1128111320
1128211321fn zirStructInit(
......@@ -11447,7 +11486,7 @@ fn finishStructInit(
1144711486 }
1144811487
1144911488 try sema.requireRuntimeBlock(block, src);
11450 return block.addVectorInit(struct_ty, field_inits);
11489 return block.addAggregateInit(struct_ty, field_inits);
1145111490}
1145211491
1145311492fn zirStructInitAnon(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {
......@@ -11527,7 +11566,7 @@ fn zirArrayInit(
1152711566 return alloc;
1152811567 }
1152911568
11530 return block.addVectorInit(array_ty, resolved_args);
11569 return block.addAggregateInit(array_ty, resolved_args);
1153111570}
1153211571
1153311572fn zirArrayInitAnon(
......@@ -11593,7 +11632,7 @@ fn zirArrayInitAnon(
1159311632 element_refs[i] = sema.resolveInst(operand);
1159411633 }
1159511634
11596 return block.addVectorInit(tuple_ty, element_refs);
11635 return block.addAggregateInit(tuple_ty, element_refs);
1159711636}
1159811637
1159911638fn addConstantMaybeRef(
......@@ -11617,31 +11656,47 @@ fn addConstantMaybeRef(
1161711656
1161811657fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1161911658 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11620 const src = inst_data.src();
11621 return sema.fail(block, src, "TODO: Sema.zirFieldTypeRef", .{});
11659 const extra = sema.code.extraData(Zir.Inst.FieldTypeRef, inst_data.payload_index).data;
11660 const ty_src = inst_data.src();
11661 const field_src = inst_data.src();
11662 const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type);
11663 const field_name = try sema.resolveConstString(block, field_src, extra.field_name);
11664 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);
1162211665}
1162311666
1162411667fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1162511668 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1162611669 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
11627 const src = inst_data.src();
11670 const ty_src = inst_data.src();
11671 const field_src = inst_data.src();
11672 const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type);
1162811673 const field_name = sema.code.nullTerminatedString(extra.name_start);
11629 const unresolved_ty = try sema.resolveType(block, src, extra.container_type);
11630 const resolved_ty = try sema.resolveTypeFields(block, src, unresolved_ty);
11674 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);
11675}
11676
11677fn fieldType(
11678 sema: *Sema,
11679 block: *Block,
11680 aggregate_ty: Type,
11681 field_name: []const u8,
11682 field_src: LazySrcLoc,
11683 ty_src: LazySrcLoc,
11684) CompileError!Air.Inst.Ref {
11685 const resolved_ty = try sema.resolveTypeFields(block, ty_src, aggregate_ty);
1163111686 switch (resolved_ty.zigTypeTag()) {
1163211687 .Struct => {
1163311688 const struct_obj = resolved_ty.castTag(.@"struct").?.data;
1163411689 const field = struct_obj.fields.get(field_name) orelse
11635 return sema.failWithBadStructFieldAccess(block, struct_obj, src, field_name);
11690 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
1163611691 return sema.addType(field.ty);
1163711692 },
1163811693 .Union => {
1163911694 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
1164011695 const field = union_obj.fields.get(field_name) orelse
11641 return sema.failWithBadUnionFieldAccess(block, union_obj, src, field_name);
11696 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
1164211697 return sema.addType(field.ty);
1164311698 },
11644 else => return sema.fail(block, src, "expected struct or union; found '{}'", .{
11699 else => return sema.fail(block, ty_src, "expected struct or union; found '{}'", .{
1164511700 resolved_ty,
1164611701 }),
1164711702 }
......@@ -16396,7 +16451,7 @@ fn coerceArrayLike(
1639616451
1639716452 if (runtime_src) |rs| {
1639816453 try sema.requireRuntimeBlock(block, rs);
16399 return block.addVectorInit(dest_ty, element_refs);
16454 return block.addAggregateInit(dest_ty, element_refs);
1640016455 }
1640116456
1640216457 return sema.addConstant(
......@@ -16453,7 +16508,7 @@ fn coerceTupleToArray(
1645316508
1645416509 if (runtime_src) |rs| {
1645516510 try sema.requireRuntimeBlock(block, rs);
16456 return block.addVectorInit(dest_ty, element_refs);
16511 return block.addAggregateInit(dest_ty, element_refs);
1645716512 }
1645816513
1645916514 return sema.addConstant(
src/Zir.zig+7-8
......@@ -721,10 +721,9 @@ pub const Inst = struct {
721721 /// Anonymous array initialization syntax, make the result a pointer.
722722 /// Uses the `pl_node` field. Payload is `MultiOp`.
723723 array_init_anon_ref,
724 /// Given a pointer to a union and a comptime known field name, activates that field
725 /// and returns a pointer to it.
726 /// Uses the `pl_node` field. Payload is `UnionInitPtr`.
727 union_init_ptr,
724 /// Implements the `@unionInit` builtin.
725 /// Uses the `pl_node` field. Payload is `UnionInit`.
726 union_init,
728727 /// Implements the `@typeInfo` builtin. Uses `un_node`.
729728 type_info,
730729 /// Implements the `@sizeOf` builtin. Uses `un_node`.
......@@ -1125,7 +1124,7 @@ pub const Inst = struct {
11251124 .array_init_anon,
11261125 .array_init_ref,
11271126 .array_init_anon_ref,
1128 .union_init_ptr,
1127 .union_init,
11291128 .field_type,
11301129 .field_type_ref,
11311130 .int_to_enum,
......@@ -1383,7 +1382,7 @@ pub const Inst = struct {
13831382 .array_init_anon = .pl_node,
13841383 .array_init_ref = .pl_node,
13851384 .array_init_anon_ref = .pl_node,
1386 .union_init_ptr = .pl_node,
1385 .union_init = .pl_node,
13871386 .type_info = .un_node,
13881387 .size_of = .un_node,
13891388 .bit_size_of = .un_node,
......@@ -2896,10 +2895,10 @@ pub const Inst = struct {
28962895 ordering: Ref,
28972896 };
28982897
2899 pub const UnionInitPtr = struct {
2900 result_ptr: Ref,
2898 pub const UnionInit = struct {
29012899 union_type: Ref,
29022900 field_name: Ref,
2901 init: Ref,
29032902 };
29042903
29052904 pub const AtomicStore = struct {
src/arch/aarch64/CodeGen.zig+11-3
......@@ -625,7 +625,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
625625 .tag_name => try self.airTagName(inst),
626626 .error_name => try self.airErrorName(inst),
627627 .splat => try self.airSplat(inst),
628 .vector_init => try self.airVectorInit(inst),
628 .aggregate_init => try self.airAggregateInit(inst),
629 .union_init => try self.airUnionInit(inst),
629630 .prefetch => try self.airPrefetch(inst),
630631
631632 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
......@@ -3472,14 +3473,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
34723473 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
34733474}
34743475
3475fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
3476fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
34763477 const vector_ty = self.air.typeOfIndex(inst);
34773478 const len = vector_ty.vectorLen();
34783479 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
34793480 const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
34803481 const result: MCValue = res: {
34813482 if (self.liveness.isUnused(inst)) break :res MCValue.dead;
3482 return self.fail("TODO implement airVectorInit for {}", .{self.target.cpu.arch});
3483 return self.fail("TODO implement airAggregateInit for {}", .{self.target.cpu.arch});
34833484 };
34843485
34853486 if (elements.len <= Liveness.bpi - 1) {
......@@ -3494,6 +3495,13 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
34943495 return bt.finishAir(result);
34953496}
34963497
3498fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
3499 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3500 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
3501 _ = extra;
3502 return self.fail("TODO implement airUnionInit for aarch64", .{});
3503}
3504
34973505fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
34983506 const prefetch = self.air.instructions.items(.data)[inst].prefetch;
34993507 return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
src/arch/arm/CodeGen.zig+12-3
......@@ -609,7 +609,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
609609 .tag_name => try self.airTagName(inst),
610610 .error_name => try self.airErrorName(inst),
611611 .splat => try self.airSplat(inst),
612 .vector_init => try self.airVectorInit(inst),
612 .aggregate_init => try self.airAggregateInit(inst),
613 .union_init => try self.airUnionInit(inst),
613614 .prefetch => try self.airPrefetch(inst),
614615
615616 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
......@@ -3937,14 +3938,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
39373938 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
39383939}
39393940
3940fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
3941fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
39413942 const vector_ty = self.air.typeOfIndex(inst);
39423943 const len = vector_ty.vectorLen();
39433944 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
39443945 const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
39453946 const result: MCValue = res: {
39463947 if (self.liveness.isUnused(inst)) break :res MCValue.dead;
3947 return self.fail("TODO implement airVectorInit for arm", .{});
3948 return self.fail("TODO implement airAggregateInit for arm", .{});
39483949 };
39493950
39503951 if (elements.len <= Liveness.bpi - 1) {
......@@ -3959,6 +3960,14 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
39593960 return bt.finishAir(result);
39603961}
39613962
3963fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
3964 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3965 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
3966 _ = extra;
3967
3968 return self.fail("TODO implement airUnionInit for arm", .{});
3969}
3970
39623971fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
39633972 const prefetch = self.air.instructions.items(.data)[inst].prefetch;
39643973 return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
src/arch/riscv64/CodeGen.zig+12-3
......@@ -596,7 +596,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
596596 .tag_name => try self.airTagName(inst),
597597 .error_name => try self.airErrorName(inst),
598598 .splat => try self.airSplat(inst),
599 .vector_init => try self.airVectorInit(inst),
599 .aggregate_init => try self.airAggregateInit(inst),
600 .union_init => try self.airUnionInit(inst),
600601 .prefetch => try self.airPrefetch(inst),
601602
602603 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
......@@ -2157,14 +2158,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
21572158 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
21582159}
21592160
2160fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
2161fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
21612162 const vector_ty = self.air.typeOfIndex(inst);
21622163 const len = vector_ty.vectorLen();
21632164 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
21642165 const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
21652166 const result: MCValue = res: {
21662167 if (self.liveness.isUnused(inst)) break :res MCValue.dead;
2167 return self.fail("TODO implement airVectorInit for riscv64", .{});
2168 return self.fail("TODO implement airAggregateInit for riscv64", .{});
21682169 };
21692170
21702171 if (elements.len <= Liveness.bpi - 1) {
......@@ -2179,6 +2180,14 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
21792180 return bt.finishAir(result);
21802181}
21812182
2183fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
2184 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2185 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
2186 _ = extra;
2187 return self.fail("TODO implement airUnionInit for riscv64", .{});
2188 // return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value });
2189}
2190
21822191fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
21832192 const prefetch = self.air.instructions.items(.data)[inst].prefetch;
21842193 return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
src/arch/wasm/CodeGen.zig+9-3
......@@ -1642,7 +1642,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
16421642 .ret_ptr => self.airRetPtr(inst),
16431643 .ret_load => self.airRetLoad(inst),
16441644 .splat => self.airSplat(inst),
1645 .vector_init => self.airVectorInit(inst),
1645 .aggregate_init => self.airAggregateInit(inst),
1646 .union_init => self.airUnionInit(inst),
16461647 .prefetch => self.airPrefetch(inst),
16471648
16481649 .slice => self.airSlice(inst),
......@@ -3350,7 +3351,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
33503351 return self.fail("TODO: Implement wasm airSplat", .{});
33513352}
33523353
3353fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3354fn airAggregateInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
33543355 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
33553356
33563357 const vector_ty = self.air.typeOfIndex(inst);
......@@ -3359,7 +3360,7 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
33593360 const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
33603361
33613362 switch (vector_ty.zigTypeTag()) {
3362 .Vector => return self.fail("TODO: Wasm backend: implement airVectorInit for vectors", .{}),
3363 .Vector => return self.fail("TODO: Wasm backend: implement airAggregateInit for vectors", .{}),
33633364 .Array => {
33643365 const result = try self.allocStack(vector_ty);
33653366 const elem_ty = vector_ty.childType();
......@@ -3413,6 +3414,11 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
34133414 }
34143415}
34153416
3417fn airUnionInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3418 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
3419 return self.fail("TODO: Wasm backend: implement airUnionInit", .{});
3420}
3421
34163422fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
34173423 const prefetch = self.air.instructions.items(.data)[inst].prefetch;
34183424 _ = prefetch;
src/arch/x86_64/CodeGen.zig+14-3
......@@ -708,7 +708,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
708708 .tag_name => try self.airTagName(inst),
709709 .error_name => try self.airErrorName(inst),
710710 .splat => try self.airSplat(inst),
711 .vector_init => try self.airVectorInit(inst),
711 .aggregate_init => try self.airAggregateInit(inst),
712 .union_init => try self.airUnionInit(inst),
712713 .prefetch => try self.airPrefetch(inst),
713714
714715 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
......@@ -5232,14 +5233,14 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
52325233 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
52335234}
52345235
5235fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
5236fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
52365237 const vector_ty = self.air.typeOfIndex(inst);
52375238 const len = vector_ty.vectorLen();
52385239 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
52395240 const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
52405241 const result: MCValue = res: {
52415242 if (self.liveness.isUnused(inst)) break :res MCValue.dead;
5242 return self.fail("TODO implement airVectorInit for x86_64", .{});
5243 return self.fail("TODO implement airAggregateInit for x86_64", .{});
52435244 };
52445245
52455246 if (elements.len <= Liveness.bpi - 1) {
......@@ -5254,6 +5255,16 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
52545255 return bt.finishAir(result);
52555256}
52565257
5258fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
5259 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5260 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
5261 const result: MCValue = res: {
5262 if (self.liveness.isUnused(inst)) break :res MCValue.dead;
5263 return self.fail("TODO implement airAggregateInit for x86_64", .{});
5264 };
5265 return self.finishAir(inst, result, .{ extra.init, .none, .none });
5266}
5267
52575268fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
52585269 const prefetch = self.air.instructions.items(.data)[inst].prefetch;
52595270 return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
src/codegen/c.zig+19-3
......@@ -1713,7 +1713,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
17131713 .tag_name => try airTagName(f, inst),
17141714 .error_name => try airErrorName(f, inst),
17151715 .splat => try airSplat(f, inst),
1716 .vector_init => try airVectorInit(f, inst),
1716 .aggregate_init => try airAggregateInit(f, inst),
1717 .union_init => try airUnionInit(f, inst),
17171718 .prefetch => try airPrefetch(f, inst),
17181719
17191720 .int_to_float,
......@@ -3526,7 +3527,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
35263527 return f.fail("TODO: C backend: implement airSplat", .{});
35273528}
35283529
3529fn airVectorInit(f: *Function, inst: Air.Inst.Index) !CValue {
3530fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
35303531 if (f.liveness.isUnused(inst)) return CValue.none;
35313532
35323533 const inst_ty = f.air.typeOfIndex(inst);
......@@ -3541,7 +3542,22 @@ fn airVectorInit(f: *Function, inst: Air.Inst.Index) !CValue {
35413542
35423543 _ = elements;
35433544 _ = local;
3544 return f.fail("TODO: C backend: implement airVectorInit", .{});
3545 return f.fail("TODO: C backend: implement airAggregateInit", .{});
3546}
3547
3548fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
3549 if (f.liveness.isUnused(inst)) return CValue.none;
3550
3551 const inst_ty = f.air.typeOfIndex(inst);
3552 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3553
3554 const writer = f.object.writer();
3555 const local = try f.allocLocal(inst_ty, .Const);
3556 try writer.writeAll(" = ");
3557
3558 _ = local;
3559 _ = ty_pl;
3560 return f.fail("TODO: C backend: implement airUnionInit", .{});
35453561}
35463562
35473563fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
src/codegen/llvm.zig+106-2
......@@ -2175,7 +2175,8 @@ pub const FuncGen = struct {
21752175 .tag_name => try self.airTagName(inst),
21762176 .error_name => try self.airErrorName(inst),
21772177 .splat => try self.airSplat(inst),
2178 .vector_init => try self.airVectorInit(inst),
2178 .aggregate_init => try self.airAggregateInit(inst),
2179 .union_init => try self.airUnionInit(inst),
21792180 .prefetch => try self.airPrefetch(inst),
21802181
21812182 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
......@@ -4608,7 +4609,7 @@ pub const FuncGen = struct {
46084609 return self.builder.buildShuffleVector(op_vector, undef_vector, mask_llvm_ty.constNull(), "");
46094610 }
46104611
4611 fn airVectorInit(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4612 fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
46124613 if (self.liveness.isUnused(inst)) return null;
46134614
46144615 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
......@@ -4693,6 +4694,109 @@ pub const FuncGen = struct {
46934694 }
46944695 }
46954696
4697 fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4698 if (self.liveness.isUnused(inst)) return null;
4699
4700 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4701 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
4702 const union_ty = self.air.typeOfIndex(inst);
4703 const union_llvm_ty = try self.dg.llvmType(union_ty);
4704 const target = self.dg.module.getTarget();
4705 const layout = union_ty.unionGetLayout(target);
4706 if (layout.payload_size == 0) {
4707 if (layout.tag_size == 0) {
4708 return null;
4709 }
4710 assert(!isByRef(union_ty));
4711 return union_llvm_ty.constInt(extra.field_index, .False);
4712 }
4713 assert(isByRef(union_ty));
4714 // The llvm type of the alloca will the the named LLVM union type, which will not
4715 // necessarily match the format that we need, depending on which tag is active. We
4716 // must construct the correct unnamed struct type here and bitcast, in order to
4717 // then set the fields appropriately.
4718 const result_ptr = self.buildAlloca(union_llvm_ty);
4719 const llvm_payload = try self.resolveInst(extra.init);
4720 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
4721 assert(union_obj.haveFieldTypes());
4722 const field = union_obj.fields.values()[extra.field_index];
4723 const field_llvm_ty = try self.dg.llvmType(field.ty);
4724 const tag_llvm_ty = try self.dg.llvmType(union_obj.tag_ty);
4725 const field_size = field.ty.abiSize(target);
4726 const field_align = field.normalAlignment(target);
4727
4728 const llvm_union_ty = t: {
4729 const payload = p: {
4730 if (!field.ty.hasRuntimeBits()) {
4731 const padding_len = @intCast(c_uint, layout.payload_size);
4732 break :p self.context.intType(8).arrayType(padding_len);
4733 }
4734 if (field_size == layout.payload_size) {
4735 break :p field_llvm_ty;
4736 }
4737 const padding_len = @intCast(c_uint, layout.payload_size - field_size);
4738 const fields: [2]*const llvm.Type = .{
4739 field_llvm_ty, self.context.intType(8).arrayType(padding_len),
4740 };
4741 break :p self.context.structType(&fields, fields.len, .False);
4742 };
4743 if (layout.tag_size == 0) {
4744 const fields: [1]*const llvm.Type = .{payload};
4745 break :t self.context.structType(&fields, fields.len, .False);
4746 }
4747 var fields: [2]*const llvm.Type = undefined;
4748 if (layout.tag_align >= layout.payload_align) {
4749 fields = .{ tag_llvm_ty, payload };
4750 } else {
4751 fields = .{ payload, tag_llvm_ty };
4752 }
4753 break :t self.context.structType(&fields, fields.len, .False);
4754 };
4755
4756 const casted_ptr = self.builder.buildBitCast(result_ptr, llvm_union_ty.pointerType(0), "");
4757
4758 // Now we follow the layout as expressed above with GEP instructions to set the
4759 // tag and the payload.
4760 const index_type = self.context.intType(32);
4761
4762 if (layout.tag_size == 0) {
4763 const indices: [3]*const llvm.Value = .{
4764 index_type.constNull(),
4765 index_type.constNull(),
4766 index_type.constNull(),
4767 };
4768 const len: c_uint = if (field_size == layout.payload_size) 2 else 3;
4769 const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, "");
4770 const store_inst = self.builder.buildStore(llvm_payload, field_ptr);
4771 store_inst.setAlignment(field_align);
4772 return result_ptr;
4773 }
4774
4775 {
4776 const indices: [3]*const llvm.Value = .{
4777 index_type.constNull(),
4778 index_type.constInt(@boolToInt(layout.tag_align >= layout.payload_align), .False),
4779 index_type.constNull(),
4780 };
4781 const len: c_uint = if (field_size == layout.payload_size) 2 else 3;
4782 const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, "");
4783 const store_inst = self.builder.buildStore(llvm_payload, field_ptr);
4784 store_inst.setAlignment(field_align);
4785 }
4786 {
4787 const indices: [2]*const llvm.Value = .{
4788 index_type.constNull(),
4789 index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False),
4790 };
4791 const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, "");
4792 const llvm_tag = union_llvm_ty.constInt(extra.field_index, .False);
4793 const store_inst = self.builder.buildStore(llvm_tag, field_ptr);
4794 store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target));
4795 }
4796
4797 return result_ptr;
4798 }
4799
46964800 fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
46974801 const prefetch = self.air.instructions.items(.data)[inst].prefetch;
46984802
src/print_air.zig+11-2
......@@ -232,7 +232,8 @@ const Writer = struct {
232232 .assembly => try w.writeAssembly(s, inst),
233233 .dbg_stmt => try w.writeDbgStmt(s, inst),
234234 .call => try w.writeCall(s, inst),
235 .vector_init => try w.writeVectorInit(s, inst),
235 .aggregate_init => try w.writeAggregateInit(s, inst),
236 .union_init => try w.writeUnionInit(s, inst),
236237 .br => try w.writeBr(s, inst),
237238 .cond_br => try w.writeCondBr(s, inst),
238239 .switch_br => try w.writeSwitchBr(s, inst),
......@@ -301,7 +302,7 @@ const Writer = struct {
301302 try s.writeAll("}");
302303 }
303304
304 fn writeVectorInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
305 fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
305306 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
306307 const vector_ty = w.air.getRefType(ty_pl.ty);
307308 const len = @intCast(usize, vector_ty.arrayLen());
......@@ -315,6 +316,14 @@ const Writer = struct {
315316 try s.writeAll("]");
316317 }
317318
319 fn writeUnionInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
320 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
321 const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data;
322
323 try s.print("{d}, ", .{extra.field_index});
324 try w.writeOperand(s, inst, 0, extra.init);
325 }
326
318327 fn writeStructField(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
319328 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
320329 const extra = w.air.extraData(Air.StructField, ty_pl.payload).data;
src/print_zir.zig+5-5
......@@ -273,7 +273,7 @@ const Writer = struct {
273273 .slice_end => try self.writeSliceEnd(stream, inst),
274274 .slice_sentinel => try self.writeSliceSentinel(stream, inst),
275275
276 .union_init_ptr => try self.writeUnionInitPtr(stream, inst),
276 .union_init => try self.writeUnionInit(stream, inst),
277277
278278 .struct_init,
279279 .struct_init_ref,
......@@ -692,14 +692,14 @@ const Writer = struct {
692692 try self.writeSrc(stream, inst_data.src());
693693 }
694694
695 fn writeUnionInitPtr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
695 fn writeUnionInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
696696 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
697 const extra = self.code.extraData(Zir.Inst.UnionInitPtr, inst_data.payload_index).data;
698 try self.writeInstRef(stream, extra.result_ptr);
699 try stream.writeAll(", ");
697 const extra = self.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
700698 try self.writeInstRef(stream, extra.union_type);
701699 try stream.writeAll(", ");
702700 try self.writeInstRef(stream, extra.field_name);
701 try stream.writeAll(", ");
702 try self.writeInstRef(stream, extra.init);
703703 try stream.writeAll(") ");
704704 try self.writeSrc(stream, inst_data.src());
705705 }
test/behavior/union.zig+39-3
......@@ -785,8 +785,40 @@ test "return union init with void payload" {
785785 comptime try S.entry();
786786}
787787
788test "@unionInit stored to a const" {
789 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
790 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
792 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
793 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
794
795 const S = struct {
796 const U = union(enum) {
797 boolean: bool,
798 byte: u8,
799 };
800 fn doTheTest() !void {
801 {
802 var t = true;
803 const u = @unionInit(U, "boolean", t);
804 try expect(u.boolean);
805 }
806 {
807 var byte: u8 = 69;
808 const u = @unionInit(U, "byte", byte);
809 try expect(u.byte == 69);
810 }
811 }
812 };
813
814 comptime try S.doTheTest();
815 try S.doTheTest();
816}
817
788818test "@unionInit can modify a union type" {
789 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
819 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
820 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
821 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
790822
791823 const UnionInitEnum = union(enum) {
792824 Boolean: bool,
......@@ -807,7 +839,9 @@ test "@unionInit can modify a union type" {
807839}
808840
809841test "@unionInit can modify a pointer value" {
810 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
842 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
843 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
811845
812846 const UnionInitEnum = union(enum) {
813847 Boolean: bool,
......@@ -825,7 +859,9 @@ test "@unionInit can modify a pointer value" {
825859}
826860
827861test "union no tag with struct member" {
828 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
862 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
863 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
864 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
829865
830866 const Struct = struct {};
831867 const Union = union {