[sil-module] Add a helper method to lookup or create a SILFunction based on the SILDeclRef.

This API is more convenient than using the old getOrCreate API, which requires 9 parameters to be provided.
I'm going to use this API in the subsequent commits.

Swift SVN r27097
This commit is contained in:
Roman Levenstein
2015-04-07 22:53:49 +00:00
parent 0c4249293a
commit 0c2fc7c1a4
2 changed files with 103 additions and 0 deletions

View File

@@ -406,6 +406,12 @@ public:
SILFunction::ClassVisibility_t CV =
SILFunction::NotRelevant);
/// \brief Return the declaration of a function, or create it if it doesn't
/// exist..
SILFunction *getOrCreateFunction(SILLocation loc,
SILDeclRef constant,
ForDefinition_t forDefinition);
/// Look up the SILWitnessTable representing the lowering of a protocol
/// conformance, and collect the substitutions to apply to the referenced
/// witnesses, if any.

View File

@@ -242,6 +242,103 @@ SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
return fn;
}
static SILFunction::ClassVisibility_t getClassVisibility(SILDeclRef constant) {
if (!constant.hasDecl())
return SILFunction::NotRelevant;
// If this decleration is a function which goes into a vtable, then it's
// symbol must be as visible as its class. Derived classes even have to put
// all less visible methods of the base class into their vtables.
auto *FD = dyn_cast<AbstractFunctionDecl>(constant.getDecl());
if (!FD)
return SILFunction::NotRelevant;
DeclContext *context = FD->getDeclContext();
// Methods from extensions don't go into vtables (yet).
if (context->isExtensionContext())
return SILFunction::NotRelevant;
auto *classType = context->isClassOrClassExtensionContext();
if (!classType || classType->isFinal())
return SILFunction::NotRelevant;
if (FD->isFinal() && !FD->getOverriddenDecl())
return SILFunction::NotRelevant;
assert(FD->getEffectiveAccess() <= classType->getEffectiveAccess() &&
"class must be as visible as its members");
switch (classType->getEffectiveAccess()) {
case Accessibility::Private:
return SILFunction::NotRelevant;
case Accessibility::Internal:
return SILFunction::InternalClass;
case Accessibility::Public:
return SILFunction::PublicClass;
}
}
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
SILDeclRef constant,
ForDefinition_t forDefinition) {
SmallVector<char, 128> buffer;
auto name = constant.mangle(buffer);
auto constantType = Types.getConstantType(constant).castTo<SILFunctionType>();
SILLinkage linkage = constant.getLinkage(forDefinition);
if (auto fn = lookUpFunction(name)) {
assert(fn->getLoweredFunctionType() == constantType);
assert(fn->getLinkage() == linkage);
return fn;
}
IsTransparent_t IsTrans = constant.isTransparent()?
IsTransparent : IsNotTransparent;
IsFragile_t IsFrag = IsNotFragile;
if (IsTrans == IsTransparent && (linkage == SILLinkage::Public
|| linkage == SILLinkage::PublicExternal)) {
IsFrag = IsFragile;
}
EffectsKind EK = constant.hasEffectsAttribute() ?
constant.getEffectsAttribute() : EffectsKind::Unspecified;
Inline_t inlineStrategy = InlineDefault;
if (constant.isNoinline())
inlineStrategy = NoInline;
else if (constant.isAlwaysInline())
inlineStrategy = AlwaysInline;
auto *F = SILFunction::create(*this, linkage, name,
constantType, nullptr,
None, IsNotBare, IsTrans, IsFrag, IsNotThunk,
getClassVisibility(constant),
inlineStrategy, EK);
if (forDefinition == ForDefinition_t::ForDefinition)
F->setDebugScope(new (*this) SILDebugScope(loc, *F));
F->setGlobalInit(constant.isGlobal());
if (constant.hasDecl())
if (auto SemanticsA =
constant.getDecl()->getAttrs().getAttribute<SemanticsAttr>())
F->setSemanticsAttr(SemanticsA->Value);
ValueDecl *VD = nullptr;
if (constant.hasDecl())
VD = constant.getDecl();
F->setDeclContext(VD);
return F;
}
SILFunction *SILModule::getOrCreateSharedFunction(SILLocation loc,
StringRef name,
CanSILFunctionType type,