[modules] Refactor macro emission. No functionality change.

llvm-svn: 235263
This commit is contained in:
Richard Smith 2015-04-19 01:34:23 +00:00
parent 43d413b698
commit cf97cf6693
1 changed files with 73 additions and 76 deletions

View File

@ -2011,12 +2011,6 @@ public:
}; };
} // end anonymous namespace } // end anonymous namespace
static int compareMacroDirectives(
const std::pair<const IdentifierInfo *, MacroDirective *> *X,
const std::pair<const IdentifierInfo *, MacroDirective *> *Y) {
return X->first->getName().compare(Y->first->getName());
}
static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule, static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
const Preprocessor &PP) { const Preprocessor &PP) {
if (MacroInfo *MI = MD->getMacroInfo()) if (MacroInfo *MI = MD->getMacroInfo())
@ -2068,8 +2062,8 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
// emitting each to the PP section. // emitting each to the PP section.
// Construct the list of macro directives that need to be serialized. // Construct the list of macro directives that need to be serialized.
SmallVector<std::pair<const IdentifierInfo *, MacroDirective *>, 2> typedef std::pair<const IdentifierInfo *, MacroDirective *> MacroChain;
MacroDirectives; SmallVector<MacroChain, 2> MacroDirectives;
for (Preprocessor::macro_iterator for (Preprocessor::macro_iterator
I = PP.macro_begin(/*IncludeExternalMacros=*/false), I = PP.macro_begin(/*IncludeExternalMacros=*/false),
E = PP.macro_end(/*IncludeExternalMacros=*/false); E = PP.macro_end(/*IncludeExternalMacros=*/false);
@ -2080,13 +2074,15 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
// Sort the set of macro definitions that need to be serialized by the // Sort the set of macro definitions that need to be serialized by the
// name of the macro, to provide a stable ordering. // name of the macro, to provide a stable ordering.
llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(), llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(),
&compareMacroDirectives); [](const MacroChain *A, const MacroChain *B) -> int {
return A->first->getName().compare(B->first->getName());
});
// Emit the macro directives as a list and associate the offset with the // Emit the macro directives as a list and associate the offset with the
// identifier they belong to. // identifier they belong to.
for (unsigned I = 0, N = MacroDirectives.size(); I != N; ++I) { for (auto &Chain : MacroDirectives) {
const IdentifierInfo *Name = MacroDirectives[I].first; const IdentifierInfo *Name = Chain.first;
MacroDirective *MD = MacroDirectives[I].second; MacroDirective *MD = Chain.second;
// If the macro or identifier need no updates, don't write the macro history // If the macro or identifier need no updates, don't write the macro history
// for this one. // for this one.
@ -3133,41 +3129,11 @@ static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts,
} }
namespace { namespace {
class ASTIdentifierTableTrait { class PublicMacroIterator {
ASTWriter &Writer; ASTWriter &Writer;
Preprocessor &PP; Preprocessor &PP;
IdentifierResolver &IdResolver;
bool IsModule; bool IsModule;
MacroDirective *Macro;
/// \brief Determines whether this is an "interesting" identifier
/// that needs a full IdentifierInfo structure written into the hash
/// table.
bool isInterestingIdentifier(IdentifierInfo *II, MacroDirective *&Macro) {
if (II->isPoisoned() ||
II->isExtensionToken() ||
II->getObjCOrBuiltinID() ||
II->hasRevertedTokenIDToIdentifier() ||
II->getFETokenInfo<void>())
return true;
return hadMacroDefinition(II, Macro);
}
bool hadMacroDefinition(IdentifierInfo *II, MacroDirective *&Macro) {
if (!II->hadMacroDefinition())
return false;
if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) {
if (!IsModule)
return !shouldIgnoreMacro(Macro, IsModule, PP);
MacroState State;
if (getFirstPublicSubmoduleMacro(Macro, State))
return true;
}
return false;
}
enum class SubmoduleMacroState { enum class SubmoduleMacroState {
/// We've seen nothing about this macro. /// We've seen nothing about this macro.
@ -3178,31 +3144,39 @@ class ASTIdentifierTableTrait {
/// module's definition of this macro is private. /// module's definition of this macro is private.
Done Done
}; };
typedef llvm::DenseMap<SubmoduleID, SubmoduleMacroState> MacroState; llvm::DenseMap<SubmoduleID, SubmoduleMacroState> State;
MacroDirective * public:
getFirstPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) { PublicMacroIterator(ASTWriter &Writer, Preprocessor &PP, bool IsModule,
if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, State)) IdentifierInfo *II)
return NextMD; : Writer(Writer), PP(PP), IsModule(IsModule), Macro(nullptr) {
return nullptr; if (!II->hadMacroDefinition())
return;
Macro = PP.getMacroDirectiveHistory(II);
if (IsModule)
Macro = skipUnexportedMacros(Macro);
else if (shouldIgnoreMacro(Macro, IsModule, PP))
Macro = nullptr;
} }
MacroDirective * MacroDirective *operator*() const { return Macro; }
getNextPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) { PublicMacroIterator &operator++() {
if (MacroDirective *NextMD = Macro = skipUnexportedMacros(Macro->getPrevious());
getPublicSubmoduleMacro(MD->getPrevious(), State)) return *this;
return NextMD;
return nullptr;
} }
explicit operator bool() const { return Macro; }
private:
/// \brief Traverses the macro directives history and returns the next /// \brief Traverses the macro directives history and returns the next
/// public macro definition or undefinition that has not been found so far. /// public macro definition or undefinition that has not been found so far.
/// ///
/// A macro that is defined in submodule A and undefined in submodule B /// A macro that is defined in submodule A and undefined in submodule B
/// will still be considered as defined/exported from submodule A. /// will still be considered as defined/exported from submodule A.
MacroDirective *getPublicSubmoduleMacro(MacroDirective *MD, MacroDirective *skipUnexportedMacros(MacroDirective *MD) {
MacroState &State) { if (!MD || !IsModule)
if (!MD)
return nullptr; return nullptr;
Optional<bool> IsPublic; Optional<bool> IsPublic;
@ -3216,7 +3190,8 @@ class ASTIdentifierTableTrait {
if (MD->isImported()) if (MD->isImported())
return MD; return MD;
SubmoduleID ModID = getSubmoduleID(MD); SubmoduleID ModID =
Writer.inferSubmoduleIDFromLocation(MD->getLocation());
auto &S = State[ModID]; auto &S = State[ModID];
assert(ModID && "found macro in no submodule"); assert(ModID && "found macro in no submodule");
@ -3237,6 +3212,31 @@ class ASTIdentifierTableTrait {
return nullptr; return nullptr;
} }
};
class ASTIdentifierTableTrait {
ASTWriter &Writer;
Preprocessor &PP;
IdentifierResolver &IdResolver;
bool IsModule;
/// \brief Determines whether this is an "interesting" identifier that needs a
/// full IdentifierInfo structure written into the hash table. Notably, this
/// doesn't check whether the name has macros defined; use PublicMacroIterator
/// to check that.
bool isInterestingIdentifier(IdentifierInfo *II) {
if (PublicMacroIterator(Writer, PP, IsModule, II))
return true;
if (II->isPoisoned() ||
II->isExtensionToken() ||
II->getObjCOrBuiltinID() ||
II->hasRevertedTokenIDToIdentifier() ||
II->getFETokenInfo<void>())
return true;
return false;
}
ArrayRef<SubmoduleID> ArrayRef<SubmoduleID>
getOverriddenSubmodules(MacroDirective *MD, getOverriddenSubmodules(MacroDirective *MD,
@ -3322,20 +3322,18 @@ public:
EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) { EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
unsigned KeyLen = II->getLength() + 1; unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
MacroDirective *Macro = nullptr; PublicMacroIterator Macros(Writer, PP, IsModule, II);
if (isInterestingIdentifier(II, Macro)) { if (Macros || isInterestingIdentifier(II)) {
DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for builtin ID
DataLen += 2; // 2 bytes for flags DataLen += 2; // 2 bytes for flags
if (hadMacroDefinition(II, Macro)) { if (Macros) {
DataLen += 4; // MacroDirectives offset. DataLen += 4; // MacroDirectives offset.
if (IsModule) { if (IsModule) {
MacroState State;
SmallVector<SubmoduleID, 16> Scratch; SmallVector<SubmoduleID, 16> Scratch;
for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State); for (; Macros; ++Macros) {
MD; MD = getNextPublicSubmoduleMacro(MD, State)) {
DataLen += 4; // MacroInfo ID or ModuleID. DataLen += 4; // MacroInfo ID or ModuleID.
if (unsigned NumOverrides = if (unsigned NumOverrides =
getOverriddenSubmodules(MD, Scratch).size()) getOverriddenSubmodules(*Macros, Scratch).size())
DataLen += 4 * (1 + NumOverrides); DataLen += 4 * (1 + NumOverrides);
} }
DataLen += 4; // 0 terminator. DataLen += 4; // 0 terminator.
@ -3384,8 +3382,9 @@ public:
IdentID ID, unsigned) { IdentID ID, unsigned) {
using namespace llvm::support; using namespace llvm::support;
endian::Writer<little> LE(Out); endian::Writer<little> LE(Out);
MacroDirective *Macro = nullptr;
if (!isInterestingIdentifier(II, Macro)) { PublicMacroIterator Macros(Writer, PP, IsModule, II);
if (!Macros && !isInterestingIdentifier(II)) {
LE.write<uint32_t>(ID << 1); LE.write<uint32_t>(ID << 1);
return; return;
} }
@ -3395,7 +3394,7 @@ public:
assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader."); assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");
LE.write<uint16_t>(Bits); LE.write<uint16_t>(Bits);
Bits = 0; Bits = 0;
bool HadMacroDefinition = hadMacroDefinition(II, Macro); bool HadMacroDefinition = !!Macros;
Bits = (Bits << 1) | unsigned(HadMacroDefinition); Bits = (Bits << 1) | unsigned(HadMacroDefinition);
Bits = (Bits << 1) | unsigned(IsModule); Bits = (Bits << 1) | unsigned(IsModule);
Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isExtensionToken());
@ -3408,11 +3407,9 @@ public:
LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II)); LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II));
if (IsModule) { if (IsModule) {
// Write the IDs of macros coming from different submodules. // Write the IDs of macros coming from different submodules.
MacroState State;
SmallVector<SubmoduleID, 16> Scratch; SmallVector<SubmoduleID, 16> Scratch;
for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State); for (; Macros; ++Macros) {
MD; MD = getNextPublicSubmoduleMacro(MD, State)) { if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(*Macros)) {
if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
// FIXME: If this macro directive was created by #pragma pop_macros, // FIXME: If this macro directive was created by #pragma pop_macros,
// or if it was created implicitly by resolving conflicting macros, // or if it was created implicitly by resolving conflicting macros,
// it may be for a different submodule from the one in the MacroInfo // it may be for a different submodule from the one in the MacroInfo
@ -3421,13 +3418,13 @@ public:
assert(InfoID); assert(InfoID);
LE.write<uint32_t>(InfoID << 1); LE.write<uint32_t>(InfoID << 1);
} else { } else {
auto *UndefMD = cast<UndefMacroDirective>(MD); auto *UndefMD = cast<UndefMacroDirective>(*Macros);
SubmoduleID Mod = UndefMD->isImported() SubmoduleID Mod = UndefMD->isImported()
? UndefMD->getOwningModuleID() ? UndefMD->getOwningModuleID()
: getSubmoduleID(UndefMD); : getSubmoduleID(UndefMD);
LE.write<uint32_t>((Mod << 1) | 1); LE.write<uint32_t>((Mod << 1) | 1);
} }
emitMacroOverrides(Out, getOverriddenSubmodules(MD, Scratch)); emitMacroOverrides(Out, getOverriddenSubmodules(*Macros, Scratch));
} }
LE.write<uint32_t>((uint32_t)-1); LE.write<uint32_t>((uint32_t)-1);
} }