authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-03 14:58:46-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-05-03 14:58:46-04:00
log3cfde183f3700999eac0b84b54cae0a7d63743a9
tree57665cd311d115c3fac2b69dfff58939b6ff8592
parent6317da8da400e40a947f6333d1afc289ec349102
parentaa3c3f66da630cddc12931e7845f4e71acbc4860
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11571 from ziglang/stage2-test-behavior

progress towards stage2 behavior tests for all targets passing with the LLVM backend

19 files changed, 190 insertions(+), 111 deletions(-)

lib/std/os/windows.zig+40-10
......@@ -2693,7 +2693,10 @@ pub const MEM_RESERVE_PLACEHOLDERS = 0x2;
26932693pub const MEM_DECOMMIT = 0x4000;
26942694pub const MEM_RELEASE = 0x8000;
26952695
2696pub const PTHREAD_START_ROUTINE = fn (LPVOID) callconv(.C) DWORD;
2696pub const PTHREAD_START_ROUTINE = switch (builtin.zig_backend) {
2697 .stage1 => fn (LPVOID) callconv(.C) DWORD,
2698 else => *const fn (LPVOID) callconv(.C) DWORD,
2699};
26972700pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE;
26982701
26992702pub const WIN32_FIND_DATAW = extern struct {
......@@ -2866,7 +2869,10 @@ pub const IMAGE_TLS_DIRECTORY = extern struct {
28662869pub const IMAGE_TLS_DIRECTORY64 = IMAGE_TLS_DIRECTORY;
28672870pub const IMAGE_TLS_DIRECTORY32 = IMAGE_TLS_DIRECTORY;
28682871
2869pub const PIMAGE_TLS_CALLBACK = ?fn (PVOID, DWORD, PVOID) callconv(.C) void;
2872pub const PIMAGE_TLS_CALLBACK = switch (builtin.zig_backend) {
2873 .stage1 => ?fn (PVOID, DWORD, PVOID) callconv(.C) void,
2874 else => ?*const fn (PVOID, DWORD, PVOID) callconv(.C) void,
2875};
28702876
28712877pub const PROV_RSA_FULL = 1;
28722878
......@@ -2892,7 +2898,10 @@ pub const FILE_ACTION_MODIFIED = 0x00000003;
28922898pub const FILE_ACTION_RENAMED_OLD_NAME = 0x00000004;
28932899pub const FILE_ACTION_RENAMED_NEW_NAME = 0x00000005;
28942900
2895pub const LPOVERLAPPED_COMPLETION_ROUTINE = ?fn (DWORD, DWORD, *OVERLAPPED) callconv(.C) void;
2901pub const LPOVERLAPPED_COMPLETION_ROUTINE = switch (builtin.zig_backend) {
2902 .stage1 => ?fn (DWORD, DWORD, *OVERLAPPED) callconv(.C) void,
2903 else => ?*const fn (DWORD, DWORD, *OVERLAPPED) callconv(.C) void,
2904};
28962905
28972906pub const FILE_NOTIFY_CHANGE_CREATION = 64;
28982907pub const FILE_NOTIFY_CHANGE_SIZE = 8;
......@@ -2945,7 +2954,10 @@ pub const RTL_CRITICAL_SECTION = extern struct {
29452954pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;
29462955pub const INIT_ONCE = RTL_RUN_ONCE;
29472956pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE_INIT;
2948pub const INIT_ONCE_FN = fn (InitOnce: *INIT_ONCE, Parameter: ?*anyopaque, Context: ?*anyopaque) callconv(.C) BOOL;
2957pub const INIT_ONCE_FN = switch (builtin.zig_backend) {
2958 .stage1 => fn (InitOnce: *INIT_ONCE, Parameter: ?*anyopaque, Context: ?*anyopaque) callconv(.C) BOOL,
2959 else => *const fn (InitOnce: *INIT_ONCE, Parameter: ?*anyopaque, Context: ?*anyopaque) callconv(.C) BOOL,
2960};
29492961
29502962pub const RTL_RUN_ONCE = extern struct {
29512963 Ptr: ?*anyopaque,
......@@ -3230,7 +3242,10 @@ pub const EXCEPTION_POINTERS = extern struct {
32303242 ContextRecord: *std.os.windows.CONTEXT,
32313243};
32323244
3233pub const VECTORED_EXCEPTION_HANDLER = fn (ExceptionInfo: *EXCEPTION_POINTERS) callconv(WINAPI) c_long;
3245pub const VECTORED_EXCEPTION_HANDLER = switch (builtin.zig_backend) {
3246 .stage1 => fn (ExceptionInfo: *EXCEPTION_POINTERS) callconv(WINAPI) c_long,
3247 else => *const fn (ExceptionInfo: *EXCEPTION_POINTERS) callconv(WINAPI) c_long,
3248};
32343249
32353250pub const OBJECT_ATTRIBUTES = extern struct {
32363251 Length: ULONG,
......@@ -3506,7 +3521,10 @@ pub const RTL_DRIVE_LETTER_CURDIR = extern struct {
35063521 DosPath: UNICODE_STRING,
35073522};
35083523
3509pub const PPS_POST_PROCESS_INIT_ROUTINE = ?fn () callconv(.C) void;
3524pub const PPS_POST_PROCESS_INIT_ROUTINE = switch (builtin.zig_backend) {
3525 .stage1 => ?fn () callconv(.C) void,
3526 else => ?*const fn () callconv(.C) void,
3527};
35103528
35113529pub const FILE_BOTH_DIR_INFORMATION = extern struct {
35123530 NextEntryOffset: ULONG,
......@@ -3526,7 +3544,10 @@ pub const FILE_BOTH_DIR_INFORMATION = extern struct {
35263544};
35273545pub const FILE_BOTH_DIRECTORY_INFORMATION = FILE_BOTH_DIR_INFORMATION;
35283546
3529pub const IO_APC_ROUTINE = fn (PVOID, *IO_STATUS_BLOCK, ULONG) callconv(.C) void;
3547pub const IO_APC_ROUTINE = switch (builtin.zig_backend) {
3548 .stage1 => fn (PVOID, *IO_STATUS_BLOCK, ULONG) callconv(.C) void,
3549 else => *const fn (PVOID, *IO_STATUS_BLOCK, ULONG) callconv(.C) void,
3550};
35303551
35313552pub const CURDIR = extern struct {
35323553 DosPath: UNICODE_STRING,
......@@ -3598,8 +3619,14 @@ pub const ENUM_PAGE_FILE_INFORMATION = extern struct {
35983619 PeakUsage: SIZE_T,
35993620};
36003621
3601pub const PENUM_PAGE_FILE_CALLBACKW = ?fn (?LPVOID, *ENUM_PAGE_FILE_INFORMATION, LPCWSTR) callconv(.C) BOOL;
3602pub const PENUM_PAGE_FILE_CALLBACKA = ?fn (?LPVOID, *ENUM_PAGE_FILE_INFORMATION, LPCSTR) callconv(.C) BOOL;
3622pub const PENUM_PAGE_FILE_CALLBACKW = switch (builtin.zig_backend) {
3623 .stage1 => ?fn (?LPVOID, *ENUM_PAGE_FILE_INFORMATION, LPCWSTR) callconv(.C) BOOL,
3624 else => ?*const fn (?LPVOID, *ENUM_PAGE_FILE_INFORMATION, LPCWSTR) callconv(.C) BOOL,
3625};
3626pub const PENUM_PAGE_FILE_CALLBACKA = switch (builtin.zig_backend) {
3627 .stage1 => ?fn (?LPVOID, *ENUM_PAGE_FILE_INFORMATION, LPCSTR) callconv(.C) BOOL,
3628 else => ?*const fn (?LPVOID, *ENUM_PAGE_FILE_INFORMATION, LPCSTR) callconv(.C) BOOL,
3629};
36033630
36043631pub const PSAPI_WS_WATCH_INFORMATION_EX = extern struct {
36053632 BasicInfo: PSAPI_WS_WATCH_INFORMATION,
......@@ -3699,4 +3726,7 @@ pub const CTRL_CLOSE_EVENT: DWORD = 2;
36993726pub const CTRL_LOGOFF_EVENT: DWORD = 5;
37003727pub const CTRL_SHUTDOWN_EVENT: DWORD = 6;
37013728
3702pub const HANDLER_ROUTINE = fn (dwCtrlType: DWORD) callconv(.C) BOOL;
3729pub const HANDLER_ROUTINE = switch (builtin.zig_backend) {
3730 .stage1 => fn (dwCtrlType: DWORD) callconv(.C) BOOL,
3731 else => *const fn (dwCtrlType: DWORD) callconv(.C) BOOL,
3732};
lib/std/pdb.zig+25-25
......@@ -14,7 +14,7 @@ const ArrayList = std.ArrayList;
1414// documentation and/or contributors.
1515
1616// https://llvm.org/docs/PDB/DbiStream.html#stream-header
17pub const DbiStreamHeader = packed struct {
17pub const DbiStreamHeader = extern struct {
1818 VersionSignature: i32,
1919 VersionHeader: u32,
2020 Age: u32,
......@@ -37,7 +37,7 @@ pub const DbiStreamHeader = packed struct {
3737 Padding: u32,
3838};
3939
40pub const SectionContribEntry = packed struct {
40pub const SectionContribEntry = extern struct {
4141 /// COFF Section index, 1-based
4242 Section: u16,
4343 Padding1: [2]u8,
......@@ -50,7 +50,7 @@ pub const SectionContribEntry = packed struct {
5050 RelocCrc: u32,
5151};
5252
53pub const ModInfo = packed struct {
53pub const ModInfo = extern struct {
5454 Unused1: u32,
5555 SectionContr: SectionContribEntry,
5656 Flags: u16,
......@@ -68,7 +68,7 @@ pub const ModInfo = packed struct {
6868 //ObjFileName: char[],
6969};
7070
71pub const SectionMapHeader = packed struct {
71pub const SectionMapHeader = extern struct {
7272 /// Number of segment descriptors
7373 Count: u16,
7474
......@@ -76,7 +76,7 @@ pub const SectionMapHeader = packed struct {
7676 LogCount: u16,
7777};
7878
79pub const SectionMapEntry = packed struct {
79pub const SectionMapEntry = extern struct {
8080 /// See the SectionMapEntryFlags enum below.
8181 Flags: u16,
8282
......@@ -310,7 +310,7 @@ pub const SymbolKind = enum(u16) {
310310
311311pub const TypeIndex = u32;
312312
313pub const ProcSym = packed struct {
313pub const ProcSym = extern struct {
314314 Parent: u32,
315315 End: u32,
316316 Next: u32,
......@@ -342,7 +342,7 @@ pub const SectionContrSubstreamVersion = enum(u32) {
342342 _,
343343};
344344
345pub const RecordPrefix = packed struct {
345pub const RecordPrefix = extern struct {
346346 /// Record length, starting from &RecordKind.
347347 RecordLen: u16,
348348
......@@ -354,7 +354,7 @@ pub const RecordPrefix = packed struct {
354354/// The structure definition follows.
355355/// LineBlockFragmentHeader Blocks[]
356356/// Each `LineBlockFragmentHeader` as specified below.
357pub const LineFragmentHeader = packed struct {
357pub const LineFragmentHeader = extern struct {
358358 /// Code offset of line contribution.
359359 RelocOffset: u32,
360360
......@@ -376,7 +376,7 @@ pub const LineFlags = packed struct {
376376/// header. The structure definitions follow.
377377/// LineNumberEntry Lines[NumLines];
378378/// ColumnNumberEntry Columns[NumLines];
379pub const LineBlockFragmentHeader = packed struct {
379pub const LineBlockFragmentHeader = extern struct {
380380 /// Offset of FileChecksum entry in File
381381 /// checksums buffer. The checksum entry then
382382 /// contains another offset into the string
......@@ -388,7 +388,7 @@ pub const LineBlockFragmentHeader = packed struct {
388388 BlockSize: u32,
389389};
390390
391pub const LineNumberEntry = packed struct {
391pub const LineNumberEntry = extern struct {
392392 /// Offset to start of code bytes for line number
393393 Offset: u32,
394394 Flags: u32,
......@@ -404,13 +404,13 @@ pub const LineNumberEntry = packed struct {
404404 };
405405};
406406
407pub const ColumnNumberEntry = packed struct {
407pub const ColumnNumberEntry = extern struct {
408408 StartColumn: u16,
409409 EndColumn: u16,
410410};
411411
412412/// Checksum bytes follow.
413pub const FileChecksumEntryHeader = packed struct {
413pub const FileChecksumEntryHeader = extern struct {
414414 /// Byte offset of filename in global string table.
415415 FileNameOffset: u32,
416416
......@@ -441,7 +441,7 @@ pub const DebugSubsectionKind = enum(u32) {
441441 CoffSymbolRVA = 0xfd,
442442};
443443
444pub const DebugSubsectionHeader = packed struct {
444pub const DebugSubsectionHeader = extern struct {
445445 /// codeview::DebugSubsectionKind enum
446446 Kind: DebugSubsectionKind,
447447
......@@ -449,7 +449,7 @@ pub const DebugSubsectionHeader = packed struct {
449449 Length: u32,
450450};
451451
452pub const PDBStringTableHeader = packed struct {
452pub const PDBStringTableHeader = extern struct {
453453 /// PDBStringTableSignature
454454 Signature: u32,
455455
......@@ -686,12 +686,12 @@ pub const Pdb = struct {
686686
687687 var symbol_i: usize = 0;
688688 while (symbol_i != module.symbols.len) {
689 const prefix = @ptrCast(*RecordPrefix, &module.symbols[symbol_i]);
689 const prefix = @ptrCast(*align(1) RecordPrefix, &module.symbols[symbol_i]);
690690 if (prefix.RecordLen < 2)
691691 return null;
692692 switch (prefix.RecordKind) {
693693 .S_LPROC32, .S_GPROC32 => {
694 const proc_sym = @ptrCast(*ProcSym, &module.symbols[symbol_i + @sizeOf(RecordPrefix)]);
694 const proc_sym = @ptrCast(*align(1) ProcSym, &module.symbols[symbol_i + @sizeOf(RecordPrefix)]);
695695 if (address >= proc_sym.CodeOffset and address < proc_sym.CodeOffset + proc_sym.CodeSize) {
696696 return mem.sliceTo(@ptrCast([*:0]u8, proc_sym) + @sizeOf(ProcSym), 0);
697697 }
......@@ -712,7 +712,7 @@ pub const Pdb = struct {
712712 var skip_len: usize = undefined;
713713 const checksum_offset = module.checksum_offset orelse return error.MissingDebugInfo;
714714 while (sect_offset != subsect_info.len) : (sect_offset += skip_len) {
715 const subsect_hdr = @ptrCast(*DebugSubsectionHeader, &subsect_info[sect_offset]);
715 const subsect_hdr = @ptrCast(*align(1) DebugSubsectionHeader, &subsect_info[sect_offset]);
716716 skip_len = subsect_hdr.Length;
717717 sect_offset += @sizeOf(DebugSubsectionHeader);
718718
......@@ -720,7 +720,7 @@ pub const Pdb = struct {
720720 .Lines => {
721721 var line_index = sect_offset;
722722
723 const line_hdr = @ptrCast(*LineFragmentHeader, &subsect_info[line_index]);
723 const line_hdr = @ptrCast(*align(1) LineFragmentHeader, &subsect_info[line_index]);
724724 if (line_hdr.RelocSegment == 0)
725725 return error.MissingDebugInfo;
726726 line_index += @sizeOf(LineFragmentHeader);
......@@ -734,7 +734,7 @@ pub const Pdb = struct {
734734 const subsection_end_index = sect_offset + subsect_hdr.Length;
735735
736736 while (line_index < subsection_end_index) {
737 const block_hdr = @ptrCast(*LineBlockFragmentHeader, &subsect_info[line_index]);
737 const block_hdr = @ptrCast(*align(1) LineBlockFragmentHeader, &subsect_info[line_index]);
738738 line_index += @sizeOf(LineBlockFragmentHeader);
739739 const start_line_index = line_index;
740740
......@@ -746,7 +746,7 @@ pub const Pdb = struct {
746746 // This is done with a simple linear search.
747747 var line_i: u32 = 0;
748748 while (line_i < block_hdr.NumLines) : (line_i += 1) {
749 const line_num_entry = @ptrCast(*LineNumberEntry, &subsect_info[line_index]);
749 const line_num_entry = @ptrCast(*align(1) LineNumberEntry, &subsect_info[line_index]);
750750 line_index += @sizeOf(LineNumberEntry);
751751
752752 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
......@@ -758,7 +758,7 @@ pub const Pdb = struct {
758758 // line_i == 0 would mean that no matching LineNumberEntry was found.
759759 if (line_i > 0) {
760760 const subsect_index = checksum_offset + block_hdr.NameIndex;
761 const chksum_hdr = @ptrCast(*FileChecksumEntryHeader, &module.subsect_info[subsect_index]);
761 const chksum_hdr = @ptrCast(*align(1) FileChecksumEntryHeader, &module.subsect_info[subsect_index]);
762762 const strtab_offset = @sizeOf(PDBStringTableHeader) + chksum_hdr.FileNameOffset;
763763 try self.string_table.?.seekTo(strtab_offset);
764764 const source_file_name = try self.string_table.?.reader().readUntilDelimiterAlloc(self.allocator, 0, 1024);
......@@ -768,12 +768,12 @@ pub const Pdb = struct {
768768 const column = if (has_column) blk: {
769769 const start_col_index = start_line_index + @sizeOf(LineNumberEntry) * block_hdr.NumLines;
770770 const col_index = start_col_index + @sizeOf(ColumnNumberEntry) * line_entry_idx;
771 const col_num_entry = @ptrCast(*ColumnNumberEntry, &subsect_info[col_index]);
771 const col_num_entry = @ptrCast(*align(1) ColumnNumberEntry, &subsect_info[col_index]);
772772 break :blk col_num_entry.StartColumn;
773773 } else 0;
774774
775775 const found_line_index = start_line_index + line_entry_idx * @sizeOf(LineNumberEntry);
776 const line_num_entry = @ptrCast(*LineNumberEntry, &subsect_info[found_line_index]);
776 const line_num_entry = @ptrCast(*align(1) LineNumberEntry, &subsect_info[found_line_index]);
777777 const flags = @ptrCast(*LineNumberEntry.Flags, &line_num_entry.Flags);
778778
779779 return debug.LineInfo{
......@@ -833,7 +833,7 @@ pub const Pdb = struct {
833833 var sect_offset: usize = 0;
834834 var skip_len: usize = undefined;
835835 while (sect_offset != mod.subsect_info.len) : (sect_offset += skip_len) {
836 const subsect_hdr = @ptrCast(*DebugSubsectionHeader, &mod.subsect_info[sect_offset]);
836 const subsect_hdr = @ptrCast(*align(1) DebugSubsectionHeader, &mod.subsect_info[sect_offset]);
837837 skip_len = subsect_hdr.Length;
838838 sect_offset += @sizeOf(DebugSubsectionHeader);
839839
......@@ -969,7 +969,7 @@ fn blockCountFromSize(size: u32, block_size: u32) u32 {
969969}
970970
971971// https://llvm.org/docs/PDB/MsfFile.html#the-superblock
972const SuperBlock = packed struct {
972const SuperBlock = extern struct {
973973 /// The LLVM docs list a space between C / C++ but empirically this is not the case.
974974 const file_magic = "Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\x00\x00\x00";
975975
lib/std/special/test_runner.zig+1-1
......@@ -28,7 +28,7 @@ pub fn main() void {
2828 {
2929 return main2() catch @panic("test failure");
3030 }
31 if (builtin.zig_backend == .stage1) processArgs();
31 processArgs();
3232 const test_fn_list = builtin.test_functions;
3333 var ok_count: usize = 0;
3434 var skip_count: usize = 0;
lib/std/start.zig+1-3
......@@ -29,9 +29,7 @@ comptime {
2929 builtin.zig_backend == .stage2_aarch64 or
3030 builtin.zig_backend == .stage2_arm or
3131 builtin.zig_backend == .stage2_riscv64 or
32 builtin.zig_backend == .stage2_sparcv9 or
33 (builtin.zig_backend == .stage2_llvm and native_os != .linux and native_os != .macos) or
34 (builtin.zig_backend == .stage2_llvm and native_arch != .x86_64 and native_arch != .aarch64))
32 builtin.zig_backend == .stage2_sparcv9)
3533 {
3634 if (builtin.output_mode == .Exe) {
3735 if ((builtin.link_libc or builtin.object_format == .c) and @hasDecl(root, "main")) {
src/Air.zig+2
......@@ -815,6 +815,8 @@ pub const VectorCmp = struct {
815815/// 1. `Inst.Ref` for every inputs_len
816816/// 2. for every outputs_len
817817/// - constraint: memory at this position is reinterpreted as a null
818/// terminated string.
819/// - name: memory at this position is reinterpreted as a null
818820/// terminated string. pad to the next u32 after the null byte.
819821/// 3. for every inputs_len
820822/// - constraint: memory at this position is reinterpreted as a null
src/Sema.zig+14-6
......@@ -4323,7 +4323,7 @@ pub fn analyzeExport(
43234323 const exported_decl = mod.declPtr(exported_decl_index);
43244324 // TODO run the same checks as we do for C ABI struct fields
43254325 switch (exported_decl.ty.zigTypeTag()) {
4326 .Fn, .Int, .Enum, .Struct, .Union, .Array, .Float => {},
4326 .Fn, .Int, .Enum, .Struct, .Union, .Array, .Float, .Pointer, .Optional => {},
43274327 else => return sema.fail(block, src, "unable to export type '{}'", .{
43284328 exported_decl.ty.fmt(sema.mod),
43294329 }),
......@@ -10535,7 +10535,11 @@ fn zirAsm(
1053510535 var output_type_bits = extra.data.output_type_bits;
1053610536 var needed_capacity: usize = @typeInfo(Air.Asm).Struct.fields.len + outputs_len + inputs_len;
1053710537
10538 const Output = struct { constraint: []const u8, ty: Type };
10538 const Output = struct {
10539 constraint: []const u8,
10540 name: []const u8,
10541 ty: Type,
10542 };
1053910543 const output: ?Output = if (outputs_len == 0) null else blk: {
1054010544 const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i);
1054110545 extra_i = output.end;
......@@ -10548,10 +10552,12 @@ fn zirAsm(
1054810552 }
1054910553
1055010554 const constraint = sema.code.nullTerminatedString(output.data.constraint);
10551 needed_capacity += constraint.len / 4 + 1;
10555 const name = sema.code.nullTerminatedString(output.data.name);
10556 needed_capacity += (constraint.len + name.len + (2 + 3)) / 4;
1055210557
1055310558 break :blk Output{
1055410559 .constraint = constraint,
10560 .name = name,
1055510561 .ty = try sema.resolveType(block, ret_ty_src, output.data.operand),
1055610562 };
1055710563 };
......@@ -10573,7 +10579,7 @@ fn zirAsm(
1057310579
1057410580 const constraint = sema.code.nullTerminatedString(input.data.constraint);
1057510581 const name = sema.code.nullTerminatedString(input.data.name);
10576 needed_capacity += (constraint.len + name.len + 1) / 4 + 1;
10582 needed_capacity += (constraint.len + name.len + (2 + 3)) / 4;
1057710583 inputs[arg_i] = .{ .c = constraint, .n = name };
1057810584 }
1057910585
......@@ -10611,7 +10617,9 @@ fn zirAsm(
1061110617 const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
1061210618 mem.copy(u8, buffer, o.constraint);
1061310619 buffer[o.constraint.len] = 0;
10614 sema.air_extra.items.len += o.constraint.len / 4 + 1;
10620 mem.copy(u8, buffer[o.constraint.len + 1 ..], o.name);
10621 buffer[o.constraint.len + 1 + o.name.len] = 0;
10622 sema.air_extra.items.len += (o.constraint.len + o.name.len + (2 + 3)) / 4;
1061510623 }
1061610624 for (inputs) |input| {
1061710625 const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
......@@ -10619,7 +10627,7 @@ fn zirAsm(
1061910627 buffer[input.c.len] = 0;
1062010628 mem.copy(u8, buffer[input.c.len + 1 ..], input.n);
1062110629 buffer[input.c.len + 1 + input.n.len] = 0;
10622 sema.air_extra.items.len += (input.c.len + input.n.len + 1) / 4 + 1;
10630 sema.air_extra.items.len += (input.c.len + input.n.len + (2 + 3)) / 4;
1062310631 }
1062410632 for (clobbers) |clobber| {
1062510633 const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
src/arch/aarch64/CodeGen.zig+5-3
......@@ -3272,10 +3272,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
32723272 if (output != .none) {
32733273 return self.fail("TODO implement codegen for non-expr asm", .{});
32743274 }
3275 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
32753276 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
3277 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
32763278 // This equation accounts for the fact that even if we have exactly 4 bytes
32773279 // for the string, we still use the next u32 for the null terminator.
3278 extra_i += constraint.len / 4 + 1;
3280 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
32793281
32803282 break constraint;
32813283 } else null;
......@@ -3283,10 +3285,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
32833285 for (inputs) |input| {
32843286 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
32853287 const constraint = std.mem.sliceTo(input_bytes, 0);
3286 const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
3288 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
32873289 // This equation accounts for the fact that even if we have exactly 4 bytes
32883290 // for the string, we still use the next u32 for the null terminator.
3289 extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
3291 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
32903292
32913293 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
32923294 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
src/arch/arm/CodeGen.zig+5-3
......@@ -4078,10 +4078,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
40784078 if (output != .none) {
40794079 return self.fail("TODO implement codegen for non-expr asm", .{});
40804080 }
4081 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
40814082 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
4083 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
40824084 // This equation accounts for the fact that even if we have exactly 4 bytes
40834085 // for the string, we still use the next u32 for the null terminator.
4084 extra_i += constraint.len / 4 + 1;
4086 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
40854087
40864088 break constraint;
40874089 } else null;
......@@ -4089,10 +4091,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
40894091 for (inputs) |input| {
40904092 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
40914093 const constraint = std.mem.sliceTo(input_bytes, 0);
4092 const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
4094 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
40934095 // This equation accounts for the fact that even if we have exactly 4 bytes
40944096 // for the string, we still use the next u32 for the null terminator.
4095 extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
4097 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
40964098
40974099 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
40984100 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
src/arch/riscv64/CodeGen.zig+5-3
......@@ -2098,10 +2098,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
20982098 if (output != .none) {
20992099 return self.fail("TODO implement codegen for non-expr asm", .{});
21002100 }
2101 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
21012102 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
2103 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
21022104 // This equation accounts for the fact that even if we have exactly 4 bytes
21032105 // for the string, we still use the next u32 for the null terminator.
2104 extra_i += constraint.len / 4 + 1;
2106 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
21052107
21062108 break constraint;
21072109 } else null;
......@@ -2109,10 +2111,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
21092111 for (inputs) |input| {
21102112 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
21112113 const constraint = std.mem.sliceTo(input_bytes, 0);
2112 const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
2114 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
21132115 // This equation accounts for the fact that even if we have exactly 4 bytes
21142116 // for the string, we still use the next u32 for the null terminator.
2115 extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
2117 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
21162118
21172119 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
21182120 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
src/arch/sparcv9/CodeGen.zig+5-3
......@@ -642,10 +642,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
642642 if (output != .none) {
643643 return self.fail("TODO implement codegen for non-expr asm", .{});
644644 }
645 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
645646 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
647 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
646648 // This equation accounts for the fact that even if we have exactly 4 bytes
647649 // for the string, we still use the next u32 for the null terminator.
648 extra_i += constraint.len / 4 + 1;
650 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
649651
650652 break constraint;
651653 } else null;
......@@ -653,10 +655,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
653655 for (inputs) |input| {
654656 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
655657 const constraint = std.mem.sliceTo(input_bytes, 0);
656 const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
658 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
657659 // This equation accounts for the fact that even if we have exactly 4 bytes
658660 // for the string, we still use the next u32 for the null terminator.
659 extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
661 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
660662
661663 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
662664 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
src/arch/x86_64/CodeGen.zig+5-3
......@@ -4738,10 +4738,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
47384738 if (output != .none) {
47394739 return self.fail("TODO implement codegen for non-expr asm", .{});
47404740 }
4741 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
47414742 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
4743 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
47424744 // This equation accounts for the fact that even if we have exactly 4 bytes
47434745 // for the string, we still use the next u32 for the null terminator.
4744 extra_i += constraint.len / 4 + 1;
4746 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
47454747
47464748 break constraint;
47474749 } else null;
......@@ -4749,10 +4751,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
47494751 for (inputs) |input| {
47504752 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
47514753 const constraint = std.mem.sliceTo(input_bytes, 0);
4752 const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
4754 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
47534755 // This equation accounts for the fact that even if we have exactly 4 bytes
47544756 // for the string, we still use the next u32 for the null terminator.
4755 extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
4757 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
47564758
47574759 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
47584760 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
src/codegen/c.zig+7-3
......@@ -3018,10 +3018,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
30183018 if (output != .none) {
30193019 return f.fail("TODO implement codegen for non-expr asm", .{});
30203020 }
3021 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
30213022 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
3023 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
30223024 // This equation accounts for the fact that even if we have exactly 4 bytes
30233025 // for the string, we still use the next u32 for the null terminator.
3024 extra_i += constraint.len / 4 + 1;
3026 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
30253027
30263028 break constraint;
30273029 } else null;
......@@ -3031,10 +3033,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
30313033
30323034 const inputs_extra_begin = extra_i;
30333035 for (inputs) |input, i| {
3034 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
3036 const input_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3037 const constraint = std.mem.sliceTo(input_bytes, 0);
3038 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
30353039 // This equation accounts for the fact that even if we have exactly 4 bytes
30363040 // for the string, we still use the next u32 for the null terminator.
3037 extra_i += constraint.len / 4 + 1;
3041 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
30383042
30393043 if (constraint[0] == '{' and constraint[constraint.len - 1] == '}') {
30403044 const reg = constraint[1 .. constraint.len - 1];
src/codegen/llvm.zig+41-20
......@@ -340,6 +340,10 @@ pub const Object = struct {
340340
341341 llvm_module.setModuleDataLayout(target_data);
342342
343 if (options.pic) llvm_module.setModulePICLevel();
344 if (options.pie) llvm_module.setModulePIELevel();
345 if (code_model != .Default) llvm_module.setModuleCodeModel(code_model);
346
343347 return Object{
344348 .gpa = gpa,
345349 .module = options.module.?,
......@@ -4577,6 +4581,10 @@ pub const FuncGen = struct {
45774581 const operand_ty = self.air.typeOf(pl_op.operand);
45784582 const name = self.air.nullTerminatedString(pl_op.payload);
45794583
4584 if (needDbgVarWorkaround(self.dg, operand_ty)) {
4585 return null;
4586 }
4587
45804588 const di_local_var = dib.createAutoVariable(
45814589 self.di_scope.?,
45824590 name.ptr,
......@@ -4638,14 +4646,19 @@ pub const FuncGen = struct {
46384646 var llvm_param_i: usize = 0;
46394647 var total_i: usize = 0;
46404648
4649 var name_map: std.StringArrayHashMapUnmanaged(void) = .{};
4650 try name_map.ensureUnusedCapacity(arena, outputs.len + inputs.len);
4651
46414652 for (outputs) |output| {
46424653 if (output != .none) {
46434654 return self.todo("implement inline asm with non-returned output", .{});
46444655 }
4656 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
46454657 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
4658 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
46464659 // This equation accounts for the fact that even if we have exactly 4 bytes
46474660 // for the string, we still use the next u32 for the null terminator.
4648 extra_i += constraint.len / 4 + 1;
4661 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
46494662
46504663 try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1);
46514664 if (total_i != 0) {
......@@ -4654,17 +4667,17 @@ pub const FuncGen = struct {
46544667 llvm_constraints.appendAssumeCapacity('=');
46554668 llvm_constraints.appendSliceAssumeCapacity(constraint[1..]);
46564669
4670 name_map.putAssumeCapacityNoClobber(name, {});
46574671 total_i += 1;
46584672 }
46594673
4660 const input_start_extra_i = extra_i;
46614674 for (inputs) |input| {
4662 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
4663 const constraint = std.mem.sliceTo(input_bytes, 0);
4664 const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
4675 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
4676 const constraint = std.mem.sliceTo(extra_bytes, 0);
4677 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
46654678 // This equation accounts for the fact that even if we have exactly 4 bytes
46664679 // for the string, we still use the next u32 for the null terminator.
4667 extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
4680 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
46684681
46694682 const arg_llvm_value = try self.resolveInst(input);
46704683
......@@ -4677,6 +4690,7 @@ pub const FuncGen = struct {
46774690 }
46784691 llvm_constraints.appendSliceAssumeCapacity(constraint);
46794692
4693 name_map.putAssumeCapacityNoClobber(name, {});
46804694 llvm_param_i += 1;
46814695 total_i += 1;
46824696 }
......@@ -4739,20 +4753,11 @@ pub const FuncGen = struct {
47394753 const name = asm_source[name_start..i];
47404754 state = .start;
47414755
4742 extra_i = input_start_extra_i;
4743 for (inputs) |_, input_i| {
4744 const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
4745 const constraint = std.mem.sliceTo(input_bytes, 0);
4746 const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
4747 extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
4748
4749 if (std.mem.eql(u8, name, input_name)) {
4750 try rendered_template.writer().print("{d}", .{input_i});
4751 break;
4752 }
4753 } else {
4754 return self.todo("TODO validate asm in Sema", .{});
4755 }
4756 const index = name_map.getIndex(name) orelse {
4757 // we should validate the assembly in Sema; by now it is too late
4758 return self.todo("unknown input or output name: '{s}'", .{name});
4759 };
4760 try rendered_template.writer().print("{d}", .{index});
47564761 },
47574762 else => {},
47584763 },
......@@ -6150,6 +6155,10 @@ pub const FuncGen = struct {
61506155
61516156 const inst_ty = self.air.typeOfIndex(inst);
61526157 if (self.dg.object.di_builder) |dib| {
6158 if (needDbgVarWorkaround(self.dg, inst_ty)) {
6159 return arg_val;
6160 }
6161
61536162 const src_index = self.getSrcArgIndex(self.arg_index - 1);
61546163 const func = self.dg.decl.getFunction().?;
61556164 const lbrace_line = self.dg.module.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
......@@ -8251,3 +8260,15 @@ const AnnotatedDITypePtr = enum(usize) {
82518260};
82528261
82538262const lt_errors_fn_name = "__zig_lt_errors_len";
8263
8264/// Without this workaround, LLVM crashes with "unknown codeview register H1"
8265/// TODO use llvm-reduce and file upstream LLVM bug for this.
8266fn needDbgVarWorkaround(dg: *DeclGen, ty: Type) bool {
8267 if (ty.tag() == .f16) {
8268 const target = dg.module.getTarget();
8269 if (target.os.tag == .windows and target.cpu.arch == .aarch64) {
8270 return true;
8271 }
8272 }
8273 return false;
8274}
src/codegen/llvm/bindings.zig+9
......@@ -310,6 +310,15 @@ pub const Module = opaque {
310310 pub const setModuleDataLayout = LLVMSetModuleDataLayout;
311311 extern fn LLVMSetModuleDataLayout(*const Module, *const TargetData) void;
312312
313 pub const setModulePICLevel = ZigLLVMSetModulePICLevel;
314 extern fn ZigLLVMSetModulePICLevel(module: *const Module) void;
315
316 pub const setModulePIELevel = ZigLLVMSetModulePIELevel;
317 extern fn ZigLLVMSetModulePIELevel(module: *const Module) void;
318
319 pub const setModuleCodeModel = ZigLLVMSetModuleCodeModel;
320 extern fn ZigLLVMSetModuleCodeModel(module: *const Module, code_model: CodeModel) void;
321
313322 pub const addFunction = LLVMAddFunction;
314323 extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value;
315324
src/print_air.zig+18-10
......@@ -542,15 +542,19 @@ const Writer = struct {
542542 extra_i += inputs.len;
543543
544544 for (outputs) |output| {
545 const constraint = w.air.nullTerminatedString(extra_i);
545 const extra_bytes = std.mem.sliceAsBytes(w.air.extra[extra_i..]);
546 const constraint = std.mem.sliceTo(extra_bytes, 0);
547 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
548
546549 // This equation accounts for the fact that even if we have exactly 4 bytes
547 // for the string, we still use the next u32 for the null terminator.
548 extra_i += constraint.len / 4 + 1;
550 // for the strings and their null terminators, we still use the next u32
551 // for the null terminator.
552 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
549553
550554 if (output == .none) {
551 try s.print(", -> {s}", .{constraint});
555 try s.print(", [{s}] -> {s}", .{ name, constraint });
552556 } else {
553 try s.print(", out {s} = (", .{constraint});
557 try s.print(", [{s}] out {s} = (", .{ name, constraint });
554558 try w.writeOperand(s, inst, op_index, output);
555559 op_index += 1;
556560 try s.writeByte(')');
......@@ -558,12 +562,15 @@ const Writer = struct {
558562 }
559563
560564 for (inputs) |input| {
561 const constraint = w.air.nullTerminatedString(extra_i);
565 const extra_bytes = std.mem.sliceAsBytes(w.air.extra[extra_i..]);
566 const constraint = std.mem.sliceTo(extra_bytes, 0);
567 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
562568 // This equation accounts for the fact that even if we have exactly 4 bytes
563 // for the string, we still use the next u32 for the null terminator.
564 extra_i += constraint.len / 4 + 1;
569 // for the strings and their null terminators, we still use the next u32
570 // for the null terminator.
571 extra_i += (constraint.len + name.len + 1) / 4 + 1;
565572
566 try s.print(", in {s} = (", .{constraint});
573 try s.print(", [{s}] in {s} = (", .{ name, constraint });
567574 try w.writeOperand(s, inst, op_index, input);
568575 op_index += 1;
569576 try s.writeByte(')');
......@@ -572,7 +579,8 @@ const Writer = struct {
572579 {
573580 var clobber_i: u32 = 0;
574581 while (clobber_i < clobbers_len) : (clobber_i += 1) {
575 const clobber = w.air.nullTerminatedString(extra_i);
582 const extra_bytes = std.mem.sliceAsBytes(w.air.extra[extra_i..]);
583 const clobber = std.mem.sliceTo(extra_bytes, 0);
576584 // This equation accounts for the fact that even if we have exactly 4 bytes
577585 // for the string, we still use the next u32 for the null terminator.
578586 extra_i += clobber.len / 4 + 1;
test/behavior/struct.zig+4-15
......@@ -421,21 +421,10 @@ test "packed struct 24bits" {
421421 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO
422422
423423 comptime {
424 // TODO Remove if and leave only the else branch when it is also fixed in stage2
425 if (builtin.zig_backend == .stage2_llvm or builtin.zig_backend == .stage2_x86 or
426 builtin.zig_backend == .stage2_riscv64)
427 {
428 // Stage 2 still expects the wrong values
429 try expect(@sizeOf(Foo24Bits) == 4);
430 if (@sizeOf(usize) == 4) {
431 try expect(@sizeOf(Foo96Bits) == 12);
432 } else {
433 try expect(@sizeOf(Foo96Bits) == 16);
434 }
435 } else {
436 // Stage1 is now fixed and is expected to return right values
437 try expectEqual(@sizeOf(Foo24Bits), 3);
438 try expectEqual(@sizeOf(Foo96Bits), 12);
424 // stage1 gets the wrong answer for sizeof
425 if (builtin.zig_backend != .stage1) {
426 std.debug.assert(@sizeOf(Foo24Bits) == @sizeOf(u24));
427 std.debug.assert(@sizeOf(Foo96Bits) == @sizeOf(u96));
439428 }
440429 }
441430
test/incremental/aarch64-macos/hello_world_with_updates.0.zig+1-1
......@@ -2,4 +2,4 @@
22// output_mode=Exe
33// target=aarch64-macos
44//
5// :109:9: error: struct 'tmp.tmp' has no member named 'main'
5// :107:9: error: struct 'tmp.tmp' has no member named 'main'
test/incremental/x86_64-linux/hello_world_with_updates.0.zig+1-1
......@@ -2,4 +2,4 @@
22// output_mode=Exe
33// target=x86_64-linux
44//
5// :109:9: error: struct 'tmp.tmp' has no member named 'main'
5// :107:9: error: struct 'tmp.tmp' has no member named 'main'
test/incremental/x86_64-macos/hello_world_with_updates.0.zig+1-1
......@@ -2,4 +2,4 @@
22// output_mode=Exe
33// target=x86_64-macos
44//
5// :109:9: error: struct 'tmp.tmp' has no member named 'main'
5// :107:9: error: struct 'tmp.tmp' has no member named 'main'