WIP Update to use clang::ModuleMacro instead of clang::MacroInfo.

Untested and still missing a few pieces.
This commit is contained in:
Jordan Rose
2017-06-23 16:04:24 -07:00
parent 90ca8f119a
commit c3d6be64ab
7 changed files with 341 additions and 215 deletions

View File

@@ -18,6 +18,7 @@
namespace clang { namespace clang {
class Decl; class Decl;
class MacroInfo; class MacroInfo;
class ModuleMacro;
class Module; class Module;
class SourceLocation; class SourceLocation;
class SourceRange; class SourceRange;
@@ -40,18 +41,21 @@ namespace detail {
}; };
} }
/// Represents a clang declaration, macro, or module. /// Represents a clang declaration, macro, or module. A macro definition
/// imported from a module is recorded as the ModuleMacro, and a macro
/// defined locally is represented by the MacroInfo.
class ClangNode { class ClangNode {
template <typename T> template <typename T>
using Box = detail::ClangNodeBox<T>; using Box = detail::ClangNodeBox<T>;
llvm::PointerUnion3<Box<clang::Decl>, Box<clang::MacroInfo>, llvm::PointerUnion4<Box<clang::Decl>, Box<clang::MacroInfo>,
Box<clang::Module>> Ptr; Box<clang::ModuleMacro>, Box<clang::Module>> Ptr;
public: public:
ClangNode() = default; ClangNode() = default;
ClangNode(const clang::Decl *D) : Ptr(D) {} ClangNode(const clang::Decl *D) : Ptr(D) {}
ClangNode(const clang::MacroInfo *MI) : Ptr(MI) {} ClangNode(const clang::MacroInfo *MI) : Ptr(MI) {}
ClangNode(const clang::ModuleMacro *MM) : Ptr(MM) {}
ClangNode(const clang::Module *Mod) : Ptr(Mod) {} ClangNode(const clang::Module *Mod) : Ptr(Mod) {}
bool isNull() const { return Ptr.isNull(); } bool isNull() const { return Ptr.isNull(); }
@@ -60,9 +64,12 @@ public:
const clang::Decl *getAsDecl() const { const clang::Decl *getAsDecl() const {
return Ptr.dyn_cast<Box<clang::Decl>>().value; return Ptr.dyn_cast<Box<clang::Decl>>().value;
} }
const clang::MacroInfo *getAsMacro() const { const clang::MacroInfo *getAsMacroInfo() const {
return Ptr.dyn_cast<Box<clang::MacroInfo>>().value; return Ptr.dyn_cast<Box<clang::MacroInfo>>().value;
} }
const clang::ModuleMacro *getAsModuleMacro() const {
return Ptr.dyn_cast<Box<clang::ModuleMacro>>().value;
}
const clang::Module *getAsModule() const { const clang::Module *getAsModule() const {
return Ptr.dyn_cast<Box<clang::Module>>().value; return Ptr.dyn_cast<Box<clang::Module>>().value;
} }
@@ -70,13 +77,20 @@ public:
const clang::Decl *castAsDecl() const { const clang::Decl *castAsDecl() const {
return Ptr.get<Box<clang::Decl>>().value; return Ptr.get<Box<clang::Decl>>().value;
} }
const clang::MacroInfo *castAsMacro() const { const clang::MacroInfo *castAsMacroInfo() const {
return Ptr.get<Box<clang::MacroInfo>>().value; return Ptr.get<Box<clang::MacroInfo>>().value;
} }
const clang::ModuleMacro *castAsModuleMacro() const {
return Ptr.get<Box<clang::ModuleMacro>>().value;
}
const clang::Module *castAsModule() const { const clang::Module *castAsModule() const {
return Ptr.get<Box<clang::Module>>().value; return Ptr.get<Box<clang::Module>>().value;
} }
// Get the MacroInfo for a local definition, one imported from a
// ModuleMacro, or null if it's neither.
const clang::MacroInfo *getAsMacro() const;
/// Returns the module either the one wrapped directly, the one from a /// Returns the module either the one wrapped directly, the one from a
/// clang::ImportDecl or null if it's neither. /// clang::ImportDecl or null if it's neither.
const clang::Module *getClangModule() const; const clang::Module *getClangModule() const;

View File

@@ -61,6 +61,12 @@ STATISTIC(NumLazyGenericEnvironments,
STATISTIC(NumLazyGenericEnvironmentsLoaded, STATISTIC(NumLazyGenericEnvironmentsLoaded,
"# of lazily-deserialized generic environments loaded"); "# of lazily-deserialized generic environments loaded");
const clang::MacroInfo *ClangNode::getAsMacro() const {
if (auto MM = getAsModuleMacro())
return MM->getMacroInfo();
return getAsMacroInfo();
}
clang::SourceLocation ClangNode::getLocation() const { clang::SourceLocation ClangNode::getLocation() const {
if (auto D = getAsDecl()) if (auto D = getAsDecl())
return D->getLocation(); return D->getLocation();

View File

@@ -1878,15 +1878,21 @@ static bool isDeclaredInModule(const ClangModuleUnit *ModuleFilter,
return ModuleFilter == ContainingUnit; return ModuleFilter == ContainingUnit;
} }
static const clang::Module *getClangOwningModule(ClangNode Node, static const clang::Module *
const clang::ASTContext &ClangCtx) { getClangOwningModule(ClangNode Node, const clang::ASTContext &ClangCtx) {
assert(!Node.getAsModule() && "not implemented for modules");
if (const clang::Decl *D = Node.getAsDecl()) {
auto ExtSource = ClangCtx.getExternalSource(); auto ExtSource = ClangCtx.getExternalSource();
assert(ExtSource); assert(ExtSource);
if (const clang::Decl *D = Node.getAsDecl())
return ExtSource->getModule(D->getOwningModuleID()); return ExtSource->getModule(D->getOwningModuleID());
if (const clang::MacroInfo *MI = Node.getAsMacro()) }
return ExtSource->getModule(MI->getOwningModuleID());
if (const clang::ModuleMacro *M = Node.getAsModuleMacro())
return M->getOwningModule();
// A locally-defined MacroInfo does not have an owning module.
assert(Node.getAsMacroInfo());
return nullptr; return nullptr;
} }
@@ -2075,6 +2081,17 @@ public:
} // unnamed namespace } // unnamed namespace
/// Translate a MacroDefinition to a ClangNode, either a ModuleMacro for
/// a definition imported from a module or a MacroInfo for a macro defined
/// locally.
ClangNode getClangNodeForMacroDefinition(clang::MacroDefinition &M) {
if (!M.getModuleMacros().empty())
return ClangNode(M.getModuleMacros().back()->getMacroInfo());
if (auto *MD = M.getLocalDirective())
return ClangNode(MD->getMacroInfo());
return ClangNode();
}
void ClangImporter::lookupBridgingHeaderDecls( void ClangImporter::lookupBridgingHeaderDecls(
llvm::function_ref<bool(ClangNode)> filter, llvm::function_ref<bool(ClangNode)> filter,
llvm::function_ref<void(Decl*)> receiver) const { llvm::function_ref<void(Decl*)> receiver) const {
@@ -2094,10 +2111,12 @@ void ClangImporter::lookupBridgingHeaderDecls(
auto &ClangPP = Impl.getClangPreprocessor(); auto &ClangPP = Impl.getClangPreprocessor();
for (clang::IdentifierInfo *II : Impl.BridgeHeaderMacros) { for (clang::IdentifierInfo *II : Impl.BridgeHeaderMacros) {
if (auto *MI = ClangPP.getMacroInfo(II)) { auto MD = ClangPP.getMacroDefinition(II);
if (filter(MI)) { if (auto macroNode = getClangNodeForMacroDefinition(MD)) {
if (filter(macroNode)) {
auto MI = macroNode.getAsMacro();
Identifier Name = Impl.getNameImporter().importMacroName(II, MI); Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
if (Decl *imported = Impl.importMacro(Name, MI)) if (Decl *imported = Impl.importMacro(Name, macroNode))
receiver(imported); receiver(imported);
} }
} }
@@ -2169,12 +2188,14 @@ bool ClangImporter::lookupDeclsFromHeader(StringRef Filename,
clang::PreprocessedEntity *PPE = *I; clang::PreprocessedEntity *PPE = *I;
if (!PPE) if (!PPE)
continue; continue;
if (auto *MD = dyn_cast<clang::MacroDefinitionRecord>(PPE)) { if (auto *MDR = dyn_cast<clang::MacroDefinitionRecord>(PPE)) {
auto *II = const_cast<clang::IdentifierInfo*>(MD->getName()); auto *II = const_cast<clang::IdentifierInfo*>(MDR->getName());
if (auto *MI = ClangPP.getMacroInfo(II)) { auto MD = ClangPP.getMacroDefinition(II);
if (filter(MI)) { if (auto macroNode = getClangNodeForMacroDefinition(MD)) {
if (filter(macroNode)) {
auto MI = macroNode.getAsMacro();
Identifier Name = Impl.getNameImporter().importMacroName(II, MI); Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
if (Decl *imported = Impl.importMacro(Name, MI)) if (Decl *imported = Impl.importMacro(Name, macroNode))
receiver(imported); receiver(imported);
} }
} }
@@ -2378,11 +2399,9 @@ static bool isVisibleClangEntry(clang::ASTContext &ctx,
} }
// Check whether the macro is defined. // Check whether the macro is defined.
auto clangMacro = entry.get<clang::MacroInfo *>(); // auto clangMacro = entry.get<clang::MacroInfo *>();
if (auto moduleID = clangMacro->getOwningModuleID()) { // if (module)
if (auto module = ctx.getExternalSource()->getModule(moduleID)) // return module->NameVisibility == clang::Module::AllVisible;
return module->NameVisibility == clang::Module::AllVisible;
}
return true; return true;
} }
@@ -2616,6 +2635,11 @@ const clang::CompilerInstance &ClangImporter::getClangInstance() const {
} }
const clang::Module *ClangImporter::getClangOwningModule(ClangNode Node) const { const clang::Module *ClangImporter::getClangOwningModule(ClangNode Node) const {
return Impl.getClangOwningModule(Node);
}
const clang::Module *
ClangImporter::Implementation::getClangOwningModule(ClangNode Node) const {
return ::getClangOwningModule(Node, getClangASTContext()); return ::getClangOwningModule(Node, getClangASTContext());
} }
@@ -2943,8 +2967,12 @@ void ClangImporter::Implementation::lookupValue(
if (!decl) continue; if (!decl) continue;
} else if (!name.isSpecial()) { } else if (!name.isSpecial()) {
// Try to import a macro. // Try to import a macro.
auto clangMacro = entry.get<clang::MacroInfo *>(); if (auto modMacro = entry.dyn_cast<clang::ModuleMacro *>())
decl = importMacro(name.getBaseIdentifier(), modMacro);
else if (auto clangMacro = entry.dyn_cast<clang::MacroInfo *>())
decl = importMacro(name.getBaseIdentifier(), clangMacro); decl = importMacro(name.getBaseIdentifier(), clangMacro);
else
llvm_unreachable("new kind of lookup table entry");
if (!decl) continue; if (!decl) continue;
} else { } else {
continue; continue;

View File

@@ -32,28 +32,6 @@
using namespace swift; using namespace swift;
using namespace importer; using namespace importer;
Optional<clang::Module *>
ClangImporter::Implementation::getClangSubmoduleForMacro(
const clang::MacroInfo *MI) {
auto *ExternalSource = getClangASTContext().getExternalSource();
return ExternalSource->getModule(MI->getOwningModuleID());
}
ClangModuleUnit *ClangImporter::Implementation::getClangModuleForMacro(
const clang::MacroInfo *MI) {
auto maybeModule = getClangSubmoduleForMacro(MI);
if (!maybeModule)
return nullptr;
if (!maybeModule.getValue())
return ImportedHeaderUnit;
// Get the parent module because currently we don't represent submodules with
// ClangModule.
auto *M = maybeModule.getValue()->getTopLevelModule();
return getWrapperForModule(M);
}
template <typename T = clang::Expr> template <typename T = clang::Expr>
static const T * static const T *
parseNumericLiteral(ClangImporter::Implementation &impl, parseNumericLiteral(ClangImporter::Implementation &impl,
@@ -90,7 +68,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
Identifier name, Identifier name,
const clang::Token *signTok, const clang::Token *signTok,
const clang::Token &tok, const clang::Token &tok,
const clang::MacroInfo *ClangN, ClangNode ClangN,
clang::QualType castType) { clang::QualType castType) {
assert(tok.getKind() == clang::tok::numeric_constant && assert(tok.getKind() == clang::tok::numeric_constant &&
"not a numeric token"); "not a numeric token");
@@ -189,7 +167,7 @@ static ValueDecl *importStringLiteral(ClangImporter::Implementation &Impl,
Identifier name, Identifier name,
const clang::Token &tok, const clang::Token &tok,
MappedStringLiteralKind kind, MappedStringLiteralKind kind,
const clang::MacroInfo *ClangN) { ClangNode ClangN) {
assert(isStringToken(tok)); assert(isStringToken(tok));
clang::ActionResult<clang::Expr*> result = clang::ActionResult<clang::Expr*> result =
@@ -215,7 +193,7 @@ static ValueDecl *importLiteral(ClangImporter::Implementation &Impl,
const clang::MacroInfo *MI, const clang::MacroInfo *MI,
Identifier name, Identifier name,
const clang::Token &tok, const clang::Token &tok,
const clang::MacroInfo *ClangN, ClangNode ClangN,
clang::QualType castType) { clang::QualType castType) {
switch (tok.getKind()) { switch (tok.getKind()) {
case clang::tok::numeric_constant: case clang::tok::numeric_constant:
@@ -235,7 +213,7 @@ static ValueDecl *importLiteral(ClangImporter::Implementation &Impl,
static ValueDecl *importNil(ClangImporter::Implementation &Impl, static ValueDecl *importNil(ClangImporter::Implementation &Impl,
DeclContext *DC, Identifier name, DeclContext *DC, Identifier name,
const clang::MacroInfo *clangN) { ClangNode clangN) {
// We use a dummy type since we don't have a convenient type for 'nil'. Any // We use a dummy type since we don't have a convenient type for 'nil'. Any
// use of this will be an error anyway. // use of this will be an error anyway.
auto type = TupleType::getEmpty(Impl.SwiftContext); auto type = TupleType::getEmpty(Impl.SwiftContext);
@@ -310,6 +288,8 @@ static Optional<std::pair<llvm::APSInt, Type>>
auto rawID = token.getIdentifierInfo(); auto rawID = token.getIdentifierInfo();
auto macroInfo = impl.getClangPreprocessor().getMacroInfo(rawID); auto macroInfo = impl.getClangPreprocessor().getMacroInfo(rawID);
if (!macroInfo)
return None;
auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo); auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo);
impl.importMacro(importedID, macroInfo); impl.importMacro(importedID, macroInfo);
@@ -332,7 +312,7 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
DeclContext *DC, DeclContext *DC,
Identifier name, Identifier name,
const clang::MacroInfo *macro, const clang::MacroInfo *macro,
const clang::MacroInfo *ClangN, ClangNode ClangN,
clang::QualType castType) { clang::QualType castType) {
if (name.empty()) return nullptr; if (name.empty()) return nullptr;
@@ -636,7 +616,8 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
} }
ValueDecl *ClangImporter::Implementation::importMacro(Identifier name, ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
clang::MacroInfo *macro) { ClangNode macroNode) {
const clang::MacroInfo *macro = macroNode.getAsMacro();
if (!macro) if (!macro)
return nullptr; return nullptr;
@@ -665,11 +646,17 @@ ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
// We haven't tried to import this macro yet. Do so now, and cache the // We haven't tried to import this macro yet. Do so now, and cache the
// result. // result.
DeclContext *DC = getClangModuleForMacro(macro); DeclContext *DC;
if (!DC) if (const clang::Module *module = getClangOwningModule(macroNode)) {
return nullptr; // Get the parent module because currently we don't model Clang submodules
// in Swift.
DC = getWrapperForModule(module->getTopLevelModule());
} else {
DC = ImportedHeaderUnit;
}
auto valueDecl = ::importMacro(*this, DC, name, macro, macro, /*castType*/{}); auto valueDecl = ::importMacro(*this, DC, name, macro, macroNode,
/*castType*/{});
ImportedMacros[name].push_back({macro, valueDecl}); ImportedMacros[name].push_back({macro, valueDecl});
return valueDecl; return valueDecl;
} }

View File

@@ -375,7 +375,8 @@ public:
/// Multiple macro definitions can map to the same declaration if the /// Multiple macro definitions can map to the same declaration if the
/// macros are identically defined. /// macros are identically defined.
llvm::DenseMap<Identifier, llvm::DenseMap<Identifier,
SmallVector<std::pair<clang::MacroInfo *, ValueDecl *>, 2>> SmallVector<std::pair<const clang::MacroInfo *, ValueDecl *>,
2>>
ImportedMacros; ImportedMacros;
// Mapping from macro to value for macros that expand to constant values. // Mapping from macro to value for macros that expand to constant values.
@@ -606,10 +607,7 @@ public:
/// ///
/// The returned module may be null (but not \c None) if \p MI comes from /// The returned module may be null (but not \c None) if \p MI comes from
/// an imported header. /// an imported header.
Optional<clang::Module *> const clang::Module *getClangOwningModule(ClangNode Node) const;
getClangSubmoduleForMacro(const clang::MacroInfo *MI);
ClangModuleUnit *getClangModuleForMacro(const clang::MacroInfo *MI);
/// Whether NSUInteger can be imported as Int in certain contexts. If false, /// Whether NSUInteger can be imported as Int in certain contexts. If false,
/// should always be imported as UInt. /// should always be imported as UInt.
@@ -667,9 +665,11 @@ public:
/// \brief Import the given Clang preprocessor macro as a Swift value decl. /// \brief Import the given Clang preprocessor macro as a Swift value decl.
/// ///
/// \p macroNode must be a MacroInfo or a ModuleMacro.
///
/// \returns The imported declaration, or null if the macro could not be /// \returns The imported declaration, or null if the macro could not be
/// translated into Swift. /// translated into Swift.
ValueDecl *importMacro(Identifier name, clang::MacroInfo *macro); ValueDecl *importMacro(Identifier name, ClangNode macroNode);
/// Map a Clang identifier name to its imported Swift equivalent. /// Map a Clang identifier name to its imported Swift equivalent.
StringRef getSwiftNameFromClangName(StringRef name); StringRef getSwiftNameFromClangName(StringRef name);

View File

@@ -79,44 +79,44 @@ considerReplacingExistingMacro(const clang::MacroInfo *newMacro,
assert(PP); assert(PP);
assert(newMacro); assert(newMacro);
assert(existingMacro); assert(existingMacro);
assert(newMacro->getOwningModuleID() == 0); // assert(newMacro->getOwningModuleID() == 0);
assert(existingMacro->getOwningModuleID() == 0); // assert(existingMacro->getOwningModuleID() == 0);
if (PP->getLangOpts().CurrentModule.empty()) // if (PP->getLangOpts().CurrentModule.empty())
return MacroConflictAction::Discard; return MacroConflictAction::Discard;
clang::ModuleMap &moduleInfo = PP->getHeaderSearchInfo().getModuleMap(); // clang::ModuleMap &moduleInfo = PP->getHeaderSearchInfo().getModuleMap();
const clang::SourceManager &sourceMgr = PP->getSourceManager(); // const clang::SourceManager &sourceMgr = PP->getSourceManager();
//
auto findContainingExplicitModule = // auto findContainingExplicitModule =
[&moduleInfo, &sourceMgr](const clang::MacroInfo *macro) // [&moduleInfo, &sourceMgr](const clang::MacroInfo *macro)
-> const clang::Module * { // -> const clang::Module * {
//
clang::SourceLocation definitionLoc = macro->getDefinitionLoc(); // clang::SourceLocation definitionLoc = macro->getDefinitionLoc();
assert(definitionLoc.isValid() && // assert(definitionLoc.isValid() &&
"implicitly-defined macros shouldn't show up in a module's lookup"); // "implicitly-defined macros shouldn't show up in a module's lookup");
clang::FullSourceLoc fullLoc(definitionLoc, sourceMgr); // clang::FullSourceLoc fullLoc(definitionLoc, sourceMgr);
//
const clang::Module *module = moduleInfo.inferModuleFromLocation(fullLoc); // const clang::Module *module = moduleInfo.inferModuleFromLocation(fullLoc);
assert(module && "we are building a module; everything should be modular"); // assert(module && "we are building a module; everything should be modular");
//
while (module->isSubModule()) { // while (module->isSubModule()) {
if (module->IsExplicit) // if (module->IsExplicit)
break; // break;
module = module->Parent; // module = module->Parent;
} // }
return module; // return module;
}; // };
//
const clang::Module *newModule = findContainingExplicitModule(newMacro); // const clang::Module *newModule = findContainingExplicitModule(newMacro);
const clang::Module *existingModule = // const clang::Module *existingModule =
findContainingExplicitModule(existingMacro); // findContainingExplicitModule(existingMacro);
//
if (existingModule == newModule) // if (existingModule == newModule)
return MacroConflictAction::Discard; // return MacroConflictAction::Discard;
if (existingModule->isSubModuleOf(newModule)) // if (existingModule->isSubModuleOf(newModule))
return MacroConflictAction::Replace; // return MacroConflictAction::Replace;
return MacroConflictAction::AddAsAlternative; // return MacroConflictAction::AddAsAlternative;
} }
namespace swift { namespace swift {
@@ -201,7 +201,7 @@ public:
/// ///
/// \returns true if we found anything, false otherwise. /// \returns true if we found anything, false otherwise.
bool lookupGlobalsAsMembers(SwiftLookupTable::StoredContext context, bool lookupGlobalsAsMembers(SwiftLookupTable::StoredContext context,
SmallVectorImpl<uintptr_t> &entries); SmallVectorImpl<uint64_t> &entries);
}; };
} // namespace swift } // namespace swift
@@ -432,11 +432,12 @@ static bool isGlobalAsMember(SwiftLookupTable::SingleEntry entry,
} }
bool SwiftLookupTable::addLocalEntry(SingleEntry newEntry, bool SwiftLookupTable::addLocalEntry(SingleEntry newEntry,
SmallVectorImpl<uintptr_t> &entries, SmallVectorImpl<uint64_t> &entries,
const clang::Preprocessor *PP) { const clang::Preprocessor *PP) {
// Check whether this entry matches any existing entry. // Check whether this entry matches any existing entry.
auto decl = newEntry.dyn_cast<clang::NamedDecl *>(); auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
auto macro = newEntry.dyn_cast<clang::MacroInfo *>(); auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
auto moduleMacro = newEntry.dyn_cast<clang::ModuleMacro *>();
for (auto &existingEntry : entries) { for (auto &existingEntry : entries) {
// If it matches an existing declaration, there's nothing to do. // If it matches an existing declaration, there's nothing to do.
if (decl && isDeclEntry(existingEntry) && if (decl && isDeclEntry(existingEntry) &&
@@ -445,27 +446,30 @@ bool SwiftLookupTable::addLocalEntry(SingleEntry newEntry,
// If it matches an existing macro, decide on the best course of action. // If it matches an existing macro, decide on the best course of action.
if (macro && isMacroEntry(existingEntry)) { if (macro && isMacroEntry(existingEntry)) {
MacroConflictAction action =
considerReplacingExistingMacro(macro,
mapStoredMacro(existingEntry),
PP);
switch (action) {
case MacroConflictAction::Discard:
return false; return false;
case MacroConflictAction::Replace: // MacroConflictAction action =
existingEntry = encodeEntry(macro); // considerReplacingExistingMacro(macro,
return false; // mapStoredMacro(existingEntry),
case MacroConflictAction::AddAsAlternative: // PP);
break; // switch (action) {
} // case MacroConflictAction::Discard:
// return false;
// case MacroConflictAction::Replace:
// existingEntry = encodeEntry(macro);
// return false;
// case MacroConflictAction::AddAsAlternative:
// break;
// }
} }
} }
// Add an entry to this context. // Add an entry to this context.
if (decl) if (decl)
entries.push_back(encodeEntry(decl)); entries.push_back(encodeEntry(decl));
else else if (macro)
entries.push_back(encodeEntry(macro)); entries.push_back(encodeEntry(macro));
else
entries.push_back(encodeEntry(moduleMacro));
return true; return true;
} }
@@ -502,6 +506,7 @@ void SwiftLookupTable::addEntry(DeclName name, SingleEntry newEntry,
auto &entries = LookupTable[name.getBaseIdentifier().str()]; auto &entries = LookupTable[name.getBaseIdentifier().str()];
auto decl = newEntry.dyn_cast<clang::NamedDecl *>(); auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
auto macro = newEntry.dyn_cast<clang::MacroInfo *>(); auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
auto moduleMacro = newEntry.dyn_cast<clang::ModuleMacro *>();
for (auto &entry : entries) { for (auto &entry : entries) {
if (entry.Context == context) { if (entry.Context == context) {
// We have entries for this context. // We have entries for this context.
@@ -515,8 +520,10 @@ void SwiftLookupTable::addEntry(DeclName name, SingleEntry newEntry,
entry.Context = context; entry.Context = context;
if (decl) if (decl)
entry.DeclsOrMacros.push_back(encodeEntry(decl)); entry.DeclsOrMacros.push_back(encodeEntry(decl));
else else if (macro)
entry.DeclsOrMacros.push_back(encodeEntry(macro)); entry.DeclsOrMacros.push_back(encodeEntry(macro));
else
entry.DeclsOrMacros.push_back(encodeEntry(moduleMacro));
entries.push_back(entry); entries.push_back(entry);
} }
@@ -562,7 +569,8 @@ SwiftLookupTable::lookup(StringRef baseName,
// Map each of the declarations. // Map each of the declarations.
for (auto &stored : entry.DeclsOrMacros) for (auto &stored : entry.DeclsOrMacros)
result.push_back(mapStored(stored)); if (auto entry = mapStored(stored))
result.push_back(entry);
} }
return result; return result;
@@ -581,7 +589,7 @@ SwiftLookupTable::lookupGlobalsAsMembers(StoredContext context) {
if (!Reader) return result; if (!Reader) return result;
// Lookup this base name in the module extension file. // Lookup this base name in the module extension file.
SmallVector<uintptr_t, 2> results; SmallVector<uint64_t, 2> results;
(void)Reader->lookupGlobalsAsMembers(context, results); (void)Reader->lookupGlobalsAsMembers(context, results);
// Add an entry to the table so we don't look again. // Add an entry to the table so we don't look again.
@@ -789,12 +797,41 @@ static void printStoredContext(SwiftLookupTable::StoredContext context,
} }
} }
static uint32_t getEncodedDeclID(uint64_t entry) {
assert(SwiftLookupTable::isSerializationIDEntry(entry));
assert(SwiftLookupTable::isDeclEntry(entry));
return entry >> 2;
}
namespace {
struct LocalMacroIDs {
uint32_t moduleID;
uint32_t nameOrMacroID;
};
}
static LocalMacroIDs getEncodedModuleMacroIDs(uint64_t entry) {
assert(SwiftLookupTable::isSerializationIDEntry(entry));
assert(SwiftLookupTable::isMacroEntry(entry));
return {static_cast<uint32_t>((entry & 0xFFFFFFFF) >> 2),
static_cast<uint32_t>(entry >> 32)};
}
/// Print a stored entry (Clang macro or declaration) for debugging purposes. /// Print a stored entry (Clang macro or declaration) for debugging purposes.
static void printStoredEntry(const SwiftLookupTable *table, uintptr_t entry, static void printStoredEntry(const SwiftLookupTable *table, uint64_t entry,
llvm::raw_ostream &out) { llvm::raw_ostream &out) {
if (SwiftLookupTable::isSerializationIDEntry(entry)) { if (SwiftLookupTable::isSerializationIDEntry(entry)) {
llvm::errs() << (SwiftLookupTable::isMacroEntry(entry) ? "macro" : "decl") if (SwiftLookupTable::isDeclEntry(entry)) {
<< " ID #" << SwiftLookupTable::getSerializationID(entry); llvm::errs() << "decl ID #" << getEncodedDeclID(entry);
} else {
LocalMacroIDs macroIDs = getEncodedModuleMacroIDs(entry);
if (macroIDs.moduleID == 0) {
llvm::errs() << "macro ID #" << macroIDs.nameOrMacroID;
} else {
llvm::errs() << "macro with name ID #" << macroIDs.nameOrMacroID
<< "in submodule #" << macroIDs.moduleID;
}
}
} else if (SwiftLookupTable::isMacroEntry(entry)) { } else if (SwiftLookupTable::isMacroEntry(entry)) {
llvm::errs() << "Macro"; llvm::errs() << "Macro";
} else { } else {
@@ -820,7 +857,7 @@ void SwiftLookupTable::dump() const {
llvm::errs() << ": "; llvm::errs() << ": ";
interleave(entry.DeclsOrMacros.begin(), entry.DeclsOrMacros.end(), interleave(entry.DeclsOrMacros.begin(), entry.DeclsOrMacros.end(),
[this](uintptr_t entry) { [this](uint64_t entry) {
printStoredEntry(this, entry, llvm::errs()); printStoredEntry(this, entry, llvm::errs());
}, },
[] { [] {
@@ -867,7 +904,7 @@ void SwiftLookupTable::dump() const {
const auto &entries = GlobalsAsMembers.find(context)->second; const auto &entries = GlobalsAsMembers.find(context)->second;
interleave(entries.begin(), entries.end(), interleave(entries.begin(), entries.end(),
[this](uintptr_t entry) { [this](uint64_t entry) {
printStoredEntry(this, entry, llvm::errs()); printStoredEntry(this, entry, llvm::errs());
}, },
[] { [] {
@@ -957,8 +994,7 @@ namespace {
dataLength += sizeof(uint16_t); dataLength += sizeof(uint16_t);
// Actual entries. // Actual entries.
dataLength += (sizeof(clang::serialization::DeclID) * dataLength += (sizeof(uint64_t) * entry.DeclsOrMacros.size());
entry.DeclsOrMacros.size());
} }
endian::Writer<little> writer(out); endian::Writer<little> writer(out);
@@ -978,6 +1014,7 @@ namespace {
// # of entries // # of entries
writer.write<uint16_t>(data.size()); writer.write<uint16_t>(data.size());
bool isModule = Writer.getLangOpts().isCompilingModule();
for (auto &fullEntry : data) { for (auto &fullEntry : data) {
// Context. // Context.
writer.write<uint8_t>(static_cast<uint8_t>(fullEntry.Context.first)); writer.write<uint8_t>(static_cast<uint8_t>(fullEntry.Context.first));
@@ -991,15 +1028,22 @@ namespace {
// Write the declarations and macros. // Write the declarations and macros.
for (auto &entry : fullEntry.DeclsOrMacros) { for (auto &entry : fullEntry.DeclsOrMacros) {
uint32_t id; uint64_t id;
if (SwiftLookupTable::isDeclEntry(entry)) { auto mappedEntry = Table.mapStored(entry, isModule);
auto decl = Table.mapStoredDecl(entry); if (auto *decl = mappedEntry.dyn_cast<clang::NamedDecl *>()) {
id = (Writer.getDeclID(decl) << 2) | 0x02; id = (Writer.getDeclID(decl) << 2) | 0x02;
} else if (auto *macro = mappedEntry.dyn_cast<clang::MacroInfo *>()) {
id = static_cast<uint64_t>(Writer.getMacroID(macro)) << 32;
id |= 0x02 | 0x01;
} else { } else {
auto macro = Table.mapStoredMacro(entry); auto *moduleMacro = mappedEntry.get<clang::ModuleMacro *>();
id = (Writer.getMacroID(macro) << 2) | 0x02 | 0x01; uint32_t nameID = Writer.getIdentifierRef(moduleMacro->getName());
uint32_t submoduleID = Writer.getLocalOrImportedSubmoduleID(
moduleMacro->getOwningModule());
id = (static_cast<uint64_t>(nameID) << 32) | (submoduleID << 2);
id |= 0x02 | 0x01;
} }
writer.write<uint32_t>(id); writer.write<uint64_t>(id);
} }
} }
} }
@@ -1014,7 +1058,7 @@ namespace {
public: public:
using key_type = std::pair<SwiftLookupTable::ContextKind, StringRef>; using key_type = std::pair<SwiftLookupTable::ContextKind, StringRef>;
using key_type_ref = key_type; using key_type_ref = key_type;
using data_type = SmallVector<uintptr_t, 2>; using data_type = SmallVector<uint64_t, 2>;
using data_type_ref = data_type &; using data_type_ref = data_type &;
using hash_value_type = uint32_t; using hash_value_type = uint32_t;
using offset_type = unsigned; using offset_type = unsigned;
@@ -1039,7 +1083,7 @@ namespace {
// # of entries // # of entries
uint32_t dataLength = uint32_t dataLength =
sizeof(uint16_t) + sizeof(clang::serialization::DeclID) * data.size(); sizeof(uint16_t) + sizeof(uint64_t) * data.size();
endian::Writer<little> writer(out); endian::Writer<little> writer(out);
writer.write<uint16_t>(keyLength); writer.write<uint16_t>(keyLength);
@@ -1062,16 +1106,24 @@ namespace {
writer.write<uint16_t>(data.size()); writer.write<uint16_t>(data.size());
// Actual entries. // Actual entries.
bool isModule = Writer.getLangOpts().isCompilingModule();
for (auto &entry : data) { for (auto &entry : data) {
uint32_t id; uint64_t id;
if (SwiftLookupTable::isDeclEntry(entry)) { auto mappedEntry = Table.mapStored(entry, isModule);
auto decl = Table.mapStoredDecl(entry); if (auto *decl = mappedEntry.dyn_cast<clang::NamedDecl *>()) {
id = (Writer.getDeclID(decl) << 2) | 0x02; id = (Writer.getDeclID(decl) << 2) | 0x02;
} else if (auto *macro = mappedEntry.dyn_cast<clang::MacroInfo *>()) {
id = static_cast<uint64_t>(Writer.getMacroID(macro)) << 32;
id |= 0x02 | 0x01;
} else { } else {
auto macro = Table.mapStoredMacro(entry); auto *moduleMacro = mappedEntry.get<clang::ModuleMacro *>();
id = (Writer.getMacroID(macro) << 2) | 0x02 | 0x01; uint32_t nameID = Writer.getIdentifierRef(moduleMacro->getName());
uint32_t submoduleID = Writer.getLocalOrImportedSubmoduleID(
moduleMacro->getOwningModule());
id = (static_cast<uint64_t>(nameID) << 32) | (submoduleID << 2);
id |= 0x02 | 0x01;
} }
writer.write<uint32_t>(id); writer.write<uint64_t>(id);
} }
} }
}; };
@@ -1221,7 +1273,7 @@ namespace {
unsigned numDeclsOrMacros = unsigned numDeclsOrMacros =
endian::readNext<uint16_t, little, unaligned>(data); endian::readNext<uint16_t, little, unaligned>(data);
while (numDeclsOrMacros--) { while (numDeclsOrMacros--) {
auto id = endian::readNext<uint32_t, little, unaligned>(data); auto id = endian::readNext<uint64_t, little, unaligned>(data);
entry.DeclsOrMacros.push_back(id); entry.DeclsOrMacros.push_back(id);
} }
@@ -1237,7 +1289,7 @@ namespace {
public: public:
using internal_key_type = SwiftLookupTable::StoredContext; using internal_key_type = SwiftLookupTable::StoredContext;
using external_key_type = internal_key_type; using external_key_type = internal_key_type;
using data_type = SmallVector<uintptr_t, 2>; using data_type = SmallVector<uint64_t, 2>;
using hash_value_type = uint32_t; using hash_value_type = uint32_t;
using offset_type = unsigned; using offset_type = unsigned;
@@ -1280,7 +1332,7 @@ namespace {
// Read all of the entries. // Read all of the entries.
while (numEntries--) { while (numEntries--) {
auto id = endian::readNext<uint32_t, little, unaligned>(data); auto id = endian::readNext<uint64_t, little, unaligned>(data);
result.push_back(id); result.push_back(id);
} }
@@ -1297,7 +1349,7 @@ namespace swift {
llvm::OnDiskIterableChainedHashTable<GlobalsAsMembersTableReaderInfo>; llvm::OnDiskIterableChainedHashTable<GlobalsAsMembersTableReaderInfo>;
} // namespace swift } // namespace swift
clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) { clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uint64_t &entry) {
assert(isDeclEntry(entry) && "Not a declaration entry"); assert(isDeclEntry(entry) && "Not a declaration entry");
// If we have an AST node here, just cast it. // If we have an AST node here, just cast it.
@@ -1307,7 +1359,7 @@ clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) {
// Otherwise, resolve the declaration. // Otherwise, resolve the declaration.
assert(Reader && "Cannot resolve the declaration without a reader"); assert(Reader && "Cannot resolve the declaration without a reader");
clang::serialization::DeclID declID = getSerializationID(entry); uint32_t declID = getEncodedDeclID(entry);
auto decl = cast_or_null<clang::NamedDecl>( auto decl = cast_or_null<clang::NamedDecl>(
Reader->getASTReader().GetLocalDecl(Reader->getModuleFile(), Reader->getASTReader().GetLocalDecl(Reader->getModuleFile(),
declID)); declID));
@@ -1317,33 +1369,66 @@ clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) {
return decl; return decl;
} }
clang::MacroInfo *SwiftLookupTable::mapStoredMacro(uintptr_t &entry) { static bool isPCH(SwiftLookupTableReader &reader) {
return reader.getModuleFile().Kind == clang::serialization::MK_PCH;
}
SwiftLookupTable::SingleEntry
SwiftLookupTable::mapStoredMacro(uint64_t &entry, bool assumeModule) {
assert(isMacroEntry(entry) && "Not a macro entry"); assert(isMacroEntry(entry) && "Not a macro entry");
// If we have an AST node here, just cast it. // If we have an AST node here, just cast it.
if (isASTNodeEntry(entry)) { if (isASTNodeEntry(entry)) {
if (assumeModule || (Reader && !isPCH(*Reader)))
return static_cast<clang::ModuleMacro *>(getPointerFromEntry(entry));
else
return static_cast<clang::MacroInfo *>(getPointerFromEntry(entry)); return static_cast<clang::MacroInfo *>(getPointerFromEntry(entry));
} }
// Otherwise, resolve the macro. // Otherwise, resolve the macro.
assert(Reader && "Cannot resolve the macro without a reader"); assert(Reader && "Cannot resolve the macro without a reader");
clang::serialization::MacroID macroID = getSerializationID(entry); clang::ASTReader &astReader = Reader->getASTReader();
auto macro = cast_or_null<clang::MacroInfo>(
Reader->getASTReader().getMacro( LocalMacroIDs macroIDs = getEncodedModuleMacroIDs(entry);
Reader->getASTReader().getGlobalMacroID( if (!assumeModule && macroIDs.moduleID == 0) {
Reader->getModuleFile(), assert(isPCH(*Reader));
macroID))); // Not a module, and the second key is actually a macroID.
auto macro =
astReader.getMacro(astReader.getGlobalMacroID(Reader->getModuleFile(),
macroIDs.nameOrMacroID));
// Update the entry now that we've resolved the macro. // Update the entry now that we've resolved the macro.
entry = encodeEntry(macro); entry = encodeEntry(macro);
return macro; return macro;
} }
SwiftLookupTable::SingleEntry SwiftLookupTable::mapStored(uintptr_t &entry) { // FIXME: Clang should help us out here, but it doesn't. It can only give us
// MacroInfos and not ModuleMacros.
assert(!isPCH(*Reader));
clang::IdentifierInfo *name =
astReader.getLocalIdentifier(Reader->getModuleFile(),
macroIDs.nameOrMacroID);
auto submoduleID = astReader.getGlobalSubmoduleID(Reader->getModuleFile(),
macroIDs.moduleID);
clang::Module *submodule = astReader.getSubmodule(submoduleID);
assert(submodule);
clang::Preprocessor &pp = Reader->getASTReader().getPreprocessor();
// Force the ModuleMacro to be loaded if this module is visible.
(void)pp.getLeafModuleMacros(name);
clang::ModuleMacro *macro = pp.getModuleMacro(submodule, name);
// This might still be NULL if the module has been imported but not made
// visible. We need a better answer here.
if (macro)
entry = encodeEntry(macro);
return macro;
}
SwiftLookupTable::SingleEntry SwiftLookupTable::mapStored(uint64_t &entry,
bool assumeModule) {
if (isDeclEntry(entry)) if (isDeclEntry(entry))
return mapStoredDecl(entry); return mapStoredDecl(entry);
return mapStoredMacro(entry, assumeModule);
return mapStoredMacro(entry);
} }
SwiftLookupTableReader::~SwiftLookupTableReader() { SwiftLookupTableReader::~SwiftLookupTableReader() {
@@ -1486,7 +1571,7 @@ SwiftLookupTableReader::getGlobalsAsMembersContexts() {
bool SwiftLookupTableReader::lookupGlobalsAsMembers( bool SwiftLookupTableReader::lookupGlobalsAsMembers(
SwiftLookupTable::StoredContext context, SwiftLookupTable::StoredContext context,
SmallVectorImpl<uintptr_t> &entries) { SmallVectorImpl<uint64_t> &entries) {
auto table = auto table =
static_cast<SerializedGlobalsAsMembersTable*>(GlobalsAsMembersTable); static_cast<SerializedGlobalsAsMembersTable*>(GlobalsAsMembersTable);
if (!table) return false; if (!table) return false;
@@ -1596,49 +1681,52 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
void importer::addMacrosToLookupTable(SwiftLookupTable &table, void importer::addMacrosToLookupTable(SwiftLookupTable &table,
NameImporter &nameImporter) { NameImporter &nameImporter) {
auto &pp = nameImporter.getClangPreprocessor(); auto &pp = nameImporter.getClangPreprocessor();
auto *tu = nameImporter.getClangContext().getTranslationUnitDecl();
for (const auto &macro : pp.macros(false)) { for (const auto &macro : pp.macros(false)) {
// Find the local history of this macro directive. auto maybeAddMacro = [&](clang::MacroInfo *info,
clang::MacroDirective *MD = pp.getLocalMacroDirectiveHistory(macro.first); clang::ModuleMacro *moduleMacro) {
// If this is a #undef, return.
// Walk the history. if (!info)
for (; MD; MD = MD->getPrevious()) { return;
// Don't look at any definitions that are followed by undefs.
// FIXME: This isn't quite correct across explicit submodules -- one
// submodule might define a macro, while another defines and then
// undefines the same macro. If they are processed in that order, the
// history will have the undef at the end, and we'll miss the first
// definition.
if (isa<clang::UndefMacroDirective>(MD))
break;
// Only interested in macro definitions.
auto *defMD = dyn_cast<clang::DefMacroDirective>(MD);
if (!defMD)
continue;
// Is this definition from this module?
auto info = defMD->getInfo();
if (!info || info->isFromASTFile())
continue;
// If we hit a builtin macro, we're done. // If we hit a builtin macro, we're done.
if (info->isBuiltinMacro()) if (info->isBuiltinMacro())
break; return;
// If we hit a macro with invalid or predefined location, we're done. // If we hit a macro with invalid or predefined location, we're done.
auto loc = defMD->getLocation(); auto loc = info->getDefinitionLoc();
if (loc.isInvalid()) if (loc.isInvalid())
break; return;
if (pp.getSourceManager().getFileID(loc) == pp.getPredefinesFileID()) if (pp.getSourceManager().getFileID(loc) == pp.getPredefinesFileID())
break; return;
// Add this entry. // Add this entry.
auto name = nameImporter.importMacroName(macro.first, info); auto name = nameImporter.importMacroName(macro.first, info);
if (name.empty()) if (name.empty())
return;
if (moduleMacro)
table.addEntry(name, moduleMacro, tu, &pp);
else
table.addEntry(name, info, tu, &pp);
};
ArrayRef<clang::ModuleMacro *> moduleMacros =
macro.second.getActiveModuleMacros(pp, macro.first);
if (moduleMacros.empty()) {
// Handle the bridging header case.
clang::MacroDirective *MD = pp.getLocalMacroDirective(macro.first);
if (!MD)
continue; continue;
table.addEntry(name, info,
nameImporter.getClangContext().getTranslationUnitDecl(), // If we hit a builtin macro, we're done.
&pp); maybeAddMacro(MD->getMacroInfo(), nullptr);
} else {
for (clang::ModuleMacro *moduleMacro : moduleMacros) {
clang::Module *owningModule = moduleMacro->getOwningModule();
if (!owningModule->isSubModuleOf(pp.getCurrentModule()))
continue;
maybeAddMacro(moduleMacro->getMacroInfo(), moduleMacro);
}
} }
} }
} }

View File

@@ -39,6 +39,7 @@ namespace clang {
class NamedDecl; class NamedDecl;
class DeclContext; class DeclContext;
class MacroInfo; class MacroInfo;
class ModuleMacro;
class ObjCCategoryDecl; class ObjCCategoryDecl;
class TypedefNameDecl; class TypedefNameDecl;
} }
@@ -204,7 +205,8 @@ public:
static bool contextRequiresName(ContextKind kind); static bool contextRequiresName(ContextKind kind);
/// A single entry referencing either a named declaration or a macro. /// A single entry referencing either a named declaration or a macro.
typedef llvm::PointerUnion<clang::NamedDecl *, clang::MacroInfo *> typedef llvm::PointerUnion3<clang::NamedDecl *, clang::MacroInfo *,
clang::ModuleMacro *>
SingleEntry; SingleEntry;
/// A stored version of the context of an entity, which is Clang /// A stored version of the context of an entity, which is Clang
@@ -224,50 +226,51 @@ public:
/// The low bit indicates whether we have a declaration or macro /// The low bit indicates whether we have a declaration or macro
/// (declaration = unset, macro = set) and the second lowest bit /// (declaration = unset, macro = set) and the second lowest bit
/// indicates whether we have a serialization ID (set = DeclID or /// indicates whether we have a serialization ID (set = DeclID or
/// MacroID, as appropriate) vs. a pointer (unset, /// {IdentifierID,SubmoduleID}, as appropriate) vs. a pointer (unset,
/// clang::NamedDecl * or clang::MacroInfo *). In the ID case, the /// clang::NamedDecl *, clang::MacroInfo *, clang::ModuleMacro *).
/// upper N-2 bits are the ID value; in the pointer case, the /// In the ID case, the upper N-2 bits are the ID value; in the pointer
/// lower two bits will always be clear due to the alignment of /// case, the lower two bits will always be clear due to the alignment of
/// the Clang pointers. /// the Clang pointers.
llvm::SmallVector<uintptr_t, 2> DeclsOrMacros; llvm::SmallVector<uint64_t, 2> DeclsOrMacros;
}; };
/// Whether the given entry is a macro entry. /// Whether the given entry is a macro entry.
static bool isMacroEntry(uintptr_t entry) { return entry & 0x01; } static bool isMacroEntry(uint64_t entry) { return entry & 0x01; }
/// Whether the given entry is a declaration entry. /// Whether the given entry is a declaration entry.
static bool isDeclEntry(uintptr_t entry) { return !isMacroEntry(entry); } static bool isDeclEntry(uint64_t entry) { return !isMacroEntry(entry); }
/// Whether the given entry is a serialization ID. /// Whether the given entry is a serialization ID.
static bool isSerializationIDEntry(uintptr_t entry) { return (entry & 0x02); } static bool isSerializationIDEntry(uint64_t entry) { return (entry & 0x02); }
/// Whether the given entry is an AST node. /// Whether the given entry is an AST node.
static bool isASTNodeEntry(uintptr_t entry) { static bool isASTNodeEntry(uint64_t entry) {
return !isSerializationIDEntry(entry); return !isSerializationIDEntry(entry);
} }
/// Retrieve the serialization ID for an entry.
static uint32_t getSerializationID(uintptr_t entry) {
assert(isSerializationIDEntry(entry) && "Not a serialization entry");
return entry >> 2;
}
/// Retrieve the pointer for an entry. /// Retrieve the pointer for an entry.
static void *getPointerFromEntry(uintptr_t entry) { static void *getPointerFromEntry(uint64_t entry) {
assert(isASTNodeEntry(entry) && "Not an AST node entry"); assert(isASTNodeEntry(entry) && "Not an AST node entry");
const uintptr_t mask = ~static_cast<uintptr_t>(0x03); const uint64_t mask = ~static_cast<uint64_t>(0x03);
return reinterpret_cast<void *>(entry & mask); return reinterpret_cast<void *>(entry & mask);
} }
/// Encode a Clang named declaration as an entry in the table. /// Encode a Clang named declaration as an entry in the table.
static uintptr_t encodeEntry(clang::NamedDecl *decl) { static uint64_t encodeEntry(clang::NamedDecl *decl) {
auto bits = reinterpret_cast<uintptr_t>(decl); auto bits = reinterpret_cast<uintptr_t>(decl);
assert((bits & 0x03) == 0 && "low bits set?"); assert((bits & 0x03) == 0 && "low bits set?");
return bits; return bits;
} }
// Encode a Clang macro as an entry in the table. // Encode a Clang macro as an entry in the table.
static uintptr_t encodeEntry(clang::MacroInfo *macro) { static uint64_t encodeEntry(clang::MacroInfo *macro) {
auto bits = reinterpret_cast<uintptr_t>(macro);
assert((bits & 0x03) == 0 && "low bits set?");
return bits | 0x01;
}
// Encode a Clang macro as an entry in the table.
static uint64_t encodeEntry(clang::ModuleMacro *macro) {
auto bits = reinterpret_cast<uintptr_t>(macro); auto bits = reinterpret_cast<uintptr_t>(macro);
assert((bits & 0x03) == 0 && "low bits set?"); assert((bits & 0x03) == 0 && "low bits set?");
return bits | 0x01; return bits | 0x01;
@@ -286,7 +289,7 @@ private:
/// ///
/// The values use the same representation as /// The values use the same representation as
/// FullTableEntry::DeclsOrMacros. /// FullTableEntry::DeclsOrMacros.
llvm::DenseMap<StoredContext, SmallVector<uintptr_t, 2>> GlobalsAsMembers; llvm::DenseMap<StoredContext, SmallVector<uint64_t, 2>> GlobalsAsMembers;
/// The reader responsible for lazily loading the contents of this table. /// The reader responsible for lazily loading the contents of this table.
SwiftLookupTableReader *Reader; SwiftLookupTableReader *Reader;
@@ -307,20 +310,20 @@ private:
/// present. /// present.
/// ///
/// \returns true if the entry was added, false otherwise. /// \returns true if the entry was added, false otherwise.
bool addLocalEntry(SingleEntry newEntry, SmallVectorImpl<uintptr_t> &entries, bool addLocalEntry(SingleEntry newEntry, SmallVectorImpl<uint64_t> &entries,
const clang::Preprocessor *PP); const clang::Preprocessor *PP);
public: public:
explicit SwiftLookupTable(SwiftLookupTableReader *reader) : Reader(reader) { } explicit SwiftLookupTable(SwiftLookupTableReader *reader) : Reader(reader) { }
/// Maps a stored declaration entry to an actual Clang declaration. /// Maps a stored declaration entry to an actual Clang declaration.
clang::NamedDecl *mapStoredDecl(uintptr_t &entry); clang::NamedDecl *mapStoredDecl(uint64_t &entry);
/// Maps a stored macro entry to an actual Clang macro. /// Maps a stored macro entry to an actual Clang macro.
clang::MacroInfo *mapStoredMacro(uintptr_t &entry); SingleEntry mapStoredMacro(uint64_t &entry, bool assumeModule = false);
/// Maps a stored entry to an actual Clang AST node. /// Maps a stored entry to an actual Clang AST node.
SingleEntry mapStored(uintptr_t &entry); SingleEntry mapStored(uint64_t &entry, bool assumeModule = false);
/// Translate a Clang DeclContext into a context kind and name. /// Translate a Clang DeclContext into a context kind and name.
static llvm::Optional<StoredContext> translateDeclContext( static llvm::Optional<StoredContext> translateDeclContext(