authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-08 10:53:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-08 10:53:22-07:00
logb6bb0ee1acd6fb9e3360f35d7b63687f755785f6
tree34f42b24cc683d13a9e78bd27f914dfee00c37b0
parent28353b315935e54b497f4abb875fac387e20f65f
parent84d5cc31c560749eda1e36b7bc9e6cf542eee550

Merge remote-tracking branch 'origin/master' into stage2-whole-file-astgen

Conflicts: * lib/std/os/linux/tls.zig * test/behavior/align.zig * test/behavior/atomics.zig * test/behavior/vector.zig

22 files changed, 305 insertions(+), 55 deletions(-)

lib/std/os/bits/linux.zig+1-1
......@@ -18,7 +18,7 @@ pub usingnamespace switch (arch) {
1818 .i386 => @import("linux/i386.zig"),
1919 .x86_64 => @import("linux/x86_64.zig"),
2020 .aarch64 => @import("linux/arm64.zig"),
21 .arm => @import("linux/arm-eabi.zig"),
21 .arm, .thumb => @import("linux/arm-eabi.zig"),
2222 .riscv64 => @import("linux/riscv64.zig"),
2323 .sparcv9 => @import("linux/sparc64.zig"),
2424 .mips, .mipsel => @import("linux/mips.zig"),
lib/std/os/linux.zig+1
......@@ -24,6 +24,7 @@ pub usingnamespace switch (native_arch) {
2424 .x86_64 => @import("linux/x86_64.zig"),
2525 .aarch64 => @import("linux/arm64.zig"),
2626 .arm => @import("linux/arm-eabi.zig"),
27 .thumb => @import("linux/thumb.zig"),
2728 .riscv64 => @import("linux/riscv64.zig"),
2829 .sparcv9 => @import("linux/sparc64.zig"),
2930 .mips, .mipsel => @import("linux/mips.zig"),
lib/std/os/linux/thumb.zig created+168
......@@ -0,0 +1,168 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2021 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6usingnamespace @import("../bits.zig");
7
8// The syscall interface is identical to the ARM one but we're facing an extra
9// challenge: r7, the register where the syscall number is stored, may be
10// reserved for the frame pointer.
11// Save and restore r7 around the syscall without touching the stack pointer not
12// to break the frame chain.
13
14pub fn syscall0(number: SYS) usize {
15 @setRuntimeSafety(false);
16
17 var buf: [2]usize = .{ @enumToInt(number), undefined };
18 return asm volatile (
19 \\ str r7, [%[tmp], #4]
20 \\ ldr r7, [%[tmp]]
21 \\ svc #0
22 \\ ldr r7, [%[tmp], #4]
23 : [ret] "={r0}" (-> usize)
24 : [tmp] "{r1}" (buf)
25 : "memory"
26 );
27}
28
29pub fn syscall1(number: SYS, arg1: usize) usize {
30 @setRuntimeSafety(false);
31
32 var buf: [2]usize = .{ @enumToInt(number), undefined };
33 return asm volatile (
34 \\ str r7, [%[tmp], #4]
35 \\ ldr r7, [%[tmp]]
36 \\ svc #0
37 \\ ldr r7, [%[tmp], #4]
38 : [ret] "={r0}" (-> usize)
39 : [tmp] "{r1}" (buf),
40 [arg1] "{r0}" (arg1)
41 : "memory"
42 );
43}
44
45pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
46 @setRuntimeSafety(false);
47
48 var buf: [2]usize = .{ @enumToInt(number), undefined };
49 return asm volatile (
50 \\ str r7, [%[tmp], #4]
51 \\ ldr r7, [%[tmp]]
52 \\ svc #0
53 \\ ldr r7, [%[tmp], #4]
54 : [ret] "={r0}" (-> usize)
55 : [tmp] "{r2}" (buf),
56 [arg1] "{r0}" (arg1),
57 [arg2] "{r1}" (arg2)
58 : "memory"
59 );
60}
61
62pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
63 @setRuntimeSafety(false);
64
65 var buf: [2]usize = .{ @enumToInt(number), undefined };
66 return asm volatile (
67 \\ str r7, [%[tmp], #4]
68 \\ ldr r7, [%[tmp]]
69 \\ svc #0
70 \\ ldr r7, [%[tmp], #4]
71 : [ret] "={r0}" (-> usize)
72 : [tmp] "{r3}" (buf),
73 [arg1] "{r0}" (arg1),
74 [arg2] "{r1}" (arg2),
75 [arg3] "{r2}" (arg3)
76 : "memory"
77 );
78}
79
80pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
81 @setRuntimeSafety(false);
82
83 var buf: [2]usize = .{ @enumToInt(number), undefined };
84 return asm volatile (
85 \\ str r7, [%[tmp], #4]
86 \\ ldr r7, [%[tmp]]
87 \\ svc #0
88 \\ ldr r7, [%[tmp], #4]
89 : [ret] "={r0}" (-> usize)
90 : [tmp] "{r4}" (buf),
91 [arg1] "{r0}" (arg1),
92 [arg2] "{r1}" (arg2),
93 [arg3] "{r2}" (arg3),
94 [arg4] "{r3}" (arg4)
95 : "memory"
96 );
97}
98
99pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
100 @setRuntimeSafety(false);
101
102 var buf: [2]usize = .{ @enumToInt(number), undefined };
103 return asm volatile (
104 \\ str r7, [%[tmp], #4]
105 \\ ldr r7, [%[tmp]]
106 \\ svc #0
107 \\ ldr r7, [%[tmp], #4]
108 : [ret] "={r0}" (-> usize)
109 : [tmp] "{r5}" (buf),
110 [arg1] "{r0}" (arg1),
111 [arg2] "{r1}" (arg2),
112 [arg3] "{r2}" (arg3),
113 [arg4] "{r3}" (arg4),
114 [arg5] "{r4}" (arg5)
115 : "memory"
116 );
117}
118
119pub fn syscall6(
120 number: SYS,
121 arg1: usize,
122 arg2: usize,
123 arg3: usize,
124 arg4: usize,
125 arg5: usize,
126 arg6: usize,
127) usize {
128 @setRuntimeSafety(false);
129
130 var buf: [2]usize = .{ @enumToInt(number), undefined };
131 return asm volatile (
132 \\ str r7, [%[tmp], #4]
133 \\ ldr r7, [%[tmp]]
134 \\ svc #0
135 \\ ldr r7, [%[tmp], #4]
136 : [ret] "={r0}" (-> usize)
137 : [tmp] "{r6}" (buf),
138 [arg1] "{r0}" (arg1),
139 [arg2] "{r1}" (arg2),
140 [arg3] "{r2}" (arg3),
141 [arg4] "{r3}" (arg4),
142 [arg5] "{r4}" (arg5),
143 [arg6] "{r5}" (arg6)
144 : "memory"
145 );
146}
147
148/// This matches the libc clone function.
149pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
150
151pub fn restore() callconv(.Naked) void {
152 return asm volatile (
153 \\ mov r7, %[number]
154 \\ svc #0
155 :
156 : [number] "I" (@enumToInt(SYS.sigreturn))
157 );
158}
159
160pub fn restore_rt() callconv(.Naked) void {
161 return asm volatile (
162 \\ mov r7, %[number]
163 \\ svc #0
164 :
165 : [number] "I" (@enumToInt(SYS.rt_sigreturn))
166 : "memory"
167 );
168}
lib/std/os/linux/tls.zig+3-3
......@@ -53,7 +53,7 @@ const TLSVariant = enum {
5353};
5454
5555const tls_variant = switch (native_arch) {
56 .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,
56 .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,
5757 .x86_64, .i386, .sparcv9 => TLSVariant.VariantII,
5858 else => @compileError("undefined tls_variant for this architecture"),
5959};
......@@ -62,7 +62,7 @@ const tls_variant = switch (native_arch) {
6262const tls_tcb_size = switch (native_arch) {
6363 // ARM EABI mandates enough space for two pointers: the first one points to
6464 // the DTV while the second one is unspecified but reserved
65 .arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),
65 .arm, .armeb, .thumb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),
6666 // One pointer-sized word that points either to the DTV or the TCB itself
6767 else => @sizeOf(usize),
6868};
......@@ -150,7 +150,7 @@ pub fn setThreadPointer(addr: usize) void {
150150 : [addr] "r" (addr)
151151 );
152152 },
153 .arm => {
153 .arm, .thumb => {
154154 const rc = std.os.linux.syscall1(.set_tls, addr);
155155 assert(rc == 0);
156156 },
lib/std/os/test.zig+2
......@@ -43,6 +43,8 @@ test "chdir smoke test" {
4343 // Next, change current working directory to one level above
4444 const parent = fs.path.dirname(old_cwd) orelse unreachable; // old_cwd should be absolute
4545 try os.chdir(parent);
46 // Restore cwd because process may have other tests that do not tolerate chdir.
47 defer os.chdir(old_cwd) catch unreachable;
4648 var new_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined;
4749 const new_cwd = try os.getcwd(new_cwd_buf[0..]);
4850 expect(mem.eql(u8, parent, new_cwd));
lib/std/special/c.zig+1-1
......@@ -388,7 +388,7 @@ fn clone() callconv(.Naked) void {
388388 \\ svc #0
389389 );
390390 },
391 .arm => {
391 .arm, .thumb => {
392392 // __clone(func, stack, flags, arg, ptid, tls, ctid)
393393 // r0, r1, r2, r3, +0, +4, +8
394394
lib/std/special/compiler_rt/clzsi2.zig+20-7
......@@ -26,6 +26,8 @@ fn __clzsi2_generic(a: i32) callconv(.C) i32 {
2626}
2727
2828fn __clzsi2_thumb1() callconv(.Naked) void {
29 @setRuntimeSafety(false);
30
2931 // Similar to the generic version with the last two rounds replaced by a LUT
3032 asm volatile (
3133 \\ movs r1, #32
......@@ -58,6 +60,8 @@ fn __clzsi2_thumb1() callconv(.Naked) void {
5860}
5961
6062fn __clzsi2_arm32() callconv(.Naked) void {
63 @setRuntimeSafety(false);
64
6165 asm volatile (
6266 \\ // Assumption: n != 0
6367 \\ // r0: n
......@@ -104,13 +108,22 @@ fn __clzsi2_arm32() callconv(.Naked) void {
104108 unreachable;
105109}
106110
107pub const __clzsi2 = switch (std.Target.current.cpu.arch) {
108 .arm, .armeb => if (std.Target.arm.featureSetHas(std.Target.current.cpu.features, .noarm))
109 __clzsi2_thumb1
110 else
111 __clzsi2_arm32,
112 .thumb, .thumbeb => __clzsi2_thumb1,
113 else => __clzsi2_generic,
111pub const __clzsi2 = impl: {
112 switch (std.Target.current.cpu.arch) {
113 .arm, .armeb, .thumb, .thumbeb => {
114 const use_thumb1 =
115 (std.Target.current.cpu.arch.isThumb() or
116 std.Target.arm.featureSetHas(std.Target.current.cpu.features, .noarm)) and
117 !std.Target.arm.featureSetHas(std.Target.current.cpu.features, .thumb2);
118
119 if (use_thumb1) break :impl __clzsi2_thumb1
120 // From here on we're either targeting Thumb2 or ARM.
121 else if (!std.Target.current.cpu.arch.isThumb()) break :impl __clzsi2_arm32
122 // Use the generic implementation otherwise.
123 else break :impl __clzsi2_generic;
124 },
125 else => break :impl __clzsi2_generic,
126 }
114127};
115128
116129test "test clzsi2" {
lib/std/special/compiler_rt/clzsi2_test.zig+2
......@@ -7,6 +7,8 @@ const clzsi2 = @import("clzsi2.zig");
77const testing = @import("std").testing;
88
99fn test__clzsi2(a: u32, expected: i32) void {
10 // XXX At high optimization levels this test may be horribly miscompiled if
11 // one of the naked implementations is selected.
1012 var nakedClzsi2 = clzsi2.__clzsi2;
1113 var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2);
1214 var x = @bitCast(i32, a);
lib/std/start.zig+1-1
......@@ -182,7 +182,7 @@ fn _start() callconv(.Naked) noreturn {
182182 : [argc] "={esp}" (-> [*]usize)
183183 );
184184 },
185 .aarch64, .aarch64_be, .arm, .armeb => {
185 .aarch64, .aarch64_be, .arm, .armeb, .thumb => {
186186 argc_argv_ptr = asm volatile (
187187 \\ mov fp, #0
188188 \\ mov lr, #0
lib/std/zig/system.zig+9
......@@ -350,6 +350,15 @@ pub const NativeTargetInfo = struct {
350350 }
351351 }
352352 },
353 .arm, .armeb => {
354 // XXX What do we do if the target has the noarm feature?
355 // What do we do if the user specifies +thumb_mode?
356 },
357 .thumb, .thumbeb => {
358 result.target.cpu.features.addFeature(
359 @enumToInt(std.Target.arm.Feature.thumb_mode),
360 );
361 },
353362 else => {},
354363 }
355364 cross_target.updateCpuFeatures(&result.target.cpu.features);
src/link/MachO/Archive.zig+6-3
......@@ -16,7 +16,7 @@ allocator: *Allocator,
1616arch: ?std.Target.Cpu.Arch = null,
1717file: ?fs.File = null,
1818header: ?ar_hdr = null,
19name: ?[]u8 = null,
19name: ?[]const u8 = null,
2020
2121/// Parsed table of contents.
2222/// Each symbol name points to a list of all definition
......@@ -195,7 +195,7 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void {
195195}
196196
197197/// Caller owns the Object instance.
198pub fn parseObject(self: Archive, offset: u32) !Object {
198pub fn parseObject(self: Archive, offset: u32) !*Object {
199199 var reader = self.file.?.reader();
200200 try reader.context.seekTo(offset);
201201
......@@ -217,7 +217,10 @@ pub fn parseObject(self: Archive, offset: u32) !Object {
217217 break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });
218218 };
219219
220 var object = Object.init(self.allocator);
220 var object = try self.allocator.create(Object);
221 errdefer self.allocator.destroy(object);
222
223 object.* = Object.init(self.allocator);
221224 object.arch = self.arch.?;
222225 object.file = try fs.cwd().openFile(self.name.?, .{});
223226 object.name = name;
src/link/MachO/Object.zig+21-5
......@@ -22,7 +22,7 @@ arch: ?std.Target.Cpu.Arch = null,
2222header: ?macho.mach_header_64 = null,
2323file: ?fs.File = null,
2424file_offset: ?u32 = null,
25name: ?[]u8 = null,
25name: ?[]const u8 = null,
2626
2727load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
2828sections: std.ArrayListUnmanaged(Section) = .{},
......@@ -343,14 +343,22 @@ pub fn parseSymbols(self: *Object) !void {
343343 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff);
344344
345345 for (slice) |sym| {
346 const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
347
346348 if (Symbol.isStab(sym)) {
347 log.err("TODO handle stabs embedded within object files", .{});
348 return error.HandleStabsInObjects;
349 log.err("stab {s} in {s}", .{ sym_name, self.name.? });
350 return error.UnhandledSymbolType;
351 }
352 if (Symbol.isIndr(sym)) {
353 log.err("indirect symbol {s} in {s}", .{ sym_name, self.name.? });
354 return error.UnhandledSymbolType;
355 }
356 if (Symbol.isAbs(sym)) {
357 log.err("absolute symbol {s} in {s}", .{ sym_name, self.name.? });
358 return error.UnhandledSymbolType;
349359 }
350360
351 const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
352361 const name = try self.allocator.dupe(u8, sym_name);
353
354362 const symbol: *Symbol = symbol: {
355363 if (Symbol.isSect(sym)) {
356364 const linkage: Symbol.Regular.Linkage = linkage: {
......@@ -374,6 +382,14 @@ pub fn parseSymbols(self: *Object) !void {
374382 break :symbol &regular.base;
375383 }
376384
385 if (sym.n_value != 0) {
386 log.err("common symbol {s} in {s}", .{ sym_name, self.name.? });
387 return error.UnhandledSymbolType;
388 // const comm_size = sym.n_value;
389 // const comm_align = (sym.n_desc >> 8) & 0x0f;
390 // log.warn("Common symbol: size 0x{x}, align 0x{x}", .{ comm_size, comm_align });
391 }
392
377393 const undef = try self.allocator.create(Symbol.Unresolved);
378394 errdefer self.allocator.destroy(undef);
379395 undef.* = .{
src/link/MachO/Symbol.zig+10
......@@ -133,6 +133,16 @@ pub fn isUndf(sym: macho.nlist_64) bool {
133133 return type_ == macho.N_UNDF;
134134}
135135
136pub fn isIndr(sym: macho.nlist_64) bool {
137 const type_ = macho.N_TYPE & sym.n_type;
138 return type_ == macho.N_INDR;
139}
140
141pub fn isAbs(sym: macho.nlist_64) bool {
142 const type_ = macho.N_TYPE & sym.n_type;
143 return type_ == macho.N_ABS;
144}
145
136146pub fn isWeakDef(sym: macho.nlist_64) bool {
137147 return (sym.n_desc & macho.N_WEAK_DEF) != 0;
138148}
src/link/MachO/Zld.zig+21-10
......@@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
8282strtab: std.ArrayListUnmanaged(u8) = .{},
8383strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
8484
85threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
85threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction
8686local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
8787stubs: std.ArrayListUnmanaged(*Symbol) = .{},
8888got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
......@@ -92,6 +92,15 @@ stub_helper_stubs_start_off: ?u64 = null,
9292mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{},
9393unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{},
9494
95const TlvOffset = struct {
96 source_addr: u64,
97 offset: u64,
98
99 fn cmp(context: void, a: TlvOffset, b: TlvOffset) bool {
100 return a.source_addr < b.source_addr;
101 }
102};
103
95104const MappingKey = struct {
96105 object_id: u16,
97106 source_sect_id: u16,
......@@ -277,7 +286,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
277286
278287 object.* = Object.init(self.allocator);
279288 object.arch = self.arch.?;
280 object.name = try self.allocator.dupe(u8, input.name);
289 object.name = input.name;
281290 object.file = input.file;
282291 try object.parse();
283292 try self.objects.append(self.allocator, object);
......@@ -288,7 +297,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
288297
289298 archive.* = Archive.init(self.allocator);
290299 archive.arch = self.arch.?;
291 archive.name = try self.allocator.dupe(u8, input.name);
300 archive.name = input.name;
292301 archive.file = input.file;
293302 try archive.parse();
294303 try self.archives.append(self.allocator, archive);
......@@ -1362,10 +1371,7 @@ fn resolveSymbols(self: *Zld) !void {
13621371 };
13631372 assert(offsets.items.len > 0);
13641373
1365 const object = try self.allocator.create(Object);
1366 errdefer self.allocator.destroy(object);
1367
1368 object.* = try archive.parseObject(offsets.items[0]);
1374 const object = try archive.parseObject(offsets.items[0]);
13691375 try self.objects.append(self.allocator, object);
13701376 try self.resolveSymbolsInObject(object);
13711377
......@@ -1567,7 +1573,10 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15671573 };
15681574 // Since we require TLV data to always preceed TLV bss section, we calculate
15691575 // offsets wrt to the former if it is defined; otherwise, wrt to the latter.
1570 try self.threadlocal_offsets.append(self.allocator, args.target_addr - base_addr);
1576 try self.threadlocal_offsets.append(self.allocator, .{
1577 .source_addr = args.source_addr,
1578 .offset = args.target_addr - base_addr,
1579 });
15711580 }
15721581 },
15731582 .got_page, .got_page_off, .got_load, .got => {
......@@ -2093,10 +2102,12 @@ fn flush(self: *Zld) !void {
20932102 var stream = std.io.fixedBufferStream(buffer);
20942103 var writer = stream.writer();
20952104
2105 std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
2106
20962107 const seek_amt = 2 * @sizeOf(u64);
2097 while (self.threadlocal_offsets.popOrNull()) |offset| {
2108 for (self.threadlocal_offsets.items) |tlv| {
20982109 try writer.context.seekBy(seek_amt);
2099 try writer.writeIntLittle(u64, offset);
2110 try writer.writeIntLittle(u64, tlv.offset);
21002111 }
21012112
21022113 try self.file.?.pwriteAll(buffer, sect.offset);
src/link/MachO/reloc/aarch64.zig+1-1
......@@ -25,7 +25,7 @@ pub const Branch = struct {
2525 log.debug(" | displacement 0x{x}", .{displacement});
2626
2727 var inst = branch.inst;
28 inst.unconditional_branch_immediate.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);
28 inst.unconditional_branch_immediate.imm26 = @truncate(u26, @bitCast(u28, displacement >> 2));
2929 mem.writeIntLittle(u32, branch.base.code[0..4], inst.toU32());
3030 }
3131};
src/stage1/codegen.cpp+3-1
......@@ -4880,6 +4880,9 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutableGen *executable, I
48804880 type_ref = get_llvm_type(g, wider_type);
48814881 value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref);
48824882 }
4883 } else if (handle_is_ptr(g, type)) {
4884 ZigType *gen_type = get_pointer_to_type(g, type, true);
4885 type_ref = get_llvm_type(g, gen_type);
48834886 }
48844887
48854888 param_types[param_index] = type_ref;
......@@ -9302,7 +9305,6 @@ static void init(CodeGen *g) {
93029305 char *layout_str = LLVMCopyStringRepOfTargetData(g->target_data_ref);
93039306 LLVMSetDataLayout(g->module, layout_str);
93049307
9305
93069308 assert(g->pointer_size_bytes == LLVMPointerSize(g->target_data_ref));
93079309 g->is_big_endian = (LLVMByteOrder(g->target_data_ref) == LLVMBigEndian);
93089310
src/stage1/parser.cpp+10-1
......@@ -825,7 +825,16 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
825825 AstNode *return_type = nullptr;
826826 if (anytype == nullptr) {
827827 exmark = eat_token_if(pc, TokenIdBang);
828 return_type = ast_expect(pc, ast_parse_type_expr);
828 return_type = ast_parse_type_expr(pc);
829 if (return_type == nullptr) {
830 Token *next = peek_token(pc);
831 ast_error(
832 pc,
833 next,
834 "expected return type (use 'void' to return nothing), found: '%s'",
835 token_name(next->id)
836 );
837 }
829838 }
830839
831840 AstNode *res = ast_create_node(pc, NodeTypeFnProto, first);
test/behavior/align.zig+3
......@@ -142,6 +142,7 @@ fn alignedBig() align(16) i32 {
142142test "@alignCast functions" {
143143 // function alignment is a compile error on wasm32/wasm64
144144 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
145 if (native_arch == .thumb) return error.SkipZigTest;
145146
146147 expect(fnExpectsOnly1(simple4) == 0x19);
147148}
......@@ -158,6 +159,7 @@ fn simple4() align(4) i32 {
158159test "generic function with align param" {
159160 // function alignment is a compile error on wasm32/wasm64
160161 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
162 if (native_arch == .thumb) return error.SkipZigTest;
161163
162164 expect(whyWouldYouEverDoThis(1) == 0x1);
163165 expect(whyWouldYouEverDoThis(4) == 0x1);
......@@ -339,6 +341,7 @@ test "align(@alignOf(T)) T does not force resolution of T" {
339341test "align(N) on functions" {
340342 // function alignment is a compile error on wasm32/wasm64
341343 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
344 if (native_arch == .thumb) return error.SkipZigTest;
342345
343346 expect((@ptrToInt(overaligned_fn) & (0x1000 - 1)) == 0);
344347}
test/behavior/asm.zig+15
......@@ -87,6 +87,21 @@ test "sized integer/float in asm input" {
8787 );
8888}
8989
90test "struct/array/union types as input values" {
91 asm volatile (""
92 :
93 : [_] "m" (@as([1]u32, undefined))
94 ); // fails
95 asm volatile (""
96 :
97 : [_] "m" (@as(struct { x: u32, y: u8 }, undefined))
98 ); // fails
99 asm volatile (""
100 :
101 : [_] "m" (@as(union { x: u32, y: u8 }, undefined))
102 ); // fails
103}
104
90105extern fn this_is_my_alias() i32;
91106
92107export fn derp() i32 {
test/behavior/async_fn.zig+4-1
......@@ -1,5 +1,5 @@
11const std = @import("std");
2const builtin = std.builtin;
2const builtin = @import("builtin");
33const expect = std.testing.expect;
44const expectEqual = std.testing.expectEqual;
55const expectEqualStrings = std.testing.expectEqualStrings;
......@@ -110,6 +110,9 @@ test "calling an inferred async function" {
110110}
111111
112112test "@frameSize" {
113 if (builtin.target.cpu.arch == .thumb or builtin.target.cpu.arch == .thumbeb)
114 return error.SkipZigTest;
115
113116 const S = struct {
114117 fn doTheTest() void {
115118 {
test/behavior/atomics.zig+3-5
......@@ -149,12 +149,10 @@ fn testAtomicStore() void {
149149}
150150
151151test "atomicrmw with floats" {
152 if (builtin.target.cpu.arch == .aarch64 or
153 builtin.target.cpu.arch == .arm or
154 builtin.target.cpu.arch == .riscv64)
155 {
152 switch (builtin.target.cpu.arch) {
156153 // https://github.com/ziglang/zig/issues/4457
157 return error.SkipZigTest;
154 .aarch64, .arm, .thumb, .riscv64 => return error.SkipZigTest,
155 else => {},
158156 }
159157 testAtomicRmwFloat();
160158 comptime testAtomicRmwFloat();
test/behavior/vector.zig-15
......@@ -510,21 +510,6 @@ test "vector reduce operation" {
510510 const N = @typeInfo(@TypeOf(x)).Array.len;
511511 const TX = @typeInfo(@TypeOf(x)).Array.child;
512512
513 // wasmtime: unknown import: `env::fminf` has not been defined
514 // https://github.com/ziglang/zig/issues/8131
515 switch (builtin.target.cpu.arch) {
516 .wasm32 => switch (@typeInfo(TX)) {
517 .Float => switch (op) {
518 .Min,
519 .Max,
520 => return,
521 else => {},
522 },
523 else => {},
524 },
525 else => {},
526 }
527
528513 var r = @reduce(op, @as(Vector(N, TX), x));
529514 switch (@typeInfo(TX)) {
530515 .Int, .Bool => expectEqual(expected, r),