mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Refactor to use RuntimeAvailability
This commit is contained in:
@@ -590,6 +590,10 @@ public:
|
||||
/// Get the runtime availability of the opaque types language feature for the target platform.
|
||||
AvailabilityContext getOpaqueTypeAvailability();
|
||||
|
||||
/// Get the runtime availability of features introduced in the Swift 5.1
|
||||
/// compiler for the target platform.
|
||||
AvailabilityContext getSwift51Availability();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Diagnostics Helper functions
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
namespace swift {
|
||||
|
||||
class AvailabilityContext;
|
||||
class ASTContext;
|
||||
|
||||
enum class RuntimeAvailability {
|
||||
AlwaysAvailable,
|
||||
AvailableByCompatibilityLibrary,
|
||||
ConditionallyAvailable
|
||||
};
|
||||
|
||||
/// Generate an llvm declaration for a runtime entry with a
|
||||
/// given name, return types, argument types, attributes and
|
||||
@@ -30,7 +37,8 @@ llvm::Constant *getRuntimeFn(llvm::Module &Module,
|
||||
llvm::Constant *&cache,
|
||||
char const *name,
|
||||
llvm::CallingConv::ID cc,
|
||||
bool isWeakLinked,
|
||||
RuntimeAvailability availability,
|
||||
ASTContext *context,
|
||||
llvm::ArrayRef<llvm::Type*> retTypes,
|
||||
llvm::ArrayRef<llvm::Type*> argTypes,
|
||||
llvm::ArrayRef<llvm::Attribute::AttrKind> attrs);
|
||||
|
||||
@@ -638,7 +638,7 @@ FUNCTION(GetGenericMetadata, swift_getGenericMetadata,
|
||||
// const OpaqueTypeDescriptor *descriptor,
|
||||
// uintptr_t index);
|
||||
FUNCTION(GetOpaqueTypeMetadata, swift_getOpaqueTypeMetadata,
|
||||
SwiftCC, OpaqueTypeAvailability,
|
||||
SwiftCC, ConditionallyAvailable,
|
||||
RETURNS(TypeMetadataResponseTy),
|
||||
ARGS(SizeTy, Int8PtrTy, OpaqueTypeDescriptorPtrTy, SizeTy),
|
||||
ATTRS(NoUnwind, ReadOnly))
|
||||
@@ -647,7 +647,7 @@ FUNCTION(GetOpaqueTypeMetadata, swift_getOpaqueTypeMetadata,
|
||||
// const OpaqueTypeDescriptor *descriptor,
|
||||
// uintptr_t index);
|
||||
FUNCTION(GetOpaqueTypeConformance, swift_getOpaqueTypeConformance,
|
||||
SwiftCC, OpaqueTypeAvailability,
|
||||
SwiftCC, ConditionallyAvailable,
|
||||
RETURNS(WitnessTablePtrTy),
|
||||
ARGS(Int8PtrTy, OpaqueTypeDescriptorPtrTy, SizeTy),
|
||||
ATTRS(NoUnwind, ReadOnly))
|
||||
@@ -1226,25 +1226,13 @@ FUNCTION(EndAccess, swift_endAccess, C_CC, AlwaysAvailable,
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
FUNCTION(GetOrigOfReplaceable, swift_getOrigOfReplaceable, C_CC,
|
||||
GetReplacementAvailability,
|
||||
AvailableByCompatibilityLibrary,
|
||||
RETURNS(FunctionPtrTy),
|
||||
ARGS(FunctionPtrTy->getPointerTo()),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
FUNCTION(GetReplacement, swift_getFunctionReplacement, C_CC,
|
||||
GetReplacementAvailability,
|
||||
RETURNS(FunctionPtrTy),
|
||||
ARGS(FunctionPtrTy->getPointerTo(), FunctionPtrTy),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
FUNCTION(GetOrigOfReplaceable50, swift_getOrigOfReplaceable50, C_CC,
|
||||
AlwaysAvailable,
|
||||
RETURNS(FunctionPtrTy),
|
||||
ARGS(FunctionPtrTy->getPointerTo()),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
FUNCTION(GetReplacement50, swift_getFunctionReplacement50, C_CC,
|
||||
AlwaysAvailable,
|
||||
AvailableByCompatibilityLibrary,
|
||||
RETURNS(FunctionPtrTy),
|
||||
ARGS(FunctionPtrTy->getPointerTo(), FunctionPtrTy),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
@@ -218,6 +218,10 @@ AvailabilityContext AvailabilityInference::inferForType(Type t) {
|
||||
}
|
||||
|
||||
AvailabilityContext ASTContext::getOpaqueTypeAvailability() {
|
||||
return getSwift51Availability();
|
||||
}
|
||||
|
||||
AvailabilityContext ASTContext::getSwift51Availability() {
|
||||
auto target = LangOpts.Target;
|
||||
|
||||
if (target.isMacOSX()) {
|
||||
|
||||
@@ -2239,12 +2239,8 @@ void IRGenModule::createReplaceableProlog(IRGenFunction &IGF, SILFunction *f) {
|
||||
rhs = FnAddr;
|
||||
} else {
|
||||
// Call swift_getFunctionReplacement to check which function to call.
|
||||
auto *getReplacementFn = IRGenModule::isGetReplacementAvailable(Context)
|
||||
? getGetReplacementFn()
|
||||
: getGetReplacement50Fn();
|
||||
|
||||
auto *callRTFunc =
|
||||
IGF.Builder.CreateCall(getReplacementFn, {ReplAddr, FnAddr});
|
||||
IGF.Builder.CreateCall(getGetReplacementFn(), {ReplAddr, FnAddr});
|
||||
callRTFunc->setDoesNotThrow();
|
||||
ReplFn = callRTFunc;
|
||||
rhs = llvm::ConstantExpr::getNullValue(ReplFn->getType());
|
||||
@@ -2412,10 +2408,8 @@ void IRGenModule::emitDynamicReplacementOriginalFunctionThunk(SILFunction *f) {
|
||||
llvm::ConstantExpr::getInBoundsGetElementPtr(nullptr, linkEntry, indices),
|
||||
FunctionPtrTy->getPointerTo());
|
||||
|
||||
auto *getOrigOfReplaceableFn = IRGenModule::isGetReplacementAvailable(Context)
|
||||
? getGetOrigOfReplaceableFn()
|
||||
: getGetOrigOfReplaceable50Fn();
|
||||
auto *OrigFn = IGF.Builder.CreateCall(getOrigOfReplaceableFn, {fnPtrAddr});
|
||||
auto *OrigFn =
|
||||
IGF.Builder.CreateCall(getGetOrigOfReplaceableFn(), {fnPtrAddr});
|
||||
|
||||
OrigFn->setDoesNotThrow();
|
||||
|
||||
|
||||
@@ -527,31 +527,6 @@ IRGenModule::~IRGenModule() {
|
||||
|
||||
static bool isReturnAttribute(llvm::Attribute::AttrKind Attr);
|
||||
|
||||
static AvailabilityContext
|
||||
getGetReplacementAvailability(ASTContext &context) {
|
||||
auto target = context.LangOpts.Target;
|
||||
|
||||
if (target.isMacOSX()) {
|
||||
return AvailabilityContext(
|
||||
VersionRange::allGTE(llvm::VersionTuple(10, 15, 0)));
|
||||
} else if (target.isiOS()) {
|
||||
return AvailabilityContext(
|
||||
VersionRange::allGTE(llvm::VersionTuple(13, 0, 0)));
|
||||
} else if (target.isWatchOS()) {
|
||||
return AvailabilityContext(
|
||||
VersionRange::allGTE(llvm::VersionTuple(6, 0, 0)));
|
||||
} else {
|
||||
return AvailabilityContext::alwaysAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
bool IRGenModule::isGetReplacementAvailable(ASTContext &Context) {
|
||||
auto deploymentAvailability =
|
||||
AvailabilityContext::forDeploymentTarget(Context);
|
||||
auto featureAvailability = getGetReplacementAvailability(Context);
|
||||
return deploymentAvailability.isContainedIn(featureAvailability);
|
||||
}
|
||||
|
||||
// Explicitly listing these constants is an unfortunate compromise for
|
||||
// making the database file much more compact.
|
||||
//
|
||||
@@ -565,21 +540,11 @@ namespace RuntimeConstants {
|
||||
const auto ZExt = llvm::Attribute::ZExt;
|
||||
const auto FirstParamReturned = llvm::Attribute::Returned;
|
||||
|
||||
bool AlwaysAvailable(ASTContext &Context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OpaqueTypeAvailability(ASTContext &Context) {
|
||||
auto deploymentAvailability =
|
||||
AvailabilityContext::forDeploymentTarget(Context);
|
||||
auto featureAvailability = Context.getOpaqueTypeAvailability();
|
||||
|
||||
return !deploymentAvailability.isContainedIn(featureAvailability);
|
||||
}
|
||||
|
||||
bool GetReplacementAvailability(ASTContext &Context) {
|
||||
return !IRGenModule::isGetReplacementAvailable(Context);
|
||||
}
|
||||
const auto AlwaysAvailable = RuntimeAvailability::AlwaysAvailable;
|
||||
const auto AvailableByCompatibilityLibrary =
|
||||
RuntimeAvailability::AvailableByCompatibilityLibrary;
|
||||
const auto ConditionallyAvailable =
|
||||
RuntimeAvailability::ConditionallyAvailable;
|
||||
} // namespace RuntimeConstants
|
||||
|
||||
// We don't use enough attributes to justify generalizing the
|
||||
@@ -623,13 +588,40 @@ llvm::Constant *swift::getRuntimeFn(llvm::Module &Module,
|
||||
llvm::Constant *&cache,
|
||||
const char *name,
|
||||
llvm::CallingConv::ID cc,
|
||||
bool isWeakLinked,
|
||||
RuntimeAvailability availability,
|
||||
ASTContext *context,
|
||||
llvm::ArrayRef<llvm::Type*> retTypes,
|
||||
llvm::ArrayRef<llvm::Type*> argTypes,
|
||||
ArrayRef<Attribute::AttrKind> attrs) {
|
||||
|
||||
if (cache)
|
||||
return cache;
|
||||
|
||||
bool isWeakLinked = false;
|
||||
std::string functionName(name);
|
||||
|
||||
auto isFeatureAvailable = [&]() -> bool {
|
||||
auto deploymentAvailability =
|
||||
AvailabilityContext::forDeploymentTarget(*context);
|
||||
auto featureAvailability = context->getSwift51Availability();
|
||||
return deploymentAvailability.isContainedIn(featureAvailability);
|
||||
};
|
||||
|
||||
switch (availability) {
|
||||
case RuntimeAvailability::AlwaysAvailable:
|
||||
// Nothing to do.
|
||||
break;
|
||||
case RuntimeAvailability::ConditionallyAvailable: {
|
||||
isWeakLinked = !isFeatureAvailable();
|
||||
break;
|
||||
}
|
||||
case RuntimeAvailability::AvailableByCompatibilityLibrary: {
|
||||
if (!isFeatureAvailable())
|
||||
functionName.append("50");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Type *retTy;
|
||||
if (retTypes.size() == 1)
|
||||
retTy = *retTypes.begin();
|
||||
@@ -641,7 +633,7 @@ llvm::Constant *swift::getRuntimeFn(llvm::Module &Module,
|
||||
{argTypes.begin(), argTypes.end()},
|
||||
/*isVararg*/ false);
|
||||
|
||||
cache = Module.getOrInsertFunction(name, fnTy);
|
||||
cache = Module.getOrInsertFunction(functionName.c_str(), fnTy);
|
||||
|
||||
// Add any function attributes and set the calling convention.
|
||||
if (auto fn = dyn_cast<llvm::Function>(cache)) {
|
||||
@@ -696,7 +688,7 @@ llvm::Constant *swift::getRuntimeFn(llvm::Module &Module,
|
||||
llvm::Constant *IRGenModule::get##ID##Fn() { \
|
||||
using namespace RuntimeConstants; \
|
||||
return getRuntimeFn(Module, ID##Fn, #NAME, CC, \
|
||||
(AVAILABILITY)(this->Context), \
|
||||
AVAILABILITY, &this->Context, \
|
||||
RETURNS, ARGS, ATTRS); \
|
||||
}
|
||||
|
||||
|
||||
@@ -1441,7 +1441,6 @@ public:
|
||||
|
||||
void emitOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *);
|
||||
|
||||
static bool isGetReplacementAvailable(ASTContext &context);
|
||||
private:
|
||||
llvm::Constant *
|
||||
getAddrOfSharedContextDescriptor(LinkEntity entity,
|
||||
|
||||
@@ -220,8 +220,8 @@ private:
|
||||
Retain = getRuntimeFn(
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_retain" : "swift_retain",
|
||||
DefaultCC, false, {ObjectPtrTy}, {ObjectPtrTy},
|
||||
{NoUnwind, FirstParamReturned});
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable, nullptr, {ObjectPtrTy},
|
||||
{ObjectPtrTy}, {NoUnwind, FirstParamReturned});
|
||||
|
||||
return Retain.get();
|
||||
}
|
||||
@@ -234,10 +234,11 @@ private:
|
||||
auto *VoidTy = Type::getVoidTy(getModule().getContext());
|
||||
|
||||
llvm::Constant *cache = nullptr;
|
||||
Release = getRuntimeFn(
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_release" : "swift_release",
|
||||
DefaultCC, false, {VoidTy}, {ObjectPtrTy}, {NoUnwind});
|
||||
Release = getRuntimeFn(getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_release"
|
||||
: "swift_release",
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable,
|
||||
nullptr, {VoidTy}, {ObjectPtrTy}, {NoUnwind});
|
||||
|
||||
return Release.get();
|
||||
}
|
||||
@@ -272,8 +273,8 @@ private:
|
||||
RetainN = getRuntimeFn(
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_retain_n" : "swift_retain_n",
|
||||
DefaultCC, false, {ObjectPtrTy}, {ObjectPtrTy, Int32Ty},
|
||||
{NoUnwind, FirstParamReturned});
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable, nullptr, {ObjectPtrTy},
|
||||
{ObjectPtrTy, Int32Ty}, {NoUnwind, FirstParamReturned});
|
||||
|
||||
return RetainN.get();
|
||||
}
|
||||
@@ -290,7 +291,8 @@ private:
|
||||
ReleaseN = getRuntimeFn(
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_release_n" : "swift_release_n",
|
||||
DefaultCC, false, {VoidTy}, {ObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable, nullptr, {VoidTy},
|
||||
{ObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
|
||||
return ReleaseN.get();
|
||||
}
|
||||
@@ -304,13 +306,12 @@ private:
|
||||
auto *Int32Ty = Type::getInt32Ty(getModule().getContext());
|
||||
|
||||
llvm::Constant *cache = nullptr;
|
||||
UnknownObjectRetainN =
|
||||
getRuntimeFn(getModule(), cache,
|
||||
isNonAtomic(OrigI)
|
||||
? "swift_nonatomic_unknownObjectRetain_n"
|
||||
UnknownObjectRetainN = getRuntimeFn(
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_unknownObjectRetain_n"
|
||||
: "swift_unknownObjectRetain_n",
|
||||
DefaultCC, false, {ObjectPtrTy}, {ObjectPtrTy, Int32Ty},
|
||||
{NoUnwind, FirstParamReturned});
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable, nullptr, {ObjectPtrTy},
|
||||
{ObjectPtrTy, Int32Ty}, {NoUnwind, FirstParamReturned});
|
||||
|
||||
return UnknownObjectRetainN.get();
|
||||
}
|
||||
@@ -324,13 +325,12 @@ private:
|
||||
auto *VoidTy = Type::getVoidTy(getModule().getContext());
|
||||
|
||||
llvm::Constant *cache = nullptr;
|
||||
UnknownObjectReleaseN =
|
||||
getRuntimeFn(getModule(), cache,
|
||||
isNonAtomic(OrigI)
|
||||
? "swift_nonatomic_unknownObjectRelease_n"
|
||||
UnknownObjectReleaseN = getRuntimeFn(
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_unknownObjectRelease_n"
|
||||
: "swift_unknownObjectRelease_n",
|
||||
DefaultCC, false,
|
||||
{VoidTy}, {ObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable, nullptr, {VoidTy},
|
||||
{ObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
|
||||
return UnknownObjectReleaseN.get();
|
||||
}
|
||||
@@ -343,12 +343,12 @@ private:
|
||||
auto *Int32Ty = Type::getInt32Ty(getModule().getContext());
|
||||
|
||||
llvm::Constant *cache = nullptr;
|
||||
BridgeRetainN =
|
||||
getRuntimeFn(getModule(), cache,
|
||||
BridgeRetainN = getRuntimeFn(
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_bridgeObjectRetain_n"
|
||||
: "swift_bridgeObjectRetain_n",
|
||||
DefaultCC, false, {BridgeObjectPtrTy},
|
||||
{BridgeObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable, nullptr,
|
||||
{BridgeObjectPtrTy}, {BridgeObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
return BridgeRetainN.get();
|
||||
}
|
||||
|
||||
@@ -366,7 +366,8 @@ private:
|
||||
getModule(), cache,
|
||||
isNonAtomic(OrigI) ? "swift_nonatomic_bridgeObjectRelease_n"
|
||||
: "swift_bridgeObjectRelease_n",
|
||||
DefaultCC, false, {VoidTy}, {BridgeObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
DefaultCC, RuntimeAvailability::AlwaysAvailable, nullptr, {VoidTy},
|
||||
{BridgeObjectPtrTy, Int32Ty}, {NoUnwind});
|
||||
return BridgeReleaseN.get();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user