Sema: use runtime_value instead of creating allocs

This commit is contained in:
Veikka Tuominen 2022-10-26 00:30:17 +03:00 committed by Andrew Kelley
parent 398a3aae40
commit d03c47bf85
12 changed files with 126 additions and 52 deletions

View File

@ -1827,6 +1827,22 @@ fn resolveMaybeUndefValAllowVariables(
block: *Block, block: *Block,
src: LazySrcLoc, src: LazySrcLoc,
inst: Air.Inst.Ref, inst: Air.Inst.Ref,
) CompileError!?Value {
var make_runtime = false;
if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, src, inst, &make_runtime)) |val| {
if (make_runtime) return null;
return val;
}
return null;
}
/// Returns all Value tags including `variable`, `undef` and `runtime_value`.
fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
sema: *Sema,
block: *Block,
src: LazySrcLoc,
inst: Air.Inst.Ref,
make_runtime: *bool,
) CompileError!?Value { ) CompileError!?Value {
// First section of indexes correspond to a set number of constant values. // First section of indexes correspond to a set number of constant values.
var i: usize = @enumToInt(inst); var i: usize = @enumToInt(inst);
@ -1843,7 +1859,7 @@ fn resolveMaybeUndefValAllowVariables(
.constant => { .constant => {
const ty_pl = sema.air_instructions.items(.data)[i].ty_pl; const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
const val = sema.air_values.items[ty_pl.payload]; const val = sema.air_values.items[ty_pl.payload];
if (val.tag() == .runtime_int) return null; if (val.tag() == .runtime_value) make_runtime.* = true;
return val; return val;
}, },
.const_ty => { .const_ty => {
@ -3896,6 +3912,7 @@ fn validateUnionInit(
var first_block_index = block.instructions.items.len; var first_block_index = block.instructions.items.len;
var block_index = block.instructions.items.len - 1; var block_index = block.instructions.items.len - 1;
var init_val: ?Value = null; var init_val: ?Value = null;
var make_runtime = false;
while (block_index > 0) : (block_index -= 1) { while (block_index > 0) : (block_index -= 1) {
const store_inst = block.instructions.items[block_index]; const store_inst = block.instructions.items[block_index];
if (store_inst == field_ptr_air_inst) break; if (store_inst == field_ptr_air_inst) break;
@ -3920,7 +3937,7 @@ fn validateUnionInit(
} else { } else {
first_block_index = @min(first_block_index, block_index); first_block_index = @min(first_block_index, block_index);
} }
init_val = try sema.resolveMaybeUndefValAllowVariables(block, init_src, bin_op.rhs); init_val = try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, init_src, bin_op.rhs, &make_runtime);
break; break;
} }
@ -3933,10 +3950,11 @@ fn validateUnionInit(
// instead a single `store` to the result ptr with a comptime union value. // instead a single `store` to the result ptr with a comptime union value.
block.instructions.shrinkRetainingCapacity(first_block_index); block.instructions.shrinkRetainingCapacity(first_block_index);
const union_val = try Value.Tag.@"union".create(sema.arena, .{ var union_val = try Value.Tag.@"union".create(sema.arena, .{
.tag = tag_val, .tag = tag_val,
.val = val, .val = val,
}); });
if (make_runtime) union_val = try Value.Tag.runtime_value.create(sema.arena, union_val);
const union_init = try sema.addConstant(union_ty, union_val); const union_init = try sema.addConstant(union_ty, union_val);
try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store); try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
return; return;
@ -4054,6 +4072,7 @@ fn validateStructInit(
var struct_is_comptime = true; var struct_is_comptime = true;
var first_block_index = block.instructions.items.len; var first_block_index = block.instructions.items.len;
var make_runtime = false;
const air_tags = sema.air_instructions.items(.tag); const air_tags = sema.air_instructions.items(.tag);
const air_datas = sema.air_instructions.items(.data); const air_datas = sema.air_instructions.items(.data);
@ -4130,7 +4149,7 @@ fn validateStructInit(
} else { } else {
first_block_index = @min(first_block_index, block_index); first_block_index = @min(first_block_index, block_index);
} }
if (try sema.resolveMaybeUndefValAllowVariables(block, field_src, bin_op.rhs)) |val| { if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, field_src, bin_op.rhs, &make_runtime)) |val| {
field_values[i] = val; field_values[i] = val;
} else { } else {
struct_is_comptime = false; struct_is_comptime = false;
@ -4185,7 +4204,8 @@ fn validateStructInit(
// instead a single `store` to the struct_ptr with a comptime struct value. // instead a single `store` to the struct_ptr with a comptime struct value.
block.instructions.shrinkRetainingCapacity(first_block_index); block.instructions.shrinkRetainingCapacity(first_block_index);
const struct_val = try Value.Tag.aggregate.create(sema.arena, field_values); var struct_val = try Value.Tag.aggregate.create(sema.arena, field_values);
if (make_runtime) struct_val = try Value.Tag.runtime_value.create(sema.arena, struct_val);
const struct_init = try sema.addConstant(struct_ty, struct_val); const struct_init = try sema.addConstant(struct_ty, struct_val);
try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store); try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
return; return;
@ -4265,6 +4285,7 @@ fn zirValidateArrayInit(
var array_is_comptime = true; var array_is_comptime = true;
var first_block_index = block.instructions.items.len; var first_block_index = block.instructions.items.len;
var make_runtime = false;
// Collect the comptime element values in case the array literal ends up // Collect the comptime element values in case the array literal ends up
// being comptime-known. // being comptime-known.
@ -4326,7 +4347,7 @@ fn zirValidateArrayInit(
array_is_comptime = false; array_is_comptime = false;
continue; continue;
} }
if (try sema.resolveMaybeUndefValAllowVariables(block, elem_src, bin_op.rhs)) |val| { if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| {
element_vals[i] = val; element_vals[i] = val;
} else { } else {
array_is_comptime = false; array_is_comptime = false;
@ -4352,7 +4373,7 @@ fn zirValidateArrayInit(
array_is_comptime = false; array_is_comptime = false;
continue; continue;
} }
if (try sema.resolveMaybeUndefValAllowVariables(block, elem_src, bin_op.rhs)) |val| { if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| {
element_vals[i] = val; element_vals[i] = val;
} else { } else {
array_is_comptime = false; array_is_comptime = false;
@ -4383,7 +4404,8 @@ fn zirValidateArrayInit(
block.instructions.shrinkRetainingCapacity(first_block_index); block.instructions.shrinkRetainingCapacity(first_block_index);
const array_val = try Value.Tag.aggregate.create(sema.arena, element_vals); var array_val = try Value.Tag.aggregate.create(sema.arena, element_vals);
if (make_runtime) array_val = try Value.Tag.runtime_value.create(sema.arena, array_val);
const array_init = try sema.addConstant(array_ty, array_val); const array_init = try sema.addConstant(array_ty, array_val);
try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store); try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
} }
@ -6635,20 +6657,14 @@ fn analyzeInlineCallArg(
.ty = param_ty, .ty = param_ty,
.val = arg_val, .val = arg_val,
}; };
} else if (((try sema.resolveMaybeUndefVal(arg_block, arg_src, casted_arg)) == null) or } else if (zir_tags[inst] == .param_comptime or try sema.typeRequiresComptime(param_ty)) {
try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_comptime)
{
try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
} else { } else if (try sema.resolveMaybeUndefVal(arg_block, arg_src, casted_arg)) |val| {
// We have a comptime value but we need a runtime value to preserve inlining semantics, // We have a comptime value but we need a runtime value to preserve inlining semantics,
const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ const wrapped = try sema.addConstant(param_ty, try Value.Tag.runtime_value.create(sema.arena, val));
.pointee_type = param_ty, try sema.inst_map.putNoClobber(sema.gpa, inst, wrapped);
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), } else {
}); try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
const alloc = try arg_block.addTy(.alloc, ptr_type);
_ = try arg_block.addBinOp(.store, alloc, casted_arg);
const loaded = try arg_block.addTyOp(.load, param_ty, alloc);
try sema.inst_map.putNoClobber(sema.gpa, inst, loaded);
} }
arg_i.* += 1; arg_i.* += 1;
@ -6685,20 +6701,14 @@ fn analyzeInlineCallArg(
.ty = sema.typeOf(uncasted_arg), .ty = sema.typeOf(uncasted_arg),
.val = arg_val, .val = arg_val,
}; };
} else if ((try sema.resolveMaybeUndefVal(arg_block, arg_src, uncasted_arg)) == null or } else if (zir_tags[inst] == .param_anytype_comptime or try sema.typeRequiresComptime(param_ty)) {
try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_anytype_comptime)
{
try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg); try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
} else { } else if (try sema.resolveMaybeUndefVal(arg_block, arg_src, uncasted_arg)) |val| {
// We have a comptime value but we need a runtime value to preserve inlining semantics, // We have a comptime value but we need a runtime value to preserve inlining semantics,
const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ const wrapped = try sema.addConstant(param_ty, try Value.Tag.runtime_value.create(sema.arena, val));
.pointee_type = param_ty, try sema.inst_map.putNoClobber(sema.gpa, inst, wrapped);
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), } else {
}); try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
const alloc = try arg_block.addTy(.alloc, ptr_type);
_ = try arg_block.addBinOp(.store, alloc, uncasted_arg);
const loaded = try arg_block.addTyOp(.load, param_ty, alloc);
try sema.inst_map.putNoClobber(sema.gpa, inst, loaded);
} }
arg_i.* += 1; arg_i.* += 1;
@ -14826,7 +14836,7 @@ fn zirBuiltinSrc(
// fn_name: [:0]const u8, // fn_name: [:0]const u8,
field_values[1] = func_name_val; field_values[1] = func_name_val;
// line: u32 // line: u32
field_values[2] = try Value.Tag.runtime_int.create(sema.arena, extra.line + 1); field_values[2] = try Value.Tag.runtime_value.create(sema.arena, try Value.Tag.int_u64.create(sema.arena, extra.line + 1));
// column: u32, // column: u32,
field_values[3] = try Value.Tag.int_u64.create(sema.arena, extra.column + 1); field_values[3] = try Value.Tag.int_u64.create(sema.arena, extra.column + 1);

View File

@ -477,6 +477,6 @@ pub fn print(
}, },
.generic_poison_type => return writer.writeAll("(generic poison type)"), .generic_poison_type => return writer.writeAll("(generic poison type)"),
.generic_poison => return writer.writeAll("(generic poison)"), .generic_poison => return writer.writeAll("(generic poison)"),
.runtime_int => return writer.writeAll("[runtime value]"), .runtime_value => return writer.writeAll("[runtime value]"),
}; };
} }

View File

@ -5401,7 +5401,11 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
} }
} }
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
var typed_value = arg_tv;
if (typed_value.val.castTag(.runtime_value)) |rt| {
typed_value.val = rt.data;
}
log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() }); log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
if (typed_value.val.isUndef()) if (typed_value.val.isUndef())
return MCValue{ .undef = {} }; return MCValue{ .undef = {} };

View File

@ -6047,7 +6047,11 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
} }
} }
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
var typed_value = arg_tv;
if (typed_value.val.castTag(.runtime_value)) |rt| {
typed_value.val = rt.data;
}
log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() }); log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
if (typed_value.val.isUndef()) if (typed_value.val.isUndef())
return MCValue{ .undef = {} }; return MCValue{ .undef = {} };

View File

@ -2582,7 +2582,11 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(
return @intCast(WantedT, result); return @intCast(WantedT, result);
} }
fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
var val = arg_val;
if (val.castTag(.runtime_value)) |rt| {
val = rt.data;
}
if (val.isUndefDeep()) return func.emitUndefined(ty); if (val.isUndefDeep()) return func.emitUndefined(ty);
if (val.castTag(.decl_ref)) |decl_ref| { if (val.castTag(.decl_ref)) |decl_ref| {
const decl_index = decl_ref.data; const decl_index = decl_ref.data;

View File

@ -6960,7 +6960,11 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
} }
} }
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
var typed_value = arg_tv;
if (typed_value.val.castTag(.runtime_value)) |rt| {
typed_value.val = rt.data;
}
log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() }); log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
if (typed_value.val.isUndef()) if (typed_value.val.isUndef())
return MCValue{ .undef = {} }; return MCValue{ .undef = {} };

View File

@ -149,7 +149,7 @@ fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian
pub fn generateSymbol( pub fn generateSymbol(
bin_file: *link.File, bin_file: *link.File,
src_loc: Module.SrcLoc, src_loc: Module.SrcLoc,
typed_value: TypedValue, arg_tv: TypedValue,
code: *std.ArrayList(u8), code: *std.ArrayList(u8),
debug_output: DebugInfoOutput, debug_output: DebugInfoOutput,
reloc_info: RelocInfo, reloc_info: RelocInfo,
@ -157,6 +157,11 @@ pub fn generateSymbol(
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
var typed_value = arg_tv;
if (arg_tv.val.castTag(.runtime_value)) |rt| {
typed_value.val = rt.data;
}
const target = bin_file.options.target; const target = bin_file.options.target;
const endian = target.cpu.arch.endian(); const endian = target.cpu.arch.endian();

View File

@ -555,9 +555,13 @@ pub const DeclGen = struct {
dg: *DeclGen, dg: *DeclGen,
writer: anytype, writer: anytype,
ty: Type, ty: Type,
val: Value, arg_val: Value,
location: ValueRenderLocation, location: ValueRenderLocation,
) error{ OutOfMemory, AnalysisFail }!void { ) error{ OutOfMemory, AnalysisFail }!void {
var val = arg_val;
if (val.castTag(.runtime_value)) |rt| {
val = rt.data;
}
const target = dg.module.getTarget(); const target = dg.module.getTarget();
if (val.isUndefDeep()) { if (val.isUndefDeep()) {
switch (ty.zigTypeTag()) { switch (ty.zigTypeTag()) {

View File

@ -3187,7 +3187,11 @@ pub const DeclGen = struct {
return llvm_elem_ty; return llvm_elem_ty;
} }
fn lowerValue(dg: *DeclGen, tv: TypedValue) Error!*llvm.Value { fn lowerValue(dg: *DeclGen, arg_tv: TypedValue) Error!*llvm.Value {
var tv = arg_tv;
if (tv.val.castTag(.runtime_value)) |rt| {
tv.val = rt.data;
}
if (tv.val.isUndef()) { if (tv.val.isUndef()) {
const llvm_type = try dg.lowerType(tv.ty); const llvm_type = try dg.lowerType(tv.ty);
return llvm_type.getUndef(); return llvm_type.getUndef();

View File

@ -111,10 +111,12 @@ pub const Value = extern union {
int_i64, int_i64,
int_big_positive, int_big_positive,
int_big_negative, int_big_negative,
runtime_int,
function, function,
extern_fn, extern_fn,
variable, variable,
/// A wrapper for values which are comptime-known but should
/// semantically be runtime-known.
runtime_value,
/// Represents a pointer to a Decl. /// Represents a pointer to a Decl.
/// When machine codegen backend sees this, it must set the Decl's `alive` field to true. /// When machine codegen backend sees this, it must set the Decl's `alive` field to true.
decl_ref, decl_ref,
@ -282,6 +284,7 @@ pub const Value = extern union {
.eu_payload, .eu_payload,
.opt_payload, .opt_payload,
.empty_array_sentinel, .empty_array_sentinel,
.runtime_value,
=> Payload.SubValue, => Payload.SubValue,
.eu_payload_ptr, .eu_payload_ptr,
@ -305,7 +308,6 @@ pub const Value = extern union {
.int_type => Payload.IntType, .int_type => Payload.IntType,
.int_u64 => Payload.U64, .int_u64 => Payload.U64,
.int_i64 => Payload.I64, .int_i64 => Payload.I64,
.runtime_int => Payload.U64,
.function => Payload.Function, .function => Payload.Function,
.variable => Payload.Variable, .variable => Payload.Variable,
.decl_ref_mut => Payload.DeclRefMut, .decl_ref_mut => Payload.DeclRefMut,
@ -485,7 +487,6 @@ pub const Value = extern union {
}, },
.int_type => return self.copyPayloadShallow(arena, Payload.IntType), .int_type => return self.copyPayloadShallow(arena, Payload.IntType),
.int_u64 => return self.copyPayloadShallow(arena, Payload.U64), .int_u64 => return self.copyPayloadShallow(arena, Payload.U64),
.runtime_int => return self.copyPayloadShallow(arena, Payload.U64),
.int_i64 => return self.copyPayloadShallow(arena, Payload.I64), .int_i64 => return self.copyPayloadShallow(arena, Payload.I64),
.int_big_positive, .int_big_negative => { .int_big_positive, .int_big_negative => {
const old_payload = self.cast(Payload.BigInt).?; const old_payload = self.cast(Payload.BigInt).?;
@ -567,6 +568,7 @@ pub const Value = extern union {
.eu_payload, .eu_payload,
.opt_payload, .opt_payload,
.empty_array_sentinel, .empty_array_sentinel,
.runtime_value,
=> { => {
const payload = self.cast(Payload.SubValue).?; const payload = self.cast(Payload.SubValue).?;
const new_payload = try arena.create(Payload.SubValue); const new_payload = try arena.create(Payload.SubValue);
@ -765,7 +767,7 @@ pub const Value = extern union {
.int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream), .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream),
.int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}),
.int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), .int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}),
.runtime_int => return out_stream.writeAll("[runtime value]"), .runtime_value => return out_stream.writeAll("[runtime value]"),
.function => return out_stream.print("(function decl={d})", .{val.castTag(.function).?.data.owner_decl}), .function => return out_stream.print("(function decl={d})", .{val.castTag(.function).?.data.owner_decl}),
.extern_fn => return out_stream.writeAll("(extern function)"), .extern_fn => return out_stream.writeAll("(extern function)"),
.variable => return out_stream.writeAll("(variable)"), .variable => return out_stream.writeAll("(variable)"),
@ -1081,8 +1083,6 @@ pub const Value = extern union {
.int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(), .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(),
.int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(), .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(),
.runtime_int => return BigIntMutable.init(&space.limbs, val.castTag(.runtime_int).?.data).toConst(),
.undef => unreachable, .undef => unreachable,
.lazy_align => { .lazy_align => {
@ -1138,8 +1138,6 @@ pub const Value = extern union {
.int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null, .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null,
.int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null, .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null,
.runtime_int => return val.castTag(.runtime_int).?.data,
.undef => unreachable, .undef => unreachable,
.lazy_align => { .lazy_align => {
@ -2357,6 +2355,8 @@ pub const Value = extern union {
const zig_ty_tag = ty.zigTypeTag(); const zig_ty_tag = ty.zigTypeTag();
std.hash.autoHash(hasher, zig_ty_tag); std.hash.autoHash(hasher, zig_ty_tag);
if (val.isUndef()) return; if (val.isUndef()) return;
// The value is runtime-known and shouldn't affect the hash.
if (val.tag() == .runtime_value) return;
switch (zig_ty_tag) { switch (zig_ty_tag) {
.BoundFn => unreachable, // TODO remove this from the language .BoundFn => unreachable, // TODO remove this from the language
@ -2632,9 +2632,6 @@ pub const Value = extern union {
.lazy_size, .lazy_size,
=> return hashInt(ptr_val, hasher, target), => return hashInt(ptr_val, hasher, target),
// The value is runtime-known and shouldn't affect the hash.
.runtime_int => {},
else => unreachable, else => unreachable,
} }
} }

View File

@ -10,6 +10,7 @@ inline fn setLimits(min: ?u32, max: ?u32) !void {
test { test {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
var x: u32 = 42; var x: u32 = 42;
try setLimits(x, null); try setLimits(x, null);

View File

@ -1135,3 +1135,40 @@ test "array of vectors is copied" {
points2[0..points.len].* = points; points2[0..points.len].* = points;
try std.testing.expectEqual(points2[6], Vec3{ -345, -311, 381 }); try std.testing.expectEqual(points2[6], Vec3{ -345, -311, 381 });
} }
test "byte vector initialized in inline function" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
inline fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
return .{ e0, e1, e2, e3 };
}
fn all(vb: @Vector(4, bool)) bool {
return @reduce(.And, vb);
}
};
try expect(S.all(S.boolx4(true, true, true, true)));
}
test "byte vector initialized in inline function" {
// TODO https://github.com/ziglang/zig/issues/13279
if (true) return error.SkipZigTest;
const S = struct {
fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
return .{ e0, e1, e2, e3 };
}
fn all(vb: @Vector(4, bool)) bool {
return @reduce(.And, vb);
}
};
try expect(S.all(S.boolx4(true, true, true, true)));
}