aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/CacheTokens.cpp
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
commit4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch)
tree137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Frontend/CacheTokens.cpp
parent5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff)
downloadsrc-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz
src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip
Notes
Diffstat (limited to 'lib/Frontend/CacheTokens.cpp')
-rw-r--r--lib/Frontend/CacheTokens.cpp189
1 files changed, 94 insertions, 95 deletions
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index 0065828c6de8..e7fc5660ad20 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -20,12 +20,11 @@
#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Streams.h"
+#include "llvm/ADT/StringMap.h"
// FIXME: put this somewhere else?
#ifndef S_ISDIR
@@ -41,19 +40,19 @@ using namespace clang::io;
namespace {
class VISIBILITY_HIDDEN PTHEntry {
- Offset TokenData, PPCondData;
+ Offset TokenData, PPCondData;
-public:
+public:
PTHEntry() {}
PTHEntry(Offset td, Offset ppcd)
: TokenData(td), PPCondData(ppcd) {}
-
- Offset getTokenOffset() const { return TokenData; }
+
+ Offset getTokenOffset() const { return TokenData; }
Offset getPPCondTableOffset() const { return PPCondData; }
};
-
-
+
+
class VISIBILITY_HIDDEN PTHEntryKeyVariant {
union { const FileEntry* FE; const char* Path; };
enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind;
@@ -67,15 +66,15 @@ public:
PTHEntryKeyVariant(const char* path)
: Path(path), Kind(IsNoExist), StatBuf(0) {}
-
+
bool isFile() const { return Kind == IsFE; }
-
+
const char* getCString() const {
return Kind == IsFE ? FE->getName() : Path;
}
-
+
unsigned getKind() const { return (unsigned) Kind; }
-
+
void EmitData(llvm::raw_ostream& Out) {
switch (Kind) {
case IsFE:
@@ -99,45 +98,45 @@ public:
break;
}
}
-
+
unsigned getRepresentationLength() const {
return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8;
}
};
-
+
class VISIBILITY_HIDDEN FileEntryPTHEntryInfo {
public:
typedef PTHEntryKeyVariant key_type;
typedef key_type key_type_ref;
-
+
typedef PTHEntry data_type;
typedef const PTHEntry& data_type_ref;
-
+
static unsigned ComputeHash(PTHEntryKeyVariant V) {
return BernsteinHash(V.getCString());
}
-
- static std::pair<unsigned,unsigned>
+
+ static std::pair<unsigned,unsigned>
EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
const PTHEntry& E) {
unsigned n = strlen(V.getCString()) + 1 + 1;
::Emit16(Out, n);
-
+
unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0);
::Emit8(Out, m);
return std::make_pair(n, m);
}
-
+
static void EmitKey(llvm::raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){
// Emit the entry kind.
::Emit8(Out, (unsigned) V.getKind());
// Emit the string.
Out.write(V.getCString(), n - 1);
}
-
- static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
+
+ static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
const PTHEntry& E, unsigned) {
@@ -147,12 +146,12 @@ public:
::Emit32(Out, E.getTokenOffset());
::Emit32(Out, E.getPPCondTableOffset());
}
-
+
// Emit any other data associated with the key (i.e., stat information).
V.EmitData(Out);
- }
+ }
};
-
+
class OffsetOpt {
bool valid;
Offset off;
@@ -181,16 +180,16 @@ class VISIBILITY_HIDDEN PTHWriter {
//// Get the persistent id for the given IdentifierInfo*.
uint32_t ResolveID(const IdentifierInfo* II);
-
+
/// Emit a token to the PTH file.
void EmitToken(const Token& T);
void Emit8(uint32_t V) {
Out << (unsigned char)(V);
}
-
+
void Emit16(uint32_t V) { ::Emit16(Out, V); }
-
+
void Emit24(uint32_t V) {
Out << (unsigned char)(V);
Out << (unsigned char)(V >> 8);
@@ -203,13 +202,13 @@ class VISIBILITY_HIDDEN PTHWriter {
void EmitBuf(const char *Ptr, unsigned NumBytes) {
Out.write(Ptr, NumBytes);
}
-
+
/// EmitIdentifierTable - Emits two tables to the PTH file. The first is
/// a hashtable mapping from identifier strings to persistent IDs.
/// The second is a straight table mapping from persistent IDs to string data
/// (the keys of the first table).
std::pair<Offset, Offset> EmitIdentifierTable();
-
+
/// EmitFileTable - Emit a table mapping from file name strings to PTH
/// token data.
Offset EmitFileTable() { return PM.Emit(Out); }
@@ -218,23 +217,23 @@ class VISIBILITY_HIDDEN PTHWriter {
Offset EmitCachedSpellings();
public:
- PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
+ PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
: Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
-
+
PTHMap &getPM() { return PM; }
void GeneratePTH(const std::string *MainFile = 0);
};
} // end anonymous namespace
-
-uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) {
+
+uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) {
// Null IdentifierInfo's map to the persistent ID 0.
if (!II)
return 0;
-
+
IDMap::iterator I = IM.find(II);
if (I != IM.end())
return I->second; // We've already added 1.
-
+
IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL.
return idcount;
}
@@ -243,7 +242,7 @@ void PTHWriter::EmitToken(const Token& T) {
// Emit the token kind, flags, and length.
Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)|
(((uint32_t) T.getLength()) << 16));
-
+
if (!T.isLiteral()) {
Emit32(ResolveID(T.getIdentifierInfo()));
} else {
@@ -254,18 +253,18 @@ void PTHWriter::EmitToken(const Token& T) {
// Get the string entry.
llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s, s+len);
-
+
// If this is a new string entry, bump the PTH offset.
if (!E->getValue().hasOffset()) {
E->getValue().setOffset(CurStrOffset);
StrEntries.push_back(E);
CurStrOffset += len + 1;
}
-
+
// Emit the relative offset into the PTH file for the spelling string.
Emit32(E->getValue().getOffset());
}
-
+
// Emit the offset into the original source file of this token so that we
// can reconstruct its SourceLocation.
Emit32(PP.getSourceManager().getFileOffset(T.getLocation()));
@@ -276,14 +275,14 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
// This speed up reading them back in.
Pad(Out, 4);
Offset off = (Offset) Out.tell();
-
+
// Keep track of matching '#if' ... '#endif'.
typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
PPCondTable PPCond;
std::vector<unsigned> PPStartCond;
bool ParsingPreprocessorDirective = false;
Token Tok;
-
+
do {
L.LexFromRawLexer(Tok);
NextToken:
@@ -301,7 +300,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
EmitToken(Tmp);
ParsingPreprocessorDirective = false;
}
-
+
if (Tok.is(tok::identifier)) {
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
EmitToken(Tok);
@@ -321,39 +320,39 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
// If we see the start of line, then we had a null directive "#".
if (Tok.isAtStartOfLine())
goto NextToken;
-
+
// Did we see 'include'/'import'/'include_next'?
if (Tok.isNot(tok::identifier)) {
EmitToken(Tok);
continue;
}
-
+
IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
Tok.setIdentifierInfo(II);
tok::PPKeywordKind K = II->getPPKeywordID();
-
+
ParsingPreprocessorDirective = true;
-
+
switch (K) {
case tok::pp_not_keyword:
// Invalid directives "#foo" can occur in #if 0 blocks etc, just pass
// them through.
default:
break;
-
+
case tok::pp_include:
case tok::pp_import:
- case tok::pp_include_next: {
+ case tok::pp_include_next: {
// Save the 'include' token.
EmitToken(Tok);
// Lex the next token as an include string.
L.setParsingPreprocessorDirective(true);
- L.LexIncludeFilename(Tok);
+ L.LexIncludeFilename(Tok);
L.setParsingPreprocessorDirective(false);
assert(!Tok.isAtStartOfLine());
if (Tok.is(tok::identifier))
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
-
+
break;
}
case tok::pp_if:
@@ -375,11 +374,11 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
assert(PPCond.size() > PPStartCond.back());
assert(PPCond[PPStartCond.back()].second == 0);
PPCond[PPStartCond.back()].second = index;
- PPStartCond.pop_back();
- // Add the new entry to PPCond.
+ PPStartCond.pop_back();
+ // Add the new entry to PPCond.
PPCond.push_back(std::make_pair(HashOff, index));
EmitToken(Tok);
-
+
// Some files have gibberish on the same line as '#endif'.
// Discard these tokens.
do
@@ -387,7 +386,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine());
// We have the next token in hand.
// Don't immediately lex the next one.
- goto NextToken;
+ goto NextToken;
}
case tok::pp_elif:
case tok::pp_else: {
@@ -408,7 +407,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
}
}
}
-
+
EmitToken(Tok);
}
while (Tok.isNot(tok::eof));
@@ -436,11 +435,11 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
Offset PTHWriter::EmitCachedSpellings() {
// Write each cached strings to the PTH file.
Offset SpellingsOff = Out.tell();
-
+
for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator
I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I)
EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/);
-
+
return SpellingsOff;
}
@@ -448,12 +447,12 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) {
// Generate the prologue.
Out << "cfe-pth";
Emit32(PTHManager::Version);
-
+
// Leave 4 words for the prologue.
Offset PrologueOffset = Out.tell();
for (unsigned i = 0; i < 4; ++i)
Emit32(0);
-
+
// Write the name of the MainFile.
if (MainFile && !MainFile->empty()) {
Emit16(MainFile->length());
@@ -463,17 +462,17 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) {
Emit16(0);
}
Emit8(0);
-
+
// Iterate over all the files in SourceManager. Create a lexer
// for each file and cache the tokens.
SourceManager &SM = PP.getSourceManager();
const LangOptions &LOpts = PP.getLangOptions();
-
+
for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(),
E = SM.fileinfo_end(); I != E; ++I) {
const SrcMgr::ContentCache &C = *I->second;
const FileEntry *FE = C.Entry;
-
+
// FIXME: Handle files with non-absolute paths.
llvm::sys::Path P(FE->getName());
if (!P.isAbsolute())
@@ -489,13 +488,13 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) {
// Write out the identifier table.
const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable();
-
+
// Write out the cached strings table.
Offset SpellingOff = EmitCachedSpellings();
-
+
// Write out the file table.
- Offset FileTableOff = EmitFileTable();
-
+ Offset FileTableOff = EmitFileTable();
+
// Finally, write the prologue.
Out.seek(PrologueOffset);
Emit32(IdTableOff.first);
@@ -515,20 +514,20 @@ class StatListener : public StatSysCallCache {
public:
StatListener(PTHMap &pm) : PM(pm) {}
~StatListener() {}
-
+
int stat(const char *path, struct stat *buf) {
int result = ::stat(path, buf);
-
+
if (result != 0) // Failed 'stat'.
PM.insert(path, PTHEntry());
else if (S_ISDIR(buf->st_mode)) {
// Only cache directories with absolute paths.
if (!llvm::sys::Path(path).isAbsolute())
return result;
-
+
PM.insert(PTHEntryKeyVariant(buf, path), PTHEntry());
}
-
+
return result;
}
};
@@ -541,27 +540,27 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID());
llvm::sys::Path MainFilePath(MainFile->getName());
std::string MainFileName;
-
+
if (!MainFilePath.isAbsolute()) {
llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
- P.appendComponent(MainFilePath.toString());
- MainFileName = P.toString();
+ P.appendComponent(MainFilePath.str());
+ MainFileName = P.str();
} else {
- MainFileName = MainFilePath.toString();
+ MainFileName = MainFilePath.str();
}
// Create the PTHWriter.
PTHWriter PW(*OS, PP);
-
+
// Install the 'stat' system call listener in the FileManager.
PP.getFileManager().setStatCache(new StatListener(PW.getPM()));
-
+
// Lex through the entire file. This will populate SourceManager with
// all of the header information.
Token Tok;
PP.EnterMainSourceFile();
do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
-
+
// Generate the PTH file.
PP.getFileManager().setStatCache(0);
PW.GeneratePTH(&MainFileName);
@@ -580,32 +579,32 @@ class VISIBILITY_HIDDEN PTHIdentifierTableTrait {
public:
typedef PTHIdKey* key_type;
typedef key_type key_type_ref;
-
+
typedef uint32_t data_type;
typedef data_type data_type_ref;
-
+
static unsigned ComputeHash(PTHIdKey* key) {
return BernsteinHash(key->II->getName());
}
-
- static std::pair<unsigned,unsigned>
- EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) {
+
+ static std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) {
unsigned n = strlen(key->II->getName()) + 1;
::Emit16(Out, n);
return std::make_pair(n, sizeof(uint32_t));
}
-
+
static void EmitKey(llvm::raw_ostream& Out, PTHIdKey* key, unsigned n) {
// Record the location of the key data. This is used when generating
// the mapping from persistent IDs to strings.
key->FileOffset = Out.tell();
Out.write(key->II->getName(), n);
}
-
+
static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID,
unsigned) {
::Emit32(Out, pID);
- }
+ }
};
} // end anonymous namespace
@@ -624,7 +623,7 @@ std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
// Create the hashtable.
OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;
-
+
// Generate mapping from persistent IDs -> IdentifierInfo*.
for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) {
// Decrement by 1 because we are using a vector for the lookup and
@@ -632,27 +631,27 @@ std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
assert(I->second > 0);
assert(I->second-1 < idcount);
unsigned idx = I->second-1;
-
+
// Store the mapping from persistent ID to IdentifierInfo*
IIDMap[idx].II = I->first;
-
+
// Store the reverse mapping in a hashtable.
IIOffMap.insert(&IIDMap[idx], I->second);
}
-
+
// Write out the inverse map first. This causes the PCIDKey entries to
// record PTH file offsets for the string data. This is used to write
// the second table.
Offset StringTableOffset = IIOffMap.Emit(Out);
-
- // Now emit the table mapping from persistent IDs to PTH file offsets.
+
+ // Now emit the table mapping from persistent IDs to PTH file offsets.
Offset IDOff = Out.tell();
Emit32(idcount); // Emit the number of identifiers.
for (unsigned i = 0 ; i < idcount; ++i)
Emit32(IIDMap[i].FileOffset);
-
+
// Finally, release the inverse map.
free(IIDMap);
-
+
return std::make_pair(IDOff, StringTableOffset);
}