CacheTokens.cpp revision 84021556baceb76eedf7d44be8ba71d9b8cfacce
1a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek//===--- CacheTokens.cpp - Caching of lexer tokens for PTH support --------===// 28588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// 38588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// The LLVM Compiler Infrastructure 48588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// 58588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// This file is distributed under the University of Illinois Open Source 68588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// License. See LICENSE.TXT for details. 78588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// 88588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek//===----------------------------------------------------------------------===// 98588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// 10a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek// This provides a possible implementation of PTH support for Clang that is 118588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// based on caching lexed tokens and identifiers. 128588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek// 138588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek//===----------------------------------------------------------------------===// 148588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 15b09f6e15c59b89d5820db8ef40598eb1d1323c1fEli Friedman#include "clang/Frontend/Utils.h" 1610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "clang/Basic/Diagnostic.h" 178588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Basic/FileManager.h" 1810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "clang/Basic/FileSystemStatCache.h" 198588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Basic/IdentifierTable.h" 209378ba44b3f46d697653003c784be87746e138d2Douglas Gregor#include "clang/Basic/OnDiskHashTable.h" 2110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "clang/Basic/SourceManager.h" 228588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Lex/Lexer.h" 238588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Lex/Preprocessor.h" 24df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar#include "llvm/ADT/StringExtras.h" 25df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar#include "llvm/ADT/StringMap.h" 26fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer#include "llvm/Support/FileSystem.h" 278588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "llvm/Support/MemoryBuffer.h" 288588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "llvm/Support/raw_ostream.h" 2903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 308588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 31ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet// FIXME: put this somewhere else? 32ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#ifndef S_ISDIR 33ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#define S_ISDIR(x) (((x)&_S_IFDIR)!=0) 34ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#endif 35ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet 368588896b4779a617e5d257423ef6178431c8bda3Ted Kremenekusing namespace clang; 379378ba44b3f46d697653003c784be87746e138d2Douglas Gregorusing namespace clang::io; 38f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek 39f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek//===----------------------------------------------------------------------===// 40f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek// PTH-specific stuff. 41f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek//===----------------------------------------------------------------------===// 42f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek 43be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremeneknamespace { 44bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHEntry { 451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset TokenData, PPCondData; 46be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 48a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry() {} 49be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 50a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry(Offset td, Offset ppcd) 51277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek : TokenData(td), PPCondData(ppcd) {} 521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset getTokenOffset() const { return TokenData; } 54be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek Offset getPPCondTableOffset() const { return PPCondData; } 55277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek}; 561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHEntryKeyVariant { 59ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek union { const FileEntry* FE; const char* Path; }; 60a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind; 61ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek struct stat *StatBuf; 62d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenekpublic: 63ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek PTHEntryKeyVariant(const FileEntry *fe) 64ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek : FE(fe), Kind(IsFE), StatBuf(0) {} 65ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 66ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek PTHEntryKeyVariant(struct stat* statbuf, const char* path) 67ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek : Path(path), Kind(IsDE), StatBuf(new struct stat(*statbuf)) {} 68ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 69c8e5eacaaf8174cc5cd2168ae7bede54bea83787Kovarththanan Rajaratnam explicit PTHEntryKeyVariant(const char* path) 70ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek : Path(path), Kind(IsNoExist), StatBuf(0) {} 711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek bool isFile() const { return Kind == IsFE; } 731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar llvm::StringRef getString() const { 75ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek return Kind == IsFE ? FE->getName() : Path; 76a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 78a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned getKind() const { return (unsigned) Kind; } 791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 80a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek void EmitData(llvm::raw_ostream& Out) { 81a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek switch (Kind) { 82b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case IsFE: 83b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Emit stat information. 84b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, FE->getInode()); 85b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, FE->getDevice()); 86b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit16(Out, FE->getFileMode()); 87b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, FE->getModificationTime()); 88b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, FE->getSize()); 89b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 90b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case IsDE: 91b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Emit stat information. 92b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, (uint32_t) StatBuf->st_ino); 93b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, (uint32_t) StatBuf->st_dev); 94b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit16(Out, (uint16_t) StatBuf->st_mode); 95b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, (uint64_t) StatBuf->st_mtime); 96b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, (uint64_t) StatBuf->st_size); 97b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump delete StatBuf; 98b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 99b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump default: 100b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 101a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 102a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 1031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned getRepresentationLength() const { 105ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8; 106a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 107a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek}; 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass FileEntryPTHEntryInfo { 110a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenekpublic: 111a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHEntryKeyVariant key_type; 112d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek typedef key_type key_type_ref; 1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 114a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHEntry data_type; 115a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef const PTHEntry& data_type_ref; 1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 117a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static unsigned ComputeHash(PTHEntryKeyVariant V) { 118df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar return llvm::HashString(V.getString()); 119d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::pair<unsigned,unsigned> 122a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V, 123a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const PTHEntry& E) { 124d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 125df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar unsigned n = V.getString().size() + 1 + 1; 126d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek ::Emit16(Out, n); 1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 128ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0); 129a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit8(Out, m); 130a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 131a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return std::make_pair(n, m); 132d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 134a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static void EmitKey(llvm::raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){ 135a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit the entry kind. 136a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit8(Out, (unsigned) V.getKind()); 137a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit the string. 138df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar Out.write(V.getString().data(), n - 1); 139d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V, 142a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const PTHEntry& E, unsigned) { 143a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 144a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 145a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // For file entries emit the offsets into the PTH file for token data 146a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // and the preprocessor blocks table. 147ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek if (V.isFile()) { 148a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit32(Out, E.getTokenOffset()); 149a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit32(Out, E.getPPCondTableOffset()); 150a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 1511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit any other data associated with the key (i.e., stat information). 153a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek V.EmitData(Out); 1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 155d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek}; 1561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 157277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenekclass OffsetOpt { 158277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek bool valid; 159277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset off; 160277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenekpublic: 161277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek OffsetOpt() : valid(false) {} 162277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek bool hasOffset() const { return valid; } 163277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset getOffset() const { assert(valid); return off; } 164277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek void setOffset(Offset o) { off = o; valid = true; } 165be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek}; 166be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek} // end anonymous namespace 167be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 168a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenektypedef OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap; 1698588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 170b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremeneknamespace { 171bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHWriter { 172622ab50adc847564d62dd88694166a7466a6136aKovarththanan Rajaratnam typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap; 173622ab50adc847564d62dd88694166a7466a6136aKovarththanan Rajaratnam typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy; 174622ab50adc847564d62dd88694166a7466a6136aKovarththanan Rajaratnam 175b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek IDMap IM; 176b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek llvm::raw_fd_ostream& Out; 177b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Preprocessor& PP; 178b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek uint32_t idcount; 179a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHMap PM; 180be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek CachedStrsTy CachedStrs; 181277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset CurStrOffset; 182277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries; 1838588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 184b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek //// Get the persistent id for the given IdentifierInfo*. 185b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek uint32_t ResolveID(const IdentifierInfo* II); 1861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 187b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek /// Emit a token to the PTH file. 188b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek void EmitToken(const Token& T); 1898588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 190fbcc071d63d82cbe4f197843ce369b70c2fc1c1dKovarththanan Rajaratnam void Emit8(uint32_t V) { ::Emit8(Out, V); } 1911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 192e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek void Emit16(uint32_t V) { ::Emit16(Out, V); } 1931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 194e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek void Emit32(uint32_t V) { ::Emit32(Out, V); } 195e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek 196f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner void EmitBuf(const char *Ptr, unsigned NumBytes) { 197f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Out.write(Ptr, NumBytes); 198b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek } 1991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 200c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam void EmitString(llvm::StringRef V) { 201c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam ::Emit16(Out, V.size()); 202c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam EmitBuf(V.data(), V.size()); 203c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam } 204c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam 2057e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// EmitIdentifierTable - Emits two tables to the PTH file. The first is 2067e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// a hashtable mapping from identifier strings to persistent IDs. 2077e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// The second is a straight table mapping from persistent IDs to string data 2087e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// (the keys of the first table). 209f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek std::pair<Offset, Offset> EmitIdentifierTable(); 2101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 211f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek /// EmitFileTable - Emit a table mapping from file name strings to PTH 212f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek /// token data. 213f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek Offset EmitFileTable() { return PM.Emit(Out); } 214f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek 215a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry LexTokens(Lexer& L); 216277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset EmitCachedSpellings(); 217ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 218b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenekpublic: 2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp) 220277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek : Out(out), PP(pp), idcount(0), CurStrOffset(0) {} 2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22252ba870eba17e634339622dbf103434ca31935ebChris Lattner PTHMap &getPM() { return PM; } 22374e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnam void GeneratePTH(const std::string &MainFile); 224b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek}; 225b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek} // end anonymous namespace 2261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpuint32_t PTHWriter::ResolveID(const IdentifierInfo* II) { 228fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek // Null IdentifierInfo's map to the persistent ID 0. 229fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek if (!II) 230fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek return 0; 2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2328588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek IDMap::iterator I = IM.find(II); 233f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner if (I != IM.end()) 234f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner return I->second; // We've already added 1. 2351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 236f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL. 237f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner return idcount; 2388588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 2398588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 240b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenekvoid PTHWriter::EmitToken(const Token& T) { 241f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // Emit the token kind, flags, and length. 242f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)| 243f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek (((uint32_t) T.getLength()) << 16)); 2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 245f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner if (!T.isLiteral()) { 246f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(ResolveID(T.getIdentifierInfo())); 247f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner } else { 248f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // We cache *un-cleaned* spellings. This gives us 100% fidelity with the 249f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // source code. 250f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek const char* s = T.getLiteralData(); 251f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek unsigned len = T.getLength(); 25225cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek 25347246be8ac5b0ddde6c402b8fc6946b6135487b5Chris Lattner // Get the string entry. 254f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s, s+len); 2551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 256f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // If this is a new string entry, bump the PTH offset. 257277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek if (!E->getValue().hasOffset()) { 258277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek E->getValue().setOffset(CurStrOffset); 259277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek StrEntries.push_back(E); 260f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek CurStrOffset += len + 1; 261277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek } 2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26325cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // Emit the relative offset into the PTH file for the spelling string. 264277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Emit32(E->getValue().getOffset()); 265b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek } 2661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26725cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // Emit the offset into the original source file of this token so that we 26825cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // can reconstruct its SourceLocation. 26952c29081281955d3db9e11d10573b2d38f709099Chris Lattner Emit32(PP.getSourceManager().getFileOffset(T.getLocation())); 2708588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 2718588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 272a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted KremenekPTHEntry PTHWriter::LexTokens(Lexer& L) { 2737b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek // Pad 0's so that we emit tokens to a 4-byte alignment. 2747b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek // This speed up reading them back in. 275e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek Pad(Out, 4); 2768f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam Offset TokenOff = (Offset) Out.tell(); 2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 278fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Keep track of matching '#if' ... '#endif'. 279fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek typedef std::vector<std::pair<Offset, unsigned> > PPCondTable; 280fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCondTable PPCond; 281dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek std::vector<unsigned> PPStartCond; 282e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek bool ParsingPreprocessorDirective = false; 283a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek Token Tok; 2841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 285a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek do { 286a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.LexFromRawLexer(Tok); 287726080d8dc40d993521a42687342522da06d3aacTed Kremenek NextToken: 288726080d8dc40d993521a42687342522da06d3aacTed Kremenek 289e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) && 290e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective) { 29184021556baceb76eedf7d44be8ba71d9b8cfaccePeter Collingbourne // Insert an eod token into the token cache. It has the same 292e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // position as the next token that is not on the same line as the 293e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // preprocessor directive. Observe that we continue processing 294e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // 'Tok' when we exit this branch. 295e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Token Tmp = Tok; 29684021556baceb76eedf7d44be8ba71d9b8cfaccePeter Collingbourne Tmp.setKind(tok::eod); 297e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.clearFlag(Token::StartOfLine); 298e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.setIdentifierInfo(0); 299b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tmp); 300e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 301e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 303c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.is(tok::raw_identifier)) { 30465cc1e889c0c2c617a81a0ae032fa4fb24760f38Kovarththanan Rajaratnam PP.LookUpIdentifierInfo(Tok); 305e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 306e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek continue; 307a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 308e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 309e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { 310a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Special processing for #include. Store the '#' token and lex 311a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // the next token. 312e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(!ParsingPreprocessorDirective); 313fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Offset HashOff = (Offset) Out.tell(); 314dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 315dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Get the next token. 3165c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek Token NextTok; 3175c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek L.LexFromRawLexer(NextTok); 3182135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner 3195c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // If we see the start of line, then we had a null directive "#". In 3205c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // this case, discard both tokens. 3215c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek if (NextTok.isAtStartOfLine()) 3222135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner goto NextToken; 323c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara 3245c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // The token is the start of a directive. Emit it. 3255c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek EmitToken(Tok); 3265c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek Tok = NextTok; 3271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 328a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Did we see 'include'/'import'/'include_next'? 329c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.isNot(tok::raw_identifier)) { 330e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 331a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek continue; 332e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 334a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok); 335a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek tok::PPKeywordKind K = II->getPPKeywordID(); 3361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 337e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = true; 3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 339e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek switch (K) { 340aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner case tok::pp_not_keyword: 341aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass 342aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // them through. 343e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek default: 344e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 346e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_include: 347e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_import: 3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case tok::pp_include_next: { 349a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Save the 'include' token. 350b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tok); 351a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Lex the next token as an include string. 352a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(true); 3531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump L.LexIncludeFilename(Tok); 354a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(false); 355e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(!Tok.isAtStartOfLine()); 356c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.is(tok::raw_identifier)) 35765cc1e889c0c2c617a81a0ae032fa4fb24760f38Kovarththanan Rajaratnam PP.LookUpIdentifierInfo(Tok); 3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 359e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 360a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 361e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_if: 362e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifdef: 363e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifndef: { 364e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // Add an entry for '#if' and friends. We initially set the target 365e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // index to 0. This will get backpatched when we hit #endif. 366fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.push_back(PPCond.size()); 367dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 368e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 369fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 370e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_endif: { 371fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Add an entry for '#endif'. We set the target table index to itself. 372dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This will later be set to zero when emitting to the PTH file. We 373dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // use 0 for uninitialized indices because that is easier to debug. 374fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 375fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the opening '#if' entry. 376dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 377dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 378fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 379fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PPStartCond.pop_back(); 3811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Add the new entry to PPCond. 382dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, index)); 383726080d8dc40d993521a42687342522da06d3aacTed Kremenek EmitToken(Tok); 3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 385726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Some files have gibberish on the same line as '#endif'. 386726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Discard these tokens. 387d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner do 388d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner L.LexFromRawLexer(Tok); 389d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine()); 390726080d8dc40d993521a42687342522da06d3aacTed Kremenek // We have the next token in hand. 391726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Don't immediately lex the next one. 3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump goto NextToken; 393fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 394e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_elif: 395e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_else: { 396e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Add an entry for #elif or #else. 397dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This serves as both a closing and opening of a conditional block. 398dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This means that its entry will get backpatched later. 399fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 400fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the previous '#if' entry. 401dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 402dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 403fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 404fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 405fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.pop_back(); 406fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Now add '#elif' as a new block opening. 407dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 408dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPStartCond.push_back(index); 409e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 410e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 411fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 412e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 4131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 414e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 415a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 416e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek while (Tok.isNot(tok::eof)); 417b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 418dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals."); 419b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 420fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Next write out PPCond. 421fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Offset PPCondOff = (Offset) Out.tell(); 422dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 423dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Write out the size of PPCond so that clients can identifer empty tables. 424b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(PPCond.size()); 425fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek 426dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) { 4278f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam Emit32(PPCond[i].first - TokenOff); 428dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek uint32_t x = PPCond[i].second; 429dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(x != 0 && "PPCond entry not backpatched."); 430dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Emit zero for #endifs. This allows us to do checking when 431dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // we read the PTH file back in. 432b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(x == i ? 0 : x); 433fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 434fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 4358f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam return PTHEntry(TokenOff, PPCondOff); 436be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek} 437be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 438277faca30c9f8f72b79f55695cbe3395ec246e7cTed KremenekOffset PTHWriter::EmitCachedSpellings() { 439277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek // Write each cached strings to the PTH file. 440277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingsOff = Out.tell(); 4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 442277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator 443f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I) 444f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/); 4451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 446277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek return SpellingsOff; 447a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek} 4488588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 44974e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnamvoid PTHWriter::GeneratePTH(const std::string &MainFile) { 450e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek // Generate the prologue. 451e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek Out << "cfe-pth"; 45267d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek Emit32(PTHManager::Version); 4531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 454a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Leave 4 words for the prologue. 455a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Offset PrologueOffset = Out.tell(); 456f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0; i < 4; ++i) 457f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(0); 4581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 459d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Write the name of the MainFile. 4602e6051ad0149c0e7b626558c110fba29bfc754cdKovarththanan Rajaratnam if (!MainFile.empty()) { 4618f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam EmitString(MainFile); 462f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner } else { 463d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // String with 0 bytes. 464d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit16(0); 465d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek } 466d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit8(0); 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4688588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // Iterate over all the files in SourceManager. Create a lexer 4698588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // for each file and cache the tokens. 470c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner SourceManager &SM = PP.getSourceManager(); 471c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner const LangOptions &LOpts = PP.getLangOptions(); 4721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 473c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(), 474c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner E = SM.fileinfo_end(); I != E; ++I) { 4750d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner const SrcMgr::ContentCache &C = *I->second; 476c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner const FileEntry *FE = C.Entry; 4771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 478fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek // FIXME: Handle files with non-absolute paths. 479256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (llvm::sys::path::is_relative(FE->getName())) 480fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek continue; 481a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 482e127a0d80155b45dafe77f2b4380e5fa111a3345Chris Lattner const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics(), SM); 483a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek if (!B) continue; 484fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 4852b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); 4866e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID); 4876e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner Lexer L(FID, FromFile, SM, LOpts); 488d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek PM.insert(FE, LexTokens(L)); 48931309ab547b5e9a050ee8532a061fe5f26e99c7cDaniel Dunbar } 490a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 491a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the identifier table. 492f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable(); 4931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 494be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek // Write out the cached strings table. 495277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingOff = EmitCachedSpellings(); 4961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 497a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the file table. 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset FileTableOff = EmitFileTable(); 4991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 500a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Finally, write the prologue. 501a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Out.seek(PrologueOffset); 502b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(IdTableOff.first); 503f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek Emit32(IdTableOff.second); 504b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(FileTableOff); 505277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Emit32(SpellingOff); 506b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek} 507b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 50852ba870eba17e634339622dbf103434ca31935ebChris Lattnernamespace { 50952ba870eba17e634339622dbf103434ca31935ebChris Lattner/// StatListener - A simple "interpose" object used to monitor stat calls 51052ba870eba17e634339622dbf103434ca31935ebChris Lattner/// invoked by FileManager while processing the original sources used 51152ba870eba17e634339622dbf103434ca31935ebChris Lattner/// as input to PTH generation. StatListener populates the PTHWriter's 51252ba870eba17e634339622dbf103434ca31935ebChris Lattner/// file map with stat information for directories as well as negative stats. 51352ba870eba17e634339622dbf103434ca31935ebChris Lattner/// Stat information for files are populated elsewhere. 51410e286aa8d39fb51a21412850265d9dae74613eeChris Lattnerclass StatListener : public FileSystemStatCache { 51552ba870eba17e634339622dbf103434ca31935ebChris Lattner PTHMap &PM; 51652ba870eba17e634339622dbf103434ca31935ebChris Lattnerpublic: 51752ba870eba17e634339622dbf103434ca31935ebChris Lattner StatListener(PTHMap &pm) : PM(pm) {} 51852ba870eba17e634339622dbf103434ca31935ebChris Lattner ~StatListener() {} 5191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 520898a061f69e1145bf89a987c08203132b9922a3cChris Lattner LookupResult getStat(const char *Path, struct stat &StatBuf, 521898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int *FileDescriptor) { 522898a061f69e1145bf89a987c08203132b9922a3cChris Lattner LookupResult Result = statChained(Path, StatBuf, FileDescriptor); 523d6f611198089b78e32d3a15fe8bc986204aee1aaChris Lattner 524d6f611198089b78e32d3a15fe8bc986204aee1aaChris Lattner if (Result == CacheMissing) // Failed 'stat'. 52510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner PM.insert(PTHEntryKeyVariant(Path), PTHEntry()); 52610e286aa8d39fb51a21412850265d9dae74613eeChris Lattner else if (S_ISDIR(StatBuf.st_mode)) { 52752ba870eba17e634339622dbf103434ca31935ebChris Lattner // Only cache directories with absolute paths. 528256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (llvm::sys::path::is_relative(Path)) 52910e286aa8d39fb51a21412850265d9dae74613eeChris Lattner return Result; 5301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53110e286aa8d39fb51a21412850265d9dae74613eeChris Lattner PM.insert(PTHEntryKeyVariant(&StatBuf, Path), PTHEntry()); 53252ba870eba17e634339622dbf103434ca31935ebChris Lattner } 5331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner return Result; 53552ba870eba17e634339622dbf103434ca31935ebChris Lattner } 53652ba870eba17e634339622dbf103434ca31935ebChris Lattner}; 53752ba870eba17e634339622dbf103434ca31935ebChris Lattner} // end anonymous namespace 53852ba870eba17e634339622dbf103434ca31935ebChris Lattner 53952ba870eba17e634339622dbf103434ca31935ebChris Lattner 540f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedmanvoid clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { 541d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Get the name of the main file. 542d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const SourceManager &SrcMgr = PP.getSourceManager(); 543d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID()); 544fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer llvm::SmallString<128> MainFilePath(MainFile->getName()); 5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 546fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer llvm::sys::fs::make_absolute(MainFilePath); 547ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 548ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Create the PTHWriter. 549f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedman PTHWriter PW(*OS, PP); 5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 551ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Install the 'stat' system call listener in the FileManager. 55252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatListener *StatCache = new StatListener(PW.getPM()); 55352e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true); 5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 555ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Lex through the entire file. This will populate SourceManager with 556ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // all of the header information. 557ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek Token Tok; 558e127a0d80155b45dafe77f2b4380e5fa111a3345Chris Lattner PP.EnterMainSourceFile(); 559ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); 5601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 561ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Generate the PTH file. 56252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().removeStatCache(StatCache); 56374e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnam PW.GeneratePTH(MainFilePath.str()); 5648588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 565e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek 5667e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek//===----------------------------------------------------------------------===// 5677e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 56848673e68832e9fb508401d53a63cf46481cd7f7cKovarththanan Rajaratnamnamespace { 569f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattnerclass PTHIdKey { 5707e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 5717e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek const IdentifierInfo* II; 5727e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek uint32_t FileOffset; 5737e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 5747e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 575bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHIdentifierTableTrait { 5767e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 577a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHIdKey* key_type; 5787e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef key_type key_type_ref; 5791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5807e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef uint32_t data_type; 5817e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef data_type data_type_ref; 5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 583a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static unsigned ComputeHash(PTHIdKey* key) { 58401eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar return llvm::HashString(key->II->getName()); 5857e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::pair<unsigned,unsigned> 5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) { 589e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar unsigned n = key->II->getLength() + 1; 5907e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ::Emit16(Out, n); 5917e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(n, sizeof(uint32_t)); 5927e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5943432fa591ca896e5828bbcc83807353b9b6fba2bDouglas Gregor static void EmitKey(llvm::raw_ostream& Out, PTHIdKey* key, unsigned n) { 5957e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Record the location of the key data. This is used when generating 5967e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the mapping from persistent IDs to strings. 5977e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek key->FileOffset = Out.tell(); 598e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar Out.write(key->II->getNameStart(), n); 5997e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 601a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID, 602337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek unsigned) { 6037e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ::Emit32(Out, pID); 6041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 6057e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 6067e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} // end anonymous namespace 6077e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6087e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// EmitIdentifierTable - Emits two tables to the PTH file. The first is 6097e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// a hashtable mapping from identifier strings to persistent IDs. The second 6107e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// is a straight table mapping from persistent IDs to string data (the 6117e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// keys of the first table). 6127e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// 6137e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekstd::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() { 6147e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Build two maps: 6157e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset) 6167e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs 6177e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6187e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Note that we use 'calloc', so all the bytes are 0. 619f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey)); 6207e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6217e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Create the hashtable. 622a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap; 6231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6247e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Generate mapping from persistent IDs -> IdentifierInfo*. 625f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) { 6267e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Decrement by 1 because we are using a vector for the lookup and 6277e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // 0 is reserved for NULL. 6287e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second > 0); 6297e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second-1 < idcount); 6307e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek unsigned idx = I->second-1; 6311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6327e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the mapping from persistent ID to IdentifierInfo* 6337e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIDMap[idx].II = I->first; 6341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6357e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the reverse mapping in a hashtable. 6367e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIOffMap.insert(&IIDMap[idx], I->second); 6377e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6397e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Write out the inverse map first. This causes the PCIDKey entries to 6407e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // record PTH file offsets for the string data. This is used to write 6417e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the second table. 6427e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset StringTableOffset = IIOffMap.Emit(Out); 6431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Now emit the table mapping from persistent IDs to PTH file offsets. 6457e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset IDOff = Out.tell(); 6467e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Emit32(idcount); // Emit the number of identifiers. 647f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0 ; i < idcount; ++i) 648f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(IIDMap[i].FileOffset); 6491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6507e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Finally, release the inverse map. 6517e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek free(IIDMap); 6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6537e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(IDOff, StringTableOffset); 6547e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} 655