authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-01 23:46:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-01 23:46:57-07:00
loged2364a1480f99a7380285cec15ff1962d9df519
treeda488724987e43e11a5938589a9df5b92c79d8c4
parent6f303c01f3e06fe8203563065ea32537f6eff456

stage2: introduce anonymous struct literals


13 files changed, 392 insertions(+), 141 deletions(-)

src/Sema.zig+128-34
...@@ -7704,7 +7704,7 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -7704,7 +7704,7 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
7704 const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);7704 const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
77057705
7706 // tuples are structs but they don't have a namespace7706 // tuples are structs but they don't have a namespace
7707 if (container_type.isTuple()) return Air.Inst.Ref.bool_false;7707 if (container_type.isTupleOrAnonStruct()) return Air.Inst.Ref.bool_false;
7708 const namespace = container_type.getNamespace() orelse return sema.fail(7708 const namespace = container_type.getNamespace() orelse return sema.fail(
7709 block,7709 block,
7710 lhs_src,7710 lhs_src,
...@@ -10615,15 +10615,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10615,15 +10615,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10615 const layout = struct_ty.containerLayout();10615 const layout = struct_ty.containerLayout();
1061610616
10617 const struct_field_vals = fv: {10617 const struct_field_vals = fv: {
10618 if (struct_ty.castTag(.tuple)) |payload| {10618 if (struct_ty.isTupleOrAnonStruct()) {
10619 const field_types = payload.data.types;10619 const tuple = struct_ty.tupleFields();
10620 const field_types = tuple.types;
10620 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);10621 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);
10621 for (struct_field_vals) |*struct_field_val, i| {10622 for (struct_field_vals) |*struct_field_val, i| {
10622 const field_ty = field_types[i];10623 const field_ty = field_types[i];
10623 const name_val = v: {10624 const name_val = v: {
10624 var anon_decl = try block.startAnonDecl(src);10625 var anon_decl = try block.startAnonDecl(src);
10625 defer anon_decl.deinit();10626 defer anon_decl.deinit();
10626 const bytes = try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});10627 const bytes = if (struct_ty.castTag(.anon_struct)) |payload|
10628 try anon_decl.arena().dupeZ(u8, payload.data.names[i])
10629 else
10630 try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
10627 const new_decl = try anon_decl.finish(10631 const new_decl = try anon_decl.finish(
10628 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),10632 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10629 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),10633 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
...@@ -10632,7 +10636,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10632,7 +10636,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10632 };10636 };
1063310637
10634 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);10638 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
10635 const field_val = payload.data.values[i];10639 const field_val = tuple.values[i];
10636 const is_comptime = field_val.tag() != .unreachable_value;10640 const is_comptime = field_val.tag() != .unreachable_value;
10637 const opt_default_val = if (is_comptime) field_val else null;10641 const opt_default_val = if (is_comptime) field_val else null;
10638 const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);10642 const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);
...@@ -11631,12 +11635,86 @@ fn finishStructInit(...@@ -11631,12 +11635,86 @@ fn finishStructInit(
11631 return block.addAggregateInit(struct_ty, field_inits);11635 return block.addAggregateInit(struct_ty, field_inits);
11632}11636}
1163311637
11634fn zirStructInitAnon(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {11638fn zirStructInitAnon(
11639 sema: *Sema,
11640 block: *Block,
11641 inst: Zir.Inst.Index,
11642 is_ref: bool,
11643) CompileError!Air.Inst.Ref {
11635 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;11644 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
11636 const src = inst_data.src();11645 const src = inst_data.src();
11646 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
11647 const types = try sema.arena.alloc(Type, extra.data.fields_len);
11648 const values = try sema.arena.alloc(Value, types.len);
11649 const names = try sema.arena.alloc([]const u8, types.len);
11650
11651 const opt_runtime_src = rs: {
11652 var runtime_src: ?LazySrcLoc = null;
11653 var extra_index = extra.end;
11654 for (types) |*field_ty, i| {
11655 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
11656 extra_index = item.end;
1163711657
11638 _ = is_ref;11658 names[i] = sema.code.nullTerminatedString(item.data.field_name);
11639 return sema.fail(block, src, "TODO: Sema.zirStructInitAnon", .{});11659 const init = sema.resolveInst(item.data.init);
11660 field_ty.* = sema.typeOf(init);
11661 const init_src = src; // TODO better source location
11662 if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| {
11663 values[i] = init_val;
11664 } else {
11665 values[i] = Value.initTag(.unreachable_value);
11666 runtime_src = init_src;
11667 }
11668 }
11669 break :rs runtime_src;
11670 };
11671
11672 const tuple_ty = try Type.Tag.anon_struct.create(sema.arena, .{
11673 .names = names,
11674 .types = types,
11675 .values = values,
11676 });
11677
11678 const runtime_src = opt_runtime_src orelse {
11679 const tuple_val = try Value.Tag.@"struct".create(sema.arena, values);
11680 return sema.addConstantMaybeRef(block, src, tuple_ty, tuple_val, is_ref);
11681 };
11682
11683 try sema.requireRuntimeBlock(block, runtime_src);
11684
11685 if (is_ref) {
11686 const target = sema.mod.getTarget();
11687 const alloc = try block.addTy(.alloc, tuple_ty);
11688 var extra_index = extra.end;
11689 for (types) |field_ty, i_usize| {
11690 const i = @intCast(u32, i_usize);
11691 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
11692 extra_index = item.end;
11693
11694 const field_ptr_ty = try Type.ptr(sema.arena, target, .{
11695 .mutable = true,
11696 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
11697 .pointee_type = field_ty,
11698 });
11699 if (values[i].tag() == .unreachable_value) {
11700 const init = sema.resolveInst(item.data.init);
11701 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
11702 _ = try block.addBinOp(.store, field_ptr, init);
11703 }
11704 }
11705
11706 return alloc;
11707 }
11708
11709 const element_refs = try sema.arena.alloc(Air.Inst.Ref, types.len);
11710 var extra_index = extra.end;
11711 for (types) |_, i| {
11712 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
11713 extra_index = item.end;
11714 element_refs[i] = sema.resolveInst(item.data.init);
11715 }
11716
11717 return block.addAggregateInit(tuple_ty, element_refs);
11640}11718}
1164111719
11642fn zirArrayInit(11720fn zirArrayInit(
...@@ -11764,8 +11842,10 @@ fn zirArrayInitAnon(...@@ -11764,8 +11842,10 @@ fn zirArrayInitAnon(
11764 .@"addrspace" = target_util.defaultAddressSpace(target, .local),11842 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
11765 .pointee_type = types[i],11843 .pointee_type = types[i],
11766 });11844 });
11767 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);11845 if (values[i].tag() == .unreachable_value) {
11768 _ = try block.addBinOp(.store, field_ptr, sema.resolveInst(operand));11846 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
11847 _ = try block.addBinOp(.store, field_ptr, sema.resolveInst(operand));
11848 }
11769 }11849 }
1177011850
11771 return alloc;11851 return alloc;
...@@ -12126,7 +12206,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -12126,7 +12206,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
12126 .size = ptr_size,12206 .size = ptr_size,
12127 .mutable = !is_const_val.toBool(),12207 .mutable = !is_const_val.toBool(),
12128 .@"volatile" = is_volatile_val.toBool(),12208 .@"volatile" = is_volatile_val.toBool(),
12129 .@"align" = @intCast(u8, alignment_val.toUnsignedInt()), // TODO: Validate this value.12209 .@"align" = @intCast(u16, alignment_val.toUnsignedInt()), // TODO: Validate this value.
12130 .@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace),12210 .@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace),
12131 .pointee_type = try child_ty.copy(sema.arena),12211 .pointee_type = try child_ty.copy(sema.arena),
12132 .@"allowzero" = is_allowzero_val.toBool(),12212 .@"allowzero" = is_allowzero_val.toBool(),
...@@ -14842,29 +14922,43 @@ fn structFieldVal(...@@ -14842,29 +14922,43 @@ fn structFieldVal(
14842 assert(unresolved_struct_ty.zigTypeTag() == .Struct);14922 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
1484314923
14844 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);14924 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
14845 if (struct_ty.isTuple()) {14925 switch (struct_ty.tag()) {
14846 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);14926 .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
14847 }14927 .anon_struct => {
14928 const anon_struct = struct_ty.castTag(.anon_struct).?.data;
1484814929
14849 const struct_obj = struct_ty.castTag(.@"struct").?.data;14930 const field_index = for (anon_struct.names) |name, i| {
14931 if (mem.eql(u8, name, field_name)) break @intCast(u32, i);
14932 } else {
14933 return sema.fail(block, field_name_src, "anonymous struct {} has no such field '{s}'", .{
14934 struct_ty, field_name,
14935 });
14936 };
14937 return tupleFieldValByIndex(sema, block, src, struct_byval, field_index, struct_ty);
14938 },
14939 .@"struct" => {
14940 const struct_obj = struct_ty.castTag(.@"struct").?.data;
1485014941
14851 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse14942 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
14852 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);14943 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
14853 const field_index = @intCast(u32, field_index_usize);14944 const field_index = @intCast(u32, field_index_usize);
14854 const field = struct_obj.fields.values()[field_index];14945 const field = struct_obj.fields.values()[field_index];
1485514946
14856 if (try sema.resolveMaybeUndefVal(block, src, struct_byval)) |struct_val| {14947 if (try sema.resolveMaybeUndefVal(block, src, struct_byval)) |struct_val| {
14857 if (struct_val.isUndef()) return sema.addConstUndef(field.ty);14948 if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
14858 if ((try sema.typeHasOnePossibleValue(block, src, field.ty))) |opv| {14949 if ((try sema.typeHasOnePossibleValue(block, src, field.ty))) |opv| {
14859 return sema.addConstant(field.ty, opv);14950 return sema.addConstant(field.ty, opv);
14860 }14951 }
1486114952
14862 const field_values = struct_val.castTag(.@"struct").?.data;14953 const field_values = struct_val.castTag(.@"struct").?.data;
14863 return sema.addConstant(field.ty, field_values[field_index]);14954 return sema.addConstant(field.ty, field_values[field_index]);
14864 }14955 }
1486514956
14866 try sema.requireRuntimeBlock(block, src);14957 try sema.requireRuntimeBlock(block, src);
14867 return block.addStructFieldVal(struct_byval, field_index, field.ty);14958 return block.addStructFieldVal(struct_byval, field_index, field.ty);
14959 },
14960 else => unreachable,
14961 }
14868}14962}
1486914963
14870fn tupleFieldVal(14964fn tupleFieldVal(
...@@ -14901,7 +14995,7 @@ fn tupleFieldValByIndex(...@@ -14901,7 +14995,7 @@ fn tupleFieldValByIndex(
14901 field_index: u32,14995 field_index: u32,
14902 tuple_ty: Type,14996 tuple_ty: Type,
14903) CompileError!Air.Inst.Ref {14997) CompileError!Air.Inst.Ref {
14904 const tuple = tuple_ty.castTag(.tuple).?.data;14998 const tuple = tuple_ty.tupleFields();
14905 const field_ty = tuple.types[field_index];14999 const field_ty = tuple.types[field_index];
1490615000
14907 if (tuple.values[field_index].tag() != .unreachable_value) {15001 if (tuple.values[field_index].tag() != .unreachable_value) {
...@@ -18954,8 +19048,8 @@ pub fn typeHasOnePossibleValue(...@@ -18954,8 +19048,8 @@ pub fn typeHasOnePossibleValue(
18954 return Value.initTag(.empty_struct_value);19048 return Value.initTag(.empty_struct_value);
18955 },19049 },
1895619050
18957 .tuple => {19051 .tuple, .anon_struct => {
18958 const tuple = ty.castTag(.tuple).?.data;19052 const tuple = ty.tupleFields();
18959 for (tuple.values) |val| {19053 for (tuple.values) |val| {
18960 if (val.tag() == .unreachable_value) {19054 if (val.tag() == .unreachable_value) {
18961 return null; // non-comptime field19055 return null; // non-comptime field
...@@ -19583,8 +19677,8 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C...@@ -19583,8 +19677,8 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
19583 return sema.typeRequiresComptime(block, src, ty.optionalChild(&buf));19677 return sema.typeRequiresComptime(block, src, ty.optionalChild(&buf));
19584 },19678 },
1958519679
19586 .tuple => {19680 .tuple, .anon_struct => {
19587 const tuple = ty.castTag(.tuple).?.data;19681 const tuple = ty.tupleFields();
19588 for (tuple.types) |field_ty, i| {19682 for (tuple.types) |field_ty, i| {
19589 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;19683 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
19590 if (!have_comptime_val and try sema.typeRequiresComptime(block, src, field_ty)) {19684 if (!have_comptime_val and try sema.typeRequiresComptime(block, src, field_ty)) {
src/Zir.zig+3-1
...@@ -2850,7 +2850,9 @@ pub const Inst = struct {...@@ -2850,7 +2850,9 @@ pub const Inst = struct {
2850 };2850 };
2851 };2851 };
28522852
2853 /// Trailing is an item per field.2853 /// Trailing is an Item per field.
2854 /// TODO make this instead array of inits followed by array of names because
2855 /// it will be simpler Sema code and better for CPU cache.
2854 pub const StructInitAnon = struct {2856 pub const StructInitAnon = struct {
2855 fields_len: u32,2857 fields_len: u32,
28562858
src/codegen/llvm.zig+3-3
...@@ -958,7 +958,7 @@ pub const DeclGen = struct {...@@ -958,7 +958,7 @@ pub const DeclGen = struct {
958 // reference, we need to copy it here.958 // reference, we need to copy it here.
959 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());959 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
960960
961 if (t.isTuple()) {961 if (t.isTupleOrAnonStruct()) {
962 const tuple = t.tupleFields();962 const tuple = t.tupleFields();
963 const llvm_struct_ty = dg.context.structCreateNamed("");963 const llvm_struct_ty = dg.context.structCreateNamed("");
964 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls964 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
...@@ -2104,7 +2104,7 @@ pub const DeclGen = struct {...@@ -2104,7 +2104,7 @@ pub const DeclGen = struct {
2104 var zig_big_align: u32 = 0;2104 var zig_big_align: u32 = 0;
2105 var llvm_big_align: u32 = 0;2105 var llvm_big_align: u32 = 0;
21062106
2107 if (ty.isTuple()) {2107 if (ty.isTupleOrAnonStruct()) {
2108 const tuple = ty.tupleFields();2108 const tuple = ty.tupleFields();
2109 var llvm_field_index: c_uint = 0;2109 var llvm_field_index: c_uint = 0;
2110 for (tuple.types) |field_ty, i| {2110 for (tuple.types) |field_ty, i| {
...@@ -5704,7 +5704,7 @@ fn isByRef(ty: Type) bool {...@@ -5704,7 +5704,7 @@ fn isByRef(ty: Type) bool {
5704 .Struct => {5704 .Struct => {
5705 // Packed structs are represented to LLVM as integers.5705 // Packed structs are represented to LLVM as integers.
5706 if (ty.containerLayout() == .Packed) return false;5706 if (ty.containerLayout() == .Packed) return false;
5707 if (ty.isTuple()) {5707 if (ty.isTupleOrAnonStruct()) {
5708 const tuple = ty.tupleFields();5708 const tuple = ty.tupleFields();
5709 var count: usize = 0;5709 var count: usize = 0;
5710 for (tuple.values) |field_val, i| {5710 for (tuple.values) |field_val, i| {
src/type.zig+151-24
...@@ -131,6 +131,7 @@ pub const Type = extern union {...@@ -131,6 +131,7 @@ pub const Type = extern union {
131 .export_options,131 .export_options,
132 .extern_options,132 .extern_options,
133 .tuple,133 .tuple,
134 .anon_struct,
134 => return .Struct,135 => return .Struct,
135136
136 .enum_full,137 .enum_full,
...@@ -792,6 +793,42 @@ pub const Type = extern union {...@@ -792,6 +793,42 @@ pub const Type = extern union {
792793
793 return true;794 return true;
794 },795 },
796 .anon_struct => {
797 const a_struct_obj = a.castTag(.anon_struct).?.data;
798 const b_struct_obj = (b.castTag(.anon_struct) orelse return false).data;
799
800 if (a_struct_obj.types.len != b_struct_obj.types.len) return false;
801
802 for (a_struct_obj.names) |a_name, i| {
803 const b_name = b_struct_obj.names[i];
804 if (!std.mem.eql(u8, a_name, b_name)) return false;
805 }
806
807 for (a_struct_obj.types) |a_ty, i| {
808 const b_ty = b_struct_obj.types[i];
809 if (!eql(a_ty, b_ty)) return false;
810 }
811
812 for (a_struct_obj.values) |a_val, i| {
813 const ty = a_struct_obj.types[i];
814 const b_val = b_struct_obj.values[i];
815 if (a_val.tag() == .unreachable_value) {
816 if (b_val.tag() == .unreachable_value) {
817 continue;
818 } else {
819 return false;
820 }
821 } else {
822 if (b_val.tag() == .unreachable_value) {
823 return false;
824 } else {
825 if (!Value.eql(a_val, b_val, ty)) return false;
826 }
827 }
828 }
829
830 return true;
831 },
795832
796 // we can't compare these based on tags because it wouldn't detect if,833 // we can't compare these based on tags because it wouldn't detect if,
797 // for example, a was resolved into .@"struct" but b was one of these tags.834 // for example, a was resolved into .@"struct" but b was one of these tags.
...@@ -1062,6 +1099,20 @@ pub const Type = extern union {...@@ -1062,6 +1099,20 @@ pub const Type = extern union {
1062 field_val.hash(field_ty, hasher);1099 field_val.hash(field_ty, hasher);
1063 }1100 }
1064 },1101 },
1102 .anon_struct => {
1103 const struct_obj = ty.castTag(.anon_struct).?.data;
1104 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
1105 std.hash.autoHash(hasher, struct_obj.types.len);
1106
1107 for (struct_obj.types) |field_ty, i| {
1108 const field_name = struct_obj.names[i];
1109 const field_val = struct_obj.values[i];
1110 hasher.update(field_name);
1111 hashWithHasher(field_ty, hasher);
1112 if (field_val.tag() == .unreachable_value) continue;
1113 field_val.hash(field_ty, hasher);
1114 }
1115 },
10651116
1066 // we can't hash these based on tags because they wouldn't match the expanded version.1117 // we can't hash these based on tags because they wouldn't match the expanded version.
1067 .call_options,1118 .call_options,
...@@ -1279,6 +1330,26 @@ pub const Type = extern union {...@@ -1279,6 +1330,26 @@ pub const Type = extern union {
1279 .values = values,1330 .values = values,
1280 });1331 });
1281 },1332 },
1333 .anon_struct => {
1334 const payload = self.castTag(.anon_struct).?.data;
1335 const names = try allocator.alloc([]const u8, payload.names.len);
1336 const types = try allocator.alloc(Type, payload.types.len);
1337 const values = try allocator.alloc(Value, payload.values.len);
1338 for (payload.names) |name, i| {
1339 names[i] = try allocator.dupe(u8, name);
1340 }
1341 for (payload.types) |ty, i| {
1342 types[i] = try ty.copy(allocator);
1343 }
1344 for (payload.values) |val, i| {
1345 values[i] = try val.copy(allocator);
1346 }
1347 return Tag.anon_struct.create(allocator, .{
1348 .names = names,
1349 .types = types,
1350 .values = values,
1351 });
1352 },
1282 .function => {1353 .function => {
1283 const payload = self.castTag(.function).?.data;1354 const payload = self.castTag(.function).?.data;
1284 const param_types = try allocator.alloc(Type, payload.param_types.len);1355 const param_types = try allocator.alloc(Type, payload.param_types.len);
...@@ -1533,6 +1604,26 @@ pub const Type = extern union {...@@ -1533,6 +1604,26 @@ pub const Type = extern union {
1533 try writer.writeAll("}");1604 try writer.writeAll("}");
1534 return;1605 return;
1535 },1606 },
1607 .anon_struct => {
1608 const anon_struct = ty.castTag(.anon_struct).?.data;
1609 try writer.writeAll("struct{");
1610 for (anon_struct.types) |field_ty, i| {
1611 if (i != 0) try writer.writeAll(", ");
1612 const val = anon_struct.values[i];
1613 if (val.tag() != .unreachable_value) {
1614 try writer.writeAll("comptime ");
1615 }
1616 try writer.writeAll(anon_struct.names[i]);
1617 try writer.writeAll(": ");
1618 try field_ty.format("", .{}, writer);
1619 if (val.tag() != .unreachable_value) {
1620 try writer.writeAll(" = ");
1621 try val.format("", .{}, writer);
1622 }
1623 }
1624 try writer.writeAll("}");
1625 return;
1626 },
1536 .single_const_pointer => {1627 .single_const_pointer => {
1537 const pointee_type = ty.castTag(.single_const_pointer).?.data;1628 const pointee_type = ty.castTag(.single_const_pointer).?.data;
1538 try writer.writeAll("*const ");1629 try writer.writeAll("*const ");
...@@ -2020,8 +2111,8 @@ pub const Type = extern union {...@@ -2020,8 +2111,8 @@ pub const Type = extern union {
2020 return payload.error_set.hasRuntimeBits() or payload.payload.hasRuntimeBits();2111 return payload.error_set.hasRuntimeBits() or payload.payload.hasRuntimeBits();
2021 },2112 },
20222113
2023 .tuple => {2114 .tuple, .anon_struct => {
2024 const tuple = ty.castTag(.tuple).?.data;2115 const tuple = ty.tupleFields();
2025 for (tuple.types) |field_ty, i| {2116 for (tuple.types) |field_ty, i| {
2026 const val = tuple.values[i];2117 const val = tuple.values[i];
2027 if (val.tag() != .unreachable_value) continue; // comptime field2118 if (val.tag() != .unreachable_value) continue; // comptime field
...@@ -2292,8 +2383,8 @@ pub const Type = extern union {...@@ -2292,8 +2383,8 @@ pub const Type = extern union {
2292 return big_align;2383 return big_align;
2293 },2384 },
22942385
2295 .tuple => {2386 .tuple, .anon_struct => {
2296 const tuple = self.castTag(.tuple).?.data;2387 const tuple = self.tupleFields();
2297 var big_align: u32 = 0;2388 var big_align: u32 = 0;
2298 for (tuple.types) |field_ty, i| {2389 for (tuple.types) |field_ty, i| {
2299 const val = tuple.values[i];2390 const val = tuple.values[i];
...@@ -2375,7 +2466,7 @@ pub const Type = extern union {...@@ -2375,7 +2466,7 @@ pub const Type = extern union {
2375 .void,2466 .void,
2376 => 0,2467 => 0,
23772468
2378 .@"struct", .tuple => switch (self.containerLayout()) {2469 .@"struct", .tuple, .anon_struct => switch (self.containerLayout()) {
2379 .Packed => {2470 .Packed => {
2380 const struct_obj = self.castTag(.@"struct").?.data;2471 const struct_obj = self.castTag(.@"struct").?.data;
2381 var buf: Type.Payload.Bits = undefined;2472 var buf: Type.Payload.Bits = undefined;
...@@ -2575,6 +2666,13 @@ pub const Type = extern union {...@@ -2575,6 +2666,13 @@ pub const Type = extern union {
2575 .bound_fn => unreachable,2666 .bound_fn => unreachable,
25762667
2577 .void => 0,2668 .void => 0,
2669 .bool, .u1 => 1,
2670 .u8, .i8 => 8,
2671 .i16, .u16, .f16 => 16,
2672 .i32, .u32, .f32 => 32,
2673 .i64, .u64, .f64 => 64,
2674 .f80 => 80,
2675 .u128, .i128, .f128 => 128,
25782676
2579 .@"struct" => {2677 .@"struct" => {
2580 const field_count = ty.structFieldCount();2678 const field_count = ty.structFieldCount();
...@@ -2595,8 +2693,13 @@ pub const Type = extern union {...@@ -2595,8 +2693,13 @@ pub const Type = extern union {
2595 }2693 }
2596 },2694 },
25972695
2598 .tuple => {2696 .tuple, .anon_struct => {
2599 @panic("TODO bitSize tuples");2697 const tuple = ty.tupleFields();
2698 var total: u64 = 0;
2699 for (tuple.types) |field_ty| {
2700 total += field_ty.bitSize(target);
2701 }
2702 return total;
2600 },2703 },
26012704
2602 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {2705 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
...@@ -2608,10 +2711,6 @@ pub const Type = extern union {...@@ -2608,10 +2711,6 @@ pub const Type = extern union {
2608 @panic("TODO bitSize unions");2711 @panic("TODO bitSize unions");
2609 },2712 },
26102713
2611 .u8, .i8 => 8,
2612
2613 .bool, .u1 => 1,
2614
2615 .vector => {2714 .vector => {
2616 const payload = ty.castTag(.vector).?.data;2715 const payload = ty.castTag(.vector).?.data;
2617 const elem_bit_size = payload.elem_type.bitSize(target);2716 const elem_bit_size = payload.elem_type.bitSize(target);
...@@ -2634,11 +2733,6 @@ pub const Type = extern union {...@@ -2634,11 +2733,6 @@ pub const Type = extern union {
2634 );2733 );
2635 return payload.len * 8 * elem_size + payload.elem_type.bitSize(target);2734 return payload.len * 8 * elem_size + payload.elem_type.bitSize(target);
2636 },2735 },
2637 .i16, .u16, .f16 => 16,
2638 .i32, .u32, .f32 => 32,
2639 .i64, .u64, .f64 => 64,
2640 .f80 => 80,
2641 .u128, .i128, .f128 => 128,
26422736
2643 .isize,2737 .isize,
2644 .usize,2738 .usize,
...@@ -3295,7 +3389,7 @@ pub const Type = extern union {...@@ -3295,7 +3389,7 @@ pub const Type = extern union {
32953389
3296 pub fn containerLayout(ty: Type) std.builtin.TypeInfo.ContainerLayout {3390 pub fn containerLayout(ty: Type) std.builtin.TypeInfo.ContainerLayout {
3297 return switch (ty.tag()) {3391 return switch (ty.tag()) {
3298 .tuple, .empty_struct_literal => .Auto,3392 .tuple, .empty_struct_literal, .anon_struct => .Auto,
3299 .@"struct" => ty.castTag(.@"struct").?.data.layout,3393 .@"struct" => ty.castTag(.@"struct").?.data.layout,
3300 .@"union" => ty.castTag(.@"union").?.data.layout,3394 .@"union" => ty.castTag(.@"union").?.data.layout,
3301 .union_tagged => ty.castTag(.union_tagged).?.data.layout,3395 .union_tagged => ty.castTag(.union_tagged).?.data.layout,
...@@ -3369,6 +3463,7 @@ pub const Type = extern union {...@@ -3369,6 +3463,7 @@ pub const Type = extern union {
3369 .array_u8 => ty.castTag(.array_u8).?.data,3463 .array_u8 => ty.castTag(.array_u8).?.data,
3370 .array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data,3464 .array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data,
3371 .tuple => ty.castTag(.tuple).?.data.types.len,3465 .tuple => ty.castTag(.tuple).?.data.types.len,
3466 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
3372 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),3467 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
33733468
3374 else => unreachable,3469 else => unreachable,
...@@ -3383,6 +3478,7 @@ pub const Type = extern union {...@@ -3383,6 +3478,7 @@ pub const Type = extern union {
3383 return switch (ty.tag()) {3478 return switch (ty.tag()) {
3384 .vector => @intCast(u32, ty.castTag(.vector).?.data.len),3479 .vector => @intCast(u32, ty.castTag(.vector).?.data.len),
3385 .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),3480 .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),
3481 .anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len),
3386 else => unreachable,3482 else => unreachable,
3387 };3483 };
3388 }3484 }
...@@ -3849,8 +3945,8 @@ pub const Type = extern union {...@@ -3849,8 +3945,8 @@ pub const Type = extern union {
3849 return Value.initTag(.empty_struct_value);3945 return Value.initTag(.empty_struct_value);
3850 },3946 },
38513947
3852 .tuple => {3948 .tuple, .anon_struct => {
3853 const tuple = ty.castTag(.tuple).?.data;3949 const tuple = ty.tupleFields();
3854 for (tuple.values) |val| {3950 for (tuple.values) |val| {
3855 if (val.tag() == .unreachable_value) {3951 if (val.tag() == .unreachable_value) {
3856 return null; // non-comptime field3952 return null; // non-comptime field
...@@ -4048,8 +4144,8 @@ pub const Type = extern union {...@@ -4048,8 +4144,8 @@ pub const Type = extern union {
4048 return ty.optionalChild(&buf).comptimeOnly();4144 return ty.optionalChild(&buf).comptimeOnly();
4049 },4145 },
40504146
4051 .tuple => {4147 .tuple, .anon_struct => {
4052 const tuple = ty.castTag(.tuple).?.data;4148 const tuple = ty.tupleFields();
4053 for (tuple.types) |field_ty, i| {4149 for (tuple.types) |field_ty, i| {
4054 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;4150 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
4055 if (!have_comptime_val and field_ty.comptimeOnly()) return true;4151 if (!have_comptime_val and field_ty.comptimeOnly()) return true;
...@@ -4350,6 +4446,7 @@ pub const Type = extern union {...@@ -4350,6 +4446,7 @@ pub const Type = extern union {
4350 },4446 },
4351 .empty_struct, .empty_struct_literal => return 0,4447 .empty_struct, .empty_struct_literal => return 0,
4352 .tuple => return ty.castTag(.tuple).?.data.types.len,4448 .tuple => return ty.castTag(.tuple).?.data.types.len,
4449 .anon_struct => return ty.castTag(.anon_struct).?.data.types.len,
4353 else => unreachable,4450 else => unreachable,
4354 }4451 }
4355 }4452 }
...@@ -4366,6 +4463,7 @@ pub const Type = extern union {...@@ -4366,6 +4463,7 @@ pub const Type = extern union {
4366 return union_obj.fields.values()[index].ty;4463 return union_obj.fields.values()[index].ty;
4367 },4464 },
4368 .tuple => return ty.castTag(.tuple).?.data.types[index],4465 .tuple => return ty.castTag(.tuple).?.data.types[index],
4466 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
4369 else => unreachable,4467 else => unreachable,
4370 }4468 }
4371 }4469 }
...@@ -4424,8 +4522,8 @@ pub const Type = extern union {...@@ -4424,8 +4522,8 @@ pub const Type = extern union {
4424 return std.mem.alignForwardGeneric(u64, it.offset, it.big_align);4522 return std.mem.alignForwardGeneric(u64, it.offset, it.big_align);
4425 },4523 },
44264524
4427 .tuple => {4525 .tuple, .anon_struct => {
4428 const tuple = ty.castTag(.tuple).?.data;4526 const tuple = ty.tupleFields();
44294527
4430 var offset: u64 = 0;4528 var offset: u64 = 0;
4431 var big_align: u32 = 0;4529 var big_align: u32 = 0;
...@@ -4700,6 +4798,8 @@ pub const Type = extern union {...@@ -4700,6 +4798,8 @@ pub const Type = extern union {
4700 vector,4798 vector,
4701 /// Possible Value tags for this: @"struct"4799 /// Possible Value tags for this: @"struct"
4702 tuple,4800 tuple,
4801 /// Possible Value tags for this: @"struct"
4802 anon_struct,
4703 pointer,4803 pointer,
4704 single_const_pointer,4804 single_const_pointer,
4705 single_mut_pointer,4805 single_mut_pointer,
...@@ -4846,6 +4946,7 @@ pub const Type = extern union {...@@ -4846,6 +4946,7 @@ pub const Type = extern union {
4846 .enum_numbered => Payload.EnumNumbered,4946 .enum_numbered => Payload.EnumNumbered,
4847 .empty_struct => Payload.ContainerScope,4947 .empty_struct => Payload.ContainerScope,
4848 .tuple => Payload.Tuple,4948 .tuple => Payload.Tuple,
4949 .anon_struct => Payload.AnonStruct,
4849 };4950 };
4850 }4951 }
48514952
...@@ -4869,12 +4970,26 @@ pub const Type = extern union {...@@ -4869,12 +4970,26 @@ pub const Type = extern union {
4869 };4970 };
48704971
4871 pub fn isTuple(ty: Type) bool {4972 pub fn isTuple(ty: Type) bool {
4872 return ty.tag() == .tuple or ty.tag() == .empty_struct_literal;4973 return switch (ty.tag()) {
4974 .tuple, .empty_struct_literal => true,
4975 else => false,
4976 };
4977 }
4978
4979 pub fn isTupleOrAnonStruct(ty: Type) bool {
4980 return switch (ty.tag()) {
4981 .tuple, .empty_struct_literal, .anon_struct => true,
4982 else => false,
4983 };
4873 }4984 }
48744985
4875 pub fn tupleFields(ty: Type) Payload.Tuple.Data {4986 pub fn tupleFields(ty: Type) Payload.Tuple.Data {
4876 return switch (ty.tag()) {4987 return switch (ty.tag()) {
4877 .tuple => ty.castTag(.tuple).?.data,4988 .tuple => ty.castTag(.tuple).?.data,
4989 .anon_struct => .{
4990 .types = ty.castTag(.anon_struct).?.data.types,
4991 .values = ty.castTag(.anon_struct).?.data.values,
4992 },
4878 .empty_struct_literal => .{ .types = &.{}, .values = &.{} },4993 .empty_struct_literal => .{ .types = &.{}, .values = &.{} },
4879 else => unreachable,4994 else => unreachable,
4880 };4995 };
...@@ -5042,6 +5157,18 @@ pub const Type = extern union {...@@ -5042,6 +5157,18 @@ pub const Type = extern union {
5042 };5157 };
5043 };5158 };
50445159
5160 pub const AnonStruct = struct {
5161 base: Payload = .{ .tag = .anon_struct },
5162 data: Data,
5163
5164 pub const Data = struct {
5165 names: []const []const u8,
5166 types: []Type,
5167 /// unreachable_value elements are used to indicate runtime-known.
5168 values: []Value,
5169 };
5170 };
5171
5045 pub const Union = struct {5172 pub const Union = struct {
5046 base: Payload,5173 base: Payload,
5047 data: *Module.Union,5174 data: *Module.Union,
src/value.zig+2-2
...@@ -1895,7 +1895,7 @@ pub const Value = extern union {...@@ -1895,7 +1895,7 @@ pub const Value = extern union {
1895 const a_field_vals = a.castTag(.@"struct").?.data;1895 const a_field_vals = a.castTag(.@"struct").?.data;
1896 const b_field_vals = b.castTag(.@"struct").?.data;1896 const b_field_vals = b.castTag(.@"struct").?.data;
1897 assert(a_field_vals.len == b_field_vals.len);1897 assert(a_field_vals.len == b_field_vals.len);
1898 if (ty.isTuple()) {1898 if (ty.isTupleOrAnonStruct()) {
1899 const types = ty.tupleFields().types;1899 const types = ty.tupleFields().types;
1900 assert(types.len == a_field_vals.len);1900 assert(types.len == a_field_vals.len);
1901 for (types) |field_ty, i| {1901 for (types) |field_ty, i| {
...@@ -2031,7 +2031,7 @@ pub const Value = extern union {...@@ -2031,7 +2031,7 @@ pub const Value = extern union {
2031 }2031 }
2032 },2032 },
2033 .Struct => {2033 .Struct => {
2034 if (ty.isTuple()) {2034 if (ty.isTupleOrAnonStruct()) {
2035 const fields = ty.tupleFields();2035 const fields = ty.tupleFields();
2036 for (fields.values) |field_val, i| {2036 for (fields.values) |field_val, i| {
2037 field_val.hash(fields.types[i], hasher);2037 field_val.hash(fields.types[i], hasher);
test/behavior.zig+7-7
...@@ -65,19 +65,20 @@ test {...@@ -65,19 +65,20 @@ test {
65 _ = @import("behavior/inttoptr.zig");65 _ = @import("behavior/inttoptr.zig");
66 _ = @import("behavior/ir_block_deps.zig");66 _ = @import("behavior/ir_block_deps.zig");
67 _ = @import("behavior/member_func.zig");67 _ = @import("behavior/member_func.zig");
68 _ = @import("behavior/muladd.zig");
68 _ = @import("behavior/namespace_depends_on_compile_var.zig");69 _ = @import("behavior/namespace_depends_on_compile_var.zig");
69 _ = @import("behavior/null.zig");70 _ = @import("behavior/null.zig");
70 _ = @import("behavior/optional.zig");71 _ = @import("behavior/optional.zig");
71 _ = @import("behavior/prefetch.zig");
72 _ = @import("behavior/pointers.zig");72 _ = @import("behavior/pointers.zig");
73 _ = @import("behavior/pub_enum.zig");73 _ = @import("behavior/prefetch.zig");
74 _ = @import("behavior/ptrcast.zig");74 _ = @import("behavior/ptrcast.zig");
75 _ = @import("behavior/reflection.zig");75 _ = @import("behavior/pub_enum.zig");
76 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");76 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
77 _ = @import("behavior/reflection.zig");
77 _ = @import("behavior/slice.zig");78 _ = @import("behavior/slice.zig");
78 _ = @import("behavior/slice_sentinel_comptime.zig");79 _ = @import("behavior/slice_sentinel_comptime.zig");
79 _ = @import("behavior/struct.zig");
80 _ = @import("behavior/src.zig");80 _ = @import("behavior/src.zig");
81 _ = @import("behavior/struct.zig");
81 _ = @import("behavior/this.zig");82 _ = @import("behavior/this.zig");
82 _ = @import("behavior/truncate.zig");83 _ = @import("behavior/truncate.zig");
83 _ = @import("behavior/try.zig");84 _ = @import("behavior/try.zig");
...@@ -135,6 +136,7 @@ test {...@@ -135,6 +136,7 @@ test {
135 _ = @import("behavior/bugs/5398.zig");136 _ = @import("behavior/bugs/5398.zig");
136 _ = @import("behavior/bugs/5413.zig");137 _ = @import("behavior/bugs/5413.zig");
137 _ = @import("behavior/bugs/5487.zig");138 _ = @import("behavior/bugs/5487.zig");
139 _ = @import("behavior/bugs/7003.zig");
138 _ = @import("behavior/struct_contains_null_ptr_itself.zig");140 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
139 _ = @import("behavior/switch_prong_err_enum.zig");141 _ = @import("behavior/switch_prong_err_enum.zig");
140 _ = @import("behavior/switch_prong_implicit_cast.zig");142 _ = @import("behavior/switch_prong_implicit_cast.zig");
...@@ -156,14 +158,12 @@ test {...@@ -156,14 +158,12 @@ test {
156 _ = @import("behavior/bugs/3779.zig");158 _ = @import("behavior/bugs/3779.zig");
157 _ = @import("behavior/bugs/6456.zig");159 _ = @import("behavior/bugs/6456.zig");
158 _ = @import("behavior/bugs/6781.zig");160 _ = @import("behavior/bugs/6781.zig");
159 _ = @import("behavior/bugs/7003.zig");
160 _ = @import("behavior/bugs/7027.zig");161 _ = @import("behavior/bugs/7027.zig");
161 _ = @import("behavior/bugs/7047.zig");162 _ = @import("behavior/bugs/7047.zig");
162 _ = @import("behavior/bugs/10147.zig");163 _ = @import("behavior/bugs/10147.zig");
163 _ = @import("behavior/const_slice_child.zig");164 _ = @import("behavior/const_slice_child.zig");
165 _ = @import("behavior/export.zig");
164 _ = @import("behavior/export_self_referential_type_info.zig");166 _ = @import("behavior/export_self_referential_type_info.zig");
165 _ = @import("behavior/misc.zig");
166 _ = @import("behavior/muladd.zig");
167 _ = @import("behavior/select.zig");167 _ = @import("behavior/select.zig");
168 _ = @import("behavior/shuffle.zig");168 _ = @import("behavior/shuffle.zig");
169 _ = @import("behavior/struct_contains_slice_of_itself.zig");169 _ = @import("behavior/struct_contains_slice_of_itself.zig");
test/behavior/enum.zig-16
...@@ -972,22 +972,6 @@ test "enum literal casting to error union with payload enum" {...@@ -972,22 +972,6 @@ test "enum literal casting to error union with payload enum" {
972 try expect((try bar) == Bar.B);972 try expect((try bar) == Bar.B);
973}973}
974974
975test "exporting enum type and value" {
976 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
977
978 const S = struct {
979 const E = enum(c_int) { one, two };
980 comptime {
981 @export(E, .{ .name = "E" });
982 }
983 const e: E = .two;
984 comptime {
985 @export(e, .{ .name = "e" });
986 }
987 };
988 try expect(S.e == .two);
989}
990
991test "constant enum initialization with differing sizes" {975test "constant enum initialization with differing sizes" {
992 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;976 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
993 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;977 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
test/behavior/export.zig created+50
...@@ -0,0 +1,50 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqualStrings = std.testing.expectEqualStrings;
5const mem = std.mem;
6const builtin = @import("builtin");
7
8// can't really run this test but we can make sure it has no compile error
9// and generates code
10const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
11export fn writeToVRam() void {
12 vram[0] = 'X';
13}
14
15const PackedStruct = packed struct {
16 a: u8,
17 b: u8,
18};
19const PackedUnion = packed union {
20 a: u8,
21 b: u32,
22};
23
24test "packed struct, enum, union parameters in extern function" {
25 testPackedStuff(&(PackedStruct{
26 .a = 1,
27 .b = 2,
28 }), &(PackedUnion{ .a = 1 }));
29}
30
31export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
32 if (false) {
33 a;
34 b;
35 }
36}
37
38test "exporting enum type and value" {
39 const S = struct {
40 const E = enum(c_int) { one, two };
41 comptime {
42 @export(E, .{ .name = "E" });
43 }
44 const e: E = .two;
45 comptime {
46 @export(e, .{ .name = "e" });
47 }
48 };
49 try expect(S.e == .two);
50}
test/behavior/misc.zig deleted-36
...@@ -1,36 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqualStrings = std.testing.expectEqualStrings;
5const mem = std.mem;
6const builtin = @import("builtin");
7
8// can't really run this test but we can make sure it has no compile error
9// and generates code
10const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
11export fn writeToVRam() void {
12 vram[0] = 'X';
13}
14
15const PackedStruct = packed struct {
16 a: u8,
17 b: u8,
18};
19const PackedUnion = packed union {
20 a: u8,
21 b: u32,
22};
23
24test "packed struct, enum, union parameters in extern function" {
25 testPackedStuff(&(PackedStruct{
26 .a = 1,
27 .b = 2,
28 }), &(PackedUnion{ .a = 1 }));
29}
30
31export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
32 if (false) {
33 a;
34 b;
35 }
36}
test/behavior/muladd.zig+34-12
...@@ -2,6 +2,8 @@ const builtin = @import("builtin");...@@ -2,6 +2,8 @@ const builtin = @import("builtin");
2const expect = @import("std").testing.expect;2const expect = @import("std").testing.expect;
33
4test "@mulAdd" {4test "@mulAdd" {
5 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
6
5 comptime try testMulAdd();7 comptime try testMulAdd();
6 try testMulAdd();8 try testMulAdd();
7}9}
...@@ -25,20 +27,40 @@ fn testMulAdd() !void {...@@ -25,20 +27,40 @@ fn testMulAdd() !void {
25 var c: f64 = 6.25;27 var c: f64 = 6.25;
26 try expect(@mulAdd(f64, a, b, c) == 20);28 try expect(@mulAdd(f64, a, b, c) == 20);
27 }29 }
28 // {30}
29 // var a: f16 = 5.5;31
30 // var b: f80 = 2.5;32test "@mulAdd f80" {
31 // var c: f80 = 6.25;33 if (true) {
32 // try expect(@mulAdd(f80, a, b, c) == 20);34 // https://github.com/ziglang/zig/issues/11030
33 // }35 return error.SkipZigTest;
36 }
37
38 comptime try testMulAdd80();
39 try testMulAdd80();
40}
41
42fn testMulAdd80() !void {
43 var a: f16 = 5.5;
44 var b: f80 = 2.5;
45 var c: f80 = 6.25;
46 try expect(@mulAdd(f80, a, b, c) == 20);
47}
48
49test "@mulAdd f128" {
50 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
51
34 if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) {52 if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) {
35 // https://github.com/ziglang/zig/issues/990053 // https://github.com/ziglang/zig/issues/9900
36 return error.SkipZigTest;54 return error.SkipZigTest;
37 }55 }
38 {56
39 var a: f16 = 5.5;57 comptime try testMullAdd128();
40 var b: f128 = 2.5;58 try testMullAdd128();
41 var c: f128 = 6.25;59}
42 try expect(@mulAdd(f128, a, b, c) == 20);60
43 }61fn testMullAdd128() !void {
62 var a: f16 = 5.5;
63 var b: f128 = 2.5;
64 var c: f128 = 6.25;
65 try expect(@mulAdd(f128, a, b, c) == 20);
44}66}
test/behavior/src.zig+3-1
...@@ -14,7 +14,9 @@ const builtin = @import("builtin");...@@ -14,7 +14,9 @@ const builtin = @import("builtin");
14const expect = std.testing.expect;14const expect = std.testing.expect;
1515
16test "@src" {16test "@src" {
17 if (builtin.zig_backend != .stage1) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1820
19 try doTheTest();21 try doTheTest();
20}22}
test/behavior/struct.zig+5-3
...@@ -930,7 +930,9 @@ test "anonymous struct literal syntax" {...@@ -930,7 +930,9 @@ test "anonymous struct literal syntax" {
930}930}
931931
932test "fully anonymous struct" {932test "fully anonymous struct" {
933 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO933 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
934 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
935 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
934936
935 const S = struct {937 const S = struct {
936 fn doTheTest() !void {938 fn doTheTest() !void {
...@@ -974,7 +976,7 @@ test "fully anonymous list literal" {...@@ -974,7 +976,7 @@ test "fully anonymous list literal" {
974 comptime try S.doTheTest();976 comptime try S.doTheTest();
975}977}
976978
977test "anonymous struct literal assigned to variable" {979test "tuple assigned to variable" {
978 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO980 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
979981
980 var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };982 var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
...@@ -995,7 +997,7 @@ test "comptime struct field" {...@@ -995,7 +997,7 @@ test "comptime struct field" {
995 comptime try expect(foo.b == 1234);997 comptime try expect(foo.b == 1234);
996}998}
997999
998test "anon struct literal field value initialized with fn call" {1000test "tuple element initialized with fn call" {
999 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1001 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
10001002
1001 const S = struct {1003 const S = struct {
test/behavior/type_info.zig+6-2
...@@ -503,9 +503,13 @@ test "Struct.is_tuple for anon list literal" {...@@ -503,9 +503,13 @@ test "Struct.is_tuple for anon list literal" {
503}503}
504504
505test "Struct.is_tuple for anon struct literal" {505test "Struct.is_tuple for anon struct literal" {
506 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO506 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
507509
508 try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);510 const info = @typeInfo(@TypeOf(.{ .a = 0 }));
511 try expect(!info.Struct.is_tuple);
512 try expect(std.mem.eql(u8, info.Struct.fields[0].name, "a"));
509}513}
510514
511test "StructField.is_comptime" {515test "StructField.is_comptime" {