[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
clang/lib/Serialization

View File

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