PTHLexer.cpp revision ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21
1274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===// 2274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// 3274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// The LLVM Compiler Infrastructure 4274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// 5274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// This file is distributed under the University of Illinois Open Source 6274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// License. See LICENSE.TXT for details. 7274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// 8274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek//===----------------------------------------------------------------------===// 9274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// 10274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// This file implements the PTHLexer interface. 11274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek// 12274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek//===----------------------------------------------------------------------===// 13274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 140c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "clang/Basic/TokenKinds.h" 150c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "clang/Basic/FileManager.h" 160c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "clang/Basic/IdentifierTable.h" 17274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek#include "clang/Lex/PTHLexer.h" 18274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek#include "clang/Lex/Preprocessor.h" 190c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "clang/Lex/PTHManager.h" 200c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "clang/Lex/Token.h" 210c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "clang/Lex/Preprocessor.h" 220c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "llvm/ADT/StringMap.h" 230c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "llvm/ADT/OwningPtr.h" 246f78c3b8b9343e7e9fbf2d457cccf00df6da5d47Chris Lattner#include "llvm/Support/Compiler.h" 256f78c3b8b9343e7e9fbf2d457cccf00df6da5d47Chris Lattner#include "llvm/Support/MathExtras.h" 266f78c3b8b9343e7e9fbf2d457cccf00df6da5d47Chris Lattner#include "llvm/Support/MemoryBuffer.h" 276f78c3b8b9343e7e9fbf2d457cccf00df6da5d47Chris Lattner#include "llvm/System/Host.h" 28337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek#include <sys/stat.h> 29274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenekusing namespace clang; 30274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 317b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek#define DISK_TOKEN_SIZE (1+1+2+4+4) 32268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 33e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 34e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// Utility methods for reading from the mmap'ed PTH file. 35e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 36e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 375ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattnerstatic inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) { 38d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek uint16_t V = ((uint16_t)Data[0]) | 39da9d61c96c412f6babc7f824152609562f302388Chris Lattner ((uint16_t)Data[1] << 8); 40da9d61c96c412f6babc7f824152609562f302388Chris Lattner Data += 2; 41da9d61c96c412f6babc7f824152609562f302388Chris Lattner return V; 42da9d61c96c412f6babc7f824152609562f302388Chris Lattner} 43da9d61c96c412f6babc7f824152609562f302388Chris Lattner 44d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenekstatic inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) { 45d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek uint32_t V = ((uint32_t)Data[0]) | 46d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek ((uint32_t)Data[1] << 8) | 47d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek ((uint32_t)Data[2] << 16) | 48d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek ((uint32_t)Data[3] << 24); 49d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek Data += 4; 50d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek return V; 51d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek} 52d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 53337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekstatic inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) { 54337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek uint64_t V = ((uint64_t)Data[0]) | 55337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek ((uint64_t)Data[1] << 8) | 56337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek ((uint64_t)Data[2] << 16) | 57337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek ((uint64_t)Data[3] << 24) | 58d69ab87dd98dc495fe5731a2a26e47b36a06834eTed Kremenek ((uint64_t)Data[4] << 32) | 59d69ab87dd98dc495fe5731a2a26e47b36a06834eTed Kremenek ((uint64_t)Data[5] << 40) | 60d69ab87dd98dc495fe5731a2a26e47b36a06834eTed Kremenek ((uint64_t)Data[6] << 48) | 61d69ab87dd98dc495fe5731a2a26e47b36a06834eTed Kremenek ((uint64_t)Data[7] << 56); 62337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek Data += 8; 63337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek return V; 64337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek} 65337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 665ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattnerstatic inline uint32_t ReadLE32(const unsigned char *&Data) { 67fbc33388c199d6f731170bf55719d57373a09c1fChris Lattner // Hosts that directly support little-endian 32-bit loads can just 68fbc33388c199d6f731170bf55719d57373a09c1fChris Lattner // use them. Big-endian hosts need a bswap. 69f15674c680730c652a37a16a5d3f3ff429b0c308Chris Lattner uint32_t V = *((uint32_t*)Data); 706f78c3b8b9343e7e9fbf2d457cccf00df6da5d47Chris Lattner if (llvm::sys::isBigEndianHost()) 716f78c3b8b9343e7e9fbf2d457cccf00df6da5d47Chris Lattner V = llvm::ByteSwap_32(V); 72da9d61c96c412f6babc7f824152609562f302388Chris Lattner Data += 4; 73e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek return V; 74e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek} 75e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 767e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek// Bernstein hash function: 777e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek// This is basically copy-and-paste from StringMap. This likely won't 787e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek// stay here, which is why I didn't both to expose this function from 797e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek// String Map. 807e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekstatic unsigned BernsteinHash(const char* x) { 817e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek unsigned int R = 0; 827e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek for ( ; *x != '\0' ; ++x) R = R * 33 + *x; 837e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return R + (R >> 5); 847e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} 857e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 867e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekstatic unsigned BernsteinHash(const char* x, unsigned n) { 877e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek unsigned int R = 0; 887e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x; 897e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return R + (R >> 5); 907e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} 91da9d61c96c412f6babc7f824152609562f302388Chris Lattner 92e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 93e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// PTHLexer methods. 94e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 95e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 96da9d61c96c412f6babc7f824152609562f302388Chris LattnerPTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const unsigned char *D, 97277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek const unsigned char *ppcond, PTHManager &PM) 982b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(0), 99277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM) { 1002b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner 1012b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID); 1025f074266cc59563036c40516c814d63825723e20Ted Kremenek} 103274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 104e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenekvoid PTHLexer::Lex(Token& Tok) { 105e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted KremenekLexNextToken: 106866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 107866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 108866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Read the raw token data. 109866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 110e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 111866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Shadow CurPtr into an automatic variable. 112aff6ef8e7bc3c3739f984c390e0af693e60be064Chris Lattner const unsigned char *CurPtrShadow = CurPtr; 113866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 1141b5285e1ba31975864da356b2ed927e87670e654Chris Lattner // Read in the data for the token. 1155ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner unsigned Word0 = ReadLE32(CurPtrShadow); 1165ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner uint32_t IdentifierID = ReadLE32(CurPtrShadow); 1175ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner uint32_t FileOffset = ReadLE32(CurPtrShadow); 1187b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek 1197b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek tok::TokenKind TKind = (tok::TokenKind) (Word0 & 0xFF); 1207b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek Token::TokenFlags TFlags = (Token::TokenFlags) ((Word0 >> 8) & 0xFF); 121aff6ef8e7bc3c3739f984c390e0af693e60be064Chris Lattner uint32_t Len = Word0 >> 16; 1227b78b7c6d96deb1e63f8d0655ee6fa53de0b65efTed Kremenek 123aff6ef8e7bc3c3739f984c390e0af693e60be064Chris Lattner CurPtr = CurPtrShadow; 124e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 125866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 126866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Construct the token itself. 127866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 128e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 129866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.startToken(); 130898a0bb1972efb6e03cb1151412ec7392cef07deChris Lattner Tok.setKind(TKind); 131898a0bb1972efb6e03cb1151412ec7392cef07deChris Lattner Tok.setFlag(TFlags); 13259d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 1332b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner Tok.setLocation(FileStartLoc.getFileLocWithOffset(FileOffset)); 134866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setLength(Len); 13589d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 136d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner // Handle identifiers. 137277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek if (Tok.isLiteral()) { 138277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek Tok.setLiteralData((const char*) (PTHMgr.SpellingBase + IdentifierID)); 139277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek } 140277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek else if (IdentifierID) { 141d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner MIOpt.ReadToken(); 142d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner IdentifierInfo *II = PTHMgr.GetIdentifierInfo(IdentifierID-1); 143863c486fcb6162495a94fddf7ac8409de2638995Chris Lattner 144d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner Tok.setIdentifierInfo(II); 145863c486fcb6162495a94fddf7ac8409de2638995Chris Lattner 146863c486fcb6162495a94fddf7ac8409de2638995Chris Lattner // Change the kind of this identifier to the appropriate token kind, e.g. 147863c486fcb6162495a94fddf7ac8409de2638995Chris Lattner // turning "for" into a keyword. 148863c486fcb6162495a94fddf7ac8409de2638995Chris Lattner Tok.setKind(II->getTokenID()); 149863c486fcb6162495a94fddf7ac8409de2638995Chris Lattner 150d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner if (II->isHandleIdentifierCase()) 151d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner PP->HandleIdentifier(Tok); 152d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner return; 153d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner } 154d0a69696acca62798dfc8b98f97c92bfa7fa0490Chris Lattner 155866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 156866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Process the token. 157866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 1585f074266cc59563036c40516c814d63825723e20Ted Kremenek#if 0 1595f074266cc59563036c40516c814d63825723e20Ted Kremenek SourceManager& SM = PP->getSourceManager(); 1605f074266cc59563036c40516c814d63825723e20Ted Kremenek llvm::cerr << SM.getFileEntryForID(FileID)->getName() 1615f074266cc59563036c40516c814d63825723e20Ted Kremenek << ':' << SM.getLogicalLineNumber(Tok.getLocation()) 1625f074266cc59563036c40516c814d63825723e20Ted Kremenek << ':' << SM.getLogicalColumnNumber(Tok.getLocation()) 1635f074266cc59563036c40516c814d63825723e20Ted Kremenek << '\n'; 1645f074266cc59563036c40516c814d63825723e20Ted Kremenek#endif 16589d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 166898a0bb1972efb6e03cb1151412ec7392cef07deChris Lattner if (TKind == tok::eof) { 167e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Save the end-of-file token. 168e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek EofToken = Tok; 169e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 170cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek Preprocessor *PPCache = PP; 17159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 17259d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!ParsingPreprocessorDirective); 17359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 17459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 17559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek // FIXME: Issue diagnostics similar to Lexer. 17659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->HandleEndOfFile(Tok, false)) 177d6f53dc4951aace69014619761760addac9e59ecTed Kremenek return; 17859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 179cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek assert(PPCache && "Raw buffer::LexEndOfFile should return a token"); 180cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek return PPCache->Lex(Tok); 181cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek } 182d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 183898a0bb1972efb6e03cb1151412ec7392cef07deChris Lattner if (TKind == tok::hash && Tok.isAtStartOfLine()) { 18459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE; 18559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 18659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek PP->HandleDirective(Tok); 187d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 18859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->isCurrentLexer(this)) 18959d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek goto LexNextToken; 190e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 19159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return PP->Lex(Tok); 192e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 193e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 194898a0bb1972efb6e03cb1151412ec7392cef07deChris Lattner if (TKind == tok::eom) { 19559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(ParsingPreprocessorDirective); 19659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek ParsingPreprocessorDirective = false; 19759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return; 19859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek } 199274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 20059d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek MIOpt.ReadToken(); 201cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek} 202cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek 203e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// FIXME: We can just grab the last token instead of storing a copy 204e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// into EofToken. 20559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenekvoid PTHLexer::getEOF(Token& Tok) { 206defb7094c835998bb821e894253287625ce8c74dTed Kremenek assert(EofToken.is(tok::eof)); 2070c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek Tok = EofToken; 208274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek} 20917ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek 21017ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenekvoid PTHLexer::DiscardToEndOfLine() { 21117ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek assert(ParsingPreprocessorDirective && ParsingFilename == false && 21217ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek "Must be in a preprocessing directive!"); 2134d35da2e41941965bbee8ed7e8c30e7c21000d71Ted Kremenek 214e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // We assume that if the preprocessor wishes to discard to the end of 215e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // the line that it also means to end the current preprocessor directive. 216e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 217e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 21874c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip tokens by only peeking at their token kind and the flags. 21974c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // We don't need to actually reconstruct full tokens from the token buffer. 22074c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // This saves some copies and it also reduces IdentifierInfo* lookup. 221da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* p = CurPtr; 22274c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek while (1) { 22374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token kind. Are we at the end of the file? 22474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek tok::TokenKind x = (tok::TokenKind) (uint8_t) *p; 22574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek if (x == tok::eof) break; 226e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 22774c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token flags. Are we at the start of the next line? 22874c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek Token::TokenFlags y = (Token::TokenFlags) (uint8_t) p[1]; 22980d2f3059326f99ebf7c867db1c7f106ec9485f5Ted Kremenek if (y & Token::StartOfLine) break; 23074c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 23174c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip to the next token. 23274c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek p += DISK_TOKEN_SIZE; 23374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek } 23474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 23574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek CurPtr = p; 23617ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek} 2370c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 238268ee7016a2811803989487c0ad3799486092c63Ted Kremenek/// SkipBlock - Used by Preprocessor to skip the current conditional block. 239268ee7016a2811803989487c0ad3799486092c63Ted Kremenekbool PTHLexer::SkipBlock() { 240268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(CurPPCondPtr && "No cached PP conditional information."); 241268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(LastHashTokPtr && "No known '#' token."); 242268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 243da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* HashEntryI = 0; 244268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t Offset; 245268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t TableIdx; 246268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 247268ee7016a2811803989487c0ad3799486092c63Ted Kremenek do { 24841a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the token offset from the side-table. 2495ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner Offset = ReadLE32(CurPPCondPtr); 25041a2660377d215d004fe413c03874bd066b5384cTed Kremenek 25141a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the target table index from the side-table. 2525ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner TableIdx = ReadLE32(CurPPCondPtr); 25341a2660377d215d004fe413c03874bd066b5384cTed Kremenek 25441a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Compute the actual memory address of the '#' token data for this entry. 25541a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = TokBuf + Offset; 25641a2660377d215d004fe413c03874bd066b5384cTed Kremenek 25741a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Optmization: "Sibling jumping". #if...#else...#endif blocks can 25841a2660377d215d004fe413c03874bd066b5384cTed Kremenek // contain nested blocks. In the side-table we can jump over these 25941a2660377d215d004fe413c03874bd066b5384cTed Kremenek // nested blocks instead of doing a linear search if the next "sibling" 26041a2660377d215d004fe413c03874bd066b5384cTed Kremenek // entry is not at a location greater than LastHashTokPtr. 26141a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryI < LastHashTokPtr && TableIdx) { 26241a2660377d215d004fe413c03874bd066b5384cTed Kremenek // In the side-table we are still at an entry for a '#' token that 26341a2660377d215d004fe413c03874bd066b5384cTed Kremenek // is earlier than the last one we saw. Check if the location we would 26441a2660377d215d004fe413c03874bd066b5384cTed Kremenek // stride gets us closer. 265da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* NextPPCondPtr = 266da9d61c96c412f6babc7f824152609562f302388Chris Lattner PPCond + TableIdx*(sizeof(uint32_t)*2); 26741a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 26841a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read where we should jump to. 2695ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner uint32_t TmpOffset = ReadLE32(NextPPCondPtr); 270da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* HashEntryJ = TokBuf + TmpOffset; 27141a2660377d215d004fe413c03874bd066b5384cTed Kremenek 27241a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryJ <= LastHashTokPtr) { 27341a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Jump directly to the next entry in the side table. 27441a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = HashEntryJ; 27541a2660377d215d004fe413c03874bd066b5384cTed Kremenek Offset = TmpOffset; 2765ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner TableIdx = ReadLE32(NextPPCondPtr); 27741a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPPCondPtr = NextPPCondPtr; 27841a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 27941a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 280268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 28141a2660377d215d004fe413c03874bd066b5384cTed Kremenek while (HashEntryI < LastHashTokPtr); 28241a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'"); 283268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(TableIdx && "No jumping from #endifs."); 284268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 285268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update our side-table iterator. 286da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2); 287268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 288268ee7016a2811803989487c0ad3799486092c63Ted Kremenek CurPPCondPtr = NextPPCondPtr; 289268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 290268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Read where we should jump to. 2915ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner HashEntryI = TokBuf + ReadLE32(NextPPCondPtr); 2925ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner uint32_t NextIdx = ReadLE32(NextPPCondPtr); 293268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 294268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // By construction NextIdx will be zero if this is a #endif. This is useful 295268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // to know to obviate lexing another token. 296268ee7016a2811803989487c0ad3799486092c63Ted Kremenek bool isEndif = NextIdx == 0; 297268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 298268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // This case can occur when we see something like this: 299268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 300268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #if ... 301268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // /* a comment or nothing */ 302268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #elif 303268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 304268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // If we are skipping the first #if block it will be the case that CurPtr 305268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // already points 'elif'. Just return. 306268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 30741a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (CurPtr > HashEntryI) { 30841a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE); 309268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 310268ee7016a2811803989487c0ad3799486092c63Ted Kremenek if (isEndif) 311e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE*2; 312268ee7016a2811803989487c0ad3799486092c63Ted Kremenek else 31341a2660377d215d004fe413c03874bd066b5384cTed Kremenek LastHashTokPtr = HashEntryI; 314268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 315268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 316268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 317268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 318268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Otherwise, we need to advance. Update CurPtr to point to the '#' token. 31941a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPtr = HashEntryI; 320268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 321268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update the location of the last observed '#'. This is useful if we 322268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // are skipping multiple blocks. 323268ee7016a2811803989487c0ad3799486092c63Ted Kremenek LastHashTokPtr = CurPtr; 324268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 325e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Skip the '#' token. 326da9d61c96c412f6babc7f824152609562f302388Chris Lattner assert(((tok::TokenKind)*CurPtr) == tok::hash); 327e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE; 328e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 329268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 330e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if (isEndif) { CurPtr += DISK_TOKEN_SIZE*2; } 331268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 332268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 333268ee7016a2811803989487c0ad3799486092c63Ted Kremenek} 334268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 33530a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed KremenekSourceLocation PTHLexer::getSourceLocation() { 3361b5285e1ba31975864da356b2ed927e87670e654Chris Lattner // getSourceLocation is not on the hot path. It is used to get the location 3371b5285e1ba31975864da356b2ed927e87670e654Chris Lattner // of the next token when transitioning back to this lexer when done 33830a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // handling a #included file. Just read the necessary data from the token 33930a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // data buffer to construct the SourceLocation object. 34030a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // NOTE: This is a virtual function; hence it is defined out-of-line. 341b248d53f2599d8e7b53b144b713e163ca521ffcaTed Kremenek const unsigned char *OffsetPtr = CurPtr + (DISK_TOKEN_SIZE - 4); 3425ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner uint32_t Offset = ReadLE32(OffsetPtr); 3431b5285e1ba31975864da356b2ed927e87670e654Chris Lattner return FileStartLoc.getFileLocWithOffset(Offset); 34430a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek} 34530a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek 3465f074266cc59563036c40516c814d63825723e20Ted Kremenek//===----------------------------------------------------------------------===// 347d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek// OnDiskChainedHashTable 3480c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 3490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 350d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenektemplate<typename Info> 351d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenekclass OnDiskChainedHashTable { 352d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned NumBuckets; 353d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned NumEntries; 354d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* const Buckets; 355d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* const Base; 356d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenekpublic: 357d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek typedef typename Info::internal_key_type internal_key_type; 358d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek typedef typename Info::external_key_type external_key_type; 359d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek typedef typename Info::data_type data_type; 360d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 361d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries, 362d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* buckets, 363d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* base) 364d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek : NumBuckets(numBuckets), NumEntries(numEntries), 365d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek Buckets(buckets), Base(base) { 366d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && 367d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek "'buckets' must have a 4-byte alignment"); 368d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 369d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 370337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek unsigned getNumBuckets() const { return NumBuckets; } 371337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek unsigned getNumEntries() const { return NumEntries; } 37203a2807021acd594add9d4ab5079cc740806b983Eli Friedman const unsigned char* getBase() const { return Base; } 37303a2807021acd594add9d4ab5079cc740806b983Eli Friedman const unsigned char* getBuckets() const { return Buckets; } 374337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 375d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek bool isEmpty() const { return NumEntries == 0; } 376d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 377d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek class iterator { 378a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek internal_key_type key; 379d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* const data; 380d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned len; 381d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek public: 382d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek iterator() : data(0), len(0) {} 383a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek iterator(const internal_key_type k, const unsigned char* d, unsigned l) 384a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek : key(k), data(d), len(l) {} 385d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 386a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek data_type operator*() const { return Info::ReadData(key, data, len); } 387d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek bool operator==(const iterator& X) const { return X.data == data; } 388d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek bool operator!=(const iterator& X) const { return X.data != data; } 389d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek }; 390d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 391d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek iterator find(const external_key_type& eKey) { 392d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const internal_key_type& iKey = Info::GetInternalKey(eKey); 393d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek unsigned key_hash = Info::ComputeHash(iKey); 394d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 395d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // Each bucket is just a 32-bit offset into the PTH file. 396d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek unsigned idx = key_hash & (NumBuckets - 1); 397d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx; 398d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 399d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek unsigned offset = ReadLE32(Bucket); 400d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek if (offset == 0) return iterator(); // Empty bucket. 401d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* Items = Base + offset; 402d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 403d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // 'Items' starts with a 16-bit unsigned integer representing the 404d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // number of items in this bucket. 405d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek unsigned len = ReadUnalignedLE16(Items); 406d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 407d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek for (unsigned i = 0; i < len; ++i) { 408d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // Read the hash. 409d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek uint32_t item_hash = ReadUnalignedLE32(Items); 410d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 411d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // Determine the length of the key and the data. 412d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items); 413d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek unsigned item_len = L.first + L.second; 414d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 415d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // Compare the hashes. If they are not the same, skip the entry entirely. 416d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek if (item_hash != key_hash) { 417d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek Items += item_len; 418d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek continue; 419d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 420d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 421d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // Read the key. 422d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const internal_key_type& X = 423d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek Info::ReadKey((const unsigned char* const) Items, L.first); 424d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 425d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // If the key doesn't match just skip reading the value. 426d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek if (!Info::EqualKey(X, iKey)) { 427d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek Items += item_len; 428d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek continue; 429d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 430d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 431d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek // The key matches! 432a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return iterator(X, Items + L.first, L.second); 433d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 434d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 435d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek return iterator(); 436d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 437d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 438d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek iterator end() const { return iterator(); } 439d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 440d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 441d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek static OnDiskChainedHashTable* Create(const unsigned char* buckets, 442d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const unsigned char* const base) { 443d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 444d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek assert(buckets > base); 445d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 && 446d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek "buckets should be 4-byte aligned."); 447d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 448d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek unsigned numBuckets = ReadLE32(buckets); 449d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek unsigned numEntries = ReadLE32(buckets); 450d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets, 451d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek base); 452d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 453d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek}; 454d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 455d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek//===----------------------------------------------------------------------===// 456d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek// PTH file lookup: map from strings to file data. 457d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek//===----------------------------------------------------------------------===// 4580c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4590c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// PTHFileLookup - This internal data structure is used by the PTHManager 4600c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// to map from FileEntry objects managed by FileManager to offsets within 4610c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// the PTH file. 4620c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremeneknamespace { 463d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenekclass VISIBILITY_HIDDEN PTHFileData { 464d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const uint32_t TokenOff; 465d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const uint32_t PPCondOff; 4660c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 467d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek PTHFileData(uint32_t tokenOff, uint32_t ppCondOff) 468d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek : TokenOff(tokenOff), PPCondOff(ppCondOff) {} 4690c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 470d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek uint32_t getTokenOffset() const { return TokenOff; } 471d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek uint32_t getPPCondOffset() const { return PPCondOff; } 472d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek}; 4730c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 474337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 475337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekclass VISIBILITY_HIDDEN PTHFileLookupCommonTrait { 4760c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 477a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef std::pair<unsigned char, const char*> internal_key_type; 478a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 479a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static unsigned ComputeHash(internal_key_type x) { 480a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return BernsteinHash(x.second); 481d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 482cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek 483d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek static std::pair<unsigned, unsigned> 484d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek ReadKeyDataLength(const unsigned char*& d) { 485a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned keyLen = (unsigned) ReadUnalignedLE16(d); 486a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned dataLen = (unsigned) *(d++); 487a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return std::make_pair(keyLen, dataLen); 4880c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4890c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 490a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static internal_key_type ReadKey(const unsigned char* d, unsigned) { 491a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned char k = *(d++); // Read the entry kind. 492a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return std::make_pair(k, (const char*) d); 493d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek } 494337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek}; 495337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 496337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekclass VISIBILITY_HIDDEN PTHFileLookupTrait : public PTHFileLookupCommonTrait { 497337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekpublic: 498337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek typedef const FileEntry* external_key_type; 499337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek typedef PTHFileData data_type; 500337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 501a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static internal_key_type GetInternalKey(const FileEntry* FE) { 502a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return std::make_pair((unsigned char) 0x1, FE->getName()); 503337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek } 504a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 505a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static bool EqualKey(internal_key_type a, internal_key_type b) { 506a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return a.first == b.first && strcmp(a.second, b.second) == 0; 507a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 508d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 509a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static PTHFileData ReadData(const internal_key_type& k, 510a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const unsigned char* d, unsigned) { 511a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek assert(k.first == 0x1 && "Only file lookups can match!"); 512d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek uint32_t x = ::ReadUnalignedLE32(d); 513d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek uint32_t y = ::ReadUnalignedLE32(d); 514d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek return PTHFileData(x, y); 5150c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5160c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek}; 5177e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5187e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekclass VISIBILITY_HIDDEN PTHStringLookupTrait { 5197e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenekpublic: 5207e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef uint32_t 5217e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek data_type; 5227e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5237e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef const std::pair<const char*, unsigned> 5247e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek external_key_type; 5257e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5267e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek typedef external_key_type internal_key_type; 5277e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5287e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek static bool EqualKey(const internal_key_type& a, 5297e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek const internal_key_type& b) { 5307e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0 5317e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek : false; 5327e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5337e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5347e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek static unsigned ComputeHash(const internal_key_type& a) { 5357e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return BernsteinHash(a.first, a.second); 5367e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5377e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5387e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // This hopefully will just get inlined and removed by the optimizer. 5397e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek static const internal_key_type& 5407e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek GetInternalKey(const external_key_type& x) { return x; } 5417e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5427e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek static std::pair<unsigned, unsigned> 5437e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ReadKeyDataLength(const unsigned char*& d) { 5447e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair((unsigned) ReadUnalignedLE16(d), sizeof(uint32_t)); 5457e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5467e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 5477e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek static std::pair<const char*, unsigned> 5487e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek ReadKey(const unsigned char* d, unsigned n) { 5497e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(n >= 2 && d[n-1] == '\0'); 5507e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return std::make_pair((const char*) d, n-1); 5517e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5527e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 553a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static uint32_t ReadData(const internal_key_type& k, const unsigned char* d, 554a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned) { 5557e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return ::ReadUnalignedLE32(d); 5567e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 5577e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek}; 5587e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 559d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek} // end anonymous namespace 560d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 5617e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenektypedef OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup; 5627e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenektypedef OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup; 5630c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5640c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 5650c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek// PTHManager methods. 5660c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 5670c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5680c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup, 569da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* idDataTable, 570da9d61c96c412f6babc7f824152609562f302388Chris Lattner IdentifierInfo** perIDCache, 5717e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek void* stringIdLookup, unsigned numIds, 572277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek const unsigned char* spellingBase) 5736183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup), 5747e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek IdDataTable(idDataTable), StringIdLookup(stringIdLookup), 575277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek NumIds(numIds), PP(0), SpellingBase(spellingBase) {} 5760c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5770c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::~PTHManager() { 5780c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete Buf; 5790c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete (PTHFileLookup*) FileLookup; 5807e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek delete (PTHStringIdLookup*) StringIdLookup; 5810e50b6e7c104d00614baa3d80df62f1630a94d9cTed Kremenek free(PerIDCache); 5820c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 5830c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 58426555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenekstatic void InvalidPTH(Diagnostic *Diags, const char* Msg = 0) { 58526555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek if (!Diags) return; 58626555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek if (!Msg) Msg = "Invalid or corrupted PTH file"; 58726555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek unsigned DiagID = Diags->getCustomDiagID(Diagnostic::Note, Msg); 58826555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek Diags->Report(FullSourceLoc(), DiagID); 58926555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek} 59026555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek 5918a6aec620dbec1f292fe4116c0373ac81ab90234Ted KremenekPTHManager* PTHManager::Create(const std::string& file, Diagnostic* Diags) { 5920c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Memory map the PTH file. 5930c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::OwningPtr<llvm::MemoryBuffer> 5940c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek File(llvm::MemoryBuffer::getFile(file.c_str())); 5950c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5968a6aec620dbec1f292fe4116c0373ac81ab90234Ted Kremenek if (!File) { 5978a6aec620dbec1f292fe4116c0373ac81ab90234Ted Kremenek if (Diags) { 5988a6aec620dbec1f292fe4116c0373ac81ab90234Ted Kremenek unsigned DiagID = Diags->getCustomDiagID(Diagnostic::Note, 5998a6aec620dbec1f292fe4116c0373ac81ab90234Ted Kremenek "PTH file %0 could not be read"); 6008a6aec620dbec1f292fe4116c0373ac81ab90234Ted Kremenek Diags->Report(FullSourceLoc(), DiagID) << file; 6018a6aec620dbec1f292fe4116c0373ac81ab90234Ted Kremenek } 6027e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6030c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 6048a6aec620dbec1f292fe4116c0373ac81ab90234Ted Kremenek } 6050c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6060c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the buffer ranges and check if there are at least three 32-bit 6070c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // words at the end of the file. 608da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* BufBeg = (unsigned char*)File->getBufferStart(); 609da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* BufEnd = (unsigned char*)File->getBufferEnd(); 610e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek 611e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek // Check the prologue of the file. 6124adc71ae2cfc190f8d2cf58876e2a7893aa74ee0Ted Kremenek if ((BufEnd - BufBeg) < (signed) (sizeof("cfe-pth") + 3 + 4) || 61326555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek memcmp(BufBeg, "cfe-pth", sizeof("cfe-pth") - 1) != 0) { 61426555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags); 615e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek return 0; 61626555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek } 6170c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 61867d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek // Read the PTH version. 619e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek const unsigned char *p = BufBeg + (sizeof("cfe-pth") - 1); 62067d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek unsigned Version = ReadLE32(p); 62167d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek 62226555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek if (Version != PTHManager::Version) { 62326555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags, 62426555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek Version < PTHManager::Version 62526555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek ? "PTH file uses an older PTH format that is no longer supported" 62626555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek : "PTH file uses a newer PTH format that cannot be read"); 62767d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek return 0; 62826555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek } 62967d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek 63067d15050bbea16ae256e204ecd464f2e454c3c99Ted Kremenek // Compute the address of the index table at the end of the PTH file. 631a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek const unsigned char *PrologueOffset = p; 632e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek 633a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek if (PrologueOffset >= BufEnd) { 63426555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags); 635e1b6498c41b94c3bc5cede17b0702282543385efTed Kremenek return 0; 63626555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek } 6370c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6380c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Construct the file lookup table. This will be used for mapping from 6390c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // FileEntry*'s to cached tokens. 640a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek const unsigned char* FileTableOffset = PrologueOffset + sizeof(uint32_t)*2; 6415ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner const unsigned char* FileTable = BufBeg + ReadLE32(FileTableOffset); 6420c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6430c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!(FileTable > BufBeg && FileTable < BufEnd)) { 64426555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags); 6450c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 6460c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 6470c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 648d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek llvm::OwningPtr<PTHFileLookup> FL(PTHFileLookup::Create(FileTable, BufBeg)); 64926555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek if (FL->isEmpty()) { 65026555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags, "PTH file contains no cached source data"); 651cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek return 0; 65226555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek } 6530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6540c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the location of the table mapping from persistent ids to the 6550c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // data needed to reconstruct identifiers. 656a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek const unsigned char* IDTableOffset = PrologueOffset + sizeof(uint32_t)*0; 6575ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner const unsigned char* IData = BufBeg + ReadLE32(IDTableOffset); 658cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek 659cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek if (!(IData >= BufBeg && IData < BufEnd)) { 66026555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags); 66126555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek return 0; 6620c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 6630c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6647e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Get the location of the hashtable mapping between strings and 6657e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // persistent IDs. 666a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek const unsigned char* StringIdTableOffset = PrologueOffset + sizeof(uint32_t)*1; 6677e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek const unsigned char* StringIdTable = BufBeg + ReadLE32(StringIdTableOffset); 6687e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek if (!(StringIdTable >= BufBeg && StringIdTable < BufEnd)) { 66926555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags); 67026555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek return 0; 67172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek } 6727e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek 6737e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek llvm::OwningPtr<PTHStringIdLookup> SL(PTHStringIdLookup::Create(StringIdTable, 6747e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek BufBeg)); 6757e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek if (SL->isEmpty()) { 6767e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek InvalidPTH(Diags, "PTH file contains no identifiers."); 6777e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return 0; 6787e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek } 67972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 680277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek // Get the location of the spelling cache. 681a4bd8eb4d6d4b625f6bbb62fc180b02eab6433edTed Kremenek const unsigned char* spellingBaseOffset = PrologueOffset + sizeof(uint32_t)*3; 682277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek const unsigned char* spellingBase = BufBeg + ReadLE32(spellingBaseOffset); 683277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek if (!(spellingBase >= BufBeg && spellingBase < BufEnd)) { 68426555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags); 685277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek return 0; 686277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek } 687277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek 6886183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Get the number of IdentifierInfos and pre-allocate the identifier cache. 6895ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner uint32_t NumIds = ReadLE32(IData); 690cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek 6916183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Pre-allocate the peristent ID -> IdentifierInfo* cache. We use calloc() 6926183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // so that we in the best case only zero out memory once when the OS returns 6936183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // us new pages. 694cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek IdentifierInfo** PerIDCache = 0; 6956183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 696cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek if (NumIds) { 697cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek PerIDCache = (IdentifierInfo**)calloc(NumIds, sizeof(*PerIDCache)); 698cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek if (!PerIDCache) { 69926555b18aa2c3b78744e77927acd3faa53ae7369Ted Kremenek InvalidPTH(Diags, "Could not allocate memory for processing PTH file"); 700cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek return 0; 701cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek } 7026183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek } 703cdd8f2153e18796e9e2a126ebcbd4f3e1bd7135bTed Kremenek 70472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Create the new PTHManager. 70572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return new PTHManager(File.take(), FL.take(), IData, PerIDCache, 7067e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek SL.take(), NumIds, spellingBase); 7070c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 70877ecb3a28f21496ecfdbb3d5f5b66b0d2abf48c9Chris LattnerIdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) { 7090c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Look in the PTH file for the string data for the IdentifierInfo object. 71077ecb3a28f21496ecfdbb3d5f5b66b0d2abf48c9Chris Lattner const unsigned char* TableEntry = IdDataTable + sizeof(uint32_t)*PersistentID; 711da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* IDData = 7125ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner (const unsigned char*)Buf->getBufferStart() + ReadLE32(TableEntry); 713da9d61c96c412f6babc7f824152609562f302388Chris Lattner assert(IDData < (const unsigned char*)Buf->getBufferEnd()); 7140c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 71572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Allocate the object. 716da9d61c96c412f6babc7f824152609562f302388Chris Lattner std::pair<IdentifierInfo,const unsigned char*> *Mem = 717da9d61c96c412f6babc7f824152609562f302388Chris Lattner Alloc.Allocate<std::pair<IdentifierInfo,const unsigned char*> >(); 71872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 71972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek Mem->second = IDData; 7207e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(IDData[0] != '\0'); 721ea9c26b3dbd74a1497f5609ae6e19a85f42b6073Ted Kremenek IdentifierInfo *II = new ((void*) Mem) IdentifierInfo(); 7220c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 72372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Store the new IdentifierInfo in the cache. 72477ecb3a28f21496ecfdbb3d5f5b66b0d2abf48c9Chris Lattner PerIDCache[PersistentID] = II; 7257e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(II->getName() && II->getName()[0] != '\0'); 7260c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return II; 7270c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 7280c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 72972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted KremenekIdentifierInfo* PTHManager::get(const char *NameStart, const char *NameEnd) { 7307e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek PTHStringIdLookup& SL = *((PTHStringIdLookup*)StringIdLookup); 7317e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Double check our assumption that the last character isn't '\0'. 73282320e94606cfb0f68c6049c070c3600f8df9081Daniel Dunbar assert(NameEnd==NameStart || NameStart[NameEnd-NameStart-1] != '\0'); 7337e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek PTHStringIdLookup::iterator I = SL.find(std::make_pair(NameStart, 7347e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek NameEnd - NameStart)); 7357e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek if (I == SL.end()) // No identifier found? 7367e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return 0; 73772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 7387e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek // Match found. Return the identifier! 7397e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek assert(*I > 0); 7407e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek return GetIdentifierInfo(*I-1); 7417e3a004c6ed1fe87912203b9c5a113f8da89d261Ted Kremenek} 74272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 743f056d92e182cbe4f62c8d14102544dc38066dabcChris LattnerPTHLexer *PTHManager::CreateLexer(FileID FID) { 744f056d92e182cbe4f62c8d14102544dc38066dabcChris Lattner const FileEntry *FE = PP->getSourceManager().getFileEntryForID(FID); 7450c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!FE) 7460c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 7470c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 7480c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Lookup the FileEntry object in our file lookup data structure. It will 7490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // return a variant that indicates whether or not there is an offset within 7500c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // the PTH file that contains cached tokens. 751d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek PTHFileLookup& PFL = *((PTHFileLookup*)FileLookup); 752d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek PTHFileLookup::iterator I = PFL.find(FE); 7530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 754d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek if (I == PFL.end()) // No tokens available? 7550c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 7560c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 757d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek const PTHFileData& FileData = *I; 758d8c02929fe70f03111be73e7b8c402c724238ee9Ted Kremenek 759da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char *BufStart = (const unsigned char *)Buf->getBufferStart(); 7600c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Compute the offset of the token data within the buffer. 761da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* data = BufStart + FileData.getTokenOffset(); 762268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 763268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Get the location of pp-conditional table. 764da9d61c96c412f6babc7f824152609562f302388Chris Lattner const unsigned char* ppcond = BufStart + FileData.getPPCondOffset(); 7655ff4317536dbd7f03332bb250c8b35ec04a6f5dbChris Lattner uint32_t Len = ReadLE32(ppcond); 7661b5285e1ba31975864da356b2ed927e87670e654Chris Lattner if (Len == 0) ppcond = 0; 76732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 76872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek assert(PP && "No preprocessor set yet!"); 769277faca30c9f8f72b79f55695cbe3395ec246e7cTed Kremenek return new PTHLexer(*PP, FID, data, ppcond, *this); 7700c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 771337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 772337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek//===----------------------------------------------------------------------===// 773337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek// 'stat' caching. 774337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek//===----------------------------------------------------------------------===// 775337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 776337edcdbec05316b407d0d64865c88ff8597d910Ted Kremeneknamespace { 777337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekclass VISIBILITY_HIDDEN PTHStatData { 778337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekpublic: 779a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek const bool hasStat; 780337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek const ino_t ino; 781337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek const dev_t dev; 782337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek const mode_t mode; 783337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek const time_t mtime; 784337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek const off_t size; 785337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 786337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek PTHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s) 787a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {} 788a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 789a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek PTHStatData() 790a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {} 791337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek}; 792337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 793337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekclass VISIBILITY_HIDDEN PTHStatLookupTrait : public PTHFileLookupCommonTrait { 794337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekpublic: 795a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek typedef const char* external_key_type; // const char* 796337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek typedef PTHStatData data_type; 797337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 798a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static internal_key_type GetInternalKey(const char *path) { 799a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // The key 'kind' doesn't matter here because it is ignored in EqualKey. 800a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return std::make_pair((unsigned char) 0x0, path); 801a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 802a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 803a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static bool EqualKey(internal_key_type a, internal_key_type b) { 804a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // When doing 'stat' lookups we don't care about the kind of 'a' and 'b', 805a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek // just the paths. 806a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return strcmp(a.second, b.second) == 0; 807a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 808a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek 809a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek static data_type ReadData(const internal_key_type& k, const unsigned char* d, 810a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek unsigned) { 811ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 812ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek if (k.first /* File or Directory */) { 813ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek if (k.first == 0x1 /* File */) d += 4 * 2; // Skip the first 2 words. 814a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek ino_t ino = (ino_t) ReadUnalignedLE32(d); 815a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek dev_t dev = (dev_t) ReadUnalignedLE32(d); 816a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek mode_t mode = (mode_t) ReadUnalignedLE16(d); 817a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek time_t mtime = (time_t) ReadUnalignedLE64(d); 818a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return data_type(ino, dev, mode, mtime, (off_t) ReadUnalignedLE64(d)); 819a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek } 820ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 821ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek // Negative stat. Don't read anything. 822a4b44dd9d30929a35c44d85102e5241ee847b2f2Ted Kremenek return data_type(); 823337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek } 824337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek}; 825337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek} 826337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 827337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekclass VISIBILITY_HIDDEN PTHStatCache : public StatSysCallCache { 828337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek typedef OnDiskChainedHashTable<PTHStatLookupTrait> CacheTy; 829337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek CacheTy Cache; 830337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 831337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenekpublic: 832337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek PTHStatCache(PTHFileLookup &FL) : 833337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek Cache(FL.getNumBuckets(), FL.getNumEntries(), FL.getBuckets(), 834337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek FL.getBase()) {} 835337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 836337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek ~PTHStatCache() {} 837337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 838337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek int stat(const char *path, struct stat *buf) { 839337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek // Do the lookup for the file's data in the PTH file. 840337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek CacheTy::iterator I = Cache.find(path); 841337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 842337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek // If we don't get a hit in the PTH file just forward to 'stat'. 843337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek if (I == Cache.end()) return ::stat(path, buf); 844337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 845337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek const PTHStatData& Data = *I; 846ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 847ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek if (!Data.hasStat) 848ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek return 1; 849ad6ce5cb0e3b5dd853d2b1e337797a6fc1091e21Ted Kremenek 850337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek buf->st_ino = Data.ino; 851337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek buf->st_dev = Data.dev; 852337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek buf->st_mtime = Data.mtime; 853337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek buf->st_mode = Data.mode; 854337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek buf->st_size = Data.size; 855337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek return 0; 856337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek } 857337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek}; 858337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek 859337edcdbec05316b407d0d64865c88ff8597d910Ted KremenekStatSysCallCache *PTHManager::createStatCache() { 8605f747d187bf8dc779a4acc180f9c21f1dbf83f6aTed Kremenek return new PTHStatCache(*((PTHFileLookup*) FileLookup)); 861337edcdbec05316b407d0d64865c88ff8597d910Ted Kremenek} 862