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 745f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner 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 805f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner void EmitData(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> 1225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner EmitKeyDataLength(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 1345f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitKey(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 1415f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitData(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 2005f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner void EmitString(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. 2505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef s(T.getLiteralData(), T.getLength()); 25125cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek 25247246be8ac5b0ddde6c402b8fc6946b6135487b5Chris Lattner // Get the string entry. 25365aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s); 2541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 255f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // If this is a new string entry, bump the PTH offset. 256277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek if (!E->getValue().hasOffset()) { 257277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek E->getValue().setOffset(CurStrOffset); 258277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek StrEntries.push_back(E); 25965aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad CurStrOffset += s.size() + 1; 260277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek } 2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26225cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // Emit the relative offset into the PTH file for the spelling string. 263277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Emit32(E->getValue().getOffset()); 264b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek } 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26625cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // Emit the offset into the original source file of this token so that we 26725cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // can reconstruct its SourceLocation. 26852c29081281955d3db9e11d10573b2d38f709099Chris Lattner Emit32(PP.getSourceManager().getFileOffset(T.getLocation())); 2698588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 2708588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 271a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted KremenekPTHEntry PTHWriter::LexTokens(Lexer& L) { 2727b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek // Pad 0's so that we emit tokens to a 4-byte alignment. 2737b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek // This speed up reading them back in. 274e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek Pad(Out, 4); 2758f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam Offset TokenOff = (Offset) Out.tell(); 2761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 277fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Keep track of matching '#if' ... '#endif'. 278fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek typedef std::vector<std::pair<Offset, unsigned> > PPCondTable; 279fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCondTable PPCond; 280dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek std::vector<unsigned> PPStartCond; 281e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek bool ParsingPreprocessorDirective = false; 282a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek Token Tok; 2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 284a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek do { 285a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.LexFromRawLexer(Tok); 286726080d8dc40d993521a42687342522da06d3aacTed Kremenek NextToken: 287726080d8dc40d993521a42687342522da06d3aacTed Kremenek 288e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) && 289e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective) { 29084021556baceb76eedf7d44be8ba71d9b8cfaccePeter Collingbourne // Insert an eod token into the token cache. It has the same 291e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // position as the next token that is not on the same line as the 292e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // preprocessor directive. Observe that we continue processing 293e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // 'Tok' when we exit this branch. 294e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Token Tmp = Tok; 29584021556baceb76eedf7d44be8ba71d9b8cfaccePeter Collingbourne Tmp.setKind(tok::eod); 296e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.clearFlag(Token::StartOfLine); 297e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.setIdentifierInfo(0); 298b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tmp); 299e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 300e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 302c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.is(tok::raw_identifier)) { 30365cc1e889c0c2c617a81a0ae032fa4fb24760f38Kovarththanan Rajaratnam PP.LookUpIdentifierInfo(Tok); 304e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 305e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek continue; 306a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 307e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 308e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { 309a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Special processing for #include. Store the '#' token and lex 310a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // the next token. 311e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(!ParsingPreprocessorDirective); 312fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Offset HashOff = (Offset) Out.tell(); 313dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 314dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Get the next token. 3155c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek Token NextTok; 3165c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek L.LexFromRawLexer(NextTok); 3172135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner 3185c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // If we see the start of line, then we had a null directive "#". In 3195c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // this case, discard both tokens. 3205c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek if (NextTok.isAtStartOfLine()) 3212135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner goto NextToken; 322c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara 3235c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // The token is the start of a directive. Emit it. 3245c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek EmitToken(Tok); 3255c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek Tok = NextTok; 3261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 327a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Did we see 'include'/'import'/'include_next'? 328c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.isNot(tok::raw_identifier)) { 329e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 330a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek continue; 331e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 333a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok); 334a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek tok::PPKeywordKind K = II->getPPKeywordID(); 3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 336e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = true; 3371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 338e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek switch (K) { 339aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner case tok::pp_not_keyword: 340aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass 341aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // them through. 342e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek default: 343e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 3441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 345e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_include: 346e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_import: 3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case tok::pp_include_next: { 348a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Save the 'include' token. 349b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tok); 350a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Lex the next token as an include string. 351a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(true); 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump L.LexIncludeFilename(Tok); 353a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(false); 354e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(!Tok.isAtStartOfLine()); 355c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.is(tok::raw_identifier)) 35665cc1e889c0c2c617a81a0ae032fa4fb24760f38Kovarththanan Rajaratnam PP.LookUpIdentifierInfo(Tok); 3571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 358e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 359a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 360e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_if: 361e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifdef: 362e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifndef: { 363e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // Add an entry for '#if' and friends. We initially set the target 364e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // index to 0. This will get backpatched when we hit #endif. 365fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.push_back(PPCond.size()); 366dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 367e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 368fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 369e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_endif: { 370fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Add an entry for '#endif'. We set the target table index to itself. 371dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This will later be set to zero when emitting to the PTH file. We 372dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // use 0 for uninitialized indices because that is easier to debug. 373fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 374fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the opening '#if' entry. 375dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 376dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 377fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 378fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PPStartCond.pop_back(); 3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Add the new entry to PPCond. 381dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, index)); 382726080d8dc40d993521a42687342522da06d3aacTed Kremenek EmitToken(Tok); 3831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 384726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Some files have gibberish on the same line as '#endif'. 385726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Discard these tokens. 386d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner do 387d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner L.LexFromRawLexer(Tok); 388d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine()); 389726080d8dc40d993521a42687342522da06d3aacTed Kremenek // We have the next token in hand. 390726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Don't immediately lex the next one. 3911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump goto NextToken; 392fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 393e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_elif: 394e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_else: { 395e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Add an entry for #elif or #else. 396dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This serves as both a closing and opening of a conditional block. 397dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This means that its entry will get backpatched later. 398fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 399fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the previous '#if' entry. 400dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 401dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 402fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 403fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 404fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.pop_back(); 405fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Now add '#elif' as a new block opening. 406dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 407dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPStartCond.push_back(index); 408e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 409e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 410fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 411e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 413e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 414a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 415e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek while (Tok.isNot(tok::eof)); 416b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 417dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals."); 418b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 419fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Next write out PPCond. 420fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Offset PPCondOff = (Offset) Out.tell(); 421dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 422dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Write out the size of PPCond so that clients can identifer empty tables. 423b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(PPCond.size()); 424fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek 425dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) { 4268f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam Emit32(PPCond[i].first - TokenOff); 427dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek uint32_t x = PPCond[i].second; 428dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(x != 0 && "PPCond entry not backpatched."); 429dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Emit zero for #endifs. This allows us to do checking when 430dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // we read the PTH file back in. 431b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(x == i ? 0 : x); 432fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 433fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 4348f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam return PTHEntry(TokenOff, PPCondOff); 435be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek} 436be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 437277faca30c9f8f72b79f55695cbe3395ec246e7cTed KremenekOffset PTHWriter::EmitCachedSpellings() { 438277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek // Write each cached strings to the PTH file. 439277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingsOff = Out.tell(); 4401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 441277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator 442f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I) 443f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/); 4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 445277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek return SpellingsOff; 446a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek} 4478588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 44874e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnamvoid PTHWriter::GeneratePTH(const std::string &MainFile) { 449e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek // Generate the prologue. 450e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek Out << "cfe-pth"; 45167d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek Emit32(PTHManager::Version); 4521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 453a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Leave 4 words for the prologue. 454a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Offset PrologueOffset = Out.tell(); 455f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0; i < 4; ++i) 456f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(0); 4571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 458d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Write the name of the MainFile. 4592e6051ad0149c0e7b626558c110fba29bfc754cdKovarththanan Rajaratnam if (!MainFile.empty()) { 4608f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam EmitString(MainFile); 461f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner } else { 462d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // String with 0 bytes. 463d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit16(0); 464d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek } 465d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit8(0); 4661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4678588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // Iterate over all the files in SourceManager. Create a lexer 4688588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // for each file and cache the tokens. 469c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner SourceManager &SM = PP.getSourceManager(); 4704e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const LangOptions &LOpts = PP.getLangOpts(); 4711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 472c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(), 473c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner E = SM.fileinfo_end(); I != E; ++I) { 4740d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner const SrcMgr::ContentCache &C = *I->second; 475b1c86492f9a9bef01a4567408c22f961bbd604feArgyrios Kyrtzidis const FileEntry *FE = C.OrigEntry; 4761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 477fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek // FIXME: Handle files with non-absolute paths. 478256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (llvm::sys::path::is_relative(FE->getName())) 479fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek continue; 480a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 481e127a0d80155b45dafe77f2b4380e5fa111a3345Chris Lattner const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics(), SM); 482a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek if (!B) continue; 483fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 4842b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); 4856e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID); 4866e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner Lexer L(FID, FromFile, SM, LOpts); 487d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek PM.insert(FE, LexTokens(L)); 48831309ab547b5e9a050ee8532a061fe5f26e99c7cDaniel Dunbar } 489a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 490a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the identifier table. 491f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable(); 4921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 493be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek // Write out the cached strings table. 494277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingOff = EmitCachedSpellings(); 4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 496a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the file table. 4971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset FileTableOff = EmitFileTable(); 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 499a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Finally, write the prologue. 500a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Out.seek(PrologueOffset); 501b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(IdTableOff.first); 502f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek Emit32(IdTableOff.second); 503b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(FileTableOff); 504277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Emit32(SpellingOff); 505b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek} 506b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 50752ba870eba17e634339622dbf103434ca31935ebChris Lattnernamespace { 50852ba870eba17e634339622dbf103434ca31935ebChris Lattner/// StatListener - A simple "interpose" object used to monitor stat calls 50952ba870eba17e634339622dbf103434ca31935ebChris Lattner/// invoked by FileManager while processing the original sources used 51052ba870eba17e634339622dbf103434ca31935ebChris Lattner/// as input to PTH generation. StatListener populates the PTHWriter's 51152ba870eba17e634339622dbf103434ca31935ebChris Lattner/// file map with stat information for directories as well as negative stats. 51252ba870eba17e634339622dbf103434ca31935ebChris Lattner/// Stat information for files are populated elsewhere. 51310e286aa8d39fb51a21412850265d9dae74613eeChris Lattnerclass StatListener : public FileSystemStatCache { 51452ba870eba17e634339622dbf103434ca31935ebChris Lattner PTHMap &PM; 51552ba870eba17e634339622dbf103434ca31935ebChris Lattnerpublic: 51652ba870eba17e634339622dbf103434ca31935ebChris Lattner StatListener(PTHMap &pm) : PM(pm) {} 51752ba870eba17e634339622dbf103434ca31935ebChris Lattner ~StatListener() {} 5181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 519898a061f69e1145bf89a987c08203132b9922a3cChris Lattner LookupResult getStat(const char *Path, struct stat &StatBuf, 520898a061f69e1145bf89a987c08203132b9922a3cChris Lattner int *FileDescriptor) { 521898a061f69e1145bf89a987c08203132b9922a3cChris Lattner LookupResult Result = statChained(Path, StatBuf, FileDescriptor); 522d6f611198089b78e32d3a15fe8bc986204aee1aaChris Lattner 523d6f611198089b78e32d3a15fe8bc986204aee1aaChris Lattner if (Result == CacheMissing) // Failed 'stat'. 52410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner PM.insert(PTHEntryKeyVariant(Path), PTHEntry()); 52510e286aa8d39fb51a21412850265d9dae74613eeChris Lattner else if (S_ISDIR(StatBuf.st_mode)) { 52652ba870eba17e634339622dbf103434ca31935ebChris Lattner // Only cache directories with absolute paths. 527256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (llvm::sys::path::is_relative(Path)) 52810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner return Result; 5291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53010e286aa8d39fb51a21412850265d9dae74613eeChris Lattner PM.insert(PTHEntryKeyVariant(&StatBuf, Path), PTHEntry()); 53152ba870eba17e634339622dbf103434ca31935ebChris Lattner } 5321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner return Result; 53452ba870eba17e634339622dbf103434ca31935ebChris Lattner } 53552ba870eba17e634339622dbf103434ca31935ebChris Lattner}; 53652ba870eba17e634339622dbf103434ca31935ebChris Lattner} // end anonymous namespace 53752ba870eba17e634339622dbf103434ca31935ebChris Lattner 53852ba870eba17e634339622dbf103434ca31935ebChris Lattner 539f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedmanvoid clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { 540d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Get the name of the main file. 541d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const SourceManager &SrcMgr = PP.getSourceManager(); 542d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID()); 543f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> MainFilePath(MainFile->getName()); 5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 545fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer llvm::sys::fs::make_absolute(MainFilePath); 546ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 547ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Create the PTHWriter. 548f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedman PTHWriter PW(*OS, PP); 5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 550ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Install the 'stat' system call listener in the FileManager. 55152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatListener *StatCache = new StatListener(PW.getPM()); 55252e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true); 5531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 554ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Lex through the entire file. This will populate SourceManager with 555ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // all of the header information. 556ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek Token Tok; 557e127a0d80155b45dafe77f2b4380e5fa111a3345Chris Lattner PP.EnterMainSourceFile(); 558ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); 5591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 560ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Generate the PTH file. 56152e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().removeStatCache(StatCache); 56274e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnam PW.GeneratePTH(MainFilePath.str()); 5638588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 564e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek 5657e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek//===----------------------------------------------------------------------===// 5667e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 56748673e68832e9fb508401d53a63cf46481cd7f7cKovarththanan Rajaratnamnamespace { 568f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattnerclass PTHIdKey { 5697e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 5707e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek const IdentifierInfo* II; 5717e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek uint32_t FileOffset; 5727e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 5737e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 574bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHIdentifierTableTrait { 5757e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 576a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHIdKey* key_type; 5777e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef key_type key_type_ref; 5781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5797e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef uint32_t data_type; 5807e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef data_type data_type_ref; 5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 582a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static unsigned ComputeHash(PTHIdKey* key) { 58301eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar return llvm::HashString(key->II->getName()); 5847e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::pair<unsigned,unsigned> 5875f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner EmitKeyDataLength(raw_ostream& Out, const PTHIdKey* key, uint32_t) { 588e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar unsigned n = key->II->getLength() + 1; 5897e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ::Emit16(Out, n); 5907e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(n, sizeof(uint32_t)); 5917e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5935f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitKey(raw_ostream& Out, PTHIdKey* key, unsigned n) { 5947e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Record the location of the key data. This is used when generating 5957e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the mapping from persistent IDs to strings. 5967e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek key->FileOffset = Out.tell(); 597e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar Out.write(key->II->getNameStart(), n); 5987e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6005f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitData(raw_ostream& Out, PTHIdKey*, uint32_t pID, 601337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek unsigned) { 6027e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ::Emit32(Out, pID); 6031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 6047e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 6057e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} // end anonymous namespace 6067e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6077e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// EmitIdentifierTable - Emits two tables to the PTH file. The first is 6087e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// a hashtable mapping from identifier strings to persistent IDs. The second 6097e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// is a straight table mapping from persistent IDs to string data (the 6107e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// keys of the first table). 6117e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// 6127e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekstd::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() { 6137e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Build two maps: 6147e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset) 6157e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs 6167e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6177e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Note that we use 'calloc', so all the bytes are 0. 618f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey)); 6197e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6207e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Create the hashtable. 621a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap; 6221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6237e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Generate mapping from persistent IDs -> IdentifierInfo*. 624f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) { 6257e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Decrement by 1 because we are using a vector for the lookup and 6267e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // 0 is reserved for NULL. 6277e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second > 0); 6287e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second-1 < idcount); 6297e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek unsigned idx = I->second-1; 6301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6317e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the mapping from persistent ID to IdentifierInfo* 6327e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIDMap[idx].II = I->first; 6331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6347e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the reverse mapping in a hashtable. 6357e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIOffMap.insert(&IIDMap[idx], I->second); 6367e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6387e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Write out the inverse map first. This causes the PCIDKey entries to 6397e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // record PTH file offsets for the string data. This is used to write 6407e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the second table. 6417e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset StringTableOffset = IIOffMap.Emit(Out); 6421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Now emit the table mapping from persistent IDs to PTH file offsets. 6447e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset IDOff = Out.tell(); 6457e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Emit32(idcount); // Emit the number of identifiers. 646f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0 ; i < idcount; ++i) 647f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(IIDMap[i].FileOffset); 6481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6497e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Finally, release the inverse map. 6507e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek free(IIDMap); 6511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6527e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(IDOff, StringTableOffset); 6537e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} 654