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 {...@@ -9,6 +9,7 @@ pub const Target = struct {
9 cpu: Cpu,9 cpu: Cpu,
10 os: Os,10 os: Os,
11 abi: Abi,11 abi: Abi,
12 ofmt: ObjectFormat,
1213
13 pub const Os = struct {14 pub const Os = struct {
14 tag: Tag,15 tag: Tag,
...@@ -594,6 +595,20 @@ pub const Target = struct {...@@ -594,6 +595,20 @@ pub const Target = struct {
594 .nvptx => ".ptx",595 .nvptx => ".ptx",
595 };596 };
596 }597 }
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 }
597 };612 };
598613
599 pub const SubSystem = enum {614 pub const SubSystem = enum {
...@@ -1381,24 +1396,6 @@ pub const Target = struct {...@@ -1381,24 +1396,6 @@ pub const Target = struct {
1381 return libPrefix_os_abi(self.os.tag, self.abi);1396 return libPrefix_os_abi(self.os.tag, self.abi);
1382 }1397 }
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
1402 pub fn isMinGW(self: Target) bool {1399 pub fn isMinGW(self: Target) bool {
1403 return self.os.tag == .windows and self.isGnu();1400 return self.os.tag == .windows and self.isGnu();
1404 }1401 }
...@@ -1806,24 +1803,28 @@ pub const Target = struct {...@@ -1806,24 +1803,28 @@ pub const Target = struct {
1806 else => 4,1803 else => 4,
1807 },1804 },
18081805
1809 // For x86_64, LLVMABIAlignmentOfType(i128) reports 8. However I think 161806 // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
1810 // is a better number for two reasons:1807 // is a relevant number in three cases:
1811 // 1. Better machine code when loading into SIMD register.1808 // 1. Different machine code instruction when loading into SIMD register.
1812 // 2. The C ABI wants 16 for extern structs.1809 // 2. The C ABI wants 16 for extern structs.
1813 // 3. 16-byte cmpxchg needs 16-byte alignment.1810 // 3. 16-byte cmpxchg needs 16-byte alignment.
1814 // Same logic for riscv64, powerpc64, mips64, sparc64.1811 // Same logic for powerpc64, mips64, sparc64.
1815 .x86_64,1812 .x86_64,
1816 .riscv64,
1817 .powerpc64,1813 .powerpc64,
1818 .powerpc64le,1814 .powerpc64le,
1819 .mips64,1815 .mips64,
1820 .mips64el,1816 .mips64el,
1821 .sparc64,1817 .sparc64,
1818 => return switch (target.ofmt) {
1819 .c => 16,
1820 else => 8,
1821 },
18221822
1823 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.1823 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1824 .aarch64,1824 .aarch64,
1825 .aarch64_be,1825 .aarch64_be,
1826 .aarch64_32,1826 .aarch64_32,
1827 .riscv64,
1827 .bpfel,1828 .bpfel,
1828 .bpfeb,1829 .bpfeb,
1829 .nvptx,1830 .nvptx,
lib/std/zig.zig+7-5
...@@ -103,7 +103,6 @@ pub const BinNameOptions = struct {...@@ -103,7 +103,6 @@ pub const BinNameOptions = struct {
103 target: std.Target,103 target: std.Target,
104 output_mode: std.builtin.OutputMode,104 output_mode: std.builtin.OutputMode,
105 link_mode: ?std.builtin.LinkMode = null,105 link_mode: ?std.builtin.LinkMode = null,
106 object_format: ?std.Target.ObjectFormat = null,
107 version: ?std.builtin.Version = null,106 version: ?std.builtin.Version = null,
108};107};
109108
...@@ -111,8 +110,7 @@ pub const BinNameOptions = struct {...@@ -111,8 +110,7 @@ pub const BinNameOptions = struct {
111pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 {110pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 {
112 const root_name = options.root_name;111 const root_name = options.root_name;
113 const target = options.target;112 const target = options.target;
114 const ofmt = options.object_format orelse target.getObjectFormat();113 switch (target.ofmt) {
115 switch (ofmt) {
116 .coff => switch (options.output_mode) {114 .coff => switch (options.output_mode) {
117 .Exe => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, target.exeFileExt() }),115 .Exe => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, target.exeFileExt() }),
118 .Lib => {116 .Lib => {
...@@ -186,8 +184,12 @@ pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error...@@ -186,8 +184,12 @@ pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error
186 .raw => return std.fmt.allocPrint(allocator, "{s}.bin", .{root_name}),184 .raw => return std.fmt.allocPrint(allocator, "{s}.bin", .{root_name}),
187 .plan9 => switch (options.output_mode) {185 .plan9 => switch (options.output_mode) {
188 .Exe => return allocator.dupe(u8, root_name),186 .Exe => return allocator.dupe(u8, root_name),
189 .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, ofmt.fileExt(target.cpu.arch) }),187 .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{
190 .Lib => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ target.libPrefix(), root_name }),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 }),
191 },193 },
192 .nvptx => return std.fmt.allocPrint(allocator, "{s}", .{root_name}),194 .nvptx => return std.fmt.allocPrint(allocator, "{s}", .{root_name}),
193 }195 }
lib/std/zig/CrossTarget.zig+12-1
...@@ -42,6 +42,9 @@ abi: ?Target.Abi = null,...@@ -42,6 +42,9 @@ abi: ?Target.Abi = null,
42/// based on the `os_tag`.42/// based on the `os_tag`.
43dynamic_linker: DynamicLinker = DynamicLinker{},43dynamic_linker: DynamicLinker = DynamicLinker{},
4444
45/// `null` means default for the cpu/arch/os combo.
46ofmt: ?Target.ObjectFormat = null,
47
45pub const CpuModel = union(enum) {48pub const CpuModel = union(enum) {
46 /// Always native49 /// Always native
47 native,50 native,
...@@ -168,6 +171,7 @@ pub fn toTarget(self: CrossTarget) Target {...@@ -168,6 +171,7 @@ pub fn toTarget(self: CrossTarget) Target {
168 .cpu = self.getCpu(),171 .cpu = self.getCpu(),
169 .os = self.getOs(),172 .os = self.getOs(),
170 .abi = self.getAbi(),173 .abi = self.getAbi(),
174 .ofmt = self.getObjectFormat(),
171 };175 };
172}176}
173177
...@@ -197,6 +201,8 @@ pub const ParseOptions = struct {...@@ -197,6 +201,8 @@ pub const ParseOptions = struct {
197 /// detected path, or a standard path.201 /// detected path, or a standard path.
198 dynamic_linker: ?[]const u8 = null,202 dynamic_linker: ?[]const u8 = null,
199203
204 object_format: ?[]const u8 = null,
205
200 /// If this is provided, the function will populate some information about parsing failures,206 /// If this is provided, the function will populate some information about parsing failures,
201 /// so that user-friendly error messages can be delivered.207 /// so that user-friendly error messages can be delivered.
202 diagnostics: ?*Diagnostics = null,208 diagnostics: ?*Diagnostics = null,
...@@ -321,6 +327,11 @@ pub fn parse(args: ParseOptions) !CrossTarget {...@@ -321,6 +327,11 @@ pub fn parse(args: ParseOptions) !CrossTarget {
321 }327 }
322 }328 }
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
324 return result;335 return result;
325}336}
326337
...@@ -620,7 +631,7 @@ pub fn setGnuLibCVersion(self: *CrossTarget, major: u32, minor: u32, patch: u32)...@@ -620,7 +631,7 @@ pub fn setGnuLibCVersion(self: *CrossTarget, major: u32, minor: u32, patch: u32)
620}631}
621632
622pub fn getObjectFormat(self: CrossTarget) Target.ObjectFormat {633pub 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());
624}635}
625636
626pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void {637pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void {
lib/std/zig/system/NativeTargetInfo.zig+5
...@@ -276,6 +276,7 @@ fn detectAbiAndDynamicLinker(...@@ -276,6 +276,7 @@ fn detectAbiAndDynamicLinker(
276 };276 };
277 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;277 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;
278 var ld_info_list_len: usize = 0;278 var ld_info_list_len: usize = 0;
279 const ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch);
279280
280 for (all_abis) |abi| {281 for (all_abis) |abi| {
281 // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and282 // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and
...@@ -284,6 +285,7 @@ fn detectAbiAndDynamicLinker(...@@ -284,6 +285,7 @@ fn detectAbiAndDynamicLinker(
284 .cpu = cpu,285 .cpu = cpu,
285 .os = os,286 .os = os,
286 .abi = abi,287 .abi = abi,
288 .ofmt = ofmt,
287 };289 };
288 const ld = target.standardDynamicLinkerPath();290 const ld = target.standardDynamicLinkerPath();
289 if (ld.get() == null) continue;291 if (ld.get() == null) continue;
...@@ -346,6 +348,7 @@ fn detectAbiAndDynamicLinker(...@@ -346,6 +348,7 @@ fn detectAbiAndDynamicLinker(
346 .cpu = cpu,348 .cpu = cpu,
347 .os = os_adjusted,349 .os = os_adjusted,
348 .abi = cross_target.abi orelse found_ld_info.abi,350 .abi = cross_target.abi orelse found_ld_info.abi,
351 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os_adjusted.tag, cpu.arch),
349 },352 },
350 .dynamic_linker = if (cross_target.dynamic_linker.get() == null)353 .dynamic_linker = if (cross_target.dynamic_linker.get() == null)
351 DynamicLinker.init(found_ld_path)354 DynamicLinker.init(found_ld_path)
...@@ -539,6 +542,7 @@ pub fn abiAndDynamicLinkerFromFile(...@@ -539,6 +542,7 @@ pub fn abiAndDynamicLinkerFromFile(
539 .cpu = cpu,542 .cpu = cpu,
540 .os = os,543 .os = os,
541 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),544 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
545 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
542 },546 },
543 .dynamic_linker = cross_target.dynamic_linker,547 .dynamic_linker = cross_target.dynamic_linker,
544 };548 };
...@@ -829,6 +833,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, cross_target: Cros...@@ -829,6 +833,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, cross_target: Cros
829 .cpu = cpu,833 .cpu = cpu,
830 .os = os,834 .os = os,
831 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),835 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
836 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
832 };837 };
833 return NativeTargetInfo{838 return NativeTargetInfo{
834 .target = target,839 .target = target,
src/Compilation.zig+15-15
...@@ -810,7 +810,6 @@ pub const InitOptions = struct {...@@ -810,7 +810,6 @@ pub const InitOptions = struct {
810 /// this flag would be set to disable this machinery to avoid false positives.810 /// this flag would be set to disable this machinery to avoid false positives.
811 disable_lld_caching: bool = false,811 disable_lld_caching: bool = false,
812 cache_mode: CacheMode = .incremental,812 cache_mode: CacheMode = .incremental,
813 object_format: ?std.Target.ObjectFormat = null,
814 optimize_mode: std.builtin.Mode = .Debug,813 optimize_mode: std.builtin.Mode = .Debug,
815 keep_source_files_loaded: bool = false,814 keep_source_files_loaded: bool = false,
816 clang_argv: []const []const u8 = &[0][]const u8{},815 clang_argv: []const []const u8 = &[0][]const u8{},
...@@ -1027,8 +1026,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1027,8 +1026,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1027 const comp = try arena.create(Compilation);1026 const comp = try arena.create(Compilation);
1028 const root_name = try arena.dupeZ(u8, options.root_name);1027 const root_name = try arena.dupeZ(u8, options.root_name);
10291028
1030 const ofmt = options.object_format orelse options.target.getObjectFormat();
1031
1032 const use_stage1 = options.use_stage1 orelse blk: {1029 const use_stage1 = options.use_stage1 orelse blk: {
1033 // Even though we may have no Zig code to compile (depending on `options.main_pkg`),1030 // Even though we may have no Zig code to compile (depending on `options.main_pkg`),
1034 // we may need to use stage1 for building compiler-rt and other dependencies.1031 // 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 {...@@ -1042,7 +1039,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1042 }1039 }
10431040
1044 // If LLVM does not support the target, then we can't use it.1041 // 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))
1046 break :blk false;1043 break :blk false;
10471044
1048 break :blk build_options.is_stage1;1045 break :blk build_options.is_stage1;
...@@ -1072,7 +1069,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1072,7 +1069,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1072 break :blk true;1069 break :blk true;
10731070
1074 // If LLVM does not support the target, then we can't use it.1071 // 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))
1076 break :blk false;1073 break :blk false;
10771074
1078 // Prefer LLVM for release builds.1075 // Prefer LLVM for release builds.
...@@ -1115,7 +1112,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1115,7 +1112,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1115 if (!build_options.have_llvm)1112 if (!build_options.have_llvm)
1116 break :blk false;1113 break :blk false;
11171114
1118 if (ofmt == .c)1115 if (options.target.ofmt == .c)
1119 break :blk false;1116 break :blk false;
11201117
1121 if (options.want_lto) |lto| {1118 if (options.want_lto) |lto| {
...@@ -1374,7 +1371,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1374,7 +1371,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1374 cache.hash.add(options.target.os.getVersionRange());1371 cache.hash.add(options.target.os.getVersionRange());
1375 cache.hash.add(options.is_native_os);1372 cache.hash.add(options.is_native_os);
1376 cache.hash.add(options.target.abi);1373 cache.hash.add(options.target.abi);
1377 cache.hash.add(ofmt);1374 cache.hash.add(options.target.ofmt);
1378 cache.hash.add(pic);1375 cache.hash.add(pic);
1379 cache.hash.add(pie);1376 cache.hash.add(pie);
1380 cache.hash.add(lto);1377 cache.hash.add(lto);
...@@ -1682,7 +1679,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1682,7 +1679,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1682 .sysroot = sysroot,1679 .sysroot = sysroot,
1683 .output_mode = options.output_mode,1680 .output_mode = options.output_mode,
1684 .link_mode = link_mode,1681 .link_mode = link_mode,
1685 .object_format = ofmt,
1686 .optimize_mode = options.optimize_mode,1682 .optimize_mode = options.optimize_mode,
1687 .use_lld = use_lld,1683 .use_lld = use_lld,
1688 .use_llvm = use_llvm,1684 .use_llvm = use_llvm,
...@@ -1841,7 +1837,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1841,7 +1837,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
18411837
1842 const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null;1838 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 {
1845 if (comp.getTarget().isDarwin()) {1843 if (comp.getTarget().isDarwin()) {
1846 switch (comp.getTarget().abi) {1844 switch (comp.getTarget().abi) {
1847 .none,1845 .none,
...@@ -3739,7 +3737,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P...@@ -3739,7 +3737,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
3739 else3737 else
3740 c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len];3738 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);
3743 const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: {3742 const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: {
3744 var argv = std.ArrayList([]const u8).init(comp.gpa);3743 var argv = std.ArrayList([]const u8).init(comp.gpa);
3745 defer argv.deinit();3744 defer argv.deinit();
...@@ -4092,7 +4091,7 @@ pub fn addCCArgs(...@@ -4092,7 +4091,7 @@ pub fn addCCArgs(
40924091
4093 if (!comp.bin_file.options.strip) {4092 if (!comp.bin_file.options.strip) {
4094 try argv.append("-g");4093 try argv.append("-g");
4095 switch (comp.bin_file.options.object_format) {4094 switch (target.ofmt) {
4096 .coff => try argv.append("-gcodeview"),4095 .coff => try argv.append("-gcodeview"),
4097 else => {},4096 else => {},
4098 }4097 }
...@@ -4660,7 +4659,7 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {...@@ -4660,7 +4659,7 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {
4660 };4659 };
4661 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and4660 return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
4662 comp.bin_file.options.libc_installation == null and4661 comp.bin_file.options.libc_installation == null and
4663 comp.bin_file.options.object_format != .c;4662 comp.bin_file.options.target.ofmt != .c;
4664}4663}
46654664
4666fn wantBuildGLibCFromSource(comp: Compilation) bool {4665fn wantBuildGLibCFromSource(comp: Compilation) bool {
...@@ -4688,7 +4687,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {...@@ -4688,7 +4687,7 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
4688 .Exe => true,4687 .Exe => true,
4689 };4688 };
4690 return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind and4689 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;
4692}4691}
46934692
4694fn setAllocFailure(comp: *Compilation) void {4693fn setAllocFailure(comp: *Compilation) void {
...@@ -4747,7 +4746,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca...@@ -4747,7 +4746,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
4747 const zig_backend: std.builtin.CompilerBackend = blk: {4746 const zig_backend: std.builtin.CompilerBackend = blk: {
4748 if (use_stage1) break :blk .stage1;4747 if (use_stage1) break :blk .stage1;
4749 if (build_options.have_llvm and comp.bin_file.options.use_llvm) break :blk .stage2_llvm;4748 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;
4751 break :blk switch (target.cpu.arch) {4750 break :blk switch (target.cpu.arch) {
4752 .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm,4751 .wasm32, .wasm64 => std.builtin.CompilerBackend.stage2_wasm,
4753 .arm, .armeb, .thumb, .thumbeb => .stage2_arm,4752 .arm, .armeb, .thumb, .thumbeb => .stage2_arm,
...@@ -4895,6 +4894,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca...@@ -4895,6 +4894,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
4895 \\ .cpu = cpu,4894 \\ .cpu = cpu,
4896 \\ .os = os,4895 \\ .os = os,
4897 \\ .abi = abi,4896 \\ .abi = abi,
4897 \\ .ofmt = object_format,
4898 \\}};4898 \\}};
4899 \\pub const object_format = std.Target.ObjectFormat.{};4899 \\pub const object_format = std.Target.ObjectFormat.{};
4900 \\pub const mode = std.builtin.Mode.{};4900 \\pub const mode = std.builtin.Mode.{};
...@@ -4909,7 +4909,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca...@@ -4909,7 +4909,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Alloca
4909 \\pub const code_model = std.builtin.CodeModel.{};4909 \\pub const code_model = std.builtin.CodeModel.{};
4910 \\4910 \\
4911 , .{4911 , .{
4912 std.zig.fmtId(@tagName(comp.bin_file.options.object_format)),4912 std.zig.fmtId(@tagName(target.ofmt)),
4913 std.zig.fmtId(@tagName(comp.bin_file.options.optimize_mode)),4913 std.zig.fmtId(@tagName(comp.bin_file.options.optimize_mode)),
4914 link_libc,4914 link_libc,
4915 comp.bin_file.options.link_libcpp,4915 comp.bin_file.options.link_libcpp,
src/Module.zig+33-5
...@@ -935,13 +935,41 @@ pub const Struct = struct {...@@ -935,13 +935,41 @@ pub const Struct = struct {
935 /// If true then `default_val` is the comptime field value.935 /// If true then `default_val` is the comptime field value.
936 is_comptime: bool,936 is_comptime: bool,
937937
938 /// Returns the field alignment, assuming the struct is not packed.938 /// Returns the field alignment. If the struct is packed, returns 0.
939 pub fn normalAlignment(field: Field, target: Target) u32 {939 pub fn alignment(
940 if (field.abi_align == 0) {940 field: Field,
941 return field.ty.abiAlignment(target);941 target: Target,
942 } else {942 layout: std.builtin.Type.ContainerLayout,
943 ) u32 {
944 if (field.abi_align != 0) {
945 assert(layout != .Packed);
943 return field.abi_align;946 return field.abi_align;
944 }947 }
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;
945 }973 }
946 };974 };
947975
src/Sema.zig+2-5
...@@ -14380,10 +14380,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14380,10 +14380,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14380 else14380 else
14381 field.default_val;14381 field.default_val;
14382 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);14382 const default_val_ptr = try sema.optRefValue(block, src, field.ty, opt_default_val);
14383 const alignment = switch (layout) {14383 const alignment = field.alignment(target, layout);
14384 .Auto, .Extern => field.normalAlignment(target),
14385 .Packed => 0,
14386 };
1438714384
14388 struct_field_fields.* = .{14385 struct_field_fields.* = .{
14389 // name: []const u8,14386 // name: []const u8,
...@@ -20657,7 +20654,7 @@ fn panicWithMsg(...@@ -20657,7 +20654,7 @@ fn panicWithMsg(
20657 const arena = sema.arena;20654 const arena = sema.arena;
2065820655
20659 const this_feature_is_implemented_in_the_backend =20656 const this_feature_is_implemented_in_the_backend =
20660 mod.comp.bin_file.options.object_format == .c or20657 mod.comp.bin_file.options.target.ofmt == .c or
20661 mod.comp.bin_file.options.use_llvm;20658 mod.comp.bin_file.options.use_llvm;
20662 if (!this_feature_is_implemented_in_the_backend) {20659 if (!this_feature_is_implemented_in_the_backend) {
20663 // TODO implement this feature in all the backends and then delete this branch20660 // 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 {...@@ -273,7 +273,7 @@ pub const Object = struct {
273 var di_compile_unit: ?*llvm.DICompileUnit = null;273 var di_compile_unit: ?*llvm.DICompileUnit = null;
274274
275 if (!options.strip) {275 if (!options.strip) {
276 switch (options.object_format) {276 switch (options.target.ofmt) {
277 .coff => llvm_module.addModuleCodeViewFlag(),277 .coff => llvm_module.addModuleCodeViewFlag(),
278 else => llvm_module.addModuleDebugInfoFlag(),278 else => llvm_module.addModuleDebugInfoFlag(),
279 }279 }
...@@ -1841,6 +1841,7 @@ pub const Object = struct {...@@ -1841,6 +1841,7 @@ pub const Object = struct {
1841 }1841 }
18421842
1843 const fields = ty.structFields();1843 const fields = ty.structFields();
1844 const layout = ty.containerLayout();
18441845
1845 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};1846 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
1846 defer di_fields.deinit(gpa);1847 defer di_fields.deinit(gpa);
...@@ -1854,7 +1855,7 @@ pub const Object = struct {...@@ -1854,7 +1855,7 @@ pub const Object = struct {
1854 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;1855 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
18551856
1856 const field_size = field.ty.abiSize(target);1857 const field_size = field.ty.abiSize(target);
1857 const field_align = field.normalAlignment(target);1858 const field_align = field.alignment(target, layout);
1858 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);1859 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1859 offset = field_offset + field_size;1860 offset = field_offset + field_size;
18601861
...@@ -2757,7 +2758,7 @@ pub const DeclGen = struct {...@@ -2757,7 +2758,7 @@ pub const DeclGen = struct {
2757 for (struct_obj.fields.values()) |field| {2758 for (struct_obj.fields.values()) |field| {
2758 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;2759 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);
2761 const field_ty_align = field.ty.abiAlignment(target);2762 const field_ty_align = field.ty.abiAlignment(target);
2762 any_underaligned_fields = any_underaligned_fields or2763 any_underaligned_fields = any_underaligned_fields or
2763 field_align < field_ty_align;2764 field_align < field_ty_align;
...@@ -3433,7 +3434,7 @@ pub const DeclGen = struct {...@@ -3433,7 +3434,7 @@ pub const DeclGen = struct {
3433 for (struct_obj.fields.values()) |field, i| {3434 for (struct_obj.fields.values()) |field, i| {
3434 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;3435 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);
3437 big_align = @maximum(big_align, field_align);3438 big_align = @maximum(big_align, field_align);
3438 const prev_offset = offset;3439 const prev_offset = offset;
3439 offset = std.mem.alignForwardGeneric(u64, offset, field_align);3440 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
...@@ -9376,13 +9377,14 @@ fn llvmFieldIndex(...@@ -9376,13 +9377,14 @@ fn llvmFieldIndex(
9376 }9377 }
9377 return null;9378 return null;
9378 }9379 }
9379 assert(ty.containerLayout() != .Packed);9380 const layout = ty.containerLayout();
9381 assert(layout != .Packed);
93809382
9381 var llvm_field_index: c_uint = 0;9383 var llvm_field_index: c_uint = 0;
9382 for (ty.structFields().values()) |field, i| {9384 for (ty.structFields().values()) |field, i| {
9383 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;9385 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);
9386 big_align = @maximum(big_align, field_align);9388 big_align = @maximum(big_align, field_align);
9387 const prev_offset = offset;9389 const prev_offset = offset;
9388 offset = std.mem.alignForwardGeneric(u64, offset, field_align);9390 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
src/link.zig+5-6
...@@ -72,7 +72,6 @@ pub const Options = struct {...@@ -72,7 +72,6 @@ pub const Options = struct {
72 target: std.Target,72 target: std.Target,
73 output_mode: std.builtin.OutputMode,73 output_mode: std.builtin.OutputMode,
74 link_mode: std.builtin.LinkMode,74 link_mode: std.builtin.LinkMode,
75 object_format: std.Target.ObjectFormat,
76 optimize_mode: std.builtin.Mode,75 optimize_mode: std.builtin.Mode,
77 machine_code_model: std.builtin.CodeModel,76 machine_code_model: std.builtin.CodeModel,
78 root_name: [:0]const u8,77 root_name: [:0]const u8,
...@@ -273,13 +272,13 @@ pub const File = struct {...@@ -273,13 +272,13 @@ pub const File = struct {
273 /// rewriting it. A malicious file is detected as incremental link failure272 /// rewriting it. A malicious file is detected as incremental link failure
274 /// and does not cause Illegal Behavior. This operation is not atomic.273 /// and does not cause Illegal Behavior. This operation is not atomic.
275 pub fn openPath(allocator: Allocator, options: Options) !*File {274 pub fn openPath(allocator: Allocator, options: Options) !*File {
276 if (options.object_format == .macho) {275 if (options.target.ofmt == .macho) {
277 return &(try MachO.openPath(allocator, options)).base;276 return &(try MachO.openPath(allocator, options)).base;
278 }277 }
279278
280 const use_stage1 = build_options.is_stage1 and options.use_stage1;279 const use_stage1 = build_options.is_stage1 and options.use_stage1;
281 if (use_stage1 or options.emit == null) {280 if (use_stage1 or options.emit == null) {
282 return switch (options.object_format) {281 return switch (options.target.ofmt) {
283 .coff => &(try Coff.createEmpty(allocator, options)).base,282 .coff => &(try Coff.createEmpty(allocator, options)).base,
284 .elf => &(try Elf.createEmpty(allocator, options)).base,283 .elf => &(try Elf.createEmpty(allocator, options)).base,
285 .macho => unreachable,284 .macho => unreachable,
...@@ -298,7 +297,7 @@ pub const File = struct {...@@ -298,7 +297,7 @@ pub const File = struct {
298 if (options.module == null) {297 if (options.module == null) {
299 // No point in opening a file, we would not write anything to it.298 // No point in opening a file, we would not write anything to it.
300 // Initialize with empty.299 // Initialize with empty.
301 return switch (options.object_format) {300 return switch (options.target.ofmt) {
302 .coff => &(try Coff.createEmpty(allocator, options)).base,301 .coff => &(try Coff.createEmpty(allocator, options)).base,
303 .elf => &(try Elf.createEmpty(allocator, options)).base,302 .elf => &(try Elf.createEmpty(allocator, options)).base,
304 .macho => unreachable,303 .macho => unreachable,
...@@ -314,12 +313,12 @@ pub const File = struct {...@@ -314,12 +313,12 @@ pub const File = struct {
314 // Open a temporary object file, not the final output file because we313 // Open a temporary object file, not the final output file because we
315 // want to link with LLD.314 // want to link with LLD.
316 break :blk try std.fmt.allocPrint(allocator, "{s}{s}", .{315 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),
318 });317 });
319 } else emit.sub_path;318 } else emit.sub_path;
320 errdefer if (use_lld) allocator.free(sub_path);319 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) {
323 .coff => &(try Coff.openPath(allocator, sub_path, options)).base,322 .coff => &(try Coff.openPath(allocator, sub_path, options)).base,
324 .elf => &(try Elf.openPath(allocator, sub_path, options)).base,323 .elf => &(try Elf.openPath(allocator, sub_path, options)).base,
325 .macho => unreachable,324 .macho => unreachable,
src/link/C.zig+1-1
...@@ -48,7 +48,7 @@ const DeclBlock = struct {...@@ -48,7 +48,7 @@ const DeclBlock = struct {
48};48};
4949
50pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C {50pub 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
53 if (options.use_llvm) return error.LLVMHasNoCBackend;53 if (options.use_llvm) return error.LLVMHasNoCBackend;
54 if (options.use_lld) return error.LLDHasNoCBackend;54 if (options.use_lld) return error.LLDHasNoCBackend;
src/link/Coff.zig+1-1
...@@ -128,7 +128,7 @@ pub const TextBlock = struct {...@@ -128,7 +128,7 @@ pub const TextBlock = struct {
128pub const SrcFn = void;128pub const SrcFn = void;
129129
130pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Coff {130pub 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
133 if (build_options.have_llvm and options.use_llvm) {133 if (build_options.have_llvm and options.use_llvm) {
134 return createEmpty(allocator, options);134 return createEmpty(allocator, options);
src/link/Elf.zig+1-1
...@@ -249,7 +249,7 @@ pub const Export = struct {...@@ -249,7 +249,7 @@ pub const Export = struct {
249};249};
250250
251pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Elf {251pub 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
254 if (build_options.have_llvm and options.use_llvm) {254 if (build_options.have_llvm and options.use_llvm) {
255 return createEmpty(allocator, options);255 return createEmpty(allocator, options);
src/link/MachO.zig+2-2
...@@ -270,7 +270,7 @@ pub const Export = struct {...@@ -270,7 +270,7 @@ pub const Export = struct {
270};270};
271271
272pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {272pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
273 assert(options.object_format == .macho);273 assert(options.target.ofmt == .macho);
274274
275 const use_stage1 = build_options.is_stage1 and options.use_stage1;275 const use_stage1 = build_options.is_stage1 and options.use_stage1;
276 if (use_stage1 or options.emit == null) {276 if (use_stage1 or options.emit == null) {
...@@ -289,7 +289,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {...@@ -289,7 +289,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
289 // we also want to put the intermediary object file in the cache while the289 // we also want to put the intermediary object file in the cache while the
290 // main emit directory is the cwd.290 // main emit directory is the cwd.
291 self.base.intermediary_basename = try std.fmt.allocPrint(allocator, "{s}{s}", .{291 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),
293 });293 });
294 }294 }
295295
src/link/NvPtx.zig+1-1
...@@ -57,7 +57,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx {...@@ -57,7 +57,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx {
57pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*NvPtx {57pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*NvPtx {
58 if (!build_options.have_llvm) @panic("nvptx target requires a zig compiler with llvm enabled.");58 if (!build_options.have_llvm) @panic("nvptx target requires a zig compiler with llvm enabled.");
59 if (!options.use_llvm) return error.PtxArchNotSupported;59 if (!options.use_llvm) return error.PtxArchNotSupported;
60 assert(options.object_format == .nvptx);60 assert(options.target.ofmt == .nvptx);
6161
62 const nvptx = try createEmpty(allocator, options);62 const nvptx = try createEmpty(allocator, options);
63 log.info("Opening .ptx target file {s}", .{sub_path});63 log.info("Opening .ptx target file {s}", .{sub_path});
src/link/Plan9.zig+1-1
...@@ -657,7 +657,7 @@ pub const base_tag = .plan9;...@@ -657,7 +657,7 @@ pub const base_tag = .plan9;
657pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 {657pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 {
658 if (options.use_llvm)658 if (options.use_llvm)
659 return error.LLVMBackendDoesNotSupportPlan9;659 return error.LLVMBackendDoesNotSupportPlan9;
660 assert(options.object_format == .plan9);660 assert(options.target.ofmt == .plan9);
661661
662 const self = try createEmpty(allocator, options);662 const self = try createEmpty(allocator, options);
663 errdefer self.base.destroy();663 errdefer self.base.destroy();
src/link/SpirV.zig+1-1
...@@ -99,7 +99,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV {...@@ -99,7 +99,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV {
99}99}
100100
101pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*SpirV {101pub 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
104 if (options.use_llvm) return error.LLVM_BackendIsTODO_ForSpirV; // TODO: LLVM Doesn't support SpirV at all.104 if (options.use_llvm) return error.LLVM_BackendIsTODO_ForSpirV; // TODO: LLVM Doesn't support SpirV at all.
105 if (options.use_lld) return error.LLD_LinkingIsTODO_ForSpirV; // TODO: LLD Doesn't support SpirV at all.105 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 {...@@ -282,7 +282,7 @@ pub const StringTable = struct {
282};282};
283283
284pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Wasm {284pub 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
287 if (build_options.have_llvm and options.use_llvm) {287 if (build_options.have_llvm and options.use_llvm) {
288 return createEmpty(allocator, options);288 return createEmpty(allocator, options);
src/main.zig+22-29
...@@ -2192,6 +2192,7 @@ fn buildOutputType(...@@ -2192,6 +2192,7 @@ fn buildOutputType(
2192 .arch_os_abi = target_arch_os_abi,2192 .arch_os_abi = target_arch_os_abi,
2193 .cpu_features = target_mcpu,2193 .cpu_features = target_mcpu,
2194 .dynamic_linker = target_dynamic_linker,2194 .dynamic_linker = target_dynamic_linker,
2195 .object_format = target_ofmt,
2195 };2196 };
21962197
2197 // Before passing the mcpu string in for parsing, we convert any -m flags that were2198 // Before passing the mcpu string in for parsing, we convert any -m flags that were
...@@ -2494,28 +2495,7 @@ fn buildOutputType(...@@ -2494,28 +2495,7 @@ fn buildOutputType(
2494 }2495 }
2495 }2496 }
24962497
2497 const object_format: std.Target.ObjectFormat = blk: {2498 const object_format = target_info.target.ofmt;
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 };
25192499
2520 if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) {2500 if (output_mode == .Obj and (object_format == .coff or object_format == .macho)) {
2521 const total_obj_count = c_source_files.items.len +2501 const total_obj_count = c_source_files.items.len +
...@@ -2569,7 +2549,6 @@ fn buildOutputType(...@@ -2569,7 +2549,6 @@ fn buildOutputType(
2569 .target = target_info.target,2549 .target = target_info.target,
2570 .output_mode = output_mode,2550 .output_mode = output_mode,
2571 .link_mode = link_mode,2551 .link_mode = link_mode,
2572 .object_format = object_format,
2573 .version = optional_version,2552 .version = optional_version,
2574 }),2553 }),
2575 },2554 },
...@@ -2859,7 +2838,6 @@ fn buildOutputType(...@@ -2859,7 +2838,6 @@ fn buildOutputType(
2859 .emit_implib = emit_implib_resolved.data,2838 .emit_implib = emit_implib_resolved.data,
2860 .link_mode = link_mode,2839 .link_mode = link_mode,
2861 .dll_export_fns = dll_export_fns,2840 .dll_export_fns = dll_export_fns,
2862 .object_format = object_format,
2863 .optimize_mode = optimize_mode,2841 .optimize_mode = optimize_mode,
2864 .keep_source_files_loaded = false,2842 .keep_source_files_loaded = false,
2865 .clang_argv = clang_argv.items,2843 .clang_argv = clang_argv.items,
...@@ -3173,11 +3151,11 @@ fn parseCrossTargetOrReportFatalError(...@@ -3173,11 +3151,11 @@ fn parseCrossTargetOrReportFatalError(
3173 for (diags.arch.?.allCpuModels()) |cpu| {3151 for (diags.arch.?.allCpuModels()) |cpu| {
3174 help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help;3152 help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help;
3175 }3153 }
3176 std.log.info("Available CPUs for architecture '{s}':\n{s}", .{3154 std.log.info("available CPUs for architecture '{s}':\n{s}", .{
3177 @tagName(diags.arch.?), help_text.items,3155 @tagName(diags.arch.?), help_text.items,
3178 });3156 });
3179 }3157 }
3180 fatal("Unknown CPU: '{s}'", .{diags.cpu_name.?});3158 fatal("unknown CPU: '{s}'", .{diags.cpu_name.?});
3181 },3159 },
3182 error.UnknownCpuFeature => {3160 error.UnknownCpuFeature => {
3183 help: {3161 help: {
...@@ -3186,11 +3164,26 @@ fn parseCrossTargetOrReportFatalError(...@@ -3186,11 +3164,26 @@ fn parseCrossTargetOrReportFatalError(
3186 for (diags.arch.?.allFeaturesList()) |feature| {3164 for (diags.arch.?.allFeaturesList()) |feature| {
3187 help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help;3165 help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help;
3188 }3166 }
3189 std.log.info("Available CPU features for architecture '{s}':\n{s}", .{3167 std.log.info("available CPU features for architecture '{s}':\n{s}", .{
3190 @tagName(diags.arch.?), help_text.items,3168 @tagName(diags.arch.?), help_text.items,
3191 });3169 });
3192 }3170 }
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.?});
3194 },3187 },
3195 else => |e| return e,3188 else => |e| return e,
3196 };3189 };
...@@ -3360,7 +3353,7 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void...@@ -3360,7 +3353,7 @@ fn updateModule(gpa: Allocator, comp: *Compilation, hook: AfterUpdateHook) !void
33603353
3361 // If a .pdb file is part of the expected output, we must also copy3354 // If a .pdb file is part of the expected output, we must also copy
3362 // it into place here.3355 // 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;
3364 const have_pdb = is_coff and !comp.bin_file.options.strip;3357 const have_pdb = is_coff and !comp.bin_file.options.strip;
3365 if (have_pdb) {3358 if (have_pdb) {
3366 // Replace `.out` or `.exe` with `.pdb` on both the source and destination3359 // 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) {...@@ -10082,6 +10082,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
10082 " .cpu = cpu,\n"10082 " .cpu = cpu,\n"
10083 " .os = os,\n"10083 " .os = os,\n"
10084 " .abi = abi,\n"10084 " .abi = abi,\n"
10085 " .ofmt = object_format,\n"
10085 "};\n"10086 "};\n"
10086 );10087 );
1008710088
src/test.zig+7-8
...@@ -606,7 +606,6 @@ pub const TestContext = struct {...@@ -606,7 +606,6 @@ pub const TestContext = struct {
606 output_mode: std.builtin.OutputMode,606 output_mode: std.builtin.OutputMode,
607 optimize_mode: std.builtin.Mode = .Debug,607 optimize_mode: std.builtin.Mode = .Debug,
608 updates: std.ArrayList(Update),608 updates: std.ArrayList(Update),
609 object_format: ?std.Target.ObjectFormat = null,
610 emit_h: bool = false,609 emit_h: bool = false,
611 is_test: bool = false,610 is_test: bool = false,
612 expect_exact: bool = false,611 expect_exact: bool = false,
...@@ -782,12 +781,13 @@ pub const TestContext = struct {...@@ -782,12 +781,13 @@ pub const TestContext = struct {
782 pub fn exeFromCompiledC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case {781 pub fn exeFromCompiledC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case {
783 const prefixed_name = std.fmt.allocPrint(ctx.arena, "CBE: {s}", .{name}) catch782 const prefixed_name = std.fmt.allocPrint(ctx.arena, "CBE: {s}", .{name}) catch
784 @panic("out of memory");783 @panic("out of memory");
784 var target_adjusted = target;
785 target_adjusted.ofmt = std.Target.ObjectFormat.c;
785 ctx.cases.append(Case{786 ctx.cases.append(Case{
786 .name = prefixed_name,787 .name = prefixed_name,
787 .target = target,788 .target = target_adjusted,
788 .updates = std.ArrayList(Update).init(ctx.cases.allocator),789 .updates = std.ArrayList(Update).init(ctx.cases.allocator),
789 .output_mode = .Exe,790 .output_mode = .Exe,
790 .object_format = .c,
791 .files = std.ArrayList(File).init(ctx.arena),791 .files = std.ArrayList(File).init(ctx.arena),
792 }) catch @panic("out of memory");792 }) catch @panic("out of memory");
793 return &ctx.cases.items[ctx.cases.items.len - 1];793 return &ctx.cases.items[ctx.cases.items.len - 1];
...@@ -851,12 +851,13 @@ pub const TestContext = struct {...@@ -851,12 +851,13 @@ pub const TestContext = struct {
851851
852 /// Adds a test case for Zig or ZIR input, producing C code.852 /// Adds a test case for Zig or ZIR input, producing C code.
853 pub fn addC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case {853 pub fn addC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case {
854 var target_adjusted = target;
855 target_adjusted.ofmt = std.Target.ObjectFormat.c;
854 ctx.cases.append(Case{856 ctx.cases.append(Case{
855 .name = name,857 .name = name,
856 .target = target,858 .target = target_adjusted,
857 .updates = std.ArrayList(Update).init(ctx.cases.allocator),859 .updates = std.ArrayList(Update).init(ctx.cases.allocator),
858 .output_mode = .Obj,860 .output_mode = .Obj,
859 .object_format = .c,
860 .files = std.ArrayList(File).init(ctx.arena),861 .files = std.ArrayList(File).init(ctx.arena),
861 }) catch @panic("out of memory");862 }) catch @panic("out of memory");
862 return &ctx.cases.items[ctx.cases.items.len - 1];863 return &ctx.cases.items[ctx.cases.items.len - 1];
...@@ -1501,7 +1502,6 @@ pub const TestContext = struct {...@@ -1501,7 +1502,6 @@ pub const TestContext = struct {
1501 .root_name = "test_case",1502 .root_name = "test_case",
1502 .target = target,1503 .target = target,
1503 .output_mode = case.output_mode,1504 .output_mode = case.output_mode,
1504 .object_format = case.object_format,
1505 });1505 });
15061506
1507 const emit_directory: Compilation.Directory = .{1507 const emit_directory: Compilation.Directory = .{
...@@ -1537,7 +1537,6 @@ pub const TestContext = struct {...@@ -1537,7 +1537,6 @@ pub const TestContext = struct {
1537 .emit_h = emit_h,1537 .emit_h = emit_h,
1538 .main_pkg = &main_pkg,1538 .main_pkg = &main_pkg,
1539 .keep_source_files_loaded = true,1539 .keep_source_files_loaded = true,
1540 .object_format = case.object_format,
1541 .is_native_os = case.target.isNativeOs(),1540 .is_native_os = case.target.isNativeOs(),
1542 .is_native_abi = case.target.isNativeAbi(),1541 .is_native_abi = case.target.isNativeAbi(),
1543 .dynamic_linker = target_info.dynamic_linker.get(),1542 .dynamic_linker = target_info.dynamic_linker.get(),
...@@ -1782,7 +1781,7 @@ pub const TestContext = struct {...@@ -1782,7 +1781,7 @@ pub const TestContext = struct {
1782 ".." ++ ss ++ "{s}" ++ ss ++ "{s}",1781 ".." ++ ss ++ "{s}" ++ ss ++ "{s}",
1783 .{ &tmp.sub_path, bin_name },1782 .{ &tmp.sub_path, bin_name },
1784 );1783 );
1785 if (case.object_format != null and case.object_format.? == .c) {1784 if (case.target.ofmt != null and case.target.ofmt.? == .c) {
1786 if (host.getExternalExecutor(target_info, .{ .link_libc = true }) != .native) {1785 if (host.getExternalExecutor(target_info, .{ .link_libc = true }) != .native) {
1787 // We wouldn't be able to run the compiled C code.1786 // We wouldn't be able to run the compiled C code.
1788 continue :update; // Pass test.1787 continue :update; // Pass test.
src/type.zig+74-29
...@@ -2376,6 +2376,32 @@ pub const Type = extern union {...@@ -2376,6 +2376,32 @@ pub const Type = extern union {
2376 .error_set_merged,2376 .error_set_merged,
2377 => return true,2377 => 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
2379 // These are false because they are comptime-only types.2405 // These are false because they are comptime-only types.
2380 .single_const_pointer_to_comptime_int,2406 .single_const_pointer_to_comptime_int,
2381 .void,2407 .void,
...@@ -2399,30 +2425,6 @@ pub const Type = extern union {...@@ -2399,30 +2425,6 @@ pub const Type = extern union {
2399 .fn_ccc_void_no_args,2425 .fn_ccc_void_no_args,
2400 => return false,2426 => 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
2426 .optional => {2428 .optional => {
2427 var buf: Payload.ElemType = undefined;2429 var buf: Payload.ElemType = undefined;
2428 const child_ty = ty.optionalChild(&buf);2430 const child_ty = ty.optionalChild(&buf);
...@@ -3029,6 +3031,15 @@ pub const Type = extern union {...@@ -3029,6 +3031,15 @@ pub const Type = extern union {
3029 },3031 },
3030 };3032 };
3031 big_align = @maximum(big_align, field_align);3033 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 }
3032 }3043 }
3033 return AbiAlignmentAdvanced{ .scalar = big_align };3044 return AbiAlignmentAdvanced{ .scalar = big_align };
3034 },3045 },
...@@ -3263,8 +3274,8 @@ pub const Type = extern union {...@@ -3263,8 +3274,8 @@ pub const Type = extern union {
32633274
3264 .array_u8 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8).?.data },3275 .array_u8 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8).?.data },
3265 .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 },3276 .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 },
3266 .array, .vector => {3277 .array => {
3267 const payload = ty.cast(Payload.Array).?.data;3278 const payload = ty.castTag(.array).?.data;
3268 switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {3279 switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {
3269 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },3280 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },
3270 .val => switch (strat) {3281 .val => switch (strat) {
...@@ -3286,6 +3297,28 @@ pub const Type = extern union {...@@ -3286,6 +3297,28 @@ pub const Type = extern union {
3286 }3297 }
3287 },3298 },
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
3289 .isize,3322 .isize,
3290 .usize,3323 .usize,
3291 .@"anyframe",3324 .@"anyframe",
...@@ -3329,7 +3362,13 @@ pub const Type = extern union {...@@ -3329,7 +3362,13 @@ pub const Type = extern union {
3329 .f128 => return AbiSizeAdvanced{ .scalar = 16 },3362 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
33303363
3331 .f80 => switch (target.cpu.arch) {3364 .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 },
3333 .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },3372 .x86_64 => return AbiSizeAdvanced{ .scalar = 16 },
3334 else => {3373 else => {
3335 var payload: Payload.Bits = .{3374 var payload: Payload.Bits = .{
...@@ -4540,6 +4579,12 @@ pub const Type = extern union {...@@ -4540,6 +4579,12 @@ pub const Type = extern union {
45404579
4541 .vector => ty = ty.castTag(.vector).?.data.elem_type,4580 .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
4543 else => unreachable,4588 else => unreachable,
4544 };4589 };
4545 }4590 }
...@@ -5502,7 +5547,7 @@ pub const Type = extern union {...@@ -5502,7 +5547,7 @@ pub const Type = extern union {
5502 .@"struct" => {5547 .@"struct" => {
5503 const struct_obj = ty.castTag(.@"struct").?.data;5548 const struct_obj = ty.castTag(.@"struct").?.data;
5504 assert(struct_obj.layout != .Packed);5549 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);
5506 },5551 },
5507 .@"union", .union_safety_tagged, .union_tagged => {5552 .@"union", .union_safety_tagged, .union_tagged => {
5508 const union_obj = ty.cast(Payload.Union).?.data;5553 const union_obj = ty.cast(Payload.Union).?.data;
...@@ -5609,7 +5654,7 @@ pub const Type = extern union {...@@ -5609,7 +5654,7 @@ pub const Type = extern union {
5609 if (!field.ty.hasRuntimeBits() or field.is_comptime)5654 if (!field.ty.hasRuntimeBits() or field.is_comptime)
5610 return FieldOffset{ .field = it.field, .offset = it.offset };5655 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);
5613 it.big_align = @maximum(it.big_align, field_align);5658 it.big_align = @maximum(it.big_align, field_align);
5614 it.offset = std.mem.alignForwardGeneric(u64, it.offset, field_align);5659 it.offset = std.mem.alignForwardGeneric(u64, it.offset, field_align);
5615 defer it.offset += field.ty.abiSize(it.target);5660 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" {...@@ -100,8 +100,8 @@ test "alignment and size of structs with 128-bit fields" {
100 .a_align = 8,100 .a_align = 8,
101 .a_size = 16,101 .a_size = 16,
102102
103 .b_align = 8,103 .b_align = 16,
104 .b_size = 24,104 .b_size = 32,
105105
106 .u128_align = 8,106 .u128_align = 8,
107 .u128_size = 16,107 .u128_size = 16,
...@@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" {...@@ -114,8 +114,8 @@ test "alignment and size of structs with 128-bit fields" {
114 .a_align = 8,114 .a_align = 8,
115 .a_size = 16,115 .a_size = 16,
116116
117 .b_align = 8,117 .b_align = 16,
118 .b_size = 24,118 .b_size = 32,
119119
120 .u128_align = 8,120 .u128_align = 8,
121 .u128_size = 16,121 .u128_size = 16,
...@@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" {...@@ -126,8 +126,8 @@ test "alignment and size of structs with 128-bit fields" {
126 .a_align = 4,126 .a_align = 4,
127 .a_size = 16,127 .a_size = 16,
128128
129 .b_align = 4,129 .b_align = 16,
130 .b_size = 20,130 .b_size = 32,
131131
132 .u128_align = 4,132 .u128_align = 4,
133 .u128_size = 16,133 .u128_size = 16,
...@@ -140,12 +140,39 @@ test "alignment and size of structs with 128-bit fields" {...@@ -140,12 +140,39 @@ test "alignment and size of structs with 128-bit fields" {
140 .mips64el,140 .mips64el,
141 .powerpc64,141 .powerpc64,
142 .powerpc64le,142 .powerpc64le,
143 .riscv64,
144 .sparc64,143 .sparc64,
145 .x86_64,144 .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
146 .aarch64,172 .aarch64,
147 .aarch64_be,173 .aarch64_be,
148 .aarch64_32,174 .aarch64_32,
175 .riscv64,
149 .bpfel,176 .bpfel,
150 .bpfeb,177 .bpfeb,
151 .nvptx,178 .nvptx,
...@@ -166,17 +193,17 @@ test "alignment and size of structs with 128-bit fields" {...@@ -166,17 +193,17 @@ test "alignment and size of structs with 128-bit fields" {
166 else => return error.SkipZigTest,193 else => return error.SkipZigTest,
167 };194 };
168 comptime {195 comptime {
169 std.debug.assert(@alignOf(A) == expected.a_align);196 assert(@alignOf(A) == expected.a_align);
170 std.debug.assert(@sizeOf(A) == expected.a_size);197 assert(@sizeOf(A) == expected.a_size);
171198
172 std.debug.assert(@alignOf(B) == expected.b_align);199 assert(@alignOf(B) == expected.b_align);
173 std.debug.assert(@sizeOf(B) == expected.b_size);200 assert(@sizeOf(B) == expected.b_size);
174201
175 std.debug.assert(@alignOf(u128) == expected.u128_align);202 assert(@alignOf(u128) == expected.u128_align);
176 std.debug.assert(@sizeOf(u128) == expected.u128_size);203 assert(@sizeOf(u128) == expected.u128_size);
177204
178 std.debug.assert(@alignOf(u129) == expected.u129_align);205 assert(@alignOf(u129) == expected.u129_align);
179 std.debug.assert(@sizeOf(u129) == expected.u129_size);206 assert(@sizeOf(u129) == expected.u129_size);
180 }207 }
181}208}
182209