Out << (unsigned char)(V >> 24);
}
+static void Emit64(llvm::raw_ostream& Out, uint64_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ Out << (unsigned char)(V >> 16);
+ Out << (unsigned char)(V >> 24);
+ Out << (unsigned char)(V >> 32);
+ Out << (unsigned char)(V >> 40);
+ Out << (unsigned char)(V >> 48);
+ Out << (unsigned char)(V >> 56);
+}
+
static void Pad(llvm::raw_fd_ostream& Out, unsigned A) {
Offset off = (Offset) Out.tell();
uint32_t n = ((uintptr_t)(off+A-1) & ~(uintptr_t)(A-1)) - off;
const std::pair<unsigned, unsigned>& Len =
Info::EmitKeyDataLength(out, I->key, I->data);
Info::EmitKey(out, I->key, Len.first);
- Info::EmitData(out, I->data, Len.second);
+ Info::EmitData(out, I->key, I->data, Len.second);
}
}
unsigned n = strlen(FE->getName()) + 1;
::Emit16(Out, n);
- return std::make_pair(n, 8);
+ return std::make_pair(n,(4*2)+(4+4+2+8+8));
}
static void EmitKey(llvm::raw_ostream& Out, const FileEntry* FE, unsigned n) {
Out.write(FE->getName(), n);
}
- static void EmitData(llvm::raw_ostream& Out, const PCHEntry& E, unsigned) {
+ static void EmitData(llvm::raw_ostream& Out, const FileEntry* FE,
+ const PCHEntry& E, unsigned) {
::Emit32(Out, E.getTokenOffset());
::Emit32(Out, E.getPPCondTableOffset());
+ // Emit stat information.
+ ::Emit32(Out, FE->getInode());
+ ::Emit32(Out, FE->getDevice());
+ ::Emit16(Out, FE->getFileMode());
+ ::Emit64(Out, FE->getModificationTime());
+ ::Emit64(Out, FE->getSize());
}
};
if (!P.isAbsolute())
continue;
- // assert(!PM.count(FE) && "fileinfo's are not uniqued on FileEntry?");
-
const llvm::MemoryBuffer *B = C.getBuffer();
if (!B) continue;
Out.write(key->II->getName(), n);
}
- static void EmitData(llvm::raw_ostream& Out, uint32_t pID, unsigned) {
+ static void EmitData(llvm::raw_ostream& Out, PCHIdKey*, uint32_t pID,
+ unsigned) {
::Emit32(Out, pID);
}
};
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Host.h"
+#include <sys/stat.h>
using namespace clang;
#define DISK_TOKEN_SIZE (1+1+2+4+4)
return V;
}
+static inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) {
+ uint64_t V = ((uint64_t)Data[0]) |
+ ((uint64_t)Data[1] << 8) |
+ ((uint64_t)Data[2] << 16) |
+ ((uint64_t)Data[3] << 24) |
+ ((uint64_t)Data[1] << 32) |
+ ((uint64_t)Data[2] << 40) |
+ ((uint64_t)Data[3] << 48) |
+ ((uint64_t)Data[3] << 56);
+ Data += 8;
+ return V;
+}
+
static inline uint32_t ReadLE32(const unsigned char *&Data) {
// Hosts that directly support little-endian 32-bit loads can just
// use them. Big-endian hosts need a bswap.
"'buckets' must have a 4-byte alignment");
}
-
+ unsigned getNumBuckets() const { return NumBuckets; }
+ unsigned getNumEntries() const { return NumEntries; }
+ const unsigned char* const getBase() const { return Base; }
+ const unsigned char* const getBuckets() const { return Buckets; }
+
bool isEmpty() const { return NumEntries == 0; }
class iterator {
uint32_t getPPCondOffset() const { return PPCondOff; }
};
-class VISIBILITY_HIDDEN PTHFileLookupTrait {
+
+class VISIBILITY_HIDDEN PTHFileLookupCommonTrait {
public:
- typedef PTHFileData data_type;
- typedef const FileEntry* external_key_type;
typedef const char* internal_key_type;
static bool EqualKey(const char* a, const char* b) {
return strcmp(a, b) == 0;
}
-
+
static unsigned ComputeHash(const char* x) {
return BernsteinHash(x);
}
-
- static const char* GetInternalKey(const FileEntry* FE) {
- return FE->getName();
- }
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d) {
- return std::make_pair((unsigned) ReadUnalignedLE16(d), 8U);
+ return std::make_pair((unsigned) ReadUnalignedLE16(d), 8U + (4+4+2+8+8));
}
static const char* ReadKey(const unsigned char* d, unsigned) {
return (const char*) d;
}
+};
+
+class VISIBILITY_HIDDEN PTHFileLookupTrait : public PTHFileLookupCommonTrait {
+public:
+ typedef const FileEntry* external_key_type;
+ typedef PTHFileData data_type;
+
+ static const char* GetInternalKey(const FileEntry* FE) {
+ return FE->getName();
+ }
static PTHFileData ReadData(const unsigned char* d, unsigned) {
uint32_t x = ::ReadUnalignedLE32(d);
assert(PP && "No preprocessor set yet!");
return new PTHLexer(*PP, FID, data, ppcond, *this);
}
+
+//===----------------------------------------------------------------------===//
+// 'stat' caching.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VISIBILITY_HIDDEN PTHStatData {
+public:
+ const ino_t ino;
+ const dev_t dev;
+ const mode_t mode;
+ const time_t mtime;
+ const off_t size;
+
+ PTHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
+ : ino(i), dev(d), mode(mo), mtime(m), size(s) {}
+};
+
+class VISIBILITY_HIDDEN PTHStatLookupTrait : public PTHFileLookupCommonTrait {
+public:
+ typedef internal_key_type external_key_type; // const char*
+ typedef PTHStatData data_type;
+
+ static const char* GetInternalKey(external_key_type x) { return x; }
+
+ static data_type ReadData(const unsigned char* d, unsigned) {
+ d += 4 * 2; // Skip the first 2 words.
+ ino_t ino = (ino_t) ReadUnalignedLE32(d);
+ dev_t dev = (dev_t) ReadUnalignedLE32(d);
+ mode_t mode = (mode_t) ReadUnalignedLE16(d);
+ time_t mtime = (time_t) ReadUnalignedLE64(d);
+ return data_type(ino, dev, mode, mtime, (off_t) ReadUnalignedLE64(d));
+ }
+};
+}
+
+class VISIBILITY_HIDDEN PTHStatCache : public StatSysCallCache {
+ typedef OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy;
+ CacheTy Cache;
+
+public:
+ PTHStatCache(PTHFileLookup &FL) :
+ Cache(FL.getNumBuckets(), FL.getNumEntries(), FL.getBuckets(),
+ FL.getBase()) {}
+
+ ~PTHStatCache() {}
+
+ int stat(const char *path, struct stat *buf) {
+ // Do the lookup for the file's data in the PTH file.
+ CacheTy::iterator I = Cache.find(path);
+
+ // If we don't get a hit in the PTH file just forward to 'stat'.
+ if (I == Cache.end()) return ::stat(path, buf);
+
+ const PTHStatData& Data = *I;
+ buf->st_ino = Data.ino;
+ buf->st_dev = Data.dev;
+ buf->st_mtime = Data.mtime;
+ buf->st_mode = Data.mode;
+ buf->st_size = Data.size;
+ return 0;
+ }
+};
+
+StatSysCallCache *PTHManager::createStatCache() {
+ return new PTHStatCache(*((PTHFileLookup*) FileLookup));
+}