Skip to content

Builtin.isbitwisetakable #18702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ BUILTIN_MISC_OPERATION(Strideof, "strideof", "n", Special)
/// IsPOD has type T.Type -> Bool
BUILTIN_MISC_OPERATION(IsPOD, "ispod", "n", Special)

/// IsBitwiseTakable has type T.Type -> Bool
BUILTIN_MISC_OPERATION(IsBitwiseTakable, "isbitwisetakable", "n", Special)

/// IsSameMetatype has type (Any.Type, Any.Type) -> Bool
BUILTIN_MISC_OPERATION(IsSameMetatype, "is_same_metatype", "n", Special)

Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 437; // Last change: remove pinning
const uint16_t VERSION_MINOR = 438; // Last change: add isbitwisetakable

using DeclIDField = BCFixed<31>;

Expand Down
10 changes: 10 additions & 0 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,13 @@ static ValueDecl *getIsPODOperation(ASTContext &Context, Identifier Id) {
return builder.build(Id);
}

static ValueDecl *getIsBitwiseTakable(ASTContext &Context, Identifier Id) {
BuiltinGenericSignatureBuilder builder(Context);
builder.addParameter(makeMetatype(makeGenericParam()));
builder.setResult(makeConcrete(BuiltinIntegerType::get(1,Context)));
return builder.build(Id);
}

static ValueDecl *getIsOptionalOperation(ASTContext &Context, Identifier Id) {
BuiltinGenericSignatureBuilder builder(Context);
builder.addParameter(makeMetatype(makeGenericParam()));
Expand Down Expand Up @@ -1736,6 +1743,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
case BuiltinValueKind::IsPOD:
return getIsPODOperation(Context, Id);

case BuiltinValueKind::IsBitwiseTakable:
return getIsBitwiseTakable(Context, Id);

case BuiltinValueKind::IsOptionalType:
return getIsOptionalOperation(Context, Id);

Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/FixedTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class FixedTypeInfo : public TypeInfo {
llvm::Value *getAlignmentMask(IRGenFunction &IGF, SILType T) const override;
llvm::Value *getStride(IRGenFunction &IGF, SILType T) const override;
llvm::Value *getIsPOD(IRGenFunction &IGF, SILType T) const override;
llvm::Value *getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const override;
llvm::Value *isDynamicallyPackedInline(IRGenFunction &IGF,
SILType T) const override;

Expand Down
7 changes: 7 additions & 0 deletions lib/IRGen/GenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
return;
}

if (Builtin.ID == BuiltinValueKind::IsBitwiseTakable) {
(void)args.claimAll();
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
substitutions.getReplacementTypes()[0]);
out.add(valueTy.second.getIsBitwiseTakable(IGF, valueTy.first));
return;
}

// addressof expects an lvalue argument.
if (Builtin.ID == BuiltinValueKind::AddressOf) {
Expand Down
4 changes: 4 additions & 0 deletions lib/IRGen/GenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ llvm::Value *FixedTypeInfo::getIsPOD(IRGenFunction &IGF, SILType T) const {
return llvm::ConstantInt::get(IGF.IGM.Int1Ty,
isPOD(ResilienceExpansion::Maximal) == IsPOD);
}
llvm::Value *FixedTypeInfo::getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const {
return llvm::ConstantInt::get(IGF.IGM.Int1Ty,
isBitwiseTakable(ResilienceExpansion::Maximal) == IsBitwiseTakable);
}
llvm::Constant *FixedTypeInfo::getStaticStride(IRGenModule &IGM) const {
return asSizeConstant(IGM, getFixedStride());
}
Expand Down
4 changes: 4 additions & 0 deletions lib/IRGen/NonFixedTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ class WitnessSizedTypeInfo : public IndirectTypeInfo<Impl, TypeInfo> {
return emitLoadOfIsPOD(IGF, T);
}

llvm::Value *getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const override {
return emitLoadOfIsBitwiseTakable(IGF, T);
}

llvm::Value *isDynamicallyPackedInline(IRGenFunction &IGF,
SILType T) const override {
return emitLoadOfIsInline(IGF, T);
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/TypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ class TypeInfo {
virtual llvm::Value *getAlignmentMask(IRGenFunction &IGF, SILType T) const = 0;
virtual llvm::Value *getStride(IRGenFunction &IGF, SILType T) const = 0;
virtual llvm::Value *getIsPOD(IRGenFunction &IGF, SILType T) const = 0;
virtual llvm::Value *getIsBitwiseTakable(IRGenFunction &IGF, SILType T) const = 0;
virtual llvm::Value *isDynamicallyPackedInline(IRGenFunction &IGF,
SILType T) const = 0;

Expand Down
1 change: 1 addition & 0 deletions lib/SIL/SILOwnershipVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IntToFPWithOverflow)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IntToPtr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsOptionalType)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsPOD)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsBitwiseTakable)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, IsSameMetatype)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, LShr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, Mul)
Expand Down
1 change: 1 addition & 0 deletions lib/SIL/ValueOwnershipKindClassifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, Sizeof)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Strideof)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, StringObjectOr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsPOD)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsBitwiseTakable)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsSameMetatype)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Alignof)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AllocRaw)
Expand Down
8 changes: 8 additions & 0 deletions stdlib/public/core/Builtin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,14 @@ func _isPOD<T>(_ type: T.Type) -> Bool {
return Bool(Builtin.ispod(type))
}

/// Returns `true` if type is a bitwise takable. A bitwise takable type can
/// just be moved to a different address in memory.
@_transparent
public // @testable
func _isBitwiseTakable<T>(_ type: T.Type) -> Bool {
return Bool(Builtin.isbitwisetakable(type))
}

/// Returns `true` if type is nominally an Optional type.
@_transparent
public // @testable
Expand Down
25 changes: 25 additions & 0 deletions test/IRGen/builtins.swift
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,31 @@ func ispod_test() {
var f = Builtin.ispod(Builtin.NativeObject.self)
}

// CHECK-LABEL: define {{.*}} @{{.*}}generic_isbitwisetakable_test
func generic_isbitwisetakable_test<T>(_: T) {
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
// CHECK-NEXT: [[FLAGS:%.*]] = ptrtoint i8* [[T1]] to i64
// CHECK-NEXT: [[ISNOTBITWISETAKABLE:%.*]] = and i64 [[FLAGS]], 1048576
// CHECK-NEXT: [[ISBITWISETAKABLE:%.*]] = icmp eq i64 [[ISNOTBITWISETAKABLE]], 0
// CHECK-NEXT: store i1 [[ISBITWISETAKABLE]], i1* [[S:%.*]]
var s = Builtin.isbitwisetakable(T.self)
}

// CHECK-LABEL: define {{.*}} @{{.*}}isbitwisetakable_test
func isbitwisetakable_test() {
// CHECK: store i1 true, i1*
// CHECK: store i1 true, i1*
// CHECK: store i1 true, i1*
// CHECK: store i1 true, i1*
// CHECK: store i1 false, i1*
var t1 = Builtin.isbitwisetakable(Int.self)
var t2 = Builtin.isbitwisetakable(C.self)
var t3 = Builtin.isbitwisetakable(Abc.self)
var t4 = Builtin.isbitwisetakable(Empty.self)
var f = Builtin.isbitwisetakable(W.self)
}

// CHECK-LABEL: define {{.*}} @{{.*}}is_same_metatype
func is_same_metatype_test(_ t1: Any.Type, _ t2: Any.Type) {
// CHECK: [[MT1_AS_PTR:%.*]] = bitcast %swift.type* %0 to i8*
Expand Down
11 changes: 11 additions & 0 deletions test/stdlib/Builtins.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ var tests = TestSuite("Builtins")

class X {}

struct W {
weak var weakX: X?
}

tests.test("_isUnique/NativeObject") {
var a: Builtin.NativeObject = Builtin.castToNativeObject(X())
expectNotEqual(false, _isUnique_native(&a))
Expand Down Expand Up @@ -273,6 +277,13 @@ tests.test("_isPOD") {
expectFalse(_isPOD(P.self))
}

tests.test("_isBitwiseTakable") {
expectTrue(_isBitwiseTakable(Int.self))
expectTrue(_isBitwiseTakable(X.self))
expectTrue(_isBitwiseTakable(P.self))
expectFalse(_isBitwiseTakable(W.self))
}

tests.test("_isOptional") {
expectTrue(_isOptional(Optional<Int>.self))
expectTrue(_isOptional(Optional<X>.self))
Expand Down