authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-16 23:54:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-17 00:00:41-07:00
log87779cfd93fdcb525f386d693a099e4188a3fc44
treed5dab5dfbd5a5d93645996fde1c9c1199e2adf0b
parent79d3780fbda475a50d6e0ca53d51c9e7c7690ab1

stage2: prevent UB in the LLVM backend

* Sema: fix `zirTypeInfo` allocating with the wrong arenas for some stuff. * LLVM: split `airDbgInline` into two functions, one for each AIR tag. - remove the redundant copy to type_map_arena. This is the first thing that lowerDebugType does so this hack was probably just accidentally avoiding UB (which is still present prior to this commit). - don't store an inline fn inst into the di_map for the generic decl. - use a dummy function type for the debug info to avoid whatever UB is happening. - we are now ignoring the function type passed in with the dbg_inline_begin and dbg_inline_end. * behavior tests: prepare the vector tests to be enabled one at a time. Mitigates #11199.

4 files changed, 55 insertions(+), 30 deletions(-)

src/Sema.zig+4-4
...@@ -10907,9 +10907,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10907,9 +10907,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10907 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),10907 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10908 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),10908 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
10909 );10909 );
10910 break :v try Value.Tag.slice.create(sema.arena, .{10910 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
10911 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),10911 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
10912 .len = try Value.Tag.int_u64.create(sema.arena, bytes.len),10912 .len = try Value.Tag.int_u64.create(fields_anon_decl.arena(), bytes.len),
10913 });10913 });
10914 };10914 };
1091510915
...@@ -10950,9 +10950,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10950,9 +10950,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10950 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),10950 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10951 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),10951 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
10952 );10952 );
10953 break :v try Value.Tag.slice.create(sema.arena, .{10953 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
10954 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),10954 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
10955 .len = try Value.Tag.int_u64.create(sema.arena, bytes.len),10955 .len = try Value.Tag.int_u64.create(fields_anon_decl.arena(), bytes.len),
10956 });10956 });
10957 };10957 };
1095810958
src/codegen/llvm.zig+25-25
...@@ -3472,8 +3472,8 @@ pub const FuncGen = struct {...@@ -3472,8 +3472,8 @@ pub const FuncGen = struct {
3472 .const_ty => unreachable,3472 .const_ty => unreachable,
3473 .unreach => self.airUnreach(inst),3473 .unreach => self.airUnreach(inst),
3474 .dbg_stmt => self.airDbgStmt(inst),3474 .dbg_stmt => self.airDbgStmt(inst),
3475 .dbg_inline_begin => try self.airDbgInline(inst, true),3475 .dbg_inline_begin => try self.airDbgInlineBegin(inst),
3476 .dbg_inline_end => try self.airDbgInline(inst, false),3476 .dbg_inline_end => try self.airDbgInlineEnd(inst),
3477 .dbg_var_ptr => try self.airDbgVarPtr(inst),3477 .dbg_var_ptr => try self.airDbgVarPtr(inst),
3478 .dbg_var_val => try self.airDbgVarVal(inst),3478 .dbg_var_val => try self.airDbgVarVal(inst),
3479 // zig fmt: on3479 // zig fmt: on
...@@ -4199,7 +4199,7 @@ pub const FuncGen = struct {...@@ -4199,7 +4199,7 @@ pub const FuncGen = struct {
4199 return null;4199 return null;
4200 }4200 }
42014201
4202 fn airDbgInline(self: *FuncGen, inst: Air.Inst.Index, start: bool) !?*const llvm.Value {4202 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4203 const dib = self.dg.object.di_builder orelse return null;4203 const dib = self.dg.object.di_builder orelse return null;
4204 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;4204 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
42054205
...@@ -4209,52 +4209,52 @@ pub const FuncGen = struct {...@@ -4209,52 +4209,52 @@ pub const FuncGen = struct {
4209 self.di_file = di_file;4209 self.di_file = di_file;
4210 const line_number = decl.src_line + 1;4210 const line_number = decl.src_line + 1;
4211 const cur_debug_location = self.builder.getCurrentDebugLocation2();4211 const cur_debug_location = self.builder.getCurrentDebugLocation2();
4212 if (start) {
4213 try self.dbg_inlined.append(self.gpa, .{
4214 .loc = @ptrCast(*llvm.DILocation, cur_debug_location),
4215 .scope = self.di_scope.?,
4216 .base_line = self.base_line,
4217 });
4218 } else {
4219 const old = self.dbg_inlined.pop();
4220 self.di_scope = old.scope;
4221 self.base_line = old.base_line;
4222 return null;
4223 }
42244212
4225 const fn_ty = try self.air.getRefType(ty_pl.ty).copy(self.dg.object.type_map_arena.allocator());4213 try self.dbg_inlined.append(self.gpa, .{
4214 .loc = @ptrCast(*llvm.DILocation, cur_debug_location),
4215 .scope = self.di_scope.?,
4216 .base_line = self.base_line,
4217 });
4218
4226 const fqn = try decl.getFullyQualifiedName(self.gpa);4219 const fqn = try decl.getFullyQualifiedName(self.gpa);
4227 defer self.gpa.free(fqn);4220 defer self.gpa.free(fqn);
4228 const fn_info = fn_ty.fnInfo();
42294221
4230 const is_internal_linkage = !self.dg.module.decl_exports.contains(decl);4222 const is_internal_linkage = !self.dg.module.decl_exports.contains(decl);
4231 const noret_bit: c_uint = if (fn_info.return_type.isNoReturn())
4232 llvm.DIFlags.NoReturn
4233 else
4234 0;
4235 const subprogram = dib.createFunction(4223 const subprogram = dib.createFunction(
4236 di_file.toScope(),4224 di_file.toScope(),
4237 decl.name,4225 decl.name,
4238 fqn,4226 fqn,
4239 di_file,4227 di_file,
4240 line_number,4228 line_number,
4241 try self.dg.object.lowerDebugType(fn_ty, .full),4229 try self.dg.object.lowerDebugType(Type.initTag(.fn_void_no_args), .full),
4242 is_internal_linkage,4230 is_internal_linkage,
4243 true, // is definition4231 true, // is definition
4244 line_number + func.lbrace_line, // scope line4232 line_number + func.lbrace_line, // scope line
4245 llvm.DIFlags.StaticMember | noret_bit,4233 llvm.DIFlags.StaticMember,
4246 self.dg.module.comp.bin_file.options.optimize_mode != .Debug,4234 self.dg.module.comp.bin_file.options.optimize_mode != .Debug,
4247 null, // decl_subprogram4235 null, // decl_subprogram
4248 );4236 );
42494237
4250 try self.dg.object.di_map.put(self.gpa, decl, subprogram.toNode());
4251
4252 const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file, line_number, 1);4238 const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file, line_number, 1);
4253 self.di_scope = lexical_block.toScope();4239 self.di_scope = lexical_block.toScope();
4254 self.base_line = decl.src_line;4240 self.base_line = decl.src_line;
4255 return null;4241 return null;
4256 }4242 }
42574243
4244 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4245 if (self.dg.object.di_builder == null) return null;
4246 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4247
4248 const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
4249 const decl = func.owner_decl;
4250 const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope);
4251 self.di_file = di_file;
4252 const old = self.dbg_inlined.pop();
4253 self.di_scope = old.scope;
4254 self.base_line = old.base_line;
4255 return null;
4256 }
4257
4258 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {4258 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4259 const dib = self.dg.object.di_builder orelse return null;4259 const dib = self.dg.object.di_builder orelse return null;
4260 const pl_op = self.air.instructions.items(.data)[inst].pl_op;4260 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
test/behavior.zig+1-1
...@@ -125,6 +125,7 @@ test {...@@ -125,6 +125,7 @@ test {
125 _ = @import("behavior/union.zig");125 _ = @import("behavior/union.zig");
126 _ = @import("behavior/usingnamespace.zig");126 _ = @import("behavior/usingnamespace.zig");
127 _ = @import("behavior/var_args.zig");127 _ = @import("behavior/var_args.zig");
128 _ = @import("behavior/vector.zig");
128 _ = @import("behavior/void.zig");129 _ = @import("behavior/void.zig");
129 _ = @import("behavior/while.zig");130 _ = @import("behavior/while.zig");
130131
...@@ -179,7 +180,6 @@ test {...@@ -179,7 +180,6 @@ test {
179 _ = @import("behavior/select.zig");180 _ = @import("behavior/select.zig");
180 _ = @import("behavior/struct_contains_slice_of_itself.zig");181 _ = @import("behavior/struct_contains_slice_of_itself.zig");
181 _ = @import("behavior/typename.zig");182 _ = @import("behavior/typename.zig");
182 _ = @import("behavior/vector.zig");
183 }183 }
184 }184 }
185 }185 }
test/behavior/vector.zig+25
...@@ -8,6 +8,7 @@ const expectApproxEqRel = std.testing.expectApproxEqRel;...@@ -8,6 +8,7 @@ const expectApproxEqRel = std.testing.expectApproxEqRel;
8const Vector = std.meta.Vector;8const Vector = std.meta.Vector;
99
10test "implicit cast vector to array - bool" {10test "implicit cast vector to array - bool" {
11 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
11 const S = struct {12 const S = struct {
12 fn doTheTest() !void {13 fn doTheTest() !void {
13 const a: Vector(4, bool) = [_]bool{ true, false, true, false };14 const a: Vector(4, bool) = [_]bool{ true, false, true, false };
...@@ -20,6 +21,7 @@ test "implicit cast vector to array - bool" {...@@ -20,6 +21,7 @@ test "implicit cast vector to array - bool" {
20}21}
2122
22test "vector wrap operators" {23test "vector wrap operators" {
24 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
23 const S = struct {25 const S = struct {
24 fn doTheTest() !void {26 fn doTheTest() !void {
25 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };27 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
...@@ -36,6 +38,7 @@ test "vector wrap operators" {...@@ -36,6 +38,7 @@ test "vector wrap operators" {
36}38}
3739
38test "vector bin compares with mem.eql" {40test "vector bin compares with mem.eql" {
41 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
39 const S = struct {42 const S = struct {
40 fn doTheTest() !void {43 fn doTheTest() !void {
41 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };44 var v: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
...@@ -53,6 +56,7 @@ test "vector bin compares with mem.eql" {...@@ -53,6 +56,7 @@ test "vector bin compares with mem.eql" {
53}56}
5457
55test "vector int operators" {58test "vector int operators" {
59 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
56 const S = struct {60 const S = struct {
57 fn doTheTest() !void {61 fn doTheTest() !void {
58 var v: Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };62 var v: Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
...@@ -68,6 +72,7 @@ test "vector int operators" {...@@ -68,6 +72,7 @@ test "vector int operators" {
68}72}
6973
70test "vector float operators" {74test "vector float operators" {
75 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
71 const S = struct {76 const S = struct {
72 fn doTheTest() !void {77 fn doTheTest() !void {
73 var v: Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };78 var v: Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };
...@@ -83,6 +88,7 @@ test "vector float operators" {...@@ -83,6 +88,7 @@ test "vector float operators" {
83}88}
8489
85test "vector bit operators" {90test "vector bit operators" {
91 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
86 const S = struct {92 const S = struct {
87 fn doTheTest() !void {93 fn doTheTest() !void {
88 var v: Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };94 var v: Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
...@@ -97,6 +103,7 @@ test "vector bit operators" {...@@ -97,6 +103,7 @@ test "vector bit operators" {
97}103}
98104
99test "implicit cast vector to array" {105test "implicit cast vector to array" {
106 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
100 const S = struct {107 const S = struct {
101 fn doTheTest() !void {108 fn doTheTest() !void {
102 var a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };109 var a: Vector(4, i32) = [_]i32{ 1, 2, 3, 4 };
...@@ -110,6 +117,7 @@ test "implicit cast vector to array" {...@@ -110,6 +117,7 @@ test "implicit cast vector to array" {
110}117}
111118
112test "array to vector" {119test "array to vector" {
120 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
113 var foo: f32 = 3.14;121 var foo: f32 = 3.14;
114 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };122 var arr = [4]f32{ foo, 1.5, 0.0, 0.0 };
115 var vec: Vector(4, f32) = arr;123 var vec: Vector(4, f32) = arr;
...@@ -117,6 +125,7 @@ test "array to vector" {...@@ -117,6 +125,7 @@ test "array to vector" {
117}125}
118126
119test "vector casts of sizes not divisible by 8" {127test "vector casts of sizes not divisible by 8" {
128 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
120 const S = struct {129 const S = struct {
121 fn doTheTest() !void {130 fn doTheTest() !void {
122 {131 {
...@@ -146,6 +155,7 @@ test "vector casts of sizes not divisible by 8" {...@@ -146,6 +155,7 @@ test "vector casts of sizes not divisible by 8" {
146}155}
147156
148test "vector @splat" {157test "vector @splat" {
158 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
149 const S = struct {159 const S = struct {
150 fn testForT(comptime N: comptime_int, v: anytype) !void {160 fn testForT(comptime N: comptime_int, v: anytype) !void {
151 const T = @TypeOf(v);161 const T = @TypeOf(v);
...@@ -181,6 +191,7 @@ test "vector @splat" {...@@ -181,6 +191,7 @@ test "vector @splat" {
181}191}
182192
183test "load vector elements via comptime index" {193test "load vector elements via comptime index" {
194 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
184 const S = struct {195 const S = struct {
185 fn doTheTest() !void {196 fn doTheTest() !void {
186 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };197 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
...@@ -198,6 +209,7 @@ test "load vector elements via comptime index" {...@@ -198,6 +209,7 @@ test "load vector elements via comptime index" {
198}209}
199210
200test "store vector elements via comptime index" {211test "store vector elements via comptime index" {
212 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
201 const S = struct {213 const S = struct {
202 fn doTheTest() !void {214 fn doTheTest() !void {
203 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };215 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
...@@ -221,6 +233,7 @@ test "store vector elements via comptime index" {...@@ -221,6 +233,7 @@ test "store vector elements via comptime index" {
221}233}
222234
223test "load vector elements via runtime index" {235test "load vector elements via runtime index" {
236 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
224 const S = struct {237 const S = struct {
225 fn doTheTest() !void {238 fn doTheTest() !void {
226 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };239 var v: Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
...@@ -238,6 +251,7 @@ test "load vector elements via runtime index" {...@@ -238,6 +251,7 @@ test "load vector elements via runtime index" {
238}251}
239252
240test "store vector elements via runtime index" {253test "store vector elements via runtime index" {
254 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
241 const S = struct {255 const S = struct {
242 fn doTheTest() !void {256 fn doTheTest() !void {
243 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };257 var v: Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
...@@ -256,6 +270,7 @@ test "store vector elements via runtime index" {...@@ -256,6 +270,7 @@ test "store vector elements via runtime index" {
256}270}
257271
258test "initialize vector which is a struct field" {272test "initialize vector which is a struct field" {
273 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
259 const Vec4Obj = struct {274 const Vec4Obj = struct {
260 data: Vector(4, f32),275 data: Vector(4, f32),
261 };276 };
...@@ -273,6 +288,7 @@ test "initialize vector which is a struct field" {...@@ -273,6 +288,7 @@ test "initialize vector which is a struct field" {
273}288}
274289
275test "vector comparison operators" {290test "vector comparison operators" {
291 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
276 const S = struct {292 const S = struct {
277 fn doTheTest() !void {293 fn doTheTest() !void {
278 {294 {
...@@ -307,6 +323,7 @@ test "vector comparison operators" {...@@ -307,6 +323,7 @@ test "vector comparison operators" {
307}323}
308324
309test "vector division operators" {325test "vector division operators" {
326 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
310 const S = struct {327 const S = struct {
311 fn doTheTestDiv(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {328 fn doTheTestDiv(comptime T: type, x: Vector(4, T), y: Vector(4, T)) !void {
312 if (!comptime std.meta.trait.isSignedInt(T)) {329 if (!comptime std.meta.trait.isSignedInt(T)) {
...@@ -389,6 +406,7 @@ test "vector division operators" {...@@ -389,6 +406,7 @@ test "vector division operators" {
389}406}
390407
391test "vector bitwise not operator" {408test "vector bitwise not operator" {
409 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
392 const S = struct {410 const S = struct {
393 fn doTheTestNot(comptime T: type, x: Vector(4, T)) !void {411 fn doTheTestNot(comptime T: type, x: Vector(4, T)) !void {
394 var y = ~x;412 var y = ~x;
...@@ -414,6 +432,7 @@ test "vector bitwise not operator" {...@@ -414,6 +432,7 @@ test "vector bitwise not operator" {
414}432}
415433
416test "vector shift operators" {434test "vector shift operators" {
435 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
417 const S = struct {436 const S = struct {
418 fn doTheTestShift(x: anytype, y: anytype) !void {437 fn doTheTestShift(x: anytype, y: anytype) !void {
419 const N = @typeInfo(@TypeOf(x)).Array.len;438 const N = @typeInfo(@TypeOf(x)).Array.len;
...@@ -501,6 +520,7 @@ test "vector shift operators" {...@@ -501,6 +520,7 @@ test "vector shift operators" {
501}520}
502521
503test "vector reduce operation" {522test "vector reduce operation" {
523 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
504 const S = struct {524 const S = struct {
505 fn doTheTestReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {525 fn doTheTestReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
506 const N = @typeInfo(@TypeOf(x)).Array.len;526 const N = @typeInfo(@TypeOf(x)).Array.len;
...@@ -636,6 +656,7 @@ test "vector reduce operation" {...@@ -636,6 +656,7 @@ test "vector reduce operation" {
636}656}
637657
638test "mask parameter of @shuffle is comptime scope" {658test "mask parameter of @shuffle is comptime scope" {
659 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
639 const __v4hi = std.meta.Vector(4, i16);660 const __v4hi = std.meta.Vector(4, i16);
640 var v4_a = __v4hi{ 0, 0, 0, 0 };661 var v4_a = __v4hi{ 0, 0, 0, 0 };
641 var v4_b = __v4hi{ 0, 0, 0, 0 };662 var v4_b = __v4hi{ 0, 0, 0, 0 };
...@@ -649,6 +670,7 @@ test "mask parameter of @shuffle is comptime scope" {...@@ -649,6 +670,7 @@ test "mask parameter of @shuffle is comptime scope" {
649}670}
650671
651test "saturating add" {672test "saturating add" {
673 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
652 const S = struct {674 const S = struct {
653 fn doTheTest() !void {675 fn doTheTest() !void {
654 const u8x3 = std.meta.Vector(3, u8);676 const u8x3 = std.meta.Vector(3, u8);
...@@ -662,6 +684,7 @@ test "saturating add" {...@@ -662,6 +684,7 @@ test "saturating add" {
662}684}
663685
664test "saturating subtraction" {686test "saturating subtraction" {
687 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
665 const S = struct {688 const S = struct {
666 fn doTheTest() !void {689 fn doTheTest() !void {
667 const u8x3 = std.meta.Vector(3, u8);690 const u8x3 = std.meta.Vector(3, u8);
...@@ -673,6 +696,7 @@ test "saturating subtraction" {...@@ -673,6 +696,7 @@ test "saturating subtraction" {
673}696}
674697
675test "saturating multiplication" {698test "saturating multiplication" {
699 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
676 // TODO: once #9660 has been solved, remove this line700 // TODO: once #9660 has been solved, remove this line
677 if (builtin.target.cpu.arch == .wasm32) return error.SkipZigTest;701 if (builtin.target.cpu.arch == .wasm32) return error.SkipZigTest;
678702
...@@ -688,6 +712,7 @@ test "saturating multiplication" {...@@ -688,6 +712,7 @@ test "saturating multiplication" {
688}712}
689713
690test "saturating shift-left" {714test "saturating shift-left" {
715 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
691 const S = struct {716 const S = struct {
692 fn doTheTest() !void {717 fn doTheTest() !void {
693 const u8x3 = std.meta.Vector(3, u8);718 const u8x3 = std.meta.Vector(3, u8);