authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-22 00:36:50-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-01-22 00:36:50-05:00
loga51c76541d60da81ef53e0ab1f221a80d9956bd5
tree023a1f1fbc02b646214b70d78dad0acb7ec158f3
parentf85c01d4c7520d2242626f4c0684ab97e47af373
parentaa626deadddcf26a5789d29d5ba88c978ee53b89
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14403 from Vexu/fixes

Misc fixes

13 files changed, 366 insertions(+), 223 deletions(-)

src/Sema.zig+26-31
...@@ -3948,6 +3948,7 @@ fn validateArrayInitTy(...@@ -3948,6 +3948,7 @@ fn validateArrayInitTy(
3948 return;3948 return;
3949 },3949 },
3950 .Struct => if (ty.isTuple()) {3950 .Struct => if (ty.isTuple()) {
3951 _ = try sema.resolveTypeFields(ty);
3951 const array_len = ty.arrayLen();3952 const array_len = ty.arrayLen();
3952 if (extra.init_count > array_len) {3953 if (extra.init_count > array_len) {
3953 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{3954 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
...@@ -4642,11 +4643,11 @@ fn failWithBadMemberAccess(...@@ -4642,11 +4643,11 @@ fn failWithBadMemberAccess(
4642 .Enum => "enum",4643 .Enum => "enum",
4643 else => unreachable,4644 else => unreachable,
4644 };4645 };
4645 if (sema.mod.declIsRoot(agg_ty.getOwnerDecl())) {4646 if (agg_ty.getOwnerDeclOrNull()) |some| if (sema.mod.declIsRoot(some)) {
4646 return sema.fail(block, field_src, "root struct of file '{}' has no member named '{s}'", .{4647 return sema.fail(block, field_src, "root struct of file '{}' has no member named '{s}'", .{
4647 agg_ty.fmt(sema.mod), field_name,4648 agg_ty.fmt(sema.mod), field_name,
4648 });4649 });
4649 }4650 };
4650 const msg = msg: {4651 const msg = msg: {
4651 const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{4652 const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{
4652 kw_name, agg_ty.fmt(sema.mod), field_name,4653 kw_name, agg_ty.fmt(sema.mod), field_name,
...@@ -7514,7 +7515,7 @@ fn resolveGenericInstantiationType(...@@ -7514,7 +7515,7 @@ fn resolveGenericInstantiationType(
7514}7515}
75157516
7516fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {7517fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
7517 if (!ty.isSimpleTuple()) return;7518 if (!ty.isSimpleTupleOrAnonStruct()) return;
7518 const tuple = ty.tupleFields();7519 const tuple = ty.tupleFields();
7519 for (tuple.values) |field_val, i| {7520 for (tuple.values) |field_val, i| {
7520 try sema.resolveTupleLazyValues(block, src, tuple.types[i]);7521 try sema.resolveTupleLazyValues(block, src, tuple.types[i]);
...@@ -11771,8 +11772,8 @@ fn zirShl(...@@ -11771,8 +11772,8 @@ fn zirShl(
11771 // TODO coerce rhs if air_tag is not shl_sat11772 // TODO coerce rhs if air_tag is not shl_sat
11772 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty);11773 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty);
1177311774
11774 const maybe_lhs_val = try sema.resolveMaybeUndefVal(lhs);11775 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs);
11775 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);11776 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);
1177611777
11777 if (maybe_rhs_val) |rhs_val| {11778 if (maybe_rhs_val) |rhs_val| {
11778 if (rhs_val.isUndef()) {11779 if (rhs_val.isUndef()) {
...@@ -11842,7 +11843,7 @@ fn zirShl(...@@ -11842,7 +11843,7 @@ fn zirShl(
11842 if (scalar_ty.zigTypeTag() == .ComptimeInt) {11843 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
11843 break :val shifted.wrapped_result;11844 break :val shifted.wrapped_result;
11844 }11845 }
11845 if (shifted.overflow_bit.compareAllWithZero(.eq)) {11846 if (shifted.overflow_bit.compareAllWithZero(.eq, sema.mod)) {
11846 break :val shifted.wrapped_result;11847 break :val shifted.wrapped_result;
11847 }11848 }
11848 return sema.fail(block, src, "operation caused overflow", .{});11849 return sema.fail(block, src, "operation caused overflow", .{});
...@@ -11959,8 +11960,8 @@ fn zirShr(...@@ -11959,8 +11960,8 @@ fn zirShr(
11959 const target = sema.mod.getTarget();11960 const target = sema.mod.getTarget();
11960 const scalar_ty = lhs_ty.scalarType();11961 const scalar_ty = lhs_ty.scalarType();
1196111962
11962 const maybe_lhs_val = try sema.resolveMaybeUndefVal(lhs);11963 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs);
11963 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);11964 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);
1196411965
11965 const runtime_src = if (maybe_rhs_val) |rhs_val| rs: {11966 const runtime_src = if (maybe_rhs_val) |rhs_val| rs: {
11966 if (rhs_val.isUndef()) {11967 if (rhs_val.isUndef()) {
...@@ -12799,7 +12800,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -12799,7 +12800,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
12799 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();12800 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
12800 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();12801 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
12801 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);12802 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
12802 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div);12803 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1280312804
12804 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };12805 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
12805 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{12806 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
...@@ -12831,7 +12832,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -12831,7 +12832,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
12831 const lhs_val = maybe_lhs_val orelse unreachable;12832 const lhs_val = maybe_lhs_val orelse unreachable;
12832 const rhs_val = maybe_rhs_val orelse unreachable;12833 const rhs_val = maybe_rhs_val orelse unreachable;
12833 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;12834 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;
12834 if (!rem.compareAllWithZero(.eq)) {12835 if (!rem.compareAllWithZero(.eq, mod)) {
12835 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{12836 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{
12836 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),12837 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),
12837 });12838 });
...@@ -12959,7 +12960,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12959,7 +12960,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12959 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();12960 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
12960 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();12961 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
12961 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);12962 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
12962 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_exact);12963 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1296312964
12964 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };12965 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
12965 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{12966 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
...@@ -13024,7 +13025,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13024,7 +13025,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13024 if (maybe_rhs_val) |rhs_val| {13025 if (maybe_rhs_val) |rhs_val| {
13025 if (is_int) {13026 if (is_int) {
13026 const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, mod);13027 const modulus_val = try lhs_val.intMod(rhs_val, resolved_type, sema.arena, mod);
13027 if (!(modulus_val.compareAllWithZero(.eq))) {13028 if (!(modulus_val.compareAllWithZero(.eq, mod))) {
13028 return sema.fail(block, src, "exact division produced remainder", .{});13029 return sema.fail(block, src, "exact division produced remainder", .{});
13029 }13030 }
13030 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);13031 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);
...@@ -13035,7 +13036,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13035,7 +13036,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13035 return sema.addConstant(resolved_type, res);13036 return sema.addConstant(resolved_type, res);
13036 } else {13037 } else {
13037 const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, mod);13038 const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, mod);
13038 if (!(modulus_val.compareAllWithZero(.eq))) {13039 if (!(modulus_val.compareAllWithZero(.eq, mod))) {
13039 return sema.fail(block, src, "exact division produced remainder", .{});13040 return sema.fail(block, src, "exact division produced remainder", .{});
13040 }13041 }
13041 return sema.addConstant(13042 return sema.addConstant(
...@@ -13122,7 +13123,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13122,7 +13123,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13122 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13123 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13123 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13124 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13124 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13125 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13125 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_floor);13126 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1312613127
13127 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };13128 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
13128 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{13129 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
...@@ -13238,7 +13239,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13238,7 +13239,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13238 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13239 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13239 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13240 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13240 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13241 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13241 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .div_trunc);13242 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1324213243
13243 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };13244 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
13244 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{13245 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
...@@ -13481,7 +13482,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -13481,7 +13482,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
13481 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13482 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13482 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13483 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13483 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13484 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13484 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .mod_rem);13485 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1348513486
13486 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };13487 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
13487 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{13488 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
...@@ -13664,7 +13665,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13664,7 +13665,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13664 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13665 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13665 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13666 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13666 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13667 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13667 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .mod);13668 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1366813669
13669 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };13670 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
13670 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{13671 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
...@@ -13766,7 +13767,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -13766,7 +13767,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
13766 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();13767 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13767 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();13768 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13768 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);13769 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
13769 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty, .rem);13770 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1377013771
13771 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };13772 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
13772 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{13773 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{
...@@ -14106,12 +14107,7 @@ fn analyzeArithmetic(...@@ -14106,12 +14107,7 @@ fn analyzeArithmetic(
14106 const air_tag: Air.Inst.Tag = switch (zir_tag) {14107 const air_tag: Air.Inst.Tag = switch (zir_tag) {
14107 .add => .ptr_add,14108 .add => .ptr_add,
14108 .sub => .ptr_sub,14109 .sub => .ptr_sub,
14109 else => return sema.fail(14110 else => return sema.fail(block, src, "invalid pointer arithmetic operator", .{}),
14110 block,
14111 src,
14112 "invalid pointer arithmetic operand: '{s}''",
14113 .{@tagName(zir_tag)},
14114 ),
14115 };14111 };
14116 return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src);14112 return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src);
14117 },14113 },
...@@ -19697,7 +19693,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19697,7 +19693,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19697 }19693 }
19698 }19694 }
1969919695
19700 if (try sema.resolveMaybeUndefVal(operand)) |val| {19696 if (try sema.resolveMaybeUndefValIntable(operand)) |val| {
19701 if (val.isUndef()) return sema.addConstUndef(dest_ty);19697 if (val.isUndef()) return sema.addConstUndef(dest_ty);
19702 if (!is_vector) {19698 if (!is_vector) {
19703 return sema.addConstant(19699 return sema.addConstant(
...@@ -19901,7 +19897,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -19901,7 +19897,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
19901 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };19897 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
19902 const operand = try sema.resolveInst(inst_data.operand);19898 const operand = try sema.resolveInst(inst_data.operand);
19903 const operand_ty = sema.typeOf(operand);19899 const operand_ty = sema.typeOf(operand);
19904 _ = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src);19900 const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src);
1990519901
19906 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {19902 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
19907 return sema.addConstant(operand_ty, val);19903 return sema.addConstant(operand_ty, val);
...@@ -19909,7 +19905,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -19909,7 +19905,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1990919905
19910 const target = sema.mod.getTarget();19906 const target = sema.mod.getTarget();
19911 switch (operand_ty.zigTypeTag()) {19907 switch (operand_ty.zigTypeTag()) {
19912 .Int, .ComptimeInt => {19908 .Int => {
19913 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {19909 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
19914 if (val.isUndef()) return sema.addConstUndef(operand_ty);19910 if (val.isUndef()) return sema.addConstUndef(operand_ty);
19915 const result_val = try val.bitReverse(operand_ty, target, sema.arena);19911 const result_val = try val.bitReverse(operand_ty, target, sema.arena);
...@@ -19929,7 +19925,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -19929,7 +19925,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
19929 const elems = try sema.arena.alloc(Value, vec_len);19925 const elems = try sema.arena.alloc(Value, vec_len);
19930 for (elems) |*elem, i| {19926 for (elems) |*elem, i| {
19931 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);19927 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);
19932 elem.* = try elem_val.bitReverse(operand_ty, target, sema.arena);19928 elem.* = try elem_val.bitReverse(scalar_ty, target, sema.arena);
19933 }19929 }
19934 return sema.addConstant(19930 return sema.addConstant(
19935 operand_ty,19931 operand_ty,
...@@ -20028,7 +20024,6 @@ fn checkInvalidPtrArithmetic(...@@ -20028,7 +20024,6 @@ fn checkInvalidPtrArithmetic(
20028 block: *Block,20024 block: *Block,
20029 src: LazySrcLoc,20025 src: LazySrcLoc,
20030 ty: Type,20026 ty: Type,
20031 zir_tag: Zir.Inst.Tag,
20032) CompileError!void {20027) CompileError!void {
20033 switch (try ty.zigTypeTagOrPoison()) {20028 switch (try ty.zigTypeTagOrPoison()) {
20034 .Pointer => switch (ty.ptrSize()) {20029 .Pointer => switch (ty.ptrSize()) {
...@@ -20036,8 +20031,8 @@ fn checkInvalidPtrArithmetic(...@@ -20036,8 +20031,8 @@ fn checkInvalidPtrArithmetic(
20036 .Many, .C => return sema.fail(20031 .Many, .C => return sema.fail(
20037 block,20032 block,
20038 src,20033 src,
20039 "invalid pointer arithmetic operand: '{s}''",20034 "invalid pointer arithmetic operator",
20040 .{@tagName(zir_tag)},20035 .{},
20041 ),20036 ),
20042 },20037 },
20043 else => return,20038 else => return,
src/codegen/llvm.zig+183-164
...@@ -10396,12 +10396,7 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool...@@ -10396,12 +10396,7 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool
10396 .mips, .mipsel => return false,10396 .mips, .mipsel => return false,
10397 .x86_64 => switch (target.os.tag) {10397 .x86_64 => switch (target.os.tag) {
10398 .windows => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,10398 .windows => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,
10399 else => {10399 else => return firstParamSRetSystemV(fn_info.return_type, target),
10400 const class = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret);
10401 if (class[0] == .memory) return true;
10402 if (class[0] == .x87 and class[2] != .none) return true;
10403 return false;
10404 },
10405 },10400 },
10406 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect,10401 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect,
10407 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory,10402 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory,
...@@ -10413,11 +10408,20 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool...@@ -10413,11 +10408,20 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool
10413 .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type, target) == .memory,10408 .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type, target) == .memory,
10414 else => return false, // TODO investigate C ABI for other architectures10409 else => return false, // TODO investigate C ABI for other architectures
10415 },10410 },
10411 .SysV => return firstParamSRetSystemV(fn_info.return_type, target),
10412 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,
10416 .Stdcall => return !isScalar(fn_info.return_type),10413 .Stdcall => return !isScalar(fn_info.return_type),
10417 else => return false,10414 else => return false,
10418 }10415 }
10419}10416}
1042010417
10418fn firstParamSRetSystemV(ty: Type, target: std.Target) bool {
10419 const class = x86_64_abi.classifySystemV(ty, target, .ret);
10420 if (class[0] == .memory) return true;
10421 if (class[0] == .x87 and class[2] != .none) return true;
10422 return false;
10423}
10424
10421/// In order to support the C calling convention, some return types need to be lowered10425/// In order to support the C calling convention, some return types need to be lowered
10422/// completely differently in the function prototype to honor the C ABI, and then10426/// completely differently in the function prototype to honor the C ABI, and then
10423/// be effectively bitcasted to the actual return type.10427/// be effectively bitcasted to the actual return type.
...@@ -10442,77 +10446,14 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10442,77 +10446,14 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10442 }10446 }
10443 },10447 },
10444 .C => {10448 .C => {
10445 const is_scalar = isScalar(fn_info.return_type);
10446 switch (target.cpu.arch) {10449 switch (target.cpu.arch) {
10447 .mips, .mipsel => return dg.lowerType(fn_info.return_type),10450 .mips, .mipsel => return dg.lowerType(fn_info.return_type),
10448 .x86_64 => switch (target.os.tag) {10451 .x86_64 => switch (target.os.tag) {
10449 .windows => switch (x86_64_abi.classifyWindows(fn_info.return_type, target)) {10452 .windows => return lowerWin64FnRetTy(dg, fn_info),
10450 .integer => {10453 else => return lowerSystemVFnRetTy(dg, fn_info),
10451 if (is_scalar) {
10452 return dg.lowerType(fn_info.return_type);
10453 } else {
10454 const abi_size = fn_info.return_type.abiSize(target);
10455 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10456 }
10457 },
10458 .win_i128 => return dg.context.intType(64).vectorType(2),
10459 .memory => return dg.context.voidType(),
10460 .sse => return dg.lowerType(fn_info.return_type),
10461 else => unreachable,
10462 },
10463 else => {
10464 if (is_scalar) {
10465 return dg.lowerType(fn_info.return_type);
10466 }
10467 const classes = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret);
10468 if (classes[0] == .memory) {
10469 return dg.context.voidType();
10470 }
10471 var llvm_types_buffer: [8]*llvm.Type = undefined;
10472 var llvm_types_index: u32 = 0;
10473 for (classes) |class| {
10474 switch (class) {
10475 .integer => {
10476 llvm_types_buffer[llvm_types_index] = dg.context.intType(64);
10477 llvm_types_index += 1;
10478 },
10479 .sse, .sseup => {
10480 llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
10481 llvm_types_index += 1;
10482 },
10483 .float => {
10484 llvm_types_buffer[llvm_types_index] = dg.context.floatType();
10485 llvm_types_index += 1;
10486 },
10487 .float_combine => {
10488 llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
10489 llvm_types_index += 1;
10490 },
10491 .x87 => {
10492 if (llvm_types_index != 0 or classes[2] != .none) {
10493 return dg.context.voidType();
10494 }
10495 llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
10496 llvm_types_index += 1;
10497 },
10498 .x87up => continue,
10499 .complex_x87 => {
10500 @panic("TODO");
10501 },
10502 .memory => unreachable, // handled above
10503 .win_i128 => unreachable, // windows only
10504 .none => break,
10505 }
10506 }
10507 if (classes[0] == .integer and classes[1] == .none) {
10508 const abi_size = fn_info.return_type.abiSize(target);
10509 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10510 }
10511 return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False);
10512 },
10513 },10454 },
10514 .wasm32 => {10455 .wasm32 => {
10515 if (is_scalar) {10456 if (isScalar(fn_info.return_type)) {
10516 return dg.lowerType(fn_info.return_type);10457 return dg.lowerType(fn_info.return_type);
10517 }10458 }
10518 const classes = wasm_c_abi.classifyType(fn_info.return_type, target);10459 const classes = wasm_c_abi.classifyType(fn_info.return_type, target);
...@@ -10569,6 +10510,8 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10569,6 +10510,8 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10569 else => return dg.lowerType(fn_info.return_type),10510 else => return dg.lowerType(fn_info.return_type),
10570 }10511 }
10571 },10512 },
10513 .Win64 => return lowerWin64FnRetTy(dg, fn_info),
10514 .SysV => return lowerSystemVFnRetTy(dg, fn_info),
10572 .Stdcall => {10515 .Stdcall => {
10573 if (isScalar(fn_info.return_type)) {10516 if (isScalar(fn_info.return_type)) {
10574 return dg.lowerType(fn_info.return_type);10517 return dg.lowerType(fn_info.return_type);
...@@ -10580,6 +10523,76 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10580,6 +10523,76 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10580 }10523 }
10581}10524}
1058210525
10526fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10527 const target = dg.module.getTarget();
10528 switch (x86_64_abi.classifyWindows(fn_info.return_type, target)) {
10529 .integer => {
10530 if (isScalar(fn_info.return_type)) {
10531 return dg.lowerType(fn_info.return_type);
10532 } else {
10533 const abi_size = fn_info.return_type.abiSize(target);
10534 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10535 }
10536 },
10537 .win_i128 => return dg.context.intType(64).vectorType(2),
10538 .memory => return dg.context.voidType(),
10539 .sse => return dg.lowerType(fn_info.return_type),
10540 else => unreachable,
10541 }
10542}
10543
10544fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10545 if (isScalar(fn_info.return_type)) {
10546 return dg.lowerType(fn_info.return_type);
10547 }
10548 const target = dg.module.getTarget();
10549 const classes = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret);
10550 if (classes[0] == .memory) {
10551 return dg.context.voidType();
10552 }
10553 var llvm_types_buffer: [8]*llvm.Type = undefined;
10554 var llvm_types_index: u32 = 0;
10555 for (classes) |class| {
10556 switch (class) {
10557 .integer => {
10558 llvm_types_buffer[llvm_types_index] = dg.context.intType(64);
10559 llvm_types_index += 1;
10560 },
10561 .sse, .sseup => {
10562 llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
10563 llvm_types_index += 1;
10564 },
10565 .float => {
10566 llvm_types_buffer[llvm_types_index] = dg.context.floatType();
10567 llvm_types_index += 1;
10568 },
10569 .float_combine => {
10570 llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
10571 llvm_types_index += 1;
10572 },
10573 .x87 => {
10574 if (llvm_types_index != 0 or classes[2] != .none) {
10575 return dg.context.voidType();
10576 }
10577 llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type();
10578 llvm_types_index += 1;
10579 },
10580 .x87up => continue,
10581 .complex_x87 => {
10582 @panic("TODO");
10583 },
10584 .memory => unreachable, // handled above
10585 .win_i128 => unreachable, // windows only
10586 .none => break,
10587 }
10588 }
10589 if (classes[0] == .integer and classes[1] == .none) {
10590 const abi_size = fn_info.return_type.abiSize(target);
10591 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10592 }
10593 return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False);
10594}
10595
10583const ParamTypeIterator = struct {10596const ParamTypeIterator = struct {
10584 dg: *DeclGen,10597 dg: *DeclGen,
10585 fn_info: Type.Payload.Function.Data,10598 fn_info: Type.Payload.Function.Data,
...@@ -10629,7 +10642,6 @@ const ParamTypeIterator = struct {...@@ -10629,7 +10642,6 @@ const ParamTypeIterator = struct {
10629 it.zig_index += 1;10642 it.zig_index += 1;
10630 return .no_bits;10643 return .no_bits;
10631 }10644 }
10632 const dg = it.dg;
10633 switch (it.fn_info.cc) {10645 switch (it.fn_info.cc) {
10634 .Unspecified, .Inline => {10646 .Unspecified, .Inline => {
10635 it.zig_index += 1;10647 it.zig_index += 1;
...@@ -10648,7 +10660,6 @@ const ParamTypeIterator = struct {...@@ -10648,7 +10660,6 @@ const ParamTypeIterator = struct {
10648 @panic("TODO implement async function lowering in the LLVM backend");10660 @panic("TODO implement async function lowering in the LLVM backend");
10649 },10661 },
10650 .C => {10662 .C => {
10651 const is_scalar = isScalar(ty);
10652 switch (it.target.cpu.arch) {10663 switch (it.target.cpu.arch) {
10653 .mips, .mipsel => {10664 .mips, .mipsel => {
10654 it.zig_index += 1;10665 it.zig_index += 1;
...@@ -10656,99 +10667,13 @@ const ParamTypeIterator = struct {...@@ -10656,99 +10667,13 @@ const ParamTypeIterator = struct {
10656 return .byval;10667 return .byval;
10657 },10668 },
10658 .x86_64 => switch (it.target.os.tag) {10669 .x86_64 => switch (it.target.os.tag) {
10659 .windows => switch (x86_64_abi.classifyWindows(ty, it.target)) {10670 .windows => return it.nextWin64(ty),
10660 .integer => {10671 else => return it.nextSystemV(ty),
10661 if (is_scalar) {
10662 it.zig_index += 1;
10663 it.llvm_index += 1;
10664 return .byval;
10665 } else {
10666 it.zig_index += 1;
10667 it.llvm_index += 1;
10668 return .abi_sized_int;
10669 }
10670 },
10671 .win_i128 => {
10672 it.zig_index += 1;
10673 it.llvm_index += 1;
10674 return .byref;
10675 },
10676 .memory => {
10677 it.zig_index += 1;
10678 it.llvm_index += 1;
10679 return .byref_mut;
10680 },
10681 .sse => {
10682 it.zig_index += 1;
10683 it.llvm_index += 1;
10684 return .byval;
10685 },
10686 else => unreachable,
10687 },
10688 else => {
10689 const classes = x86_64_abi.classifySystemV(ty, it.target, .arg);
10690 if (classes[0] == .memory) {
10691 it.zig_index += 1;
10692 it.llvm_index += 1;
10693 it.byval_attr = true;
10694 return .byref;
10695 }
10696 if (is_scalar) {
10697 it.zig_index += 1;
10698 it.llvm_index += 1;
10699 return .byval;
10700 }
10701 var llvm_types_buffer: [8]*llvm.Type = undefined;
10702 var llvm_types_index: u32 = 0;
10703 for (classes) |class| {
10704 switch (class) {
10705 .integer => {
10706 llvm_types_buffer[llvm_types_index] = dg.context.intType(64);
10707 llvm_types_index += 1;
10708 },
10709 .sse, .sseup => {
10710 llvm_types_buffer[llvm_types_index] = dg.context.doubleType();
10711 llvm_types_index += 1;
10712 },
10713 .float => {
10714 llvm_types_buffer[llvm_types_index] = dg.context.floatType();
10715 llvm_types_index += 1;
10716 },
10717 .float_combine => {
10718 llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2);
10719 llvm_types_index += 1;
10720 },
10721 .x87 => {
10722 it.zig_index += 1;
10723 it.llvm_index += 1;
10724 it.byval_attr = true;
10725 return .byref;
10726 },
10727 .x87up => unreachable,
10728 .complex_x87 => {
10729 @panic("TODO");
10730 },
10731 .memory => unreachable, // handled above
10732 .win_i128 => unreachable, // windows only
10733 .none => break,
10734 }
10735 }
10736 if (classes[0] == .integer and classes[1] == .none) {
10737 it.zig_index += 1;
10738 it.llvm_index += 1;
10739 return .abi_sized_int;
10740 }
10741 it.llvm_types_buffer = llvm_types_buffer;
10742 it.llvm_types_len = llvm_types_index;
10743 it.llvm_index += llvm_types_index;
10744 it.zig_index += 1;
10745 return .multiple_llvm_types;
10746 },
10747 },10672 },
10748 .wasm32 => {10673 .wasm32 => {
10749 it.zig_index += 1;10674 it.zig_index += 1;
10750 it.llvm_index += 1;10675 it.llvm_index += 1;
10751 if (is_scalar) {10676 if (isScalar(ty)) {
10752 return .byval;10677 return .byval;
10753 }10678 }
10754 const classes = wasm_c_abi.classifyType(ty, it.target);10679 const classes = wasm_c_abi.classifyType(ty, it.target);
...@@ -10766,7 +10691,7 @@ const ParamTypeIterator = struct {...@@ -10766,7 +10691,7 @@ const ParamTypeIterator = struct {
10766 .byval => return .byval,10691 .byval => return .byval,
10767 .integer => {10692 .integer => {
10768 it.llvm_types_len = 1;10693 it.llvm_types_len = 1;
10769 it.llvm_types_buffer[0] = dg.context.intType(64);10694 it.llvm_types_buffer[0] = it.dg.context.intType(64);
10770 return .multiple_llvm_types;10695 return .multiple_llvm_types;
10771 },10696 },
10772 .double_integer => return Lowering{ .i64_array = 2 },10697 .double_integer => return Lowering{ .i64_array = 2 },
...@@ -10806,6 +10731,8 @@ const ParamTypeIterator = struct {...@@ -10806,6 +10731,8 @@ const ParamTypeIterator = struct {
10806 },10731 },
10807 }10732 }
10808 },10733 },
10734 .Win64 => return it.nextWin64(ty),
10735 .SysV => return it.nextSystemV(ty),
10809 .Stdcall => {10736 .Stdcall => {
10810 it.zig_index += 1;10737 it.zig_index += 1;
10811 it.llvm_index += 1;10738 it.llvm_index += 1;
...@@ -10824,6 +10751,98 @@ const ParamTypeIterator = struct {...@@ -10824,6 +10751,98 @@ const ParamTypeIterator = struct {
10824 },10751 },
10825 }10752 }
10826 }10753 }
10754
10755 fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {
10756 switch (x86_64_abi.classifyWindows(ty, it.target)) {
10757 .integer => {
10758 if (isScalar(ty)) {
10759 it.zig_index += 1;
10760 it.llvm_index += 1;
10761 return .byval;
10762 } else {
10763 it.zig_index += 1;
10764 it.llvm_index += 1;
10765 return .abi_sized_int;
10766 }
10767 },
10768 .win_i128 => {
10769 it.zig_index += 1;
10770 it.llvm_index += 1;
10771 return .byref;
10772 },
10773 .memory => {
10774 it.zig_index += 1;
10775 it.llvm_index += 1;
10776 return .byref_mut;
10777 },
10778 .sse => {
10779 it.zig_index += 1;
10780 it.llvm_index += 1;
10781 return .byval;
10782 },
10783 else => unreachable,
10784 }
10785 }
10786
10787 fn nextSystemV(it: *ParamTypeIterator, ty: Type) ?Lowering {
10788 const classes = x86_64_abi.classifySystemV(ty, it.target, .arg);
10789 if (classes[0] == .memory) {
10790 it.zig_index += 1;
10791 it.llvm_index += 1;
10792 it.byval_attr = true;
10793 return .byref;
10794 }
10795 if (isScalar(ty)) {
10796 it.zig_index += 1;
10797 it.llvm_index += 1;
10798 return .byval;
10799 }
10800 var llvm_types_buffer: [8]*llvm.Type = undefined;
10801 var llvm_types_index: u32 = 0;
10802 for (classes) |class| {
10803 switch (class) {
10804 .integer => {
10805 llvm_types_buffer[llvm_types_index] = it.dg.context.intType(64);
10806 llvm_types_index += 1;
10807 },
10808 .sse, .sseup => {
10809 llvm_types_buffer[llvm_types_index] = it.dg.context.doubleType();
10810 llvm_types_index += 1;
10811 },
10812 .float => {
10813 llvm_types_buffer[llvm_types_index] = it.dg.context.floatType();
10814 llvm_types_index += 1;
10815 },
10816 .float_combine => {
10817 llvm_types_buffer[llvm_types_index] = it.dg.context.floatType().vectorType(2);
10818 llvm_types_index += 1;
10819 },
10820 .x87 => {
10821 it.zig_index += 1;
10822 it.llvm_index += 1;
10823 it.byval_attr = true;
10824 return .byref;
10825 },
10826 .x87up => unreachable,
10827 .complex_x87 => {
10828 @panic("TODO");
10829 },
10830 .memory => unreachable, // handled above
10831 .win_i128 => unreachable, // windows only
10832 .none => break,
10833 }
10834 }
10835 if (classes[0] == .integer and classes[1] == .none) {
10836 it.zig_index += 1;
10837 it.llvm_index += 1;
10838 return .abi_sized_int;
10839 }
10840 it.llvm_types_buffer = llvm_types_buffer;
10841 it.llvm_types_len = llvm_types_index;
10842 it.llvm_index += llvm_types_index;
10843 it.zig_index += 1;
10844 return .multiple_llvm_types;
10845 }
10827};10846};
1082810847
10829fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTypeIterator {10848fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTypeIterator {
src/type.zig+37-9
...@@ -3789,6 +3789,39 @@ pub const Type = extern union {...@@ -3789,6 +3789,39 @@ pub const Type = extern union {
3789 }3789 }
3790 }3790 }
37913791
3792 /// Returns true if the type's layout is already resolved and it is safe
3793 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.
3794 pub fn layoutIsResolved(ty: Type) bool {
3795 switch (ty.zigTypeTag()) {
3796 .Struct => {
3797 if (ty.castTag(.@"struct")) |struct_ty| {
3798 return struct_ty.data.haveLayout();
3799 }
3800 return true;
3801 },
3802 .Union => {
3803 if (ty.cast(Payload.Union)) |union_ty| {
3804 return union_ty.data.haveLayout();
3805 }
3806 return true;
3807 },
3808 .Array => {
3809 if (ty.arrayLenIncludingSentinel() == 0) return true;
3810 return ty.childType().layoutIsResolved();
3811 },
3812 .Optional => {
3813 var buf: Type.Payload.ElemType = undefined;
3814 const payload_ty = ty.optionalChild(&buf);
3815 return payload_ty.layoutIsResolved();
3816 },
3817 .ErrorUnion => {
3818 const payload_ty = ty.errorUnionPayload();
3819 return payload_ty.layoutIsResolved();
3820 },
3821 else => return true,
3822 }
3823 }
3824
3792 pub fn isSinglePointer(self: Type) bool {3825 pub fn isSinglePointer(self: Type) bool {
3793 return switch (self.tag()) {3826 return switch (self.tag()) {
3794 .single_const_pointer,3827 .single_const_pointer,
...@@ -5500,7 +5533,7 @@ pub const Type = extern union {...@@ -5500,7 +5533,7 @@ pub const Type = extern union {
5500 }5533 }
5501 const S = struct {5534 const S = struct {
5502 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {5535 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {
5503 if (int_val.compareAllWithZero(.lt)) return null;5536 if (int_val.compareAllWithZero(.lt, m)) return null;
5504 var end_payload: Value.Payload.U64 = .{5537 var end_payload: Value.Payload.U64 = .{
5505 .base = .{ .tag = .int_u64 },5538 .base = .{ .tag = .int_u64 },
5506 .data = end,5539 .data = end,
...@@ -6498,12 +6531,7 @@ pub const Type = extern union {...@@ -6498,12 +6531,7 @@ pub const Type = extern union {
6498 // pointee type needs to be resolved more, that needs to be done before calling6531 // pointee type needs to be resolved more, that needs to be done before calling
6499 // this ptr() function.6532 // this ptr() function.
6500 if (d.@"align" != 0) canonicalize: {6533 if (d.@"align" != 0) canonicalize: {
6501 if (d.pointee_type.castTag(.@"struct")) |struct_ty| {6534 if (!d.pointee_type.layoutIsResolved()) break :canonicalize;
6502 if (!struct_ty.data.haveLayout()) break :canonicalize;
6503 }
6504 if (d.pointee_type.cast(Payload.Union)) |union_ty| {
6505 if (!union_ty.data.haveLayout()) break :canonicalize;
6506 }
6507 if (d.@"align" == d.pointee_type.abiAlignment(target)) {6535 if (d.@"align" == d.pointee_type.abiAlignment(target)) {
6508 d.@"align" = 0;6536 d.@"align" = 0;
6509 }6537 }
...@@ -6528,12 +6556,12 @@ pub const Type = extern union {...@@ -6528,12 +6556,12 @@ pub const Type = extern union {
6528 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {6556 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
6529 switch (d.size) {6557 switch (d.size) {
6530 .Slice => {6558 .Slice => {
6531 if (sent.compareAllWithZero(.eq)) {6559 if (sent.compareAllWithZero(.eq, mod)) {
6532 return Type.initTag(.const_slice_u8_sentinel_0);6560 return Type.initTag(.const_slice_u8_sentinel_0);
6533 }6561 }
6534 },6562 },
6535 .Many => {6563 .Many => {
6536 if (sent.compareAllWithZero(.eq)) {6564 if (sent.compareAllWithZero(.eq, mod)) {
6537 return Type.initTag(.manyptr_const_u8_sentinel_0);6565 return Type.initTag(.manyptr_const_u8_sentinel_0);
6538 }6566 }
6539 },6567 },
src/value.zig+29-5
...@@ -2076,13 +2076,22 @@ pub const Value = extern union {...@@ -2076,13 +2076,22 @@ pub const Value = extern union {
2076 /// For vectors, returns true if comparison is true for ALL elements.2076 /// For vectors, returns true if comparison is true for ALL elements.
2077 ///2077 ///
2078 /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`2078 /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`
2079 pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator) bool {2079 pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, mod: *Module) bool {
2080 return compareAllWithZeroAdvanced(lhs, op, null) catch unreachable;2080 return compareAllWithZeroAdvancedExtra(lhs, op, mod, null) catch unreachable;
2081 }2081 }
20822082
2083 pub fn compareAllWithZeroAdvanced(2083 pub fn compareAllWithZeroAdvanced(
2084 lhs: Value,2084 lhs: Value,
2085 op: std.math.CompareOperator,2085 op: std.math.CompareOperator,
2086 sema: *Sema,
2087 ) Module.CompileError!bool {
2088 return compareAllWithZeroAdvancedExtra(lhs, op, sema.mod, sema);
2089 }
2090
2091 pub fn compareAllWithZeroAdvancedExtra(
2092 lhs: Value,
2093 op: std.math.CompareOperator,
2094 mod: *Module,
2086 opt_sema: ?*Sema,2095 opt_sema: ?*Sema,
2087 ) Module.CompileError!bool {2096 ) Module.CompileError!bool {
2088 if (lhs.isInf()) {2097 if (lhs.isInf()) {
...@@ -2095,10 +2104,25 @@ pub const Value = extern union {...@@ -2095,10 +2104,25 @@ pub const Value = extern union {
2095 }2104 }
20962105
2097 switch (lhs.tag()) {2106 switch (lhs.tag()) {
2098 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvanced(op, opt_sema),2107 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
2099 .aggregate => {2108 .aggregate => {
2100 for (lhs.castTag(.aggregate).?.data) |elem_val| {2109 for (lhs.castTag(.aggregate).?.data) |elem_val| {
2101 if (!(try elem_val.compareAllWithZeroAdvanced(op, opt_sema))) return false;2110 if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false;
2111 }
2112 return true;
2113 },
2114 .str_lit => {
2115 const str_lit = lhs.castTag(.str_lit).?.data;
2116 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
2117 for (bytes) |byte| {
2118 if (!std.math.compare(byte, op, 0)) return false;
2119 }
2120 return true;
2121 },
2122 .bytes => {
2123 const bytes = lhs.castTag(.bytes).?.data;
2124 for (bytes) |byte| {
2125 if (!std.math.compare(byte, op, 0)) return false;
2102 }2126 }
2103 return true;2127 return true;
2104 },2128 },
...@@ -3103,7 +3127,7 @@ pub const Value = extern union {...@@ -3103,7 +3127,7 @@ pub const Value = extern union {
3103 .int_i64,3127 .int_i64,
3104 .int_big_positive,3128 .int_big_positive,
3105 .int_big_negative,3129 .int_big_negative,
3106 => compareAllWithZero(self, .eq),3130 => self.orderAgainstZero().compare(.eq),
31073131
3108 .undef => unreachable,3132 .undef => unreachable,
3109 .unreachable_value => unreachable,3133 .unreachable_value => unreachable,
test/behavior.zig-1
...@@ -106,7 +106,6 @@ test {...@@ -106,7 +106,6 @@ test {
106 _ = @import("behavior/bugs/12430.zig");106 _ = @import("behavior/bugs/12430.zig");
107 _ = @import("behavior/bugs/12450.zig");107 _ = @import("behavior/bugs/12450.zig");
108 _ = @import("behavior/bugs/12486.zig");108 _ = @import("behavior/bugs/12486.zig");
109 _ = @import("behavior/bugs/12488.zig");
110 _ = @import("behavior/bugs/12498.zig");109 _ = @import("behavior/bugs/12498.zig");
111 _ = @import("behavior/bugs/12551.zig");110 _ = @import("behavior/bugs/12551.zig");
112 _ = @import("behavior/bugs/12571.zig");111 _ = @import("behavior/bugs/12571.zig");
test/behavior/bugs/12488.zig deleted-13
...@@ -1,13 +0,0 @@
1const expect = @import("std").testing.expect;
2
3const A = struct {
4 a: u32,
5};
6
7fn foo(comptime a: anytype) !void {
8 try expect(a[0][0] == @sizeOf(A));
9}
10
11test {
12 try foo(.{[_]usize{@sizeOf(A)}});
13}
test/behavior/fn.zig+23
...@@ -517,3 +517,26 @@ test "peer type resolution of inferred error set with non-void payload" {...@@ -517,3 +517,26 @@ test "peer type resolution of inferred error set with non-void payload" {
517 };517 };
518 try expect(try S.openDataFile(.read) == 1);518 try expect(try S.openDataFile(.read) == 1);
519}519}
520
521test "lazy values passed to anytype parameter" {
522 const A = struct {
523 a: u32,
524 fn foo(comptime a: anytype) !void {
525 try expect(a[0][0] == @sizeOf(@This()));
526 }
527 };
528 try A.foo(.{[_]usize{@sizeOf(A)}});
529
530 const B = struct {
531 fn foo(comptime a: anytype) !void {
532 try expect(a.x == 0);
533 }
534 };
535 try B.foo(.{ .x = @sizeOf(B) });
536
537 const C = struct {};
538 try expect(@truncate(u32, @sizeOf(C)) == 0);
539
540 const D = struct {};
541 try expect(@sizeOf(D) << 1 == 0);
542}
test/behavior/pointers.zig+15
...@@ -532,3 +532,18 @@ test "pointer alignment and element type include call expression" {...@@ -532,3 +532,18 @@ test "pointer alignment and element type include call expression" {
532 };532 };
533 try expect(@alignOf(S.P) > 0);533 try expect(@alignOf(S.P) > 0);
534}534}
535
536test "pointer to array has explicit alignment" {
537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
538
539 const S = struct {
540 const Base = extern struct { a: u8 };
541 const Base2 = extern struct { a: u8 };
542 fn func(ptr: *[4]Base) *align(1) [4]Base2 {
543 return @alignCast(1, @ptrCast(*[4]Base2, ptr));
544 }
545 };
546 var bases = [_]S.Base{.{ .a = 2 }} ** 4;
547 const casted = S.func(&bases);
548 try expect(casted[0].a == 2);
549}
test/behavior/struct.zig+5
...@@ -1573,3 +1573,8 @@ test "struct fields get automatically reordered" {...@@ -1573,3 +1573,8 @@ test "struct fields get automatically reordered" {
1573 };1573 };
1574 try expect(@sizeOf(S1) == @sizeOf(S2));1574 try expect(@sizeOf(S1) == @sizeOf(S2));
1575}1575}
1576
1577test "directly initiating tuple like struct" {
1578 const a = struct { u8 }{8};
1579 try expect(a[0] == 8);
1580}
test/behavior/vector.zig+11
...@@ -1286,3 +1286,14 @@ test "store to vector in slice" {...@@ -1286,3 +1286,14 @@ test "store to vector in slice" {
1286 s[i] = s[0];1286 s[i] = s[0];
1287 try expectEqual(v[1], v[0]);1287 try expectEqual(v[1], v[0]);
1288}1288}
1289
1290test "addition of vectors represented as strings" {
1291 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1292 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1293 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1294
1295 const V = @Vector(3, u8);
1296 const foo: V = "foo".*;
1297 const bar: V = @typeName(u32).*;
1298 try expectEqual(V{ 219, 162, 161 }, foo + bar);
1299}
test/c_abi/cfuncs.c+12
...@@ -1015,3 +1015,15 @@ void __attribute__((stdcall)) stdcall_big_union(union BigUnion x) {...@@ -1015,3 +1015,15 @@ void __attribute__((stdcall)) stdcall_big_union(union BigUnion x) {
1015 assert_or_panic(x.a.c == 3);1015 assert_or_panic(x.a.c == 3);
1016 assert_or_panic(x.a.d == 4);1016 assert_or_panic(x.a.d == 4);
1017}1017}
1018
1019#ifdef __x86_64__
1020struct ByRef __attribute__((ms_abi)) c_explict_win64(struct ByRef in) {
1021 in.val = 42;
1022 return in;
1023}
1024
1025struct ByRef __attribute__((sysv_abi)) c_explict_sys_v(struct ByRef in) {
1026 in.val = 42;
1027 return in;
1028}
1029#endif
test/c_abi/main.zig+16
...@@ -1190,3 +1190,19 @@ test "Stdcall ABI big union" {...@@ -1190,3 +1190,19 @@ test "Stdcall ABI big union" {
1190 };1190 };
1191 stdcall_big_union(x);1191 stdcall_big_union(x);
1192}1192}
1193
1194extern fn c_explict_win64(ByRef) callconv(.Win64) ByRef;
1195test "explicit SysV calling convention" {
1196 if (builtin.cpu.arch != .x86_64) return error.SkipZigTest;
1197
1198 const res = c_explict_win64(.{ .val = 1, .arr = undefined });
1199 try expect(res.val == 42);
1200}
1201
1202extern fn c_explict_sys_v(ByRef) callconv(.SysV) ByRef;
1203test "explicit Win64 calling convention" {
1204 if (builtin.cpu.arch != .x86_64) return error.SkipZigTest;
1205
1206 const res = c_explict_sys_v(.{ .val = 1, .arr = undefined });
1207 try expect(res.val == 42);
1208}
test/cases/compile_errors/bad_member_access_on_tuple.zig created+9
...@@ -0,0 +1,9 @@
1comptime {
2 _ = @TypeOf(.{}).is_optional;
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:21: error: struct '@TypeOf(.{})' has no member named 'is_optional'