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" 2010e286aa8d39fb51a21412850265d9dae74613eeChris Lattner#include "clang/Basic/SourceManager.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" 25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/EndianStream.h" 26fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer#include "llvm/Support/FileSystem.h" 278588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek#include "llvm/Support/MemoryBuffer.h" 286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/Support/OnDiskHashTable.h" 2903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 3055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 318588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 32ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet// FIXME: put this somewhere else? 33ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#ifndef S_ISDIR 34ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#define S_ISDIR(x) (((x)&_S_IFDIR)!=0) 35ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet#endif 36ea684e699ea84e61711e279f5fa7a1b9f3d46bc2Cedric Venet 378588896b4779a617e5d257423ef6178431c8bda3Ted Kremenekusing namespace clang; 38f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek 39f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek//===----------------------------------------------------------------------===// 40f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek// PTH-specific stuff. 41f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek//===----------------------------------------------------------------------===// 42f0e1f796bc3fc464331badbd40b1888f91566c38Ted Kremenek 436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinestypedef uint32_t Offset; 446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 45be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremeneknamespace { 46bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHEntry { 471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset TokenData, PPCondData; 48be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 50a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry() {} 51be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 52a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry(Offset td, Offset ppcd) 53277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek : TokenData(td), PPCondData(ppcd) {} 541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset getTokenOffset() const { return TokenData; } 56be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek Offset getPPCondTableOffset() const { return PPCondData; } 57277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek}; 581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHEntryKeyVariant { 61ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek union { const FileEntry* FE; const char* Path; }; 62a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind; 630fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola FileData *Data; 640fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola 65d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenekpublic: 666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines PTHEntryKeyVariant(const FileEntry *fe) : FE(fe), Kind(IsFE), Data(nullptr) {} 67ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 680fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola PTHEntryKeyVariant(FileData *Data, const char *path) 690fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola : Path(path), Kind(IsDE), Data(new FileData(*Data)) {} 70ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 710fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola explicit PTHEntryKeyVariant(const char *path) 726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : Path(path), Kind(IsNoExist), Data(nullptr) {} 731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek bool isFile() const { return Kind == IsFE; } 751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 765f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef getString() const { 77ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek return Kind == IsFE ? FE->getName() : Path; 78a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 80a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned getKind() const { return (unsigned) Kind; } 811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 825f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner void EmitData(raw_ostream& Out) { 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little> LE(Out); 85a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek switch (Kind) { 860fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola case IsFE: { 87b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Emit stat information. 880fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola llvm::sys::fs::UniqueID UID = FE->getUniqueID(); 89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(UID.getFile()); 90651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(UID.getDevice()); 91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(FE->getModificationTime()); 92651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(FE->getSize()); 930fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola } break; 94b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case IsDE: 95b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Emit stat information. 96651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(Data->UniqueID.getFile()); 97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(Data->UniqueID.getDevice()); 98651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(Data->ModTime); 99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint64_t>(Data->Size); 1000fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola delete Data; 101b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 102b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump default: 103b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 104a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 105a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned getRepresentationLength() const { 108ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8; 109a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 110a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek}; 1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass FileEntryPTHEntryInfo { 113a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenekpublic: 114a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHEntryKeyVariant key_type; 115d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek typedef key_type key_type_ref; 1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 117a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHEntry data_type; 118a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef const PTHEntry& data_type_ref; 1191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned hash_value_type; 1216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned offset_type; 1226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines static hash_value_type ComputeHash(PTHEntryKeyVariant V) { 124df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar return llvm::HashString(V.getString()); 125d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::pair<unsigned,unsigned> 1285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner EmitKeyDataLength(raw_ostream& Out, PTHEntryKeyVariant V, 129a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const PTHEntry& E) { 130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little> LE(Out); 132d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 133df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar unsigned n = V.getString().size() + 1 + 1; 134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint16_t>(n); 1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 136ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0); 137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint8_t>(m); 138a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 139a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return std::make_pair(n, m); 140d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1425f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitKey(raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){ 143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 144a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit the entry kind. 145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint8_t>((unsigned)V.getKind()); 146a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit the string. 147df5a237b69b5ca74dcbcf9e6306b0f86476f6b32Daniel Dunbar Out.write(V.getString().data(), n - 1); 148d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 1491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitData(raw_ostream& Out, PTHEntryKeyVariant V, 151a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const PTHEntry& E, unsigned) { 152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little> LE(Out); 154a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 155a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // For file entries emit the offsets into the PTH file for token data 156a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // and the preprocessor blocks table. 157ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek if (V.isFile()) { 158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint32_t>(E.getTokenOffset()); 159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LE.write<uint32_t>(E.getPPCondTableOffset()); 160a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 1611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 162a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // Emit any other data associated with the key (i.e., stat information). 163a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek V.EmitData(Out); 1641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 165d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek}; 1661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 167277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenekclass OffsetOpt { 168277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek bool valid; 169277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset off; 170277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenekpublic: 171277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek OffsetOpt() : valid(false) {} 172277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek bool hasOffset() const { return valid; } 173277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset getOffset() const { assert(valid); return off; } 174277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek void setOffset(Offset o) { off = o; valid = true; } 175be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek}; 176be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek} // end anonymous namespace 177be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 1786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinestypedef llvm::OnDiskChainedHashTableGenerator<FileEntryPTHEntryInfo> PTHMap; 1798588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 180b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremeneknamespace { 181bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHWriter { 182622ab50adc847564d62dd88694166a7466a6136aKovarththanan Rajaratnam typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap; 183622ab50adc847564d62dd88694166a7466a6136aKovarththanan Rajaratnam typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy; 184622ab50adc847564d62dd88694166a7466a6136aKovarththanan Rajaratnam 185b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek IDMap IM; 186b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek llvm::raw_fd_ostream& Out; 187b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Preprocessor& PP; 188b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek uint32_t idcount; 189a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHMap PM; 190be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek CachedStrsTy CachedStrs; 191277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset CurStrOffset; 192277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries; 1938588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 194b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek //// Get the persistent id for the given IdentifierInfo*. 195b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek uint32_t ResolveID(const IdentifierInfo* II); 1961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 197b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek /// Emit a token to the PTH file. 198b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek void EmitToken(const Token& T); 1998588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Emit8(uint32_t V) { 201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint8_t>(V); 203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Emit16(uint32_t V) { 206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint16_t>(V); 208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Emit32(uint32_t V) { 211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint32_t>(V); 213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 214e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek 215f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner void EmitBuf(const char *Ptr, unsigned NumBytes) { 216f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Out.write(Ptr, NumBytes); 217b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek } 2181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2195f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner void EmitString(StringRef V) { 220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint16_t>(V.size()); 222c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam EmitBuf(V.data(), V.size()); 223c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam } 224c3cde071b41ca83e43de8dc2abe9a99f77a9ebb8Kovarththanan Rajaratnam 2257e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// EmitIdentifierTable - Emits two tables to the PTH file. The first is 2267e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// a hashtable mapping from identifier strings to persistent IDs. 2277e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// The second is a straight table mapping from persistent IDs to string data 2287e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek /// (the keys of the first table). 229f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek std::pair<Offset, Offset> EmitIdentifierTable(); 2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 231f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek /// EmitFileTable - Emit a table mapping from file name strings to PTH 232f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek /// token data. 233f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek Offset EmitFileTable() { return PM.Emit(Out); } 234f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek 235a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHEntry LexTokens(Lexer& L); 236277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset EmitCachedSpellings(); 237ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 238b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenekpublic: 2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp) 240277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek : Out(out), PP(pp), idcount(0), CurStrOffset(0) {} 2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24252ba870eba17e634339622dbf103434ca31935ebChris Lattner PTHMap &getPM() { return PM; } 24374e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnam void GeneratePTH(const std::string &MainFile); 244b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek}; 245b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek} // end anonymous namespace 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpuint32_t PTHWriter::ResolveID(const IdentifierInfo* II) { 248fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek // Null IdentifierInfo's map to the persistent ID 0. 249fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek if (!II) 250fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek return 0; 2511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2528588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek IDMap::iterator I = IM.find(II); 253f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner if (I != IM.end()) 254f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner return I->second; // We've already added 1. 2551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 256f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL. 257f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner return idcount; 2588588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 2598588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 260b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenekvoid PTHWriter::EmitToken(const Token& T) { 261f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // Emit the token kind, flags, and length. 262f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)| 263f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek (((uint32_t) T.getLength()) << 16)); 2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 265f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner if (!T.isLiteral()) { 266f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(ResolveID(T.getIdentifierInfo())); 267f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner } else { 268f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // We cache *un-cleaned* spellings. This gives us 100% fidelity with the 269f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // source code. 2705f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef s(T.getLiteralData(), T.getLength()); 27125cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek 27247246be8ac5b0ddde6c402b8fc6946b6135487b5Chris Lattner // Get the string entry. 27365aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s); 2741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 275f2a223f6eba2cb68630fda10f4c561cf58daa859Ted Kremenek // If this is a new string entry, bump the PTH offset. 276277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek if (!E->getValue().hasOffset()) { 277277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek E->getValue().setOffset(CurStrOffset); 278277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek StrEntries.push_back(E); 27965aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad CurStrOffset += s.size() + 1; 280277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek } 2811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28225cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // Emit the relative offset into the PTH file for the spelling string. 283277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Emit32(E->getValue().getOffset()); 284b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek } 2851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28625cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // Emit the offset into the original source file of this token so that we 28725cbd9ffd59ce575761295f094031daf1afda881Ted Kremenek // can reconstruct its SourceLocation. 28852c29081281955d3db9e11d10573b2d38f709099Chris Lattner Emit32(PP.getSourceManager().getFileOffset(T.getLocation())); 2898588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 2908588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 291a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted KremenekPTHEntry PTHWriter::LexTokens(Lexer& L) { 2927b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek // Pad 0's so that we emit tokens to a 4-byte alignment. 2937b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek // This speed up reading them back in. 2946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines using namespace llvm::support; 2956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines endian::Writer<little> LE(Out); 2966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines uint32_t TokenOff = Out.tell(); 2976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (uint64_t N = llvm::OffsetToAlignment(TokenOff, 4); N; --N, ++TokenOff) 2986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines LE.write<uint8_t>(0); 2991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 300fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Keep track of matching '#if' ... '#endif'. 301fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek typedef std::vector<std::pair<Offset, unsigned> > PPCondTable; 302fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCondTable PPCond; 303dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek std::vector<unsigned> PPStartCond; 304e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek bool ParsingPreprocessorDirective = false; 305a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek Token Tok; 3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 307a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek do { 308a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.LexFromRawLexer(Tok); 309726080d8dc40d993521a42687342522da06d3aacTed Kremenek NextToken: 310726080d8dc40d993521a42687342522da06d3aacTed Kremenek 311e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) && 312e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective) { 31384021556baceb76eedf7d44be8ba71d9b8cfaccePeter Collingbourne // Insert an eod token into the token cache. It has the same 314e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // position as the next token that is not on the same line as the 315e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // preprocessor directive. Observe that we continue processing 316e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // 'Tok' when we exit this branch. 317e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Token Tmp = Tok; 31884021556baceb76eedf7d44be8ba71d9b8cfaccePeter Collingbourne Tmp.setKind(tok::eod); 319e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek Tmp.clearFlag(Token::StartOfLine); 3206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Tmp.setIdentifierInfo(nullptr); 321b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tmp); 322e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 323e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 3241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 325c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.is(tok::raw_identifier)) { 32665cc1e889c0c2c617a81a0ae032fa4fb24760f38Kovarththanan Rajaratnam PP.LookUpIdentifierInfo(Tok); 327e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 328e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek continue; 329a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 330e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 331e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { 332a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Special processing for #include. Store the '#' token and lex 333a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // the next token. 334e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(!ParsingPreprocessorDirective); 335fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Offset HashOff = (Offset) Out.tell(); 336dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 337dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Get the next token. 3385c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek Token NextTok; 3395c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek L.LexFromRawLexer(NextTok); 3402135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner 3415c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // If we see the start of line, then we had a null directive "#". In 3425c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // this case, discard both tokens. 3435c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek if (NextTok.isAtStartOfLine()) 3442135619d9302224d26292906d286d6bdaa9ab0f2Chris Lattner goto NextToken; 345c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara 3465c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek // The token is the start of a directive. Emit it. 3475c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek EmitToken(Tok); 3485c53f4cb1e46691d788db27153b406869cc4c53fTed Kremenek Tok = NextTok; 3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 350a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Did we see 'include'/'import'/'include_next'? 351c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.isNot(tok::raw_identifier)) { 352e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 353a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek continue; 354e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 3551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 356a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok); 357a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek tok::PPKeywordKind K = II->getPPKeywordID(); 3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 359e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = true; 3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 361e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek switch (K) { 362aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner case tok::pp_not_keyword: 363aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass 364aa269c2e9c242a2fdf1f47ea400f58823ae9e395Chris Lattner // them through. 365e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek default: 366e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 3671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 368e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_include: 369e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_import: 3701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case tok::pp_include_next: { 371a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Save the 'include' token. 372b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek EmitToken(Tok); 373a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Lex the next token as an include string. 374a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(true); 3751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump L.LexIncludeFilename(Tok); 376a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek L.setParsingPreprocessorDirective(false); 377e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(!Tok.isAtStartOfLine()); 378c4bf2b9afb7d47445a9dc6bc848657098a4e3851Abramo Bagnara if (Tok.is(tok::raw_identifier)) 37965cc1e889c0c2c617a81a0ae032fa4fb24760f38Kovarththanan Rajaratnam PP.LookUpIdentifierInfo(Tok); 3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 381e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 382a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 383e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_if: 384e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifdef: 385e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_ifndef: { 386e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // Add an entry for '#if' and friends. We initially set the target 387e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek // index to 0. This will get backpatched when we hit #endif. 388fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.push_back(PPCond.size()); 389dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 390e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 391fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 392e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_endif: { 393fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Add an entry for '#endif'. We set the target table index to itself. 394dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This will later be set to zero when emitting to the PTH file. We 395dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // use 0 for uninitialized indices because that is easier to debug. 396fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 397fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the opening '#if' entry. 398dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 399dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 400fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 401fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PPStartCond.pop_back(); 4031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Add the new entry to PPCond. 404dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, index)); 405726080d8dc40d993521a42687342522da06d3aacTed Kremenek EmitToken(Tok); 4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 407726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Some files have gibberish on the same line as '#endif'. 408726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Discard these tokens. 409d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner do 410d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner L.LexFromRawLexer(Tok); 411d4b1446dfa0bb7eb3da46cad37378c07ae22632bChris Lattner while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine()); 412726080d8dc40d993521a42687342522da06d3aacTed Kremenek // We have the next token in hand. 413726080d8dc40d993521a42687342522da06d3aacTed Kremenek // Don't immediately lex the next one. 4141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump goto NextToken; 415fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 416e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_elif: 417e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek case tok::pp_else: { 418e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Add an entry for #elif or #else. 419dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This serves as both a closing and opening of a conditional block. 420dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // This means that its entry will get backpatched later. 421fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek unsigned index = PPCond.size(); 422fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Backpatch the previous '#if' entry. 423dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(!PPStartCond.empty()); 424dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPCond.size() > PPStartCond.back()); 425fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(PPCond[PPStartCond.back()].second == 0); 426fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPCond[PPStartCond.back()].second = index; 427fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PPStartCond.pop_back(); 428fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Now add '#elif' as a new block opening. 429dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPCond.push_back(std::make_pair(HashOff, 0U)); 430dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek PPStartCond.push_back(index); 431e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek break; 432e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 433fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 434e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek } 4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 436e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek EmitToken(Tok); 437a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek } 438e4f6b1ef01f0d7207f746429d47859470c0d50c0Ted Kremenek while (Tok.isNot(tok::eof)); 439b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 440dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals."); 441b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 442fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek // Next write out PPCond. 443fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Offset PPCondOff = (Offset) Out.tell(); 444dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek 445dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Write out the size of PPCond so that clients can identifer empty tables. 446b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(PPCond.size()); 447fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek 448dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) { 4498f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam Emit32(PPCond[i].first - TokenOff); 450dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek uint32_t x = PPCond[i].second; 451dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek assert(x != 0 && "PPCond entry not backpatched."); 452dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // Emit zero for #endifs. This allows us to do checking when 453dad7b34a33cc318e53b889c2232fa97d4ed142e7Ted Kremenek // we read the PTH file back in. 454b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(x == i ? 0 : x); 455fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 456fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 4578f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam return PTHEntry(TokenOff, PPCondOff); 458be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek} 459be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek 460277faca30c9f8f72b79f55695cbe3395ec246e7cTed KremenekOffset PTHWriter::EmitCachedSpellings() { 461277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek // Write each cached strings to the PTH file. 462277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingsOff = Out.tell(); 4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 464277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator 465f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I) 466f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/); 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 468277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek return SpellingsOff; 469a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek} 4708588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek 47174e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnamvoid PTHWriter::GeneratePTH(const std::string &MainFile) { 472e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek // Generate the prologue. 473c141b51d78b40c7b0b04f27adfa70ec5bbddc49cRichard Smith Out << "cfe-pth" << '\0'; 47467d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek Emit32(PTHManager::Version); 4751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 476a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Leave 4 words for the prologue. 477a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Offset PrologueOffset = Out.tell(); 478f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0; i < 4; ++i) 479f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(0); 4801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 481d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Write the name of the MainFile. 4822e6051ad0149c0e7b626558c110fba29bfc754cdKovarththanan Rajaratnam if (!MainFile.empty()) { 4838f0d270c7db1ccee7b56c895a1de9b8bc4599355Kovarththanan Rajaratnam EmitString(MainFile); 484f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner } else { 485d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // String with 0 bytes. 486d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit16(0); 487d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek } 488d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek Emit8(0); 4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4908588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // Iterate over all the files in SourceManager. Create a lexer 4918588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek // for each file and cache the tokens. 492c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner SourceManager &SM = PP.getSourceManager(); 4934e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const LangOptions &LOpts = PP.getLangOpts(); 4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 495c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(), 496c6fe32a91c7372caf09152ee31a24c4b5d24deedChris Lattner E = SM.fileinfo_end(); I != E; ++I) { 4970d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner const SrcMgr::ContentCache &C = *I->second; 498b1c86492f9a9bef01a4567408c22f961bbd604feArgyrios Kyrtzidis const FileEntry *FE = C.OrigEntry; 4991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 500fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek // FIXME: Handle files with non-absolute paths. 501256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (llvm::sys::path::is_relative(FE->getName())) 502fc7e2ead4306416b893c92693a2cb6d3b0492bdbTed Kremenek continue; 503a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 504e127a0d80155b45dafe77f2b4380e5fa111a3345Chris Lattner const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics(), SM); 505a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek if (!B) continue; 506fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 5072b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); 5086e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID); 5096e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner Lexer L(FID, FromFile, SM, LOpts); 510d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek PM.insert(FE, LexTokens(L)); 51131309ab547b5e9a050ee8532a061fe5f26e99c7cDaniel Dunbar } 512a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek 513a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the identifier table. 514f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable(); 5151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 516be29533f573f0f3d72401d2ed3b1fb627a97aafeTed Kremenek // Write out the cached strings table. 517277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Offset SpellingOff = EmitCachedSpellings(); 5181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 519a3d764cf77f36eea2748e5f1bb225ed6c475af76Ted Kremenek // Write out the file table. 5201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Offset FileTableOff = EmitFileTable(); 5211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 522a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek // Finally, write the prologue. 523a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek Out.seek(PrologueOffset); 524b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(IdTableOff.first); 525f1de4649e917f891d24e0718d02ee904b9edbe9dTed Kremenek Emit32(IdTableOff.second); 526b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek Emit32(FileTableOff); 527277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Emit32(SpellingOff); 528b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek} 529b978c66430cf0383756d9ccfae52876a7158fae6Ted Kremenek 53052ba870eba17e634339622dbf103434ca31935ebChris Lattnernamespace { 53152ba870eba17e634339622dbf103434ca31935ebChris Lattner/// StatListener - A simple "interpose" object used to monitor stat calls 53252ba870eba17e634339622dbf103434ca31935ebChris Lattner/// invoked by FileManager while processing the original sources used 53352ba870eba17e634339622dbf103434ca31935ebChris Lattner/// as input to PTH generation. StatListener populates the PTHWriter's 53452ba870eba17e634339622dbf103434ca31935ebChris Lattner/// file map with stat information for directories as well as negative stats. 53552ba870eba17e634339622dbf103434ca31935ebChris Lattner/// Stat information for files are populated elsewhere. 53610e286aa8d39fb51a21412850265d9dae74613eeChris Lattnerclass StatListener : public FileSystemStatCache { 53752ba870eba17e634339622dbf103434ca31935ebChris Lattner PTHMap &PM; 53852ba870eba17e634339622dbf103434ca31935ebChris Lattnerpublic: 53952ba870eba17e634339622dbf103434ca31935ebChris Lattner StatListener(PTHMap &pm) : PM(pm) {} 54052ba870eba17e634339622dbf103434ca31935ebChris Lattner ~StatListener() {} 5411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5420fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola LookupResult getStat(const char *Path, FileData &Data, bool isFile, 543ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::unique_ptr<vfs::File> *F, 544ef8225444452a1486bd721f3285301fe84643b00Stephen Hines vfs::FileSystem &FS) override { 545651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LookupResult Result = statChained(Path, Data, isFile, F, FS); 546d6f611198089b78e32d3a15fe8bc986204aee1aaChris Lattner 547d6f611198089b78e32d3a15fe8bc986204aee1aaChris Lattner if (Result == CacheMissing) // Failed 'stat'. 54810e286aa8d39fb51a21412850265d9dae74613eeChris Lattner PM.insert(PTHEntryKeyVariant(Path), PTHEntry()); 5490fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola else if (Data.IsDirectory) { 55052ba870eba17e634339622dbf103434ca31935ebChris Lattner // Only cache directories with absolute paths. 551256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer if (llvm::sys::path::is_relative(Path)) 55210e286aa8d39fb51a21412850265d9dae74613eeChris Lattner return Result; 5531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5540fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola PM.insert(PTHEntryKeyVariant(&Data, Path), PTHEntry()); 55552ba870eba17e634339622dbf103434ca31935ebChris Lattner } 5561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55710e286aa8d39fb51a21412850265d9dae74613eeChris Lattner return Result; 55852ba870eba17e634339622dbf103434ca31935ebChris Lattner } 55952ba870eba17e634339622dbf103434ca31935ebChris Lattner}; 56052ba870eba17e634339622dbf103434ca31935ebChris Lattner} // end anonymous namespace 56152ba870eba17e634339622dbf103434ca31935ebChris Lattner 56252ba870eba17e634339622dbf103434ca31935ebChris Lattner 563f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedmanvoid clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { 564d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek // Get the name of the main file. 565d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const SourceManager &SrcMgr = PP.getSourceManager(); 566d5cded40432da737ef85a29a1b9de3a6dcf08793Ted Kremenek const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID()); 567f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> MainFilePath(MainFile->getName()); 5681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 569fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer llvm::sys::fs::make_absolute(MainFilePath); 570ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 571ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Create the PTHWriter. 572f54fce8ff8818cde6b421265f709319f5fea0844Eli Friedman PTHWriter PW(*OS, PP); 5731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 574ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Install the 'stat' system call listener in the FileManager. 57552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor StatListener *StatCache = new StatListener(PW.getPM()); 57652e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true); 5771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 578ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Lex through the entire file. This will populate SourceManager with 579ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // all of the header information. 580ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek Token Tok; 581e127a0d80155b45dafe77f2b4380e5fa111a3345Chris Lattner PP.EnterMainSourceFile(); 582ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); 5831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 584ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Generate the PTH file. 58552e7108f51a4a9f4d6e84f33fb594d06e1d79560Douglas Gregor PP.getFileManager().removeStatCache(StatCache); 58674e485e74e82ad2eefc546fbd32cb0a0274b0d1eKovarththanan Rajaratnam PW.GeneratePTH(MainFilePath.str()); 5878588896b4779a617e5d257423ef6178431c8bda3Ted Kremenek} 588e0ea5dc5fd5077bf21771213fde168ba92ce826bTed Kremenek 5897e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek//===----------------------------------------------------------------------===// 5907e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 59148673e68832e9fb508401d53a63cf46481cd7f7cKovarththanan Rajaratnamnamespace { 592f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattnerclass PTHIdKey { 5937e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 5947e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek const IdentifierInfo* II; 5957e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek uint32_t FileOffset; 5967e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 5977e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 598bd21828179a61bd0954b082825cfb8a93345f602Benjamin Kramerclass PTHIdentifierTableTrait { 5997e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 600a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef PTHIdKey* key_type; 6017e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef key_type key_type_ref; 6021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6037e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef uint32_t data_type; 6047e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef data_type data_type_ref; 6051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned hash_value_type; 6076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines typedef unsigned offset_type; 6086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 6096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines static hash_value_type ComputeHash(PTHIdKey* key) { 61001eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar return llvm::HashString(key->II->getName()); 6117e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump static std::pair<unsigned,unsigned> 6145f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner EmitKeyDataLength(raw_ostream& Out, const PTHIdKey* key, uint32_t) { 615651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 616e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar unsigned n = key->II->getLength() + 1; 617651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint16_t>(n); 6187e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(n, sizeof(uint32_t)); 6197e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitKey(raw_ostream& Out, PTHIdKey* key, unsigned n) { 6227e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Record the location of the key data. This is used when generating 6237e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the mapping from persistent IDs to strings. 6247e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek key->FileOffset = Out.tell(); 625e013d685c6689ac7ae103ee88acf573422d1ed6aDaniel Dunbar Out.write(key->II->getNameStart(), n); 6267e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner static void EmitData(raw_ostream& Out, PTHIdKey*, uint32_t pID, 629337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek unsigned) { 630651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::support; 631651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines endian::Writer<little>(Out).write<uint32_t>(pID); 6321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 6337e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 6347e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} // end anonymous namespace 6357e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6367e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// EmitIdentifierTable - Emits two tables to the PTH file. The first is 6377e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// a hashtable mapping from identifier strings to persistent IDs. The second 6387e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// is a straight table mapping from persistent IDs to string data (the 6397e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// keys of the first table). 6407e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek/// 6417e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekstd::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() { 6427e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Build two maps: 6437e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset) 6447e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs 6457e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6467e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Note that we use 'calloc', so all the bytes are 0. 647f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey)); 6487e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6497e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Create the hashtable. 6506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap; 6511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6527e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Generate mapping from persistent IDs -> IdentifierInfo*. 653f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) { 6547e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Decrement by 1 because we are using a vector for the lookup and 6557e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // 0 is reserved for NULL. 6567e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second > 0); 6577e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(I->second-1 < idcount); 6587e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek unsigned idx = I->second-1; 6591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6607e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the mapping from persistent ID to IdentifierInfo* 6617e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIDMap[idx].II = I->first; 6621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6637e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Store the reverse mapping in a hashtable. 6647e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IIOffMap.insert(&IIDMap[idx], I->second); 6657e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 6661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6677e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Write out the inverse map first. This causes the PCIDKey entries to 6687e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // record PTH file offsets for the string data. This is used to write 6697e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // the second table. 6707e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset StringTableOffset = IIOffMap.Emit(Out); 6711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Now emit the table mapping from persistent IDs to PTH file offsets. 6737e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Offset IDOff = Out.tell(); 6747e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek Emit32(idcount); // Emit the number of identifiers. 675f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner for (unsigned i = 0 ; i < idcount; ++i) 676f2390367a0771b9118dc5c1b4b832ae84f2be897Chris Lattner Emit32(IIDMap[i].FileOffset); 6771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6787e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Finally, release the inverse map. 6797e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek free(IIDMap); 6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6817e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair(IDOff, StringTableOffset); 6827e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} 683