mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Serialize local types and provide a lookup API
rdar://problem/18295292 Locally scoped type declarations were previously not serialized into the module, which meant that the debugger couldn't reason about the structure of instances of those types. Introduce a new mangling for local types: [file basename MD5][counter][identifier] This allows the demangle node's data to be used directly for lookup without having to backtrack in the debugger. Local decls are now serialized into a LOCAL_TYPE_DECLS table in the module, which acts as the backing hash table for looking up [file basename MD5][counter][identifier] -> DeclID mappings. New tests: * swift-ide-test mode for testing the demangle/lookup/mangle lifecycle of a module that contains local decls * mangling * module merging with local decls Swift SVN r24426
This commit is contained in:
@@ -27,10 +27,13 @@
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MD5.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
namespace clang {
|
||||
class Module;
|
||||
@@ -66,6 +69,7 @@ namespace swift {
|
||||
class Type;
|
||||
class TypeRefinementContext;
|
||||
class ValueDecl;
|
||||
class TypeDecl;
|
||||
class VarDecl;
|
||||
class VisibleDeclConsumer;
|
||||
|
||||
@@ -282,6 +286,13 @@ public:
|
||||
void lookupValue(AccessPathTy AccessPath, DeclName Name, NLKind LookupKind,
|
||||
SmallVectorImpl<ValueDecl*> &Result) const;
|
||||
|
||||
/// Look up a type that was defined in a local scope.
|
||||
///
|
||||
/// This does a simple local lookup, not recursively looking through imports.
|
||||
TypeDecl *lookupLocalType(StringRef FileHash,
|
||||
unsigned LocalDiscriminator,
|
||||
StringRef Name) const ;
|
||||
|
||||
/// Find ValueDecls in the module and pass them to the given consumer object.
|
||||
///
|
||||
/// This does a simple local lookup, not recursively looking through imports.
|
||||
@@ -369,6 +380,12 @@ public:
|
||||
/// The order of the results is not guaranteed to be meaningful.
|
||||
void getTopLevelDecls(SmallVectorImpl<Decl*> &Results) const;
|
||||
|
||||
/// Finds all local decls of this module.
|
||||
///
|
||||
/// This does a simple local lookup, not recursively looking through imports.
|
||||
/// The order of the results is not guaranteed to be meaningful.
|
||||
void getLocalTypeDecls(SmallVectorImpl<Decl*> &Results) const;
|
||||
|
||||
/// Finds all top-level decls that should be displayed to a client of this
|
||||
/// module.
|
||||
///
|
||||
@@ -502,9 +519,21 @@ class FileUnit : public DeclContext {
|
||||
// FIXME: Stick this in a PointerIntPair.
|
||||
const FileUnitKind Kind;
|
||||
|
||||
/// A unique identifier representing this file; used to mark private decls
|
||||
/// within the file to keep them from conflicting with other files in the
|
||||
/// same module.
|
||||
mutable Identifier Discriminator;
|
||||
|
||||
/// A map holding the next discriminator for declarations with
|
||||
/// various identifiers.
|
||||
llvm::DenseMap<Identifier, unsigned> LocalDiscriminators;
|
||||
|
||||
DummyLocalContext LocalContext;
|
||||
|
||||
protected:
|
||||
FileUnit(FileUnitKind kind, Module &M)
|
||||
: DeclContext(DeclContextKind::FileUnit, &M), Kind(kind) {
|
||||
: DeclContext(DeclContextKind::FileUnit, &M), Kind(kind),
|
||||
LocalContext(this) {
|
||||
}
|
||||
|
||||
virtual ~FileUnit() = default;
|
||||
@@ -514,6 +543,19 @@ public:
|
||||
return Kind;
|
||||
}
|
||||
|
||||
virtual StringRef getFilename() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
/// Return a number that'll be unique in this context across all
|
||||
/// declarations with the given name.
|
||||
unsigned claimNextNamedDiscriminator(Identifier name) {
|
||||
assert(!name.empty() &&
|
||||
"setting a local discriminator on an anonymous decl; "
|
||||
"maybe the name hasn't been set yet?");
|
||||
return LocalDiscriminators[name]++;
|
||||
}
|
||||
|
||||
/// Look up a (possibly overloaded) value set at top-level scope
|
||||
/// (but with the specified access path, which may come from an import decl)
|
||||
/// within this file.
|
||||
@@ -523,6 +565,12 @@ public:
|
||||
NLKind lookupKind,
|
||||
SmallVectorImpl<ValueDecl*> &result) const = 0;
|
||||
|
||||
virtual TypeDecl *lookupLocalType(StringRef FileHash,
|
||||
unsigned LocalDiscriminator,
|
||||
StringRef Name) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Find ValueDecls in the module and pass them to the given consumer object.
|
||||
///
|
||||
/// This does a simple local lookup, not recursively looking through imports.
|
||||
@@ -553,6 +601,16 @@ public:
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Returns an implementation-defined "discriminator" representing this file's
|
||||
/// basename.
|
||||
Identifier getDiscriminator() const;
|
||||
|
||||
/// Returns a placeholder contexts for local declarations that appeared
|
||||
/// somewhere in this file.
|
||||
DeclContext *getDummyLocalContext() {
|
||||
return &LocalContext;
|
||||
}
|
||||
|
||||
/// Returns an implementation-defined "discriminator" for \p D, which
|
||||
/// distinguishes \p D from other declarations in the same module with the
|
||||
/// same name.
|
||||
@@ -562,12 +620,29 @@ public:
|
||||
virtual Identifier
|
||||
getDiscriminatorForPrivateValue(const ValueDecl *D) const = 0;
|
||||
|
||||
/// Returns an implementation-defined "discriminator" for \p D, which
|
||||
/// distinguishes \p D from other local declarations in the same module with
|
||||
/// the same name.
|
||||
///
|
||||
/// Since this value is used in name mangling, it should be a valid ASCII-only
|
||||
/// identifier.
|
||||
virtual Identifier
|
||||
getDiscriminatorForLocalValue(const ValueDecl *D) const {
|
||||
return getDiscriminator();
|
||||
}
|
||||
|
||||
/// Finds all top-level decls in this file.
|
||||
///
|
||||
/// This does a simple local lookup, not recursively looking through imports.
|
||||
/// The order of the results is not guaranteed to be meaningful.
|
||||
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {}
|
||||
|
||||
/// Finds all local type declarations in this file.
|
||||
///
|
||||
/// This does a simple local lookup, not recursively looking through imports.
|
||||
/// The order of the results is not guaranteed to be meaningful.
|
||||
virtual void getLocalTypeDecls(SmallVectorImpl<Decl*> &results) const {}
|
||||
|
||||
/// Adds all top-level decls to the given vector.
|
||||
///
|
||||
/// This includes all decls that should be displayed to clients of the module.
|
||||
@@ -735,11 +810,6 @@ private:
|
||||
/// This is filled in by the Name Binding phase.
|
||||
ArrayRef<std::pair<Module::ImportedModule, bool>> Imports;
|
||||
|
||||
/// A unique identifier representing this file; used to mark private decls
|
||||
/// within the file to keep them from conflicting with other files in the
|
||||
/// same module.
|
||||
mutable Identifier PrivateDiscriminator;
|
||||
|
||||
/// \brief The ID for the memory buffer containing this file's source.
|
||||
///
|
||||
/// May be -1, to indicate no association with a buffer.
|
||||
@@ -750,13 +820,16 @@ private:
|
||||
|
||||
/// If non-null, used to track name lookups that happen within this file.
|
||||
ReferencedNameTracker *ReferencedNames = nullptr;
|
||||
|
||||
|
||||
friend ASTContext;
|
||||
~SourceFile();
|
||||
public:
|
||||
/// The list of top-level declarations in the source file.
|
||||
std::vector<Decl*> Decls;
|
||||
|
||||
/// The list of type declarations in a local context.
|
||||
std::vector<Decl*> LocalTypeDecls;
|
||||
|
||||
/// The first location where an @objc attribute appeared.
|
||||
Optional<SourceLoc> FirstObjCAttrLoc;
|
||||
|
||||
@@ -820,7 +893,10 @@ public:
|
||||
lookupClassMember(Module::AccessPathTy accessPath, DeclName name,
|
||||
SmallVectorImpl<ValueDecl*> &results) const override;
|
||||
|
||||
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
|
||||
void getTopLevelDecls(SmallVectorImpl<Decl*> &Results) const;
|
||||
|
||||
virtual void
|
||||
getLocalTypeDecls(SmallVectorImpl<Decl*> &Results) const override;
|
||||
|
||||
virtual void
|
||||
getImportedModules(SmallVectorImpl<Module::ImportedModule> &imports,
|
||||
@@ -830,7 +906,6 @@ public:
|
||||
collectLinkLibraries(Module::LinkLibraryCallback callback) const override;
|
||||
|
||||
Identifier getDiscriminatorForPrivateValue(const ValueDecl *D) const override;
|
||||
Identifier getPrivateDiscriminator() const { return PrivateDiscriminator; }
|
||||
|
||||
virtual bool walk(ASTWalker &walker) override;
|
||||
|
||||
@@ -869,7 +944,7 @@ public:
|
||||
|
||||
/// If this buffer corresponds to a file on disk, returns the path.
|
||||
/// Otherwise, return an empty string.
|
||||
StringRef getFilename() const;
|
||||
StringRef getFilename() const override;
|
||||
|
||||
void dump() const;
|
||||
void dump(raw_ostream &os) const;
|
||||
@@ -967,11 +1042,6 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Returns an arbitrary string representing the storage backing this file.
|
||||
///
|
||||
/// This is usually a filesystem path.
|
||||
virtual StringRef getFilename() const;
|
||||
|
||||
/// Look up an operator declaration.
|
||||
///
|
||||
/// \param name The operator name ("+", ">>", etc.)
|
||||
|
||||
Reference in New Issue
Block a user