CacheTokens.cpp revision 8f0d270c7db1ccee7b56c895a1de9b8bc4599355
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" 168588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Basic/FileManager.h" 178588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Basic/SourceManager.h" 188588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Basic/IdentifierTable.h" 198588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Basic/Diagnostic.h" 209378ba44b3f46d697653003c784be87746e138d2Douglas Gregor#include "clang/Basic/OnDiskHashTable.h" 218588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Lex/Lexer.h" 228588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "clang/Lex/Preprocessor.h" 23df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar#include "llvm/ADT/StringExtras.h" 24df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar#include "llvm/ADT/StringMap.h" 258588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "llvm/Support/MemoryBuffer.h" 268588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "llvm/Support/raw_ostream.h" 27fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek#include "llvm/System/Path.h" 288588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 29ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet// FIXME: put this somewhere else? 30ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#ifndef S_ISDIR 31ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#define S_ISDIR(x) (((x)&_S_IFDIR)!=0) 32ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#endif 33ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet 348588896b4779a617e5d257423ef6178431c8bda3Ted Kremenekusing namespace clang; 359378ba44b3f46d697653003c784be87746e138d2Douglas Gregorusing namespace clang::io; 36f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek 37f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek//===----------------------------------------------------------------------===// 38f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek// PTH-specific stuff. 39f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek//===----------------------------------------------------------------------===// 40f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek 41be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremeneknamespace { 42bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHEntry { 431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset TokenData, PPCondData; 44be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 46a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry() {} 47be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 48a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry(Offset td, Offset ppcd) 49277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek : TokenData(td), PPCondData(ppcd) {} 501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset getTokenOffset() const { return TokenData; } 52be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek Offset getPPCondTableOffset() const { return PPCondData; } 53277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek}; 541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 56bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHEntryKeyVariant { 57ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek union { const FileEntry* FE; const char* Path; }; 58a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind; 59ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek struct stat *StatBuf; 60d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenekpublic: 61ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek PTHEntryKeyVariant(const FileEntry *fe) 62ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek : FE(fe), Kind(IsFE), StatBuf(0) {} 63ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 64ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek PTHEntryKeyVariant(struct stat* statbuf, const char* path) 65ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek : Path(path), Kind(IsDE), StatBuf(new struct stat(*statbuf)) {} 66ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 67c8e5eacaaf8174cc5cd2168ae7bede54bea83787Kovarththanan Rajaratnam explicit PTHEntryKeyVariant(const char* path) 68ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek : Path(path), Kind(IsNoExist), StatBuf(0) {} 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek bool isFile() const { return Kind == IsFE; } 711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 72df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar llvm::StringRef getString() const { 73ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek return Kind == IsFE ? FE->getName() : Path; 74a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 76a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned getKind() const { return (unsigned) Kind; } 771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 78a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek void EmitData(llvm::raw_ostream& Out) { 79a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek switch (Kind) { 80b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case IsFE: 81b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Emit stat information. 82b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, FE->getInode()); 83b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, FE->getDevice()); 84b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit16(Out, FE->getFileMode()); 85b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, FE->getModificationTime()); 86b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, FE->getSize()); 87b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 88b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case IsDE: 89b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Emit stat information. 90b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, (uint32_t) StatBuf->st_ino); 91b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit32(Out, (uint32_t) StatBuf->st_dev); 92b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit16(Out, (uint16_t) StatBuf->st_mode); 93b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, (uint64_t) StatBuf->st_mtime); 94b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump ::Emit64(Out, (uint64_t) StatBuf->st_size); 95b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump delete StatBuf; 96b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 97b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump default: 98b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 99a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 100a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned getRepresentationLength() const { 103ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8; 104a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 105a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek}; 1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass FileEntryPTHEntryInfo { 108a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenekpublic: 109a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHEntryKeyVariant key_type; 110d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek typedef key_type key_type_ref; 1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHEntry data_type; 113a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef const PTHEntry& data_type_ref; 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static unsigned ComputeHash(PTHEntryKeyVariant V) { 116df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar return llvm::HashString(V.getString()); 117d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::pair<unsigned,unsigned> 120a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V, 121a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const PTHEntry& E) { 122d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 123df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar unsigned n = V.getString().size() + 1 + 1; 124d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek ::Emit16(Out, n); 1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 126ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0); 127a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit8(Out, m); 128a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 129a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return std::make_pair(n, m); 130d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 132a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static void EmitKey(llvm::raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){ 133a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit the entry kind. 134a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit8(Out, (unsigned) V.getKind()); 135a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit the string. 136df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar Out.write(V.getString().data(), n - 1); 137d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V, 140a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const PTHEntry& E, unsigned) { 141a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 142a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 143a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // For file entries emit the offsets into the PTH file for token data 144a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // and the preprocessor blocks table. 145ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek if (V.isFile()) { 146a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit32(Out, E.getTokenOffset()); 147a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ::Emit32(Out, E.getPPCondTableOffset()); 148a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 1491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 150a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit any other data associated with the key (i.e., stat information). 151a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek V.EmitData(Out); 1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 153d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek}; 1541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 155277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenekclass OffsetOpt { 156277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek bool valid; 157277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset off; 158277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenekpublic: 159277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek OffsetOpt() : valid(false) {} 160277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek bool hasOffset() const { return valid; } 161277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset getOffset() const { assert(valid); return off; } 162277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek void setOffset(Offset o) { off = o; valid = true; } 163be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek}; 164be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek} // end anonymous namespace 165be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 166a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenektypedef OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap; 167fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenektypedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap; 168277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenektypedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy; 1698588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 170b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremeneknamespace { 171bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHWriter { 172b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek IDMap IM; 173b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek llvm::raw_fd_ostream& Out; 174b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Preprocessor& PP; 175b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek uint32_t idcount; 176a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHMap PM; 177be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek CachedStrsTy CachedStrs; 178277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset CurStrOffset; 179277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries; 1808588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 181b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek //// Get the persistent id for the given IdentifierInfo*. 182b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek uint32_t ResolveID(const IdentifierInfo* II); 1831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 184b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek /// Emit a token to the PTH file. 185b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek void EmitToken(const Token& T); 1868588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 187fbcc071d63d82cbe4f197843ce369b70c2fc1c1dKovarththanan Rajaratnam void Emit8(uint32_t V) { ::Emit8(Out, V); } 1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 189e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek void Emit16(uint32_t V) { ::Emit16(Out, V); } 1901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 191be08ac7afbb2aca5f6718687787658a928599b21Kovarththanan Rajaratnam void Emit24(uint32_t V) { ::Emit24(Out, V); } 19218d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek 193e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek void Emit32(uint32_t V) { ::Emit32(Out, V); } 194e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek 195f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner void EmitBuf(const char *Ptr, unsigned NumBytes) { 196f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Out.write(Ptr, NumBytes); 197b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek } 1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 199c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam void EmitString(llvm::StringRef V) { 200c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam ::Emit16(Out, V.size()); 201c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam EmitBuf(V.data(), V.size()); 202c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam } 203c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam 2047e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// EmitIdentifierTable - Emits two tables to the PTH file. The first is 2057e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// a hashtable mapping from identifier strings to persistent IDs. 2067e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// The second is a straight table mapping from persistent IDs to string data 2077e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// (the keys of the first table). 208f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek std::pair<Offset, Offset> EmitIdentifierTable(); 2091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 210f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek /// EmitFileTable - Emit a table mapping from file name strings to PTH 211f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek /// token data. 212f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek Offset EmitFileTable() { return PM.Emit(Out); } 213f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek 214a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry LexTokens(Lexer& L); 215277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset EmitCachedSpellings(); 216ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 217b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenekpublic: 2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp) 219277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek : Out(out), PP(pp), idcount(0), CurStrOffset(0) {} 2201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22152ba870eba17e634339622dbf103434ca31935ebChris Lattner PTHMap &getPM() { return PM; } 22274e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnam void GeneratePTH(const std::string &MainFile); 223b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek}; 224b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek} // end anonymous namespace 2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpuint32_t PTHWriter::ResolveID(const IdentifierInfo* II) { 227fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek // Null IdentifierInfo's map to the persistent ID 0. 228fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek if (!II) 229fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek return 0; 2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2318588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek IDMap::iterator I = IM.find(II); 232f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner if (I != IM.end()) 233f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner return I->second; // We've already added 1. 2341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 235f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL. 236f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner return idcount; 2378588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 2388588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 239b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenekvoid PTHWriter::EmitToken(const Token& T) { 240f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // Emit the token kind, flags, and length. 241f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)| 242f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek (((uint32_t) T.getLength()) << 16)); 2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 244f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner if (!T.isLiteral()) { 245f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(ResolveID(T.getIdentifierInfo())); 246f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner } else { 247f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // We cache *un-cleaned* spellings. This gives us 100% fidelity with the 248f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // source code. 249f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek const char* s = T.getLiteralData(); 250f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek unsigned len = T.getLength(); 25125cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek 25247246be8ac5b0ddde6c402b8fc6946b6135487b5Chris Lattner // Get the string entry. 253f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s, s+len); 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); 259f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek CurStrOffset += len + 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) { 290e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Insert an eom 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; 295e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.setKind(tok::eom); 296e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.clearFlag(Token::StartOfLine); 297e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.setIdentifierInfo(0); 298b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tmp); 299e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 300e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 302a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek if (Tok.is(tok::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(); 313b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tok); 314dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 315dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Get the next token. 316a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.LexFromRawLexer(Tok); 3172135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner 3182135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner // If we see the start of line, then we had a null directive "#". 3192135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner if (Tok.isAtStartOfLine()) 3202135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner goto NextToken; 3211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 322a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Did we see 'include'/'import'/'include_next'? 323d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner if (Tok.isNot(tok::identifier)) { 324e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 325a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek continue; 326e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 3271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 328a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok); 329a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek tok::PPKeywordKind K = II->getPPKeywordID(); 3301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 331e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = true; 3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 333e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek switch (K) { 334aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner case tok::pp_not_keyword: 335aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass 336aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // them through. 337e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek default: 338e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 340e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_include: 341e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_import: 3421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case tok::pp_include_next: { 343a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Save the 'include' token. 344b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tok); 345a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Lex the next token as an include string. 346a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(true); 3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump L.LexIncludeFilename(Tok); 348a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(false); 349e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(!Tok.isAtStartOfLine()); 350a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek if (Tok.is(tok::identifier)) 35165cc1e889c0c2c617a81a0ae032fa4fb24760f38Kovarththanan Rajaratnam PP.LookUpIdentifierInfo(Tok); 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 353e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 354a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 355e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_if: 356e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifdef: 357e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifndef: { 358e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // Add an entry for '#if' and friends. We initially set the target 359e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // index to 0. This will get backpatched when we hit #endif. 360fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.push_back(PPCond.size()); 361dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 362e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 363fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 364e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_endif: { 365fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Add an entry for '#endif'. We set the target table index to itself. 366dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This will later be set to zero when emitting to the PTH file. We 367dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // use 0 for uninitialized indices because that is easier to debug. 368fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 369fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the opening '#if' entry. 370dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 371dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 372fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 373fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PPStartCond.pop_back(); 3751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Add the new entry to PPCond. 376dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, index)); 377726080d8dc40d993521a42687342522da06d3aacTed Kremenek EmitToken(Tok); 3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 379726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Some files have gibberish on the same line as '#endif'. 380726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Discard these tokens. 381d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner do 382d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner L.LexFromRawLexer(Tok); 383d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine()); 384726080d8dc40d993521a42687342522da06d3aacTed Kremenek // We have the next token in hand. 385726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Don't immediately lex the next one. 3861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump goto NextToken; 387fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 388e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_elif: 389e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_else: { 390e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Add an entry for #elif or #else. 391dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This serves as both a closing and opening of a conditional block. 392dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This means that its entry will get backpatched later. 393fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 394fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the previous '#if' entry. 395dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 396dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 397fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 398fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 399fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.pop_back(); 400fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Now add '#elif' as a new block opening. 401dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 402dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPStartCond.push_back(index); 403e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 404e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 405fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 406e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 408e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 409a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 410e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek while (Tok.isNot(tok::eof)); 411b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 412dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals."); 413b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 414fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Next write out PPCond. 415fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Offset PPCondOff = (Offset) Out.tell(); 416dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 417dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Write out the size of PPCond so that clients can identifer empty tables. 418b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(PPCond.size()); 419fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek 420dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) { 4218f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam Emit32(PPCond[i].first - TokenOff); 422dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek uint32_t x = PPCond[i].second; 423dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(x != 0 && "PPCond entry not backpatched."); 424dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Emit zero for #endifs. This allows us to do checking when 425dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // we read the PTH file back in. 426b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(x == i ? 0 : x); 427fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 428fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 4298f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam return PTHEntry(TokenOff, PPCondOff); 430be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek} 431be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 432277faca30c9f8f72b79f55695cbe3395ec246e7cTed KremenekOffset PTHWriter::EmitCachedSpellings() { 433277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek // Write each cached strings to the PTH file. 434277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingsOff = Out.tell(); 4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 436277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator 437f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I) 438f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/); 4391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 440277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek return SpellingsOff; 441a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek} 4428588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 44374e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnamvoid PTHWriter::GeneratePTH(const std::string &MainFile) { 444e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek // Generate the prologue. 445e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek Out << "cfe-pth"; 44667d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek Emit32(PTHManager::Version); 4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 448a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Leave 4 words for the prologue. 449a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Offset PrologueOffset = Out.tell(); 450f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0; i < 4; ++i) 451f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(0); 4521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 453d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Write the name of the MainFile. 4542e6051ad0149c0e7b626558c110fba29bfc754cdKovarththanan Rajaratnam if (!MainFile.empty()) { 4558f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam EmitString(MainFile); 456f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner } else { 457d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // String with 0 bytes. 458d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit16(0); 459d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek } 460d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit8(0); 4611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4628588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // Iterate over all the files in SourceManager. Create a lexer 4638588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // for each file and cache the tokens. 464c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner SourceManager &SM = PP.getSourceManager(); 465c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner const LangOptions &LOpts = PP.getLangOptions(); 4661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 467c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(), 468c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner E = SM.fileinfo_end(); I != E; ++I) { 4690d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner const SrcMgr::ContentCache &C = *I->second; 470c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner const FileEntry *FE = C.Entry; 4711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 472fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek // FIXME: Handle files with non-absolute paths. 473fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek llvm::sys::Path P(FE->getName()); 474fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek if (!P.isAbsolute()) 475fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek continue; 476a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 47736c35ba0aca641e60e5dbee8efbc620c08b9bd61Douglas Gregor const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics()); 478a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek if (!B) continue; 479fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 4802b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); 4816e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID); 4826e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner Lexer L(FID, FromFile, SM, LOpts); 483d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek PM.insert(FE, LexTokens(L)); 48431309ab547b5e9a050ee8532a061fe5f26e99c7cDaniel Dunbar } 485a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 486a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the identifier table. 487f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable(); 4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 489be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek // Write out the cached strings table. 490277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingOff = EmitCachedSpellings(); 4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 492a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the file table. 4931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset FileTableOff = EmitFileTable(); 4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 495a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Finally, write the prologue. 496a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Out.seek(PrologueOffset); 497b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(IdTableOff.first); 498f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek Emit32(IdTableOff.second); 499b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(FileTableOff); 500277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Emit32(SpellingOff); 501b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek} 502b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 50352ba870eba17e634339622dbf103434ca31935ebChris Lattnernamespace { 50452ba870eba17e634339622dbf103434ca31935ebChris Lattner/// StatListener - A simple "interpose" object used to monitor stat calls 50552ba870eba17e634339622dbf103434ca31935ebChris Lattner/// invoked by FileManager while processing the original sources used 50652ba870eba17e634339622dbf103434ca31935ebChris Lattner/// as input to PTH generation. StatListener populates the PTHWriter's 50752ba870eba17e634339622dbf103434ca31935ebChris Lattner/// file map with stat information for directories as well as negative stats. 50852ba870eba17e634339622dbf103434ca31935ebChris Lattner/// Stat information for files are populated elsewhere. 50952ba870eba17e634339622dbf103434ca31935ebChris Lattnerclass StatListener : public StatSysCallCache { 51052ba870eba17e634339622dbf103434ca31935ebChris Lattner PTHMap &PM; 51152ba870eba17e634339622dbf103434ca31935ebChris Lattnerpublic: 51252ba870eba17e634339622dbf103434ca31935ebChris Lattner StatListener(PTHMap &pm) : PM(pm) {} 51352ba870eba17e634339622dbf103434ca31935ebChris Lattner ~StatListener() {} 5141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 51552ba870eba17e634339622dbf103434ca31935ebChris Lattner int stat(const char *path, struct stat *buf) { 51652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor int result = StatSysCallCache::stat(path, buf); 5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 51852ba870eba17e634339622dbf103434ca31935ebChris Lattner if (result != 0) // Failed 'stat'. 519c8e5eacaaf8174cc5cd2168ae7bede54bea83787Kovarththanan Rajaratnam PM.insert(PTHEntryKeyVariant(path), PTHEntry()); 52052ba870eba17e634339622dbf103434ca31935ebChris Lattner else if (S_ISDIR(buf->st_mode)) { 52152ba870eba17e634339622dbf103434ca31935ebChris Lattner // Only cache directories with absolute paths. 52252ba870eba17e634339622dbf103434ca31935ebChris Lattner if (!llvm::sys::Path(path).isAbsolute()) 52352ba870eba17e634339622dbf103434ca31935ebChris Lattner return result; 5241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52552ba870eba17e634339622dbf103434ca31935ebChris Lattner PM.insert(PTHEntryKeyVariant(buf, path), PTHEntry()); 52652ba870eba17e634339622dbf103434ca31935ebChris Lattner } 5271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52852ba870eba17e634339622dbf103434ca31935ebChris Lattner return result; 52952ba870eba17e634339622dbf103434ca31935ebChris Lattner } 53052ba870eba17e634339622dbf103434ca31935ebChris Lattner}; 53152ba870eba17e634339622dbf103434ca31935ebChris Lattner} // end anonymous namespace 53252ba870eba17e634339622dbf103434ca31935ebChris Lattner 53352ba870eba17e634339622dbf103434ca31935ebChris Lattner 534f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedmanvoid clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { 535d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Get the name of the main file. 536d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const SourceManager &SrcMgr = PP.getSourceManager(); 537d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID()); 538d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek llvm::sys::Path MainFilePath(MainFile->getName()); 5391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54011a18f115e8974ef24e8d5bb549ed3289871efa4Kovarththanan Rajaratnam MainFilePath.makeAbsolute(); 541ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 542ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Create the PTHWriter. 543f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedman PTHWriter PW(*OS, PP); 5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 545ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Install the 'stat' system call listener in the FileManager. 54652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatListener *StatCache = new StatListener(PW.getPM()); 54752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true); 5481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 549ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Lex through the entire file. This will populate SourceManager with 550ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // all of the header information. 551ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek Token Tok; 552dbf8ee630e4c86e5150492eaf8dbceea3c718ee1Douglas Gregor if (PP.EnterMainSourceFile()) 553dbf8ee630e4c86e5150492eaf8dbceea3c718ee1Douglas Gregor return; 554ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); 5551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 556ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Generate the PTH file. 55752e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().removeStatCache(StatCache); 55874e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnam PW.GeneratePTH(MainFilePath.str()); 5598588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 560e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek 5617e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek//===----------------------------------------------------------------------===// 5627e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 56348673e68832e9fb508401d53a63cf46481cd7f7cKovarththanan Rajaratnamnamespace { 564f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattnerclass PTHIdKey { 5657e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 5667e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek const IdentifierInfo* II; 5677e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek uint32_t FileOffset; 5687e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 5697e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 570bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHIdentifierTableTrait { 5717e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 572a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHIdKey* key_type; 5737e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef key_type key_type_ref; 5741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5757e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef uint32_t data_type; 5767e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef data_type data_type_ref; 5771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 578a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static unsigned ComputeHash(PTHIdKey* key) { 57901eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar return llvm::HashString(key->II->getName()); 5807e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::pair<unsigned,unsigned> 5831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) { 584e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar unsigned n = key->II->getLength() + 1; 5857e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ::Emit16(Out, n); 5867e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(n, sizeof(uint32_t)); 5877e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5893432fa591ca896e5828bbcc83807353b9b6fba2bDouglas Gregor static void EmitKey(llvm::raw_ostream& Out, PTHIdKey* key, unsigned n) { 5907e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Record the location of the key data. This is used when generating 5917e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the mapping from persistent IDs to strings. 5927e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek key->FileOffset = Out.tell(); 593e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar Out.write(key->II->getNameStart(), n); 5947e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 596a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID, 597337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek unsigned) { 5987e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ::Emit32(Out, pID); 5991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 6007e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 6017e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} // end anonymous namespace 6027e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6037e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// EmitIdentifierTable - Emits two tables to the PTH file. The first is 6047e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// a hashtable mapping from identifier strings to persistent IDs. The second 6057e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// is a straight table mapping from persistent IDs to string data (the 6067e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// keys of the first table). 6077e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// 6087e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekstd::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() { 6097e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Build two maps: 6107e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset) 6117e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs 6127e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6137e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Note that we use 'calloc', so all the bytes are 0. 614f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey)); 6157e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6167e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Create the hashtable. 617a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap; 6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6197e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Generate mapping from persistent IDs -> IdentifierInfo*. 620f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) { 6217e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Decrement by 1 because we are using a vector for the lookup and 6227e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // 0 is reserved for NULL. 6237e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second > 0); 6247e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second-1 < idcount); 6257e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek unsigned idx = I->second-1; 6261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6277e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the mapping from persistent ID to IdentifierInfo* 6287e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIDMap[idx].II = I->first; 6291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6307e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the reverse mapping in a hashtable. 6317e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIOffMap.insert(&IIDMap[idx], I->second); 6327e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6347e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Write out the inverse map first. This causes the PCIDKey entries to 6357e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // record PTH file offsets for the string data. This is used to write 6367e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the second table. 6377e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset StringTableOffset = IIOffMap.Emit(Out); 6381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Now emit the table mapping from persistent IDs to PTH file offsets. 6407e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset IDOff = Out.tell(); 6417e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Emit32(idcount); // Emit the number of identifiers. 642f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0 ; i < idcount; ++i) 643f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(IIDMap[i].FileOffset); 6441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6457e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Finally, release the inverse map. 6467e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek free(IIDMap); 6471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6487e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(IDOff, StringTableOffset); 6497e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} 650