| author | |
| committer | |
| log | a51c76541d60da81ef53e0ab1f221a80d9956bd5 |
| tree | 023a1f1fbc02b646214b70d78dad0acb7ec158f3 |
| parent | f85c01d4c7520d2242626f4c0684ab97e47af373 |
| parent | aa626deadddcf26a5789d29d5ba88c978ee53b89 |
| signature |
Misc fixes13 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 | } |
| 7515 | 7516 | ||
| 7516 | fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { | 7517 | fn 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_sat | 11772 | // 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); |
| 11773 | 11774 | ||
| 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); |
| 11776 | 11777 | ||
| 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(); |
| 11961 | 11962 | ||
| 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); |
| 11964 | 11965 | ||
| 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); |
| 12803 | 12804 | ||
| 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); |
| 12963 | 12964 | ||
| 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); |
| 13126 | 13127 | ||
| 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); |
| 13242 | 13243 | ||
| 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); |
| 13485 | 13486 | ||
| 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); |
| 13668 | 13669 | ||
| 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); |
| 13770 | 13771 | ||
| 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 | } |
| 19699 | 19695 | ||
| 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); |
| 19905 | 19901 | ||
| 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! |
| 19909 | 19905 | ||
| 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 architectures | 10409 | 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 | } |
| 10420 | 10417 | ||
| 10418 | fn 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 lowered | 10425 | /// 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 then | 10426 | /// 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 | } |
| 10582 | 10525 | ||
| 10526 | fn 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 | |||
| 10544 | fn 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 | |||
| 10583 | const ParamTypeIterator = struct { | 10596 | const 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 | }; |
| 10828 | 10847 | ||
| 10829 | fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTypeIterator { | 10848 | fn 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 | } |
| 3791 | 3791 | ||
| 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 calling | 6531 | // 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 | } |
| 2082 | 2082 | ||
| 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 | } |
| 2096 | 2105 | ||
| 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), |
| 3107 | 3131 | ||
| 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 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | |||
| 3 | const A = struct { | ||
| 4 | a: u32, | ||
| 5 | }; | ||
| 6 | |||
| 7 | fn foo(comptime a: anytype) !void { | ||
| 8 | try expect(a[0][0] == @sizeOf(A)); | ||
| 9 | } | ||
| 10 | |||
| 11 | test { | ||
| 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 | |||
| 521 | test "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 | |||
| 536 | test "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 | |||
| 1577 | test "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 | |||
| 1290 | test "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__ | ||
| 1020 | struct ByRef __attribute__((ms_abi)) c_explict_win64(struct ByRef in) { | ||
| 1021 | in.val = 42; | ||
| 1022 | return in; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | struct 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 | |||
| 1194 | extern fn c_explict_win64(ByRef) callconv(.Win64) ByRef; | ||
| 1195 | test "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 | |||
| 1202 | extern fn c_explict_sys_v(ByRef) callconv(.SysV) ByRef; | ||
| 1203 | test "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 @@ | ||
| 1 | comptime { | ||
| 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' | ||