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 {
class Decl;
class MacroInfo;
class ModuleMacro;
class Module;
class SourceLocation;
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 {
template <typename T>
using Box = detail::ClangNodeBox<T>;
llvm::PointerUnion3<Box<clang::Decl>, Box<clang::MacroInfo>,
Box<clang::Module>> Ptr;
llvm::PointerUnion4<Box<clang::Decl>, Box<clang::MacroInfo>,
Box<clang::ModuleMacro>, Box<clang::Module>> Ptr;
public:
ClangNode() = default;
ClangNode(const clang::Decl *D) : Ptr(D) {}
ClangNode(const clang::MacroInfo *MI) : Ptr(MI) {}
ClangNode(const clang::ModuleMacro *MM) : Ptr(MM) {}
ClangNode(const clang::Module *Mod) : Ptr(Mod) {}
bool isNull() const { return Ptr.isNull(); }
@@ -60,9 +64,12 @@ public:
const clang::Decl *getAsDecl() const {
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;
}
const clang::ModuleMacro *getAsModuleMacro() const {
return Ptr.dyn_cast<Box<clang::ModuleMacro>>().value;
}
const clang::Module *getAsModule() const {
return Ptr.dyn_cast<Box<clang::Module>>().value;
}
@@ -70,13 +77,20 @@ public:
const clang::Decl *castAsDecl() const {
return Ptr.get<Box<clang::Decl>>().value;
}
const clang::MacroInfo *castAsMacro() const {
const clang::MacroInfo *castAsMacroInfo() const {
return Ptr.get<Box<clang::MacroInfo>>().value;
}
const clang::ModuleMacro *castAsModuleMacro() const {
return Ptr.get<Box<clang::ModuleMacro>>().value;
}
const clang::Module *castAsModule() const {
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
/// clang::ImportDecl or null if it's neither.
const clang::Module *getClangModule() const;

View File

@@ -61,6 +61,12 @@ STATISTIC(NumLazyGenericEnvironments,
STATISTIC(NumLazyGenericEnvironmentsLoaded,
"# 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 {
if (auto D = getAsDecl())
return D->getLocation();

View File

@@ -1878,15 +1878,21 @@ static bool isDeclaredInModule(const ClangModuleUnit *ModuleFilter,
return ModuleFilter == ContainingUnit;
}
static const clang::Module *getClangOwningModule(ClangNode Node,
const clang::ASTContext &ClangCtx) {
static const clang::Module *
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();
assert(ExtSource);
if (const clang::Decl *D = Node.getAsDecl())
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;
}
@@ -2075,6 +2081,17 @@ public:
} // 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(
llvm::function_ref<bool(ClangNode)> filter,
llvm::function_ref<void(Decl*)> receiver) const {
@@ -2094,10 +2111,12 @@ void ClangImporter::lookupBridgingHeaderDecls(
auto &ClangPP = Impl.getClangPreprocessor();
for (clang::IdentifierInfo *II : Impl.BridgeHeaderMacros) {
if (auto *MI = ClangPP.getMacroInfo(II)) {
if (filter(MI)) {
auto MD = ClangPP.getMacroDefinition(II);
if (auto macroNode = getClangNodeForMacroDefinition(MD)) {
if (filter(macroNode)) {
auto MI = macroNode.getAsMacro();
Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
if (Decl *imported = Impl.importMacro(Name, MI))
if (Decl *imported = Impl.importMacro(Name, macroNode))
receiver(imported);
}
}
@@ -2169,12 +2188,14 @@ bool ClangImporter::lookupDeclsFromHeader(StringRef Filename,
clang::PreprocessedEntity *PPE = *I;
if (!PPE)
continue;
if (auto *MD = dyn_cast<clang::MacroDefinitionRecord>(PPE)) {
auto *II = const_cast<clang::IdentifierInfo*>(MD->getName());
if (auto *MI = ClangPP.getMacroInfo(II)) {
if (filter(MI)) {
if (auto *MDR = dyn_cast<clang::MacroDefinitionRecord>(PPE)) {
auto *II = const_cast<clang::IdentifierInfo*>(MDR->getName());
auto MD = ClangPP.getMacroDefinition(II);
if (auto macroNode = getClangNodeForMacroDefinition(MD)) {
if (filter(macroNode)) {
auto MI = macroNode.getAsMacro();
Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
if (Decl *imported = Impl.importMacro(Name, MI))
if (Decl *imported = Impl.importMacro(Name, macroNode))
receiver(imported);
}
}
@@ -2378,11 +2399,9 @@ static bool isVisibleClangEntry(clang::ASTContext &ctx,
}
// Check whether the macro is defined.
auto clangMacro = entry.get<clang::MacroInfo *>();
if (auto moduleID = clangMacro->getOwningModuleID()) {
if (auto module = ctx.getExternalSource()->getModule(moduleID))
return module->NameVisibility == clang::Module::AllVisible;
}
// auto clangMacro = entry.get<clang::MacroInfo *>();
// if (module)
// return module->NameVisibility == clang::Module::AllVisible;
return true;
}
@@ -2616,6 +2635,11 @@ const clang::CompilerInstance &ClangImporter::getClangInstance() 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());
}
@@ -2943,8 +2967,12 @@ void ClangImporter::Implementation::lookupValue(
if (!decl) continue;
} else if (!name.isSpecial()) {
// 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);
else
llvm_unreachable("new kind of lookup table entry");
if (!decl) continue;
} else {
continue;

View File

@@ -32,28 +32,6 @@
using namespace swift;
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>
static const T *
parseNumericLiteral(ClangImporter::Implementation &impl,
@@ -90,7 +68,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
Identifier name,
const clang::Token *signTok,
const clang::Token &tok,
const clang::MacroInfo *ClangN,
ClangNode ClangN,
clang::QualType castType) {
assert(tok.getKind() == clang::tok::numeric_constant &&
"not a numeric token");
@@ -189,7 +167,7 @@ static ValueDecl *importStringLiteral(ClangImporter::Implementation &Impl,
Identifier name,
const clang::Token &tok,
MappedStringLiteralKind kind,
const clang::MacroInfo *ClangN) {
ClangNode ClangN) {
assert(isStringToken(tok));
clang::ActionResult<clang::Expr*> result =
@@ -215,7 +193,7 @@ static ValueDecl *importLiteral(ClangImporter::Implementation &Impl,
const clang::MacroInfo *MI,
Identifier name,
const clang::Token &tok,
const clang::MacroInfo *ClangN,
ClangNode ClangN,
clang::QualType castType) {
switch (tok.getKind()) {
case clang::tok::numeric_constant:
@@ -235,7 +213,7 @@ static ValueDecl *importLiteral(ClangImporter::Implementation &Impl,
static ValueDecl *importNil(ClangImporter::Implementation &Impl,
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
// use of this will be an error anyway.
auto type = TupleType::getEmpty(Impl.SwiftContext);
@@ -310,6 +288,8 @@ static Optional<std::pair<llvm::APSInt, Type>>
auto rawID = token.getIdentifierInfo();
auto macroInfo = impl.getClangPreprocessor().getMacroInfo(rawID);
if (!macroInfo)
return None;
auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo);
impl.importMacro(importedID, macroInfo);
@@ -332,7 +312,7 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
DeclContext *DC,
Identifier name,
const clang::MacroInfo *macro,
const clang::MacroInfo *ClangN,
ClangNode ClangN,
clang::QualType castType) {
if (name.empty()) return nullptr;
@@ -636,7 +616,8 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
}
ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
clang::MacroInfo *macro) {
ClangNode macroNode) {
const clang::MacroInfo *macro = macroNode.getAsMacro();
if (!macro)
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
// result.
DeclContext *DC = getClangModuleForMacro(macro);
if (!DC)
return nullptr;
DeclContext *DC;
if (const clang::Module *module = getClangOwningModule(macroNode)) {
// 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});
return valueDecl;
}

View File

@@ -375,7 +375,8 @@ public:
/// Multiple macro definitions can map to the same declaration if the
/// macros are identically defined.
llvm::DenseMap<Identifier,
SmallVector<std::pair<clang::MacroInfo *, ValueDecl *>, 2>>
SmallVector<std::pair<const clang::MacroInfo *, ValueDecl *>,
2>>
ImportedMacros;
// 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
/// an imported header.
Optional<clang::Module *>
getClangSubmoduleForMacro(const clang::MacroInfo *MI);
ClangModuleUnit *getClangModuleForMacro(const clang::MacroInfo *MI);
const clang::Module *getClangOwningModule(ClangNode Node) const;
/// Whether NSUInteger can be imported as Int in certain contexts. If false,
/// should always be imported as UInt.
@@ -667,9 +665,11 @@ public:
/// \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
/// 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.
StringRef getSwiftNameFromClangName(StringRef name);

View File

@@ -79,44 +79,44 @@ considerReplacingExistingMacro(const clang::MacroInfo *newMacro,
assert(PP);
assert(newMacro);
assert(existingMacro);
assert(newMacro->getOwningModuleID() == 0);
assert(existingMacro->getOwningModuleID() == 0);
// assert(newMacro->getOwningModuleID() == 0);
// assert(existingMacro->getOwningModuleID() == 0);
if (PP->getLangOpts().CurrentModule.empty())
// if (PP->getLangOpts().CurrentModule.empty())
return MacroConflictAction::Discard;
clang::ModuleMap &moduleInfo = PP->getHeaderSearchInfo().getModuleMap();
const clang::SourceManager &sourceMgr = PP->getSourceManager();
auto findContainingExplicitModule =
[&moduleInfo, &sourceMgr](const clang::MacroInfo *macro)
-> const clang::Module * {
clang::SourceLocation definitionLoc = macro->getDefinitionLoc();
assert(definitionLoc.isValid() &&
"implicitly-defined macros shouldn't show up in a module's lookup");
clang::FullSourceLoc fullLoc(definitionLoc, sourceMgr);
const clang::Module *module = moduleInfo.inferModuleFromLocation(fullLoc);
assert(module && "we are building a module; everything should be modular");
while (module->isSubModule()) {
if (module->IsExplicit)
break;
module = module->Parent;
}
return module;
};
const clang::Module *newModule = findContainingExplicitModule(newMacro);
const clang::Module *existingModule =
findContainingExplicitModule(existingMacro);
if (existingModule == newModule)
return MacroConflictAction::Discard;
if (existingModule->isSubModuleOf(newModule))
return MacroConflictAction::Replace;
return MacroConflictAction::AddAsAlternative;
// clang::ModuleMap &moduleInfo = PP->getHeaderSearchInfo().getModuleMap();
// const clang::SourceManager &sourceMgr = PP->getSourceManager();
//
// auto findContainingExplicitModule =
// [&moduleInfo, &sourceMgr](const clang::MacroInfo *macro)
// -> const clang::Module * {
//
// clang::SourceLocation definitionLoc = macro->getDefinitionLoc();
// assert(definitionLoc.isValid() &&
// "implicitly-defined macros shouldn't show up in a module's lookup");
// clang::FullSourceLoc fullLoc(definitionLoc, sourceMgr);
//
// const clang::Module *module = moduleInfo.inferModuleFromLocation(fullLoc);
// assert(module && "we are building a module; everything should be modular");
//
// while (module->isSubModule()) {
// if (module->IsExplicit)
// break;
// module = module->Parent;
// }
// return module;
// };
//
// const clang::Module *newModule = findContainingExplicitModule(newMacro);
// const clang::Module *existingModule =
// findContainingExplicitModule(existingMacro);
//
// if (existingModule == newModule)
// return MacroConflictAction::Discard;
// if (existingModule->isSubModuleOf(newModule))
// return MacroConflictAction::Replace;
// return MacroConflictAction::AddAsAlternative;
}
namespace swift {
@@ -201,7 +201,7 @@ public:
///
/// \returns true if we found anything, false otherwise.
bool lookupGlobalsAsMembers(SwiftLookupTable::StoredContext context,
SmallVectorImpl<uintptr_t> &entries);
SmallVectorImpl<uint64_t> &entries);
};
} // namespace swift
@@ -432,11 +432,12 @@ static bool isGlobalAsMember(SwiftLookupTable::SingleEntry entry,
}
bool SwiftLookupTable::addLocalEntry(SingleEntry newEntry,
SmallVectorImpl<uintptr_t> &entries,
SmallVectorImpl<uint64_t> &entries,
const clang::Preprocessor *PP) {
// Check whether this entry matches any existing entry.
auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
auto moduleMacro = newEntry.dyn_cast<clang::ModuleMacro *>();
for (auto &existingEntry : entries) {
// If it matches an existing declaration, there's nothing to do.
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 (macro && isMacroEntry(existingEntry)) {
MacroConflictAction action =
considerReplacingExistingMacro(macro,
mapStoredMacro(existingEntry),
PP);
switch (action) {
case MacroConflictAction::Discard:
return false;
case MacroConflictAction::Replace:
existingEntry = encodeEntry(macro);
return false;
case MacroConflictAction::AddAsAlternative:
break;
}
// MacroConflictAction action =
// considerReplacingExistingMacro(macro,
// mapStoredMacro(existingEntry),
// PP);
// 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.
if (decl)
entries.push_back(encodeEntry(decl));
else
else if (macro)
entries.push_back(encodeEntry(macro));
else
entries.push_back(encodeEntry(moduleMacro));
return true;
}
@@ -502,6 +506,7 @@ void SwiftLookupTable::addEntry(DeclName name, SingleEntry newEntry,
auto &entries = LookupTable[name.getBaseIdentifier().str()];
auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
auto moduleMacro = newEntry.dyn_cast<clang::ModuleMacro *>();
for (auto &entry : entries) {
if (entry.Context == context) {
// We have entries for this context.
@@ -515,8 +520,10 @@ void SwiftLookupTable::addEntry(DeclName name, SingleEntry newEntry,
entry.Context = context;
if (decl)
entry.DeclsOrMacros.push_back(encodeEntry(decl));
else
else if (macro)
entry.DeclsOrMacros.push_back(encodeEntry(macro));
else
entry.DeclsOrMacros.push_back(encodeEntry(moduleMacro));
entries.push_back(entry);
}
@@ -562,7 +569,8 @@ SwiftLookupTable::lookup(StringRef baseName,
// Map each of the declarations.
for (auto &stored : entry.DeclsOrMacros)
result.push_back(mapStored(stored));
if (auto entry = mapStored(stored))
result.push_back(entry);
}
return result;
@@ -581,7 +589,7 @@ SwiftLookupTable::lookupGlobalsAsMembers(StoredContext context) {
if (!Reader) return result;
// Lookup this base name in the module extension file.
SmallVector<uintptr_t, 2> results;
SmallVector<uint64_t, 2> results;
(void)Reader->lookupGlobalsAsMembers(context, results);
// 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.
static void printStoredEntry(const SwiftLookupTable *table, uintptr_t entry,
static void printStoredEntry(const SwiftLookupTable *table, uint64_t entry,
llvm::raw_ostream &out) {
if (SwiftLookupTable::isSerializationIDEntry(entry)) {
llvm::errs() << (SwiftLookupTable::isMacroEntry(entry) ? "macro" : "decl")
<< " ID #" << SwiftLookupTable::getSerializationID(entry);
if (SwiftLookupTable::isDeclEntry(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)) {
llvm::errs() << "Macro";
} else {
@@ -820,7 +857,7 @@ void SwiftLookupTable::dump() const {
llvm::errs() << ": ";
interleave(entry.DeclsOrMacros.begin(), entry.DeclsOrMacros.end(),
[this](uintptr_t entry) {
[this](uint64_t entry) {
printStoredEntry(this, entry, llvm::errs());
},
[] {
@@ -867,7 +904,7 @@ void SwiftLookupTable::dump() const {
const auto &entries = GlobalsAsMembers.find(context)->second;
interleave(entries.begin(), entries.end(),
[this](uintptr_t entry) {
[this](uint64_t entry) {
printStoredEntry(this, entry, llvm::errs());
},
[] {
@@ -957,8 +994,7 @@ namespace {
dataLength += sizeof(uint16_t);
// Actual entries.
dataLength += (sizeof(clang::serialization::DeclID) *
entry.DeclsOrMacros.size());
dataLength += (sizeof(uint64_t) * entry.DeclsOrMacros.size());
}
endian::Writer<little> writer(out);
@@ -978,6 +1014,7 @@ namespace {
// # of entries
writer.write<uint16_t>(data.size());
bool isModule = Writer.getLangOpts().isCompilingModule();
for (auto &fullEntry : data) {
// Context.
writer.write<uint8_t>(static_cast<uint8_t>(fullEntry.Context.first));
@@ -991,15 +1028,22 @@ namespace {
// Write the declarations and macros.
for (auto &entry : fullEntry.DeclsOrMacros) {
uint32_t id;
if (SwiftLookupTable::isDeclEntry(entry)) {
auto decl = Table.mapStoredDecl(entry);
uint64_t id;
auto mappedEntry = Table.mapStored(entry, isModule);
if (auto *decl = mappedEntry.dyn_cast<clang::NamedDecl *>()) {
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 {
auto macro = Table.mapStoredMacro(entry);
id = (Writer.getMacroID(macro) << 2) | 0x02 | 0x01;
auto *moduleMacro = mappedEntry.get<clang::ModuleMacro *>();
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:
using key_type = std::pair<SwiftLookupTable::ContextKind, StringRef>;
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 hash_value_type = uint32_t;
using offset_type = unsigned;
@@ -1039,7 +1083,7 @@ namespace {
// # of entries
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);
writer.write<uint16_t>(keyLength);
@@ -1062,16 +1106,24 @@ namespace {
writer.write<uint16_t>(data.size());
// Actual entries.
bool isModule = Writer.getLangOpts().isCompilingModule();
for (auto &entry : data) {
uint32_t id;
if (SwiftLookupTable::isDeclEntry(entry)) {
auto decl = Table.mapStoredDecl(entry);
uint64_t id;
auto mappedEntry = Table.mapStored(entry, isModule);
if (auto *decl = mappedEntry.dyn_cast<clang::NamedDecl *>()) {
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 {
auto macro = Table.mapStoredMacro(entry);
id = (Writer.getMacroID(macro) << 2) | 0x02 | 0x01;
auto *moduleMacro = mappedEntry.get<clang::ModuleMacro *>();
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 =
endian::readNext<uint16_t, little, unaligned>(data);
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);
}
@@ -1237,7 +1289,7 @@ namespace {
public:
using internal_key_type = SwiftLookupTable::StoredContext;
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 offset_type = unsigned;
@@ -1280,7 +1332,7 @@ namespace {
// Read all of the entries.
while (numEntries--) {
auto id = endian::readNext<uint32_t, little, unaligned>(data);
auto id = endian::readNext<uint64_t, little, unaligned>(data);
result.push_back(id);
}
@@ -1297,7 +1349,7 @@ namespace swift {
llvm::OnDiskIterableChainedHashTable<GlobalsAsMembersTableReaderInfo>;
} // namespace swift
clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) {
clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uint64_t &entry) {
assert(isDeclEntry(entry) && "Not a declaration entry");
// 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.
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>(
Reader->getASTReader().GetLocalDecl(Reader->getModuleFile(),
declID));
@@ -1317,33 +1369,66 @@ clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) {
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");
// If we have an AST node here, just cast it.
if (isASTNodeEntry(entry)) {
if (assumeModule || (Reader && !isPCH(*Reader)))
return static_cast<clang::ModuleMacro *>(getPointerFromEntry(entry));
else
return static_cast<clang::MacroInfo *>(getPointerFromEntry(entry));
}
// Otherwise, resolve the macro.
assert(Reader && "Cannot resolve the macro without a reader");
clang::serialization::MacroID macroID = getSerializationID(entry);
auto macro = cast_or_null<clang::MacroInfo>(
Reader->getASTReader().getMacro(
Reader->getASTReader().getGlobalMacroID(
Reader->getModuleFile(),
macroID)));
clang::ASTReader &astReader = Reader->getASTReader();
LocalMacroIDs macroIDs = getEncodedModuleMacroIDs(entry);
if (!assumeModule && macroIDs.moduleID == 0) {
assert(isPCH(*Reader));
// 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.
entry = encodeEntry(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))
return mapStoredDecl(entry);
return mapStoredMacro(entry);
return mapStoredMacro(entry, assumeModule);
}
SwiftLookupTableReader::~SwiftLookupTableReader() {
@@ -1486,7 +1571,7 @@ SwiftLookupTableReader::getGlobalsAsMembersContexts() {
bool SwiftLookupTableReader::lookupGlobalsAsMembers(
SwiftLookupTable::StoredContext context,
SmallVectorImpl<uintptr_t> &entries) {
SmallVectorImpl<uint64_t> &entries) {
auto table =
static_cast<SerializedGlobalsAsMembersTable*>(GlobalsAsMembersTable);
if (!table) return false;
@@ -1596,49 +1681,52 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
void importer::addMacrosToLookupTable(SwiftLookupTable &table,
NameImporter &nameImporter) {
auto &pp = nameImporter.getClangPreprocessor();
auto *tu = nameImporter.getClangContext().getTranslationUnitDecl();
for (const auto &macro : pp.macros(false)) {
// Find the local history of this macro directive.
clang::MacroDirective *MD = pp.getLocalMacroDirectiveHistory(macro.first);
// Walk the history.
for (; MD; MD = MD->getPrevious()) {
// 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;
auto maybeAddMacro = [&](clang::MacroInfo *info,
clang::ModuleMacro *moduleMacro) {
// If this is a #undef, return.
if (!info)
return;
// If we hit a builtin macro, we're done.
if (info->isBuiltinMacro())
break;
return;
// If we hit a macro with invalid or predefined location, we're done.
auto loc = defMD->getLocation();
auto loc = info->getDefinitionLoc();
if (loc.isInvalid())
break;
return;
if (pp.getSourceManager().getFileID(loc) == pp.getPredefinesFileID())
break;
return;
// Add this entry.
auto name = nameImporter.importMacroName(macro.first, info);
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;
table.addEntry(name, info,
nameImporter.getClangContext().getTranslationUnitDecl(),
&pp);
// If we hit a builtin macro, we're done.
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 DeclContext;
class MacroInfo;
class ModuleMacro;
class ObjCCategoryDecl;
class TypedefNameDecl;
}
@@ -204,7 +205,8 @@ public:
static bool contextRequiresName(ContextKind kind);
/// 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;
/// 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
/// (declaration = unset, macro = set) and the second lowest bit
/// indicates whether we have a serialization ID (set = DeclID or
/// MacroID, as appropriate) vs. a pointer (unset,
/// clang::NamedDecl * or clang::MacroInfo *). In the ID case, the
/// upper N-2 bits are the ID value; in the pointer case, the
/// lower two bits will always be clear due to the alignment of
/// {IdentifierID,SubmoduleID}, as appropriate) vs. a pointer (unset,
/// clang::NamedDecl *, clang::MacroInfo *, clang::ModuleMacro *).
/// In the ID case, the upper N-2 bits are the ID value; in the pointer
/// case, the lower two bits will always be clear due to the alignment of
/// the Clang pointers.
llvm::SmallVector<uintptr_t, 2> DeclsOrMacros;
llvm::SmallVector<uint64_t, 2> DeclsOrMacros;
};
/// 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.
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.
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.
static bool isASTNodeEntry(uintptr_t entry) {
static bool isASTNodeEntry(uint64_t 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.
static void *getPointerFromEntry(uintptr_t entry) {
static void *getPointerFromEntry(uint64_t 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);
}
/// 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);
assert((bits & 0x03) == 0 && "low bits set?");
return bits;
}
// 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);
assert((bits & 0x03) == 0 && "low bits set?");
return bits | 0x01;
@@ -286,7 +289,7 @@ private:
///
/// The values use the same representation as
/// 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.
SwiftLookupTableReader *Reader;
@@ -307,20 +310,20 @@ private:
/// present.
///
/// \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);
public:
explicit SwiftLookupTable(SwiftLookupTableReader *reader) : Reader(reader) { }
/// 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.
clang::MacroInfo *mapStoredMacro(uintptr_t &entry);
SingleEntry mapStoredMacro(uint64_t &entry, bool assumeModule = false);
/// 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.
static llvm::Optional<StoredContext> translateDeclContext(