Implement debug info for willset/didset, and teach dispatch to be non-virtual

to didset/will set since we don't drop these in the class vtable.


Swift SVN r13056
This commit is contained in:
Chris Lattner
2014-01-28 06:33:31 +00:00
parent 7bcf701ee1
commit 290a58494e
7 changed files with 22 additions and 8 deletions

View File

@@ -3095,6 +3095,9 @@ public:
/// isGetterOrSetter - Determine whether this is a getter or a setter vs. /// isGetterOrSetter - Determine whether this is a getter or a setter vs.
/// a normal function. /// a normal function.
bool isGetterOrSetter() const { return isGetter() || isSetter(); } bool isGetterOrSetter() const { return isGetter() || isSetter(); }
bool isDidSetWillSet() const {
return getAccessorKind() == IsDidSet || getAccessorKind() == IsWillSet;
}
bool isAccessor() const { return getAccessorKind() != NotAccessor; } bool isAccessor() const { return getAccessorKind() != NotAccessor; }
/// Creates the implicit 'DynamicSelf' generic parameter. /// Creates the implicit 'DynamicSelf' generic parameter.

View File

@@ -210,7 +210,7 @@ private:
void maybeAddMethod(FuncDecl *fn, ResilienceExpansion explosionLevel, void maybeAddMethod(FuncDecl *fn, ResilienceExpansion explosionLevel,
unsigned uncurryLevel) { unsigned uncurryLevel) {
// Ignore getters and setters. This is probably wrong! // Ignore getters and setters. This is probably wrong!
if (fn->isGetterOrSetter()) if (fn->isAccessor())
return; return;
// If the method overrides something, we don't need a new entry. // If the method overrides something, we don't need a new entry.

View File

@@ -1083,7 +1083,7 @@ namespace {
// getters and setters funcdecls will be handled by their parent // getters and setters funcdecls will be handled by their parent
// var/subscript. // var/subscript.
if (method->isGetterOrSetter()) return; if (method->isAccessor()) return;
llvm::Constant *entry = emitObjCMethodDescriptor(IGM, method); llvm::Constant *entry = emitObjCMethodDescriptor(IGM, method);
if (!method->isStatic()) { if (!method->isStatic()) {

View File

@@ -1171,7 +1171,7 @@ irgen::emitObjCSubscriptMethodDescriptors(IRGenModule &IGM,
bool irgen::requiresObjCMethodDescriptor(FuncDecl *method) { bool irgen::requiresObjCMethodDescriptor(FuncDecl *method) {
// Property accessors should be generated alongside the property. // Property accessors should be generated alongside the property.
if (method->isGetterOrSetter()) if (method->isAccessor())
return false; return false;
// We don't export generic methods or subclasses to IRGen yet. // We don't export generic methods or subclasses to IRGen yet.

View File

@@ -243,7 +243,7 @@ namespace {
} }
void visitFunc(FuncDecl *func) { void visitFunc(FuncDecl *func) {
if (func->isGetterOrSetter()) if (func->isAccessor())
// FIXME: To be implemented. // FIXME: To be implemented.
return; return;

View File

@@ -366,11 +366,19 @@ llvm::DIFile IRGenDebugInfo::getOrCreateFile(const char *Filename) {
StringRef IRGenDebugInfo::getName(const FuncDecl &FD) { StringRef IRGenDebugInfo::getName(const FuncDecl &FD) {
// Getters and Setters are anonymous functions, so we forge a name // Getters and Setters are anonymous functions, so we forge a name
// using its parent declaration. // using its parent declaration.
if (FD.isGetterOrSetter()) if (FD.isAccessor())
if (ValueDecl *VD = FD.getAccessorStorageDecl()) { if (ValueDecl *VD = FD.getAccessorStorageDecl()) {
const char *Kind;
switch (FD.getAccessorKind()) {
case FuncDecl::NotAccessor: assert(0 && "we know this is an accessor");
case FuncDecl::IsGetter: Kind = ".get"; break;
case FuncDecl::IsSetter: Kind = ".set"; break;
case FuncDecl::IsWillSet: Kind = ".willset"; break;
case FuncDecl::IsDidSet: Kind = ".didset"; break;
}
SmallVector<char, 64> Buf; SmallVector<char, 64> Buf;
StringRef Name = (VD->getName().str() + StringRef Name = (VD->getName().str() +Twine(Kind)).toStringRef(Buf);
Twine(FD.isGetter() ? ".get":".set")).toStringRef(Buf);
return BumpAllocatedString(Name); return BumpAllocatedString(Name);
} }

View File

@@ -800,7 +800,10 @@ public:
// FIXME: Or if it's an ObjC method. Extension methods on classes will // FIXME: Or if it's an ObjC method. Extension methods on classes will
// hopefully become dynamically dispatched too. // hopefully become dynamically dispatched too.
if (auto *fd = dyn_cast<FuncDecl>(e->getDecl())) { if (auto *fd = dyn_cast<FuncDecl>(e->getDecl())) {
if (isa<ClassDecl>(fd->getDeclContext()) || fd->isObjC()) { if (fd->isObjC() ||
(isa<ClassDecl>(fd->getDeclContext()) &&
// didSet and willSet methods can always be directly dispatched.
!fd->isDidSetWillSet())) {
ApplyExpr *thisCallSite = callSites.back(); ApplyExpr *thisCallSite = callSites.back();
callSites.pop_back(); callSites.pop_back();
setSelfParam(gen.emitRValue(thisCallSite->getArg()), thisCallSite); setSelfParam(gen.emitRValue(thisCallSite->getArg()), thisCallSite);