Skip to content

Commit bd2de10

Browse files
committed
Builtin.isbitwisetakable
1 parent ab68f0d commit bd2de10

13 files changed

+77
-1
lines changed

include/swift/AST/Builtins.def

+3
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ BUILTIN_MISC_OPERATION(Strideof, "strideof", "n", Special)
419419
/// IsPOD has type T.Type -> Bool
420420
BUILTIN_MISC_OPERATION(IsPOD, "ispod", "n", Special)
421421

422+
/// IsBitwiseTakable has type T.Type -> Bool
423+
BUILTIN_MISC_OPERATION(IsBitwiseTakable, "isbitwisetakable", "n", Special)
424+
422425
/// IsSameMetatype has type (Any.Type, Any.Type) -> Bool
423426
BUILTIN_MISC_OPERATION(IsSameMetatype, "is_same_metatype", "n", Special)
424427

include/swift/Serialization/ModuleFormat.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 437; // Last change: remove pinning
58+
const uint16_t VERSION_MINOR = 438; // Last change: add isbitwisetakable
5959

6060
using DeclIDField = BCFixed<31>;
6161

lib/AST/Builtins.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,13 @@ static ValueDecl *getIsPODOperation(ASTContext &Context, Identifier Id) {
736736
return builder.build(Id);
737737
}
738738

739+
static ValueDecl *getIsBitwiseTakable(ASTContext &Context, Identifier Id) {
740+
BuiltinGenericSignatureBuilder builder(Context);
741+
builder.addParameter(makeMetatype(makeGenericParam()));
742+
builder.setResult(makeConcrete(BuiltinIntegerType::get(1,Context)));
743+
return builder.build(Id);
744+
}
745+
739746
static ValueDecl *getIsOptionalOperation(ASTContext &Context, Identifier Id) {
740747
BuiltinGenericSignatureBuilder builder(Context);
741748
builder.addParameter(makeMetatype(makeGenericParam()));
@@ -1736,6 +1743,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
17361743
case BuiltinValueKind::IsPOD:
17371744
return getIsPODOperation(Context, Id);
17381745

1746+
case BuiltinValueKind::IsBitwiseTakable:
1747+
return getIsBitwiseTakable(Context, Id);
1748+
17391749
case BuiltinValueKind::IsOptionalType:
17401750
return getIsOptionalOperation(Context, Id);
17411751

lib/IRGen/FixedTypeInfo.h

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class FixedTypeInfo : public TypeInfo {
9191
llvm::Value *getAlignmentMask(IRGenFunction &IGF, SILType T) const override;
9292
llvm::Value *getStride(IRGenFunction &IGF, SILType T) const override;
9393
llvm::Value *getIsPOD(IRGenFunction &IGF, SILType T) const override;
94+
llvm::Value *getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const override;
9495
llvm::Value *isDynamicallyPackedInline(IRGenFunction &IGF,
9596
SILType T) const override;
9697

lib/IRGen/GenBuiltin.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
178178
return;
179179
}
180180

181+
if (Builtin.ID == BuiltinValueKind::IsBitwiseTakable) {
182+
(void)args.claimAll();
183+
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
184+
substitutions.getReplacementTypes()[0]);
185+
out.add(valueTy.second.getIsBitwiseTakable(IGF, valueTy.first));
186+
return;
187+
}
181188

182189
// addressof expects an lvalue argument.
183190
if (Builtin.ID == BuiltinValueKind::AddressOf) {

lib/IRGen/GenType.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ llvm::Value *FixedTypeInfo::getIsPOD(IRGenFunction &IGF, SILType T) const {
220220
return llvm::ConstantInt::get(IGF.IGM.Int1Ty,
221221
isPOD(ResilienceExpansion::Maximal) == IsPOD);
222222
}
223+
llvm::Value *FixedTypeInfo::getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const {
224+
return llvm::ConstantInt::get(IGF.IGM.Int1Ty,
225+
isBitwiseTakable(ResilienceExpansion::Maximal) == IsBitwiseTakable);
226+
}
223227
llvm::Constant *FixedTypeInfo::getStaticStride(IRGenModule &IGM) const {
224228
return asSizeConstant(IGM, getFixedStride());
225229
}

lib/IRGen/NonFixedTypeInfo.h

+4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ class WitnessSizedTypeInfo : public IndirectTypeInfo<Impl, TypeInfo> {
110110
return emitLoadOfIsPOD(IGF, T);
111111
}
112112

113+
llvm::Value *getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const override {
114+
return emitLoadOfIsBitwiseTakable(IGF, T);
115+
}
116+
113117
llvm::Value *isDynamicallyPackedInline(IRGenFunction &IGF,
114118
SILType T) const override {
115119
return emitLoadOfIsInline(IGF, T);

lib/IRGen/TypeInfo.h

+1
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ class TypeInfo {
287287
virtual llvm::Value *getAlignmentMask(IRGenFunction &IGF, SILType T) const = 0;
288288
virtual llvm::Value *getStride(IRGenFunction &IGF, SILType T) const = 0;
289289
virtual llvm::Value *getIsPOD(IRGenFunction &IGF, SILType T) const = 0;
290+
virtual llvm::Value *getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const = 0;
290291
virtual llvm::Value *isDynamicallyPackedInline(IRGenFunction &IGF,
291292
SILType T) const = 0;
292293

lib/SIL/SILOwnershipVerifier.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IntToFPWithOverflow)
12341234
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IntToPtr)
12351235
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsOptionalType)
12361236
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsPOD)
1237+
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsBitwiseTakable)
12371238
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsSameMetatype)
12381239
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, LShr)
12391240
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, Mul)

lib/SIL/ValueOwnershipKindClassifier.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, Sizeof)
471471
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Strideof)
472472
CONSTANT_OWNERSHIP_BUILTIN(Trivial, StringObjectOr)
473473
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsPOD)
474+
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsBitwiseTakable)
474475
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsSameMetatype)
475476
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Alignof)
476477
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AllocRaw)

stdlib/public/core/Builtin.swift

+8
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,14 @@ func _isPOD<T>(_ type: T.Type) -> Bool {
672672
return Bool(Builtin.ispod(type))
673673
}
674674

675+
/// Returns `true` if type is a bitwise takable. A bitwise takable type can
676+
/// just be moved to a different address in memory.
677+
@_transparent
678+
public // @testable
679+
func _isBitwiseTakable<T>(_ type: T.Type) -> Bool {
680+
return Bool(Builtin.isbitwisetakable(type))
681+
}
682+
675683
/// Returns `true` if type is nominally an Optional type.
676684
@_transparent
677685
public // @testable

test/IRGen/builtins.swift

+25
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,31 @@ func ispod_test() {
692692
var f = Builtin.ispod(Builtin.NativeObject.self)
693693
}
694694

695+
// CHECK-LABEL: define {{.*}} @{{.*}}generic_isbitwisetakable_test
696+
func generic_isbitwisetakable_test<T>(_: T) {
697+
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
698+
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
699+
// CHECK-NEXT: [[FLAGS:%.*]] = ptrtoint i8* [[T1]] to i64
700+
// CHECK-NEXT: [[ISNOTBITWISETAKABLE:%.*]] = and i64 [[FLAGS]], 1048576
701+
// CHECK-NEXT: [[ISBITWISETAKABLE:%.*]] = icmp eq i64 [[ISNOTBITWISETAKABLE]], 0
702+
// CHECK-NEXT: store i1 [[ISBITWISETAKABLE]], i1* [[S:%.*]]
703+
var s = Builtin.isbitwisetakable(T.self)
704+
}
705+
706+
// CHECK-LABEL: define {{.*}} @{{.*}}isbitwisetakable_test
707+
func isbitwisetakable_test() {
708+
// CHECK: store i1 true, i1*
709+
// CHECK: store i1 true, i1*
710+
// CHECK: store i1 true, i1*
711+
// CHECK: store i1 true, i1*
712+
// CHECK: store i1 false, i1*
713+
var t1 = Builtin.isbitwisetakable(Int.self)
714+
var t2 = Builtin.isbitwisetakable(C.self)
715+
var t3 = Builtin.isbitwisetakable(Abc.self)
716+
var t4 = Builtin.isbitwisetakable(Empty.self)
717+
var f = Builtin.isbitwisetakable(W.self)
718+
}
719+
695720
// CHECK-LABEL: define {{.*}} @{{.*}}is_same_metatype
696721
func is_same_metatype_test(_ t1: Any.Type, _ t2: Any.Type) {
697722
// CHECK: [[MT1_AS_PTR:%.*]] = bitcast %swift.type* %0 to i8*

test/stdlib/Builtins.swift

+11
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ var tests = TestSuite("Builtins")
2929

3030
class X {}
3131

32+
struct W {
33+
weak var weakX: X?
34+
}
35+
3236
tests.test("_isUnique/NativeObject") {
3337
var a: Builtin.NativeObject = Builtin.castToNativeObject(X())
3438
expectNotEqual(false, _isUnique_native(&a))
@@ -273,6 +277,13 @@ tests.test("_isPOD") {
273277
expectFalse(_isPOD(P.self))
274278
}
275279

280+
tests.test("_isBitwiseTakable") {
281+
expectTrue(_isBitwiseTakable(Int.self))
282+
expectTrue(_isBitwiseTakable(X.self))
283+
expectTrue(_isBitwiseTakable(P.self))
284+
expectFalse(_isBitwiseTakable(W.self))
285+
}
286+
276287
tests.test("_isOptional") {
277288
expectTrue(_isOptional(Optional<Int>.self))
278289
expectTrue(_isOptional(Optional<X>.self))

0 commit comments

Comments
 (0)