authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-19 04:56:08-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-19 04:56:08-04:00
log2ccaa5414b904edb2f4af293291f5401d106f277
treed587757486c1ae205629c48540b66858ec6fb62a
parent7d674d5fb664b6e2d4d3d5b85751ed464dc4c4b9
parent150786e83c705a34e16f031b7848a440946b2ef9
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12145 from ziglang/fixes

More ABI size and alignment fixes

22 files changed, 266 insertions(+), 156 deletions(-)

lib/std/target.zig+24-23
......@@ -9,6 +9,7 @@ pub const Target = struct {
99 cpu: Cpu,
1010 os: Os,
1111 abi: Abi,
12 ofmt: ObjectFormat,
1213
1314 pub const Os = struct {
1415 tag: Tag,
......@@ -594,6 +595,20 @@ pub const Target = struct {
594595 .nvptx => ".ptx",
595596 };
596597 }
598
599 pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat {
600 return switch (os_tag) {
601 .windows, .uefi => .coff,
602 .ios, .macos, .watchos, .tvos => .macho,
603 .plan9 => .plan9,
604 else => return switch (cpu_arch) {
605 .wasm32, .wasm64 => .wasm,
606 .spirv32, .spirv64 => .spirv,
607 .nvptx, .nvptx64 => .nvptx,
608 else => .elf,
609 },
610 };
611 }
597612 };
598613
599614 pub const SubSystem = enum {
......@@ -1381,24 +1396,6 @@ pub const Target = struct {
13811396 return libPrefix_os_abi(self.os.tag, self.abi);
13821397 }
13831398
1384 pub fn getObjectFormatSimple(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat {
1385 return switch (os_tag) {
1386 .windows, .uefi => .coff,
1387 .ios, .macos, .watchos, .tvos => .macho,
1388 .plan9 => .plan9,
1389 else => return switch (cpu_arch) {
1390 .wasm32, .wasm64 => .wasm,
1391 .spirv32, .spirv64 => .spirv,
1392 .nvptx, .nvptx64 => .nvptx,
1393 else => .elf,
1394 },
1395 };
1396 }
1397
1398 pub fn getObjectFormat(self: Target) ObjectFormat {
1399 return getObjectFormatSimple(self.os.tag, self.cpu.arch);
1400 }
1401
14021399 pub fn isMinGW(self: Target) bool {
14031400 return self.os.tag == .windows and self.isGnu();
14041401 }
......@@ -1806,24 +1803,28 @@ pub const Target = struct {
18061803 else => 4,
18071804 },
18081805
1809 // For x86_64, LLVMABIAlignmentOfType(i128) reports 8. However I think 16
1810 // is a better number for two reasons:
1811 // 1. Better machine code when loading into SIMD register.
1806 // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
1807 // is a relevant number in three cases:
1808 // 1. Different machine code instruction when loading into SIMD register.
18121809 // 2. The C ABI wants 16 for extern structs.
18131810 // 3. 16-byte cmpxchg needs 16-byte alignment.
1814 // Same logic for riscv64, powerpc64, mips64, sparc64.
1811 // Same logic for powerpc64, mips64, sparc64.
18151812 .x86_64,
1816 .riscv64,
18171813 .powerpc64,
18181814 .powerpc64le,
18191815 .mips64,
18201816 .mips64el,
18211817 .sparc64,
1818 => return switch (target.ofmt) {
1819 .c => 16,
1820 else => 8,
1821 },
18221822
18231823 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
18241824 .aarch64,
18251825 .aarch64_be,
18261826 .aarch64_32,
1827 .riscv64,
18271828 .bpfel,
18281829 .bpfeb,
18291830 .nvptx,
lib/std/zig.zig+7-5
......@@ -103,7 +103,6 @@ pub const BinNameOptions = struct {
103103 target: std.Target,
104104 output_mode: std.builtin.OutputMode,
105105 link_mode: ?std.builtin.LinkMode = null,
106 object_format: ?std.Target.ObjectFormat = null,
107106 version: ?std.builtin.Version = null,
108107};
109108
......@@ -111,8 +110,7 @@ pub const BinNameOptions = struct {
111110pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 {
112111 const root_name = options.root_name;
113112 const target = options.target;
114 const ofmt = options.object_format orelse target.getObjectFormat();
115 switch (ofmt) {
113 switch (target.ofmt) {
116114 .coff => switch (options.output_mode) {
117115 .Exe => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, target.exeFileExt() }),
118116 .Lib => {
......@@ -186,8 +184,12 @@ pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error
186184 .raw => return std.fmt.allocPrint(allocator, "{s}.bin", .{root_name}),
187185 .plan9 => switch (options.output_mode) {
188186 .Exe => return allocator.dupe(u8, root_name),
189 .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, ofmt.fileExt(target.cpu.arch) }),
190 .Lib => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ target.libPrefix(), root_name }),
187 .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{
188 root_name, target.ofmt.fileExt(target.cpu.arch),
189 }),
190 .Lib => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{
191 target.libPrefix(), root_name,
192 }),
191193 },
192194 .nvptx => return std.fmt.allocPrint(allocator, "{s}", .{root_name}),
193195 }
lib/std/zig/CrossTarget.zig+12-1
......@@ -42,6 +42,9 @@ abi: ?Target.Abi = null,
4242/// based on the `os_tag`.
4343dynamic_linker: DynamicLinker = DynamicLinker{},
4444
45/// `null` means default for the cpu/arch/os combo.
46ofmt: ?Target.ObjectFormat = null,
47
4548pub const CpuModel = union(enum) {
4649 /// Always native
4750 native,
......@@ -168,6 +171,7 @@ pub fn toTarget(self: CrossTarget) Target {
168171 .cpu = self.getCpu(),
169172 .os = self.getOs(),
170173 .abi = self.getAbi(),
174 .ofmt = self.getObjectFormat(),
171175 };
172176}
173177
......@@ -197,6 +201,8 @@ pub const ParseOptions = struct {
197201 /// detected path, or a standard path.
198202 dynamic_linker: ?[]const u8 = null,
199203
204 object_format: ?[]const u8 = null,
205
200206 /// If this is provided, the function will populate some information about parsing failures,
201207 /// so that user-friendly error messages can be delivered.
202208 diagnostics: ?*Diagnostics = null,
......@@ -321,6 +327,11 @@ pub fn parse(args: ParseOptions) !CrossTarget {
321327 }
322328 }
323329
330 if (args.object_format) |ofmt_name| {
331 result.ofmt = std.meta.stringToEnum(Target.ObjectFormat, ofmt_name) orelse
332 return error.UnknownObjectFormat;
333 }
334
324335 return result;
325336}
326337
......@@ -620,7 +631,7 @@ pub fn setGnuLibCVersion(self: *CrossTarget, major: u32, minor: u32, patch: u32)
620631}
621632
622633pub fn getObjectFormat(self: CrossTarget) Target.ObjectFormat {
623 return Target.getObjectFormatSimple(self.getOsTag(), self.getCpuArch());
634 return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch());
624635}
625636
626637pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void {
lib/std/zig/system/NativeTargetInfo.zig+5
......@@ -276,6 +276,7 @@ fn detectAbiAndDynamicLinker(
276276 };
277277 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;
278278 var ld_info_list_len: usize = 0;
279 const ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch);
279280
280281 for (all_abis) |abi| {
281282 // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and
......@@ -284,6 +285,7 @@ fn detectAbiAndDynamicLinker(
284285 .cpu = cpu,
285286 .os = os,
286287 .abi = abi,
288 .ofmt = ofmt,
287289 };
288290 const ld = target.standardDynamicLinkerPath();
289291 if (ld.get() == null) continue;
......@@ -346,6 +348,7 @@ fn detectAbiAndDynamicLinker(
346348 .cpu = cpu,
347349 .os = os_adjusted,
348350 .abi = cross_target.abi orelse found_ld_info.abi,
351 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os_adjusted.tag, cpu.arch),
349352 },
350353 .dynamic_linker = if (cross_target.dynamic_linker.get() == null)
351354 DynamicLinker.init(found_ld_path)
......@@ -539,6 +542,7 @@ pub fn abiAndDynamicLinkerFromFile(
539542 .cpu = cpu,
540543 .os = os,
541544 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
545 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
542546 },
543547 .dynamic_linker = cross_target.dynamic_linker,
544548 };
......@@ -829,6 +833,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, cross_target: Cros
829833 .cpu = cpu,
830834 .os = os,
831835 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
836 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
832837 };
833838 return NativeTargetInfo{
834839 .target = target,
src/Compilation.zig+15-15
......@@ -810,7 +810,6 @@ pub const InitOptions = struct {
810810 /// this flag would be set to disable this machinery to avoid false positives.
811811 disable_lld_caching: bool = false,
812812 cache_mode: CacheMode = .incremental,
813 object_format: ?std.Target.ObjectFormat = null,
814813 optimize_mode: std.builtin.Mode = .Debug,
815814 keep_source_files_loaded: bool = false,
816815 clang_argv: []const []const u8 = &[0][]const u8{},
......@@ -1027,8 +1026,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
10271026 const comp = try arena.create(Compilation);
10281027 const root_name = try arena.dupeZ(u8, options.root_name);
10291028
1030 const ofmt = options.object_format orelse options.target.getObjectFormat();
1031
10321029 const use_stage1 = options.use_stage1 orelse blk: {
10331030 // Even though we may have no Zig code to compile (depending on `options.main_pkg`),
10341031 // we may need to use stage1 for building compiler-rt and other dependencies.
......@@ -1042,7 +1039,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
10421039 }
10431040
10441041 // If LLVM does not support the target, then we can't use it.
1045 if (!target_util.hasLlvmSupport(options.target, ofmt))
1042 if (!target_util.hasLlvmSupport(options.target, options.target.ofmt))
10461043 break :blk false;
10471044
10481045 break :blk build_options.is_stage1;
......@@ -1072,7 +1069,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
10721069 break :blk true;
10731070
10741071 // If LLVM does not support the target, then we can't use it.
1075 if (!target_util.hasLlvmSupport(options.target, ofmt))
1072 if (!target_util.hasLlvmSupport(options.target, options.target.ofmt))
10761073 break :blk false;
10771074
10781075 // Prefer LLVM for release builds.
......@@ -1115,7 +1112,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
11151112 if (!build_options.have_llvm)
11161113 break :blk false;
11171114
1118 if (ofmt == .c)
1115 if (options.target.ofmt == .c)
11191116 break :blk false;
11201117
11211118 if (options.want_lto) |lto| {
......@@ -1374,7 +1371,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
13741371 cache.hash.add(options.target.os.getVersionRange());
13751372 cache.hash.add(options.is_native_os);
13761373 cache.hash.add(options.target.abi);
1377 cache.hash.add(ofmt);
1374 cache.hash.add(options.target.ofmt);
13781375 cache.hash.add(pic);
13791376 cache.hash.add(pie);
13801377 cache.hash.add(lto);
......@@ -1682,7 +1679,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
16821679 .sysroot = sysroot,
16831680 .output_mode = options.output_mode,
16841681 .link_mode = link_mode,
1685 .object_format = ofmt,
16861682 .optimize_mode = options.optimize_mode,
16871683 .use_lld = use_lld,
16881684 .use_llvm = use_llvm,
......@@ -1841,7 +1837,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
18411837
18421838 const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null;
18431839
1844 if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies) {
1840 if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies and
1841 options.target.ofmt != .c)
1842 {
18451843 if (comp.getTarget().isDarwin()) {
18461844 switch (comp.getTarget().abi) {
18471845 .none,
......@@ -3739,7 +3737,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
37393737 else
37403738 c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len];
37413739
3742 const o_ext = comp.bin_file.options.object_format.fileExt(comp.bin_file.options.target.cpu.arch);
3740 const target = comp.getTarget();
3741 const o_ext = target.ofmt.fileExt(target.cpu.arch);
37433742 const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: {
37443743 var argv = std.ArrayList([]const u8).init(comp.gpa);
37453744 defer argv.deinit();
......@@ -4092,7 +4091,7 @@ pub fn addCCArgs(
40924091
40934092 if (!comp.bin_file.options.strip) {
40944093 try argv.append("-g");
4095 switch (comp.bin_file.options.object_format) {
4094 switch (target.ofmt) {
40964095 .coff => try argv.append("-gcodeview"),
40974096 else => {},
40984097 }
......@@ -4660,7 +4659,7 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {
46604659 };
46614660 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
46624661 comp.bin_file.options.libc_installation == null and
4663 comp.bin_file.options.object_format != .c;
4662 comp.bin_file.options.target.ofmt != .c;
46644663}
46654664
46664665fn wantBuildGLibCFromSource(comp: Compilation) bool {
......@@ -4688,7 +4687,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
46884687 .Exe => true,
46894688 };
46904689 return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind and
4691 comp.bin_file.options.object_format != .c;
4690 comp.bin_file.options.target.ofmt != .c;
46924691}
46934692
46944693fn setAllocFailure(comp: *Compilation) void {
......@@ -4747,7 +4746,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
47474746 const zig_backend: std.builtin.CompilerBackend = blk: {
47484747 if (use_stage1) break :blk .stage1;
47494748 if (build_options.have_llvm and comp.bin_file.options.use_llvm) break :blk .stage2_llvm;
4750 if (comp.bin_file.options.object_format == .c) break :blk .stage2_c;
4749 if (target.ofmt == .c) break :blk .stage2_c;
47514750 break :blk switch (target.cpu.arch) {
47524751 .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm,
47534752 .arm, .armeb, .thumb, .thumbeb => .stage2_arm,
......@@ -4895,6 +4894,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
48954894 \\ .cpu = cpu,
48964895 \\ .os = os,
48974896 \\ .abi = abi,
4897 \\ .ofmt = object_format,
48984898 \\}};
48994899 \\pub const object_format = std.Target.ObjectFormat.{};
49004900 \\pub const mode = std.builtin.Mode.{};
......@@ -4909,7 +4909,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
49094909 \\pub const code_model = std.builtin.CodeModel.{};
49104910 \\
49114911 , .{
4912 std.zig.fmtId(@tagName(comp.bin_file.options.object_format)),
4912 std.zig.fmtId(@tagName(target.ofmt)),
49134913 std.zig.fmtId(@tagName(comp.bin_file.options.optimize_mode)),
49144914 link_libc,
49154915 comp.bin_file.options.link_libcpp,
src/Module.zig+33-5
......@@ -935,13 +935,41 @@ pub const Struct = struct {
935935 /// If true then `default_val` is the comptime field value.
936936 is_comptime: bool,
937937
938 /// Returns the field alignment, assuming the struct is not packed.
939 pub fn normalAlignment(field: Field, target: Target) u32 {
940 if (field.abi_align == 0) {
941 return field.ty.abiAlignment(target);
942 } else {
938 /// Returns the field alignment. If the struct is packed, returns 0.
939 pub fn alignment(
940 field: Field,
941 target: Target,
942 layout: std.builtin.Type.ContainerLayout,
943 ) u32 {
944 if (field.abi_align != 0) {
945 assert(layout != .Packed);
943946 return field.abi_align;
944947 }
948
949 switch (layout) {
950 .Packed => return 0,
951 .Auto => {
952 if (target.ofmt == .c) {
953 return alignmentExtern(field, target);
954 } else {
955 return field.ty.abiAlignment(target);
956 }
957 },
958 .Extern => return alignmentExtern(field, target),
959 }
960 }
961
962 pub fn alignmentExtern(field: Field, target: Target) u32 {
963 // This logic is duplicated in Type.abiAlignmentAdvanced.
964 const ty_abi_align = field.ty.abiAlignment(target);
965
966 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
967 // The C ABI requires 128 bit integer fields of structs
968 // to be 16-bytes aligned.
969 return @maximum(ty_abi_align, 16);
970 }
971
972 return ty_abi_align;
945973 }
946974 };
947975
src/Sema.zig+2-5
......@@ -14380,10 +14380,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1438014380 else
1438114381 field.default_val;
1438214382 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);
14383 const alignment = switch (layout) {
14384 .Auto, .Extern => field.normalAlignment(target),
14385 .Packed => 0,
14386 };
14383 const alignment = field.alignment(target, layout);
1438714384
1438814385 struct_field_fields.* = .{
1438914386 // name: []const u8,
......@@ -20657,7 +20654,7 @@ fn panicWithMsg(
2065720654 const arena = sema.arena;
2065820655
2065920656 const this_feature_is_implemented_in_the_backend =
20660 mod.comp.bin_file.options.object_format == .c or
20657 mod.comp.bin_file.options.target.ofmt == .c or
2066120658 mod.comp.bin_file.options.use_llvm;
2066220659 if (!this_feature_is_implemented_in_the_backend) {
2066320660 // TODO implement this feature in all the backends and then delete this branch
src/codegen/llvm.zig+8-6
......@@ -273,7 +273,7 @@ pub const Object = struct {
273273 var di_compile_unit: ?*llvm.DICompileUnit = null;
274274
275275 if (!options.strip) {
276 switch (options.object_format) {
276 switch (options.target.ofmt) {
277277 .coff => llvm_module.addModuleCodeViewFlag(),
278278 else => llvm_module.addModuleDebugInfoFlag(),
279279 }
......@@ -1841,6 +1841,7 @@ pub const Object = struct {
18411841 }
18421842
18431843 const fields = ty.structFields();
1844 const layout = ty.containerLayout();
18441845
18451846 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
18461847 defer di_fields.deinit(gpa);
......@@ -1854,7 +1855,7 @@ pub const Object = struct {
18541855 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
18551856
18561857 const field_size = field.ty.abiSize(target);
1857 const field_align = field.normalAlignment(target);
1858 const field_align = field.alignment(target, layout);
18581859 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
18591860 offset = field_offset + field_size;
18601861
......@@ -2757,7 +2758,7 @@ pub const DeclGen = struct {
27572758 for (struct_obj.fields.values()) |field| {
27582759 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
27592760
2760 const field_align = field.normalAlignment(target);
2761 const field_align = field.alignment(target, struct_obj.layout);
27612762 const field_ty_align = field.ty.abiAlignment(target);
27622763 any_underaligned_fields = any_underaligned_fields or
27632764 field_align < field_ty_align;
......@@ -3433,7 +3434,7 @@ pub const DeclGen = struct {
34333434 for (struct_obj.fields.values()) |field, i| {
34343435 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
34353436
3436 const field_align = field.normalAlignment(target);
3437 const field_align = field.alignment(target, struct_obj.layout);
34373438 big_align = @maximum(big_align, field_align);
34383439 const prev_offset = offset;
34393440 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
......@@ -9376,13 +9377,14 @@ fn llvmFieldIndex(
93769377 }
93779378 return null;
93789379 }
9379 assert(ty.containerLayout() != .Packed);
9380 const layout = ty.containerLayout();
9381 assert(layout != .Packed);
93809382
93819383 var llvm_field_index: c_uint = 0;
93829384 for (ty.structFields().values()) |field, i| {
93839385 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
93849386
9385 const field_align = field.normalAlignment(target);
9387 const field_align = field.alignment(target, layout);
93869388 big_align = @maximum(big_align, field_align);
93879389 const prev_offset = offset;
93889390 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
src/link.zig+5-6
......@@ -72,7 +72,6 @@ pub const Options = struct {
7272 target: std.Target,
7373 output_mode: std.builtin.OutputMode,
7474 link_mode: std.builtin.LinkMode,
75 object_format: std.Target.ObjectFormat,
7675 optimize_mode: std.builtin.Mode,
7776 machine_code_model: std.builtin.CodeModel,
7877 root_name: [:0]const u8,
......@@ -273,13 +272,13 @@ pub const File = struct {
273272 /// rewriting it. A malicious file is detected as incremental link failure
274273 /// and does not cause Illegal Behavior. This operation is not atomic.
275274 pub fn openPath(allocator: Allocator, options: Options) !*File {
276 if (options.object_format == .macho) {
275 if (options.target.ofmt == .macho) {
277276 return &(try MachO.openPath(allocator, options)).base;
278277 }
279278
280279 const use_stage1 = build_options.is_stage1 and options.use_stage1;
281280 if (use_stage1 or options.emit == null) {
282 return switch (options.object_format) {
281 return switch (options.target.ofmt) {
283282 .coff => &(try Coff.createEmpty(allocator, options)).base,
284283 .elf => &(try Elf.createEmpty(allocator, options)).base,
285284 .macho => unreachable,
......@@ -298,7 +297,7 @@ pub const File = struct {
298297 if (options.module == null) {
299298 // No point in opening a file, we would not write anything to it.
300299 // Initialize with empty.
301 return switch (options.object_format) {
300 return switch (options.target.ofmt) {
302301 .coff => &(try Coff.createEmpty(allocator, options)).base,
303302 .elf => &(try Elf.createEmpty(allocator, options)).base,
304303 .macho => unreachable,
......@@ -314,12 +313,12 @@ pub const File = struct {
314313 // Open a temporary object file, not the final output file because we
315314 // want to link with LLD.
316315 break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{
317 emit.sub_path, options.object_format.fileExt(options.target.cpu.arch),
316 emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch),
318317 });
319318 } else emit.sub_path;
320319 errdefer if (use_lld) allocator.free(sub_path);
321320
322 const file: *File = switch (options.object_format) {
321 const file: *File = switch (options.target.ofmt) {
323322 .coff => &(try Coff.openPath(allocator, sub_path, options)).base,
324323 .elf => &(try Elf.openPath(allocator, sub_path, options)).base,
325324 .macho => unreachable,
src/link/C.zig+1-1
......@@ -48,7 +48,7 @@ const DeclBlock = struct {
4848};
4949
5050pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C {
51 assert(options.object_format == .c);
51 assert(options.target.ofmt == .c);
5252
5353 if (options.use_llvm) return error.LLVMHasNoCBackend;
5454 if (options.use_lld) return error.LLDHasNoCBackend;
src/link/Coff.zig+1-1
......@@ -128,7 +128,7 @@ pub const TextBlock = struct {
128128pub const SrcFn = void;
129129
130130pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Coff {
131 assert(options.object_format == .coff);
131 assert(options.target.ofmt == .coff);
132132
133133 if (build_options.have_llvm and options.use_llvm) {
134134 return createEmpty(allocator, options);
src/link/Elf.zig+1-1
......@@ -249,7 +249,7 @@ pub const Export = struct {
249249};
250250
251251pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Elf {
252 assert(options.object_format == .elf);
252 assert(options.target.ofmt == .elf);
253253
254254 if (build_options.have_llvm and options.use_llvm) {
255255 return createEmpty(allocator, options);
src/link/MachO.zig+2-2
......@@ -270,7 +270,7 @@ pub const Export = struct {
270270};
271271
272272pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
273 assert(options.object_format == .macho);
273 assert(options.target.ofmt == .macho);
274274
275275 const use_stage1 = build_options.is_stage1 and options.use_stage1;
276276 if (use_stage1 or options.emit == null) {
......@@ -289,7 +289,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
289289 // we also want to put the intermediary object file in the cache while the
290290 // main emit directory is the cwd.
291291 self.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{
292 emit.sub_path, options.object_format.fileExt(options.target.cpu.arch),
292 emit.sub_path, options.target.ofmt.fileExt(options.target.cpu.arch),
293293 });
294294 }
295295
src/link/NvPtx.zig+1-1
......@@ -57,7 +57,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx {
5757pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*NvPtx {
5858 if (!build_options.have_llvm) @panic("nvptx target requires a zig compiler with llvm enabled.");
5959 if (!options.use_llvm) return error.PtxArchNotSupported;
60 assert(options.object_format == .nvptx);
60 assert(options.target.ofmt == .nvptx);
6161
6262 const nvptx = try createEmpty(allocator, options);
6363 log.info("Opening .ptx target file {s}", .{sub_path});
src/link/Plan9.zig+1-1
......@@ -657,7 +657,7 @@ pub const base_tag = .plan9;
657657pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 {
658658 if (options.use_llvm)
659659 return error.LLVMBackendDoesNotSupportPlan9;
660 assert(options.object_format == .plan9);
660 assert(options.target.ofmt == .plan9);
661661
662662 const self = try createEmpty(allocator, options);
663663 errdefer self.base.destroy();
src/link/SpirV.zig+1-1
......@@ -99,7 +99,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV {
9999}
100100
101101pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*SpirV {
102 assert(options.object_format == .spirv);
102 assert(options.target.ofmt == .spirv);
103103
104104 if (options.use_llvm) return error.LLVM_BackendIsTODO_ForSpirV; // TODO: LLVM Doesn't support SpirV at all.
105105 if (options.use_lld) return error.LLD_LinkingIsTODO_ForSpirV; // TODO: LLD Doesn't support SpirV at all.
src/link/Wasm.zig+1-1
......@@ -282,7 +282,7 @@ pub const StringTable = struct {
282282};
283283
284284pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Wasm {
285 assert(options.object_format == .wasm);
285 assert(options.target.ofmt == .wasm);
286286
287287 if (build_options.have_llvm and options.use_llvm) {
288288 return createEmpty(allocator, options);
src/main.zig+22-29
......@@ -2192,6 +2192,7 @@ fn buildOutputType(
21922192 .arch_os_abi = target_arch_os_abi,
21932193 .cpu_features = target_mcpu,
21942194 .dynamic_linker = target_dynamic_linker,
2195 .object_format = target_ofmt,
21952196 };
21962197
21972198 // Before passing the mcpu string in for parsing, we convert any -m flags that were
......@@ -2494,28 +2495,7 @@ fn buildOutputType(
24942495 }
24952496 }
24962497
2497 const object_format: std.Target.ObjectFormat = blk: {
2498 const ofmt = target_ofmt orelse break :blk target_info.target.getObjectFormat();
2499 if (mem.eql(u8, ofmt, "elf")) {
2500 break :blk .elf;
2501 } else if (mem.eql(u8, ofmt, "c")) {
2502 break :blk .c;
2503 } else if (mem.eql(u8, ofmt, "coff")) {
2504 break :blk .coff;
2505 } else if (mem.eql(u8, ofmt, "macho")) {
2506 break :blk .macho;
2507 } else if (mem.eql(u8, ofmt, "wasm")) {
2508 break :blk .wasm;
2509 } else if (mem.eql(u8, ofmt, "hex")) {
2510 break :blk .hex;
2511 } else if (mem.eql(u8, ofmt, "raw")) {
2512 break :blk .raw;
2513 } else if (mem.eql(u8, ofmt, "spirv")) {
2514 break :blk .spirv;
2515 } else {
2516 fatal("unsupported object format: {s}", .{ofmt});
2517 }
2518 };
2498 const object_format = target_info.target.ofmt;
25192499
25202500 if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) {
25212501 const total_obj_count = c_source_files.items.len +
......@@ -2569,7 +2549,6 @@ fn buildOutputType(
25692549 .target = target_info.target,
25702550 .output_mode = output_mode,
25712551 .link_mode = link_mode,
2572 .object_format = object_format,
25732552 .version = optional_version,
25742553 }),
25752554 },
......@@ -2859,7 +2838,6 @@ fn buildOutputType(
28592838 .emit_implib = emit_implib_resolved.data,
28602839 .link_mode = link_mode,
28612840 .dll_export_fns = dll_export_fns,
2862 .object_format = object_format,
28632841 .optimize_mode = optimize_mode,
28642842 .keep_source_files_loaded = false,
28652843 .clang_argv = clang_argv.items,
......@@ -3173,11 +3151,11 @@ fn parseCrossTargetOrReportFatalError(
31733151 for (diags.arch.?.allCpuModels()) |cpu| {
31743152 help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help;
31753153 }
3176 std.log.info("Available CPUs for architecture '{s}':\n{s}", .{
3154 std.log.info("available CPUs for architecture '{s}':\n{s}", .{
31773155 @tagName(diags.arch.?), help_text.items,
31783156 });
31793157 }
3180 fatal("Unknown CPU: '{s}'", .{diags.cpu_name.?});
3158 fatal("unknown CPU: '{s}'", .{diags.cpu_name.?});
31813159 },
31823160 error.UnknownCpuFeature => {
31833161 help: {
......@@ -3186,11 +3164,26 @@ fn parseCrossTargetOrReportFatalError(
31863164 for (diags.arch.?.allFeaturesList()) |feature| {
31873165 help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help;
31883166 }
3189 std.log.info("Available CPU features for architecture '{s}':\n{s}", .{
3167 std.log.info("available CPU features for architecture '{s}':\n{s}", .{
31903168 @tagName(diags.arch.?), help_text.items,
31913169 });
31923170 }
3193 fatal("Unknown CPU feature: '{s}'", .{diags.unknown_feature_name.?});
3171 fatal("unknown CPU feature: '{s}'", .{diags.unknown_feature_name.?});
3172 },
3173 error.UnknownObjectFormat => {
3174 {
3175 var help_text = std.ArrayList(u8).init(allocator);
3176 defer help_text.deinit();
3177 inline for (@typeInfo(std.Target.ObjectFormat).Enum.fields) |field| {
3178 help_text.writer().print(" {s}\n", .{field.name}) catch
3179 // TODO change this back to `break :help`
3180 // this working around a stage1 bug.
3181 //break :help;
3182 @panic("out of memory");
3183 }
3184 std.log.info("available object formats:\n{s}", .{help_text.items});
3185 }
3186 fatal("unknown object format: '{s}'", .{opts.object_format.?});
31943187 },
31953188 else => |e| return e,
31963189 };
......@@ -3360,7 +3353,7 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void
33603353
33613354 // If a .pdb file is part of the expected output, we must also copy
33623355 // it into place here.
3363 const is_coff = comp.bin_file.options.object_format == .coff;
3356 const is_coff = comp.bin_file.options.target.ofmt == .coff;
33643357 const have_pdb = is_coff and !comp.bin_file.options.strip;
33653358 if (have_pdb) {
33663359 // Replace `.out` or `.exe` with `.pdb` on both the source and destination
src/stage1/codegen.cpp+1
......@@ -10082,6 +10082,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
1008210082 " .cpu = cpu,\n"
1008310083 " .os = os,\n"
1008410084 " .abi = abi,\n"
10085 " .ofmt = object_format,\n"
1008510086 "};\n"
1008610087 );
1008710088
src/test.zig+7-8
......@@ -606,7 +606,6 @@ pub const TestContext = struct {
606606 output_mode: std.builtin.OutputMode,
607607 optimize_mode: std.builtin.Mode = .Debug,
608608 updates: std.ArrayList(Update),
609 object_format: ?std.Target.ObjectFormat = null,
610609 emit_h: bool = false,
611610 is_test: bool = false,
612611 expect_exact: bool = false,
......@@ -782,12 +781,13 @@ pub const TestContext = struct {
782781 pub fn exeFromCompiledC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case {
783782 const prefixed_name = std.fmt.allocPrint(ctx.arena, "CBE: {s}", .{name}) catch
784783 @panic("out of memory");
784 var target_adjusted = target;
785 target_adjusted.ofmt = std.Target.ObjectFormat.c;
785786 ctx.cases.append(Case{
786787 .name = prefixed_name,
787 .target = target,
788 .target = target_adjusted,
788789 .updates = std.ArrayList(Update).init(ctx.cases.allocator),
789790 .output_mode = .Exe,
790 .object_format = .c,
791791 .files = std.ArrayList(File).init(ctx.arena),
792792 }) catch @panic("out of memory");
793793 return &ctx.cases.items[ctx.cases.items.len - 1];
......@@ -851,12 +851,13 @@ pub const TestContext = struct {
851851
852852 /// Adds a test case for Zig or ZIR input, producing C code.
853853 pub fn addC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case {
854 var target_adjusted = target;
855 target_adjusted.ofmt = std.Target.ObjectFormat.c;
854856 ctx.cases.append(Case{
855857 .name = name,
856 .target = target,
858 .target = target_adjusted,
857859 .updates = std.ArrayList(Update).init(ctx.cases.allocator),
858860 .output_mode = .Obj,
859 .object_format = .c,
860861 .files = std.ArrayList(File).init(ctx.arena),
861862 }) catch @panic("out of memory");
862863 return &ctx.cases.items[ctx.cases.items.len - 1];
......@@ -1501,7 +1502,6 @@ pub const TestContext = struct {
15011502 .root_name = "test_case",
15021503 .target = target,
15031504 .output_mode = case.output_mode,
1504 .object_format = case.object_format,
15051505 });
15061506
15071507 const emit_directory: Compilation.Directory = .{
......@@ -1537,7 +1537,6 @@ pub const TestContext = struct {
15371537 .emit_h = emit_h,
15381538 .main_pkg = &main_pkg,
15391539 .keep_source_files_loaded = true,
1540 .object_format = case.object_format,
15411540 .is_native_os = case.target.isNativeOs(),
15421541 .is_native_abi = case.target.isNativeAbi(),
15431542 .dynamic_linker = target_info.dynamic_linker.get(),
......@@ -1782,7 +1781,7 @@ pub const TestContext = struct {
17821781 ".." ++ ss ++ "{s}" ++ ss ++ "{s}",
17831782 .{ &tmp.sub_path, bin_name },
17841783 );
1785 if (case.object_format != null and case.object_format.? == .c) {
1784 if (case.target.ofmt != null and case.target.ofmt.? == .c) {
17861785 if (host.getExternalExecutor(target_info, .{ .link_libc = true }) != .native) {
17871786 // We wouldn't be able to run the compiled C code.
17881787 continue :update; // Pass test.
src/type.zig+74-29
......@@ -2376,6 +2376,32 @@ pub const Type = extern union {
23762376 .error_set_merged,
23772377 => return true,
23782378
2379 // Pointers to zero-bit types still have a runtime address; however, pointers
2380 // to comptime-only types do not, with the exception of function pointers.
2381 .anyframe_T,
2382 .optional_single_mut_pointer,
2383 .optional_single_const_pointer,
2384 .single_const_pointer,
2385 .single_mut_pointer,
2386 .many_const_pointer,
2387 .many_mut_pointer,
2388 .c_const_pointer,
2389 .c_mut_pointer,
2390 .const_slice,
2391 .mut_slice,
2392 .pointer,
2393 => {
2394 if (ignore_comptime_only) {
2395 return true;
2396 } else if (ty.childType().zigTypeTag() == .Fn) {
2397 return true;
2398 } else if (sema_kit) |sk| {
2399 return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));
2400 } else {
2401 return !comptimeOnly(ty);
2402 }
2403 },
2404
23792405 // These are false because they are comptime-only types.
23802406 .single_const_pointer_to_comptime_int,
23812407 .void,
......@@ -2399,30 +2425,6 @@ pub const Type = extern union {
23992425 .fn_ccc_void_no_args,
24002426 => return false,
24012427
2402 // These types have more than one possible value, so the result is the same as
2403 // asking whether they are comptime-only types.
2404 .anyframe_T,
2405 .optional_single_mut_pointer,
2406 .optional_single_const_pointer,
2407 .single_const_pointer,
2408 .single_mut_pointer,
2409 .many_const_pointer,
2410 .many_mut_pointer,
2411 .c_const_pointer,
2412 .c_mut_pointer,
2413 .const_slice,
2414 .mut_slice,
2415 .pointer,
2416 => {
2417 if (ignore_comptime_only) {
2418 return true;
2419 } else if (sema_kit) |sk| {
2420 return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty));
2421 } else {
2422 return !comptimeOnly(ty);
2423 }
2424 },
2425
24262428 .optional => {
24272429 var buf: Payload.ElemType = undefined;
24282430 const child_ty = ty.optionalChild(&buf);
......@@ -3029,6 +3031,15 @@ pub const Type = extern union {
30293031 },
30303032 };
30313033 big_align = @maximum(big_align, field_align);
3034
3035 // This logic is duplicated in Module.Struct.Field.alignment.
3036 if (struct_obj.layout == .Extern or target.ofmt == .c) {
3037 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
3038 // The C ABI requires 128 bit integer fields of structs
3039 // to be 16-bytes aligned.
3040 big_align = @maximum(big_align, 16);
3041 }
3042 }
30323043 }
30333044 return AbiAlignmentAdvanced{ .scalar = big_align };
30343045 },
......@@ -3263,8 +3274,8 @@ pub const Type = extern union {
32633274
32643275 .array_u8 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8).?.data },
32653276 .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 },
3266 .array, .vector => {
3267 const payload = ty.cast(Payload.Array).?.data;
3277 .array => {
3278 const payload = ty.castTag(.array).?.data;
32683279 switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {
32693280 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },
32703281 .val => switch (strat) {
......@@ -3286,6 +3297,28 @@ pub const Type = extern union {
32863297 }
32873298 },
32883299
3300 .vector => {
3301 const payload = ty.castTag(.vector).?.data;
3302 const sema_kit = switch (strat) {
3303 .sema_kit => |sk| sk,
3304 .eager => null,
3305 .lazy => |arena| return AbiSizeAdvanced{
3306 .val = try Value.Tag.lazy_size.create(arena, ty),
3307 },
3308 };
3309 const elem_bits = try payload.elem_type.bitSizeAdvanced(target, sema_kit);
3310 const total_bits = elem_bits * payload.len;
3311 const total_bytes = (total_bits + 7) / 8;
3312 const alignment = switch (try ty.abiAlignmentAdvanced(target, strat)) {
3313 .scalar => |x| x,
3314 .val => return AbiSizeAdvanced{
3315 .val = try Value.Tag.lazy_size.create(strat.lazy, ty),
3316 },
3317 };
3318 const result = std.mem.alignForwardGeneric(u64, total_bytes, alignment);
3319 return AbiSizeAdvanced{ .scalar = result };
3320 },
3321
32893322 .isize,
32903323 .usize,
32913324 .@"anyframe",
......@@ -3329,7 +3362,13 @@ pub const Type = extern union {
33293362 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
33303363
33313364 .f80 => switch (target.cpu.arch) {
3332 .i386 => return AbiSizeAdvanced{ .scalar = 12 },
3365 .i386 => switch (target.os.tag) {
3366 .windows => switch (target.abi) {
3367 .msvc => return AbiSizeAdvanced{ .scalar = 16 },
3368 else => return AbiSizeAdvanced{ .scalar = 12 },
3369 },
3370 else => return AbiSizeAdvanced{ .scalar = 12 },
3371 },
33333372 .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },
33343373 else => {
33353374 var payload: Payload.Bits = .{
......@@ -4540,6 +4579,12 @@ pub const Type = extern union {
45404579
45414580 .vector => ty = ty.castTag(.vector).?.data.elem_type,
45424581
4582 .@"struct" => {
4583 const struct_obj = ty.castTag(.@"struct").?.data;
4584 assert(struct_obj.layout == .Packed);
4585 ty = struct_obj.backing_int_ty;
4586 },
4587
45434588 else => unreachable,
45444589 };
45454590 }
......@@ -5502,7 +5547,7 @@ pub const Type = extern union {
55025547 .@"struct" => {
55035548 const struct_obj = ty.castTag(.@"struct").?.data;
55045549 assert(struct_obj.layout != .Packed);
5505 return struct_obj.fields.values()[index].normalAlignment(target);
5550 return struct_obj.fields.values()[index].alignment(target, struct_obj.layout);
55065551 },
55075552 .@"union", .union_safety_tagged, .union_tagged => {
55085553 const union_obj = ty.cast(Payload.Union).?.data;
......@@ -5609,7 +5654,7 @@ pub const Type = extern union {
56095654 if (!field.ty.hasRuntimeBits() or field.is_comptime)
56105655 return FieldOffset{ .field = it.field, .offset = it.offset };
56115656
5612 const field_align = field.normalAlignment(it.target);
5657 const field_align = field.alignment(it.target, it.struct_obj.layout);
56135658 it.big_align = @maximum(it.big_align, field_align);
56145659 it.offset = std.mem.alignForwardGeneric(u64, it.offset, field_align);
56155660 defer it.offset += field.ty.abiSize(it.target);
test/behavior/align.zig+42-15
......@@ -100,8 +100,8 @@ test "alignment and size of structs with 128-bit fields" {
100100 .a_align = 8,
101101 .a_size = 16,
102102
103 .b_align = 8,
104 .b_size = 24,
103 .b_align = 16,
104 .b_size = 32,
105105
106106 .u128_align = 8,
107107 .u128_size = 16,
......@@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" {
114114 .a_align = 8,
115115 .a_size = 16,
116116
117 .b_align = 8,
118 .b_size = 24,
117 .b_align = 16,
118 .b_size = 32,
119119
120120 .u128_align = 8,
121121 .u128_size = 16,
......@@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" {
126126 .a_align = 4,
127127 .a_size = 16,
128128
129 .b_align = 4,
130 .b_size = 20,
129 .b_align = 16,
130 .b_size = 32,
131131
132132 .u128_align = 4,
133133 .u128_size = 16,
......@@ -140,12 +140,39 @@ test "alignment and size of structs with 128-bit fields" {
140140 .mips64el,
141141 .powerpc64,
142142 .powerpc64le,
143 .riscv64,
144143 .sparc64,
145144 .x86_64,
145 => switch (builtin.object_format) {
146 .c => .{
147 .a_align = 16,
148 .a_size = 16,
149
150 .b_align = 16,
151 .b_size = 32,
152
153 .u128_align = 16,
154 .u128_size = 16,
155 .u129_align = 16,
156 .u129_size = 32,
157 },
158 else => .{
159 .a_align = 8,
160 .a_size = 16,
161
162 .b_align = 16,
163 .b_size = 32,
164
165 .u128_align = 8,
166 .u128_size = 16,
167 .u129_align = 8,
168 .u129_size = 24,
169 },
170 },
171
146172 .aarch64,
147173 .aarch64_be,
148174 .aarch64_32,
175 .riscv64,
149176 .bpfel,
150177 .bpfeb,
151178 .nvptx,
......@@ -166,17 +193,17 @@ test "alignment and size of structs with 128-bit fields" {
166193 else => return error.SkipZigTest,
167194 };
168195 comptime {
169 std.debug.assert(@alignOf(A) == expected.a_align);
170 std.debug.assert(@sizeOf(A) == expected.a_size);
196 assert(@alignOf(A) == expected.a_align);
197 assert(@sizeOf(A) == expected.a_size);
171198
172 std.debug.assert(@alignOf(B) == expected.b_align);
173 std.debug.assert(@sizeOf(B) == expected.b_size);
199 assert(@alignOf(B) == expected.b_align);
200 assert(@sizeOf(B) == expected.b_size);
174201
175 std.debug.assert(@alignOf(u128) == expected.u128_align);
176 std.debug.assert(@sizeOf(u128) == expected.u128_size);
202 assert(@alignOf(u128) == expected.u128_align);
203 assert(@sizeOf(u128) == expected.u128_size);
177204
178 std.debug.assert(@alignOf(u129) == expected.u129_align);
179 std.debug.assert(@sizeOf(u129) == expected.u129_size);
205 assert(@alignOf(u129) == expected.u129_align);
206 assert(@sizeOf(u129) == expected.u129_size);
180207 }
181208}
182209