PTHLexer.cpp revision 2b2453a7d8fe732561795431f39ceb2b2a832d84
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/Support/Compiler.h" 230c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "llvm/Support/MemoryBuffer.h" 240c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "llvm/ADT/StringMap.h" 250c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek#include "llvm/ADT/OwningPtr.h" 26274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenekusing namespace clang; 27274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 2818d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek#define DISK_TOKEN_SIZE (1+1+3+4+2) 29268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 30e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 31e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// Utility methods for reading from the mmap'ed PTH file. 32e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 33e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 34e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenekstatic inline uint8_t Read8(const char*& data) { 35e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek return (uint8_t) *(data++); 36e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek} 37e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 38e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenekstatic inline uint32_t Read32(const char*& data) { 39e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek uint32_t V = (uint32_t) Read8(data); 40e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek V |= (((uint32_t) Read8(data)) << 8); 41e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek V |= (((uint32_t) Read8(data)) << 16); 42e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek V |= (((uint32_t) Read8(data)) << 24); 43e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek return V; 44e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek} 45e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 46e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 47e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// PTHLexer methods. 48e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 49e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 502b2453a7d8fe732561795431f39ceb2b2a832d84Chris LattnerPTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const char *D, 512b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner const char *ppcond, 522b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner PTHSpellingSearch &mySpellingSrch, PTHManager &PM) 532b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(0), 545f074266cc59563036c40516c814d63825723e20Ted Kremenek PPCond(ppcond), CurPPCondPtr(ppcond), MySpellingSrch(mySpellingSrch), 552b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner PTHMgr(PM) { 562b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner 572b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID); 585f074266cc59563036c40516c814d63825723e20Ted Kremenek} 59274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 60e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenekvoid PTHLexer::Lex(Token& Tok) { 61e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted KremenekLexNextToken: 62866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 63866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 64866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Read the raw token data. 65866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 66e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 67866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Shadow CurPtr into an automatic variable. 68866bdf74547efe32c320554837ffce00fcc084feTed Kremenek const unsigned char *CurPtrShadow = (const unsigned char*) CurPtr; 69866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 70866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Read in the data for the token. 14 bytes in total. 71866bdf74547efe32c320554837ffce00fcc084feTed Kremenek tok::TokenKind k = (tok::TokenKind) CurPtrShadow[0]; 72866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Token::TokenFlags flags = (Token::TokenFlags) CurPtrShadow[1]; 73866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 746b1c9708c8fca3786c766b6d1869721656b31322Ted Kremenek uint32_t perID = ((uint32_t) CurPtrShadow[2]) 75866bdf74547efe32c320554837ffce00fcc084feTed Kremenek | (((uint32_t) CurPtrShadow[3]) << 8) 7618d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[4]) << 16); 770c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 7818d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek uint32_t FileOffset = ((uint32_t) CurPtrShadow[5]) 7918d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[6]) << 8) 8018d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[7]) << 16) 8118d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[8]) << 24); 82e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 8318d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek uint32_t Len = ((uint32_t) CurPtrShadow[9]) 8418d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[10]) << 8); 85e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 86866bdf74547efe32c320554837ffce00fcc084feTed Kremenek CurPtr = (const char*) (CurPtrShadow + DISK_TOKEN_SIZE); 87e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 88866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 89866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Construct the token itself. 90866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 91e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 92866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.startToken(); 93866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setKind(k); 9459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek Tok.setFlag(flags); 9559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 966b1c9708c8fca3786c766b6d1869721656b31322Ted Kremenek Tok.setIdentifierInfo(perID ? PTHMgr.GetIdentifierInfo(perID-1) : 0); 972b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner Tok.setLocation(FileStartLoc.getFileLocWithOffset(FileOffset)); 98866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setLength(Len); 9989d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 100866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 101866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Process the token. 102866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 1035f074266cc59563036c40516c814d63825723e20Ted Kremenek#if 0 1045f074266cc59563036c40516c814d63825723e20Ted Kremenek SourceManager& SM = PP->getSourceManager(); 1055f074266cc59563036c40516c814d63825723e20Ted Kremenek llvm::cerr << SM.getFileEntryForID(FileID)->getName() 1065f074266cc59563036c40516c814d63825723e20Ted Kremenek << ':' << SM.getLogicalLineNumber(Tok.getLocation()) 1075f074266cc59563036c40516c814d63825723e20Ted Kremenek << ':' << SM.getLogicalColumnNumber(Tok.getLocation()) 1085f074266cc59563036c40516c814d63825723e20Ted Kremenek << '\n'; 1095f074266cc59563036c40516c814d63825723e20Ted Kremenek#endif 11089d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 11159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::identifier) { 11259d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek MIOpt.ReadToken(); 11359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return PP->HandleIdentifier(Tok); 11459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek } 11559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 11659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::eof) { 117e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Save the end-of-file token. 118e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek EofToken = Tok; 119e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 120cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek Preprocessor *PPCache = PP; 12159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 12259d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!ParsingPreprocessorDirective); 12359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 12459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 12559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek // FIXME: Issue diagnostics similar to Lexer. 12659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->HandleEndOfFile(Tok, false)) 127d6f53dc4951aace69014619761760addac9e59ecTed Kremenek return; 12859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 129cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek assert(PPCache && "Raw buffer::LexEndOfFile should return a token"); 130cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek return PPCache->Lex(Tok); 131cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek } 132d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 13359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::hash && Tok.isAtStartOfLine()) { 13459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE; 13559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 13659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek PP->HandleDirective(Tok); 137d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 13859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->isCurrentLexer(this)) 13959d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek goto LexNextToken; 140e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 14159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return PP->Lex(Tok); 142e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 143e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 14459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::eom) { 14559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(ParsingPreprocessorDirective); 14659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek ParsingPreprocessorDirective = false; 14759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return; 14859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek } 149274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 15059d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek MIOpt.ReadToken(); 151cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek} 152cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek 153e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// FIXME: We can just grab the last token instead of storing a copy 154e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// into EofToken. 15559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenekvoid PTHLexer::getEOF(Token& Tok) { 156defb7094c835998bb821e894253287625ce8c74dTed Kremenek assert(EofToken.is(tok::eof)); 1570c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek Tok = EofToken; 158274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek} 15917ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek 16017ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenekvoid PTHLexer::DiscardToEndOfLine() { 16117ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek assert(ParsingPreprocessorDirective && ParsingFilename == false && 16217ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek "Must be in a preprocessing directive!"); 1634d35da2e41941965bbee8ed7e8c30e7c21000d71Ted Kremenek 164e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // We assume that if the preprocessor wishes to discard to the end of 165e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // the line that it also means to end the current preprocessor directive. 166e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 167e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 16874c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip tokens by only peeking at their token kind and the flags. 16974c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // We don't need to actually reconstruct full tokens from the token buffer. 17074c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // This saves some copies and it also reduces IdentifierInfo* lookup. 17174c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek const char* p = CurPtr; 17274c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek while (1) { 17374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token kind. Are we at the end of the file? 17474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek tok::TokenKind x = (tok::TokenKind) (uint8_t) *p; 17574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek if (x == tok::eof) break; 176e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 17774c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token flags. Are we at the start of the next line? 17874c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek Token::TokenFlags y = (Token::TokenFlags) (uint8_t) p[1]; 17980d2f3059326f99ebf7c867db1c7f106ec9485f5Ted Kremenek if (y & Token::StartOfLine) break; 18074c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 18174c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip to the next token. 18274c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek p += DISK_TOKEN_SIZE; 18374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek } 18474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 18574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek CurPtr = p; 18617ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek} 1870c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 188268ee7016a2811803989487c0ad3799486092c63Ted Kremenek/// SkipBlock - Used by Preprocessor to skip the current conditional block. 189268ee7016a2811803989487c0ad3799486092c63Ted Kremenekbool PTHLexer::SkipBlock() { 190268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(CurPPCondPtr && "No cached PP conditional information."); 191268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(LastHashTokPtr && "No known '#' token."); 192268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 19341a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* HashEntryI = 0; 194268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t Offset; 195268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t TableIdx; 196268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 197268ee7016a2811803989487c0ad3799486092c63Ted Kremenek do { 19841a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the token offset from the side-table. 199268ee7016a2811803989487c0ad3799486092c63Ted Kremenek Offset = Read32(CurPPCondPtr); 20041a2660377d215d004fe413c03874bd066b5384cTed Kremenek 20141a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the target table index from the side-table. 202268ee7016a2811803989487c0ad3799486092c63Ted Kremenek TableIdx = Read32(CurPPCondPtr); 20341a2660377d215d004fe413c03874bd066b5384cTed Kremenek 20441a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Compute the actual memory address of the '#' token data for this entry. 20541a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = TokBuf + Offset; 20641a2660377d215d004fe413c03874bd066b5384cTed Kremenek 20741a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Optmization: "Sibling jumping". #if...#else...#endif blocks can 20841a2660377d215d004fe413c03874bd066b5384cTed Kremenek // contain nested blocks. In the side-table we can jump over these 20941a2660377d215d004fe413c03874bd066b5384cTed Kremenek // nested blocks instead of doing a linear search if the next "sibling" 21041a2660377d215d004fe413c03874bd066b5384cTed Kremenek // entry is not at a location greater than LastHashTokPtr. 21141a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryI < LastHashTokPtr && TableIdx) { 21241a2660377d215d004fe413c03874bd066b5384cTed Kremenek // In the side-table we are still at an entry for a '#' token that 21341a2660377d215d004fe413c03874bd066b5384cTed Kremenek // is earlier than the last one we saw. Check if the location we would 21441a2660377d215d004fe413c03874bd066b5384cTed Kremenek // stride gets us closer. 21541a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2); 21641a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 21741a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read where we should jump to. 21841a2660377d215d004fe413c03874bd066b5384cTed Kremenek uint32_t TmpOffset = Read32(NextPPCondPtr); 21941a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* HashEntryJ = TokBuf + TmpOffset; 22041a2660377d215d004fe413c03874bd066b5384cTed Kremenek 22141a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryJ <= LastHashTokPtr) { 22241a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Jump directly to the next entry in the side table. 22341a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = HashEntryJ; 22441a2660377d215d004fe413c03874bd066b5384cTed Kremenek Offset = TmpOffset; 22541a2660377d215d004fe413c03874bd066b5384cTed Kremenek TableIdx = Read32(NextPPCondPtr); 22641a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPPCondPtr = NextPPCondPtr; 22741a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 22841a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 229268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 23041a2660377d215d004fe413c03874bd066b5384cTed Kremenek while (HashEntryI < LastHashTokPtr); 23141a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'"); 232268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(TableIdx && "No jumping from #endifs."); 233268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 234268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update our side-table iterator. 235268ee7016a2811803989487c0ad3799486092c63Ted Kremenek const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2); 236268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 237268ee7016a2811803989487c0ad3799486092c63Ted Kremenek CurPPCondPtr = NextPPCondPtr; 238268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 239268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Read where we should jump to. 24041a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = TokBuf + Read32(NextPPCondPtr); 241268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t NextIdx = Read32(NextPPCondPtr); 242268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 243268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // By construction NextIdx will be zero if this is a #endif. This is useful 244268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // to know to obviate lexing another token. 245268ee7016a2811803989487c0ad3799486092c63Ted Kremenek bool isEndif = NextIdx == 0; 246268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 247268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // This case can occur when we see something like this: 248268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 249268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #if ... 250268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // /* a comment or nothing */ 251268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #elif 252268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 253268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // If we are skipping the first #if block it will be the case that CurPtr 254268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // already points 'elif'. Just return. 255268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 25641a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (CurPtr > HashEntryI) { 25741a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE); 258268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 259268ee7016a2811803989487c0ad3799486092c63Ted Kremenek if (isEndif) 260e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE*2; 261268ee7016a2811803989487c0ad3799486092c63Ted Kremenek else 26241a2660377d215d004fe413c03874bd066b5384cTed Kremenek LastHashTokPtr = HashEntryI; 263268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 264268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 265268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 266268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 267268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Otherwise, we need to advance. Update CurPtr to point to the '#' token. 26841a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPtr = HashEntryI; 269268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 270268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update the location of the last observed '#'. This is useful if we 271268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // are skipping multiple blocks. 272268ee7016a2811803989487c0ad3799486092c63Ted Kremenek LastHashTokPtr = CurPtr; 273268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 274e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Skip the '#' token. 275e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(((tok::TokenKind) (unsigned char) *CurPtr) == tok::hash); 276e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE; 277e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 278268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 279e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if (isEndif) { CurPtr += DISK_TOKEN_SIZE*2; } 280268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 281268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 282268ee7016a2811803989487c0ad3799486092c63Ted Kremenek} 283268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 28430a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed KremenekSourceLocation PTHLexer::getSourceLocation() { 28530a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // getLocation is not on the hot path. It is used to get the location of 28630a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // the next token when transitioning back to this lexer when done 28730a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // handling a #included file. Just read the necessary data from the token 28830a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // data buffer to construct the SourceLocation object. 28930a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // NOTE: This is a virtual function; hence it is defined out-of-line. 29059d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek const char* p = CurPtr + (1 + 1 + 3); 29130a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek uint32_t offset = 29230a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek ((uint32_t) ((uint8_t) p[0])) 29330a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 29430a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 29530a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 2962b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner return FileStartLoc.getFileLocWithOffset(offset); 29730a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek} 29830a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek 2995f074266cc59563036c40516c814d63825723e20Ted Kremenek//===----------------------------------------------------------------------===// 3005f074266cc59563036c40516c814d63825723e20Ted Kremenek// getSpelling() - Use cached data in PTH files for getSpelling(). 3015f074266cc59563036c40516c814d63825723e20Ted Kremenek//===----------------------------------------------------------------------===// 3025f074266cc59563036c40516c814d63825723e20Ted Kremenek 3032b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattnerunsigned PTHManager::getSpelling(FileID FID, unsigned FPos, 3042b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner const char *&Buffer) { 3052b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner llvm::DenseMap<FileID, PTHSpellingSearch*>::iterator I =SpellingMap.find(FID); 3065f074266cc59563036c40516c814d63825723e20Ted Kremenek 3075f074266cc59563036c40516c814d63825723e20Ted Kremenek if (I == SpellingMap.end()) 3085f074266cc59563036c40516c814d63825723e20Ted Kremenek return 0; 309f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek 3102b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner return I->second->getSpellingBinarySearch(FPos, Buffer); 3112b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner} 3122b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner 3132b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattnerunsigned PTHManager::getSpelling(SourceLocation Loc, const char *&Buffer) { 3142b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner std::pair<FileID, unsigned> LocInfo = 3152b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner PP->getSourceManager().getDecomposedFileLoc(Loc); 3162b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner return getSpelling(LocInfo.first, LocInfo.second, Buffer); 3175f074266cc59563036c40516c814d63825723e20Ted Kremenek} 3185f074266cc59563036c40516c814d63825723e20Ted Kremenek 3195f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHManager::getSpellingAtPTHOffset(unsigned PTHOffset, 3205f074266cc59563036c40516c814d63825723e20Ted Kremenek const char *& Buffer) { 3215f074266cc59563036c40516c814d63825723e20Ted Kremenek 32232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* p = Buf->getBufferStart() + PTHOffset; 32332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek assert(p < Buf->getBufferEnd()); 32432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 32532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // The string is prefixed by 16 bits for its length, followed by the string 32632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // itself. 32732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek unsigned len = ((unsigned) ((uint8_t) p[0])) 32832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((unsigned) ((uint8_t) p[1])) << 8); 32932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 33032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek Buffer = p + 2; 33132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek return len; 33232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek} 33332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 3345f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHSpellingSearch::getSpellingLinearSearch(unsigned fpos, 3355f074266cc59563036c40516c814d63825723e20Ted Kremenek const char *&Buffer) { 3365f074266cc59563036c40516c814d63825723e20Ted Kremenek const char* p = LinearItr; 33732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek unsigned len = 0; 3385f074266cc59563036c40516c814d63825723e20Ted Kremenek 339f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek if (p == TableEnd) 3405f074266cc59563036c40516c814d63825723e20Ted Kremenek return getSpellingBinarySearch(fpos, Buffer); 3415f074266cc59563036c40516c814d63825723e20Ted Kremenek 3425f074266cc59563036c40516c814d63825723e20Ted Kremenek do { 34332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek uint32_t TokOffset = 34432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek ((uint32_t) ((uint8_t) p[0])) 34532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 34632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 34732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 34832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 34932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (TokOffset > fpos) 3505f074266cc59563036c40516c814d63825723e20Ted Kremenek return getSpellingBinarySearch(fpos, Buffer); 35132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 35232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // Did we find a matching token offset for this spelling? 35332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (TokOffset == fpos) { 35432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek uint32_t SpellingPTHOffset = 35532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek ((uint32_t) ((uint8_t) p[4])) 35632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[5])) << 8) 35732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[6])) << 16) 35832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[7])) << 24); 35932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 360f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek p += SpellingEntrySize; 3615f074266cc59563036c40516c814d63825723e20Ted Kremenek len = PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer); 36232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek break; 36332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek } 36432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 36532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // No match. Keep on looking. 366f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek p += SpellingEntrySize; 36732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek } 368f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek while (p != TableEnd); 36932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 3705f074266cc59563036c40516c814d63825723e20Ted Kremenek LinearItr = p; 37132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek return len; 372b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek} 373b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 3745f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHSpellingSearch::getSpellingBinarySearch(unsigned fpos, 3755f074266cc59563036c40516c814d63825723e20Ted Kremenek const char *& Buffer) { 3765f074266cc59563036c40516c814d63825723e20Ted Kremenek 377f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek assert((TableEnd - TableBeg) % SpellingEntrySize == 0); 378f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek 379f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek if (TableEnd == TableBeg) 380f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek return 0; 381f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek 382f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek assert(TableEnd > TableBeg); 3835f074266cc59563036c40516c814d63825723e20Ted Kremenek 3845f074266cc59563036c40516c814d63825723e20Ted Kremenek unsigned min = 0; 3855f074266cc59563036c40516c814d63825723e20Ted Kremenek const char* tb = TableBeg; 386f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek unsigned max = NumSpellings; 3875f074266cc59563036c40516c814d63825723e20Ted Kremenek 388f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek do { 3895f074266cc59563036c40516c814d63825723e20Ted Kremenek unsigned i = (max - min) / 2 + min; 3905f074266cc59563036c40516c814d63825723e20Ted Kremenek const char* p = tb + (i * SpellingEntrySize); 3915f074266cc59563036c40516c814d63825723e20Ted Kremenek 3925f074266cc59563036c40516c814d63825723e20Ted Kremenek uint32_t TokOffset = 3935f074266cc59563036c40516c814d63825723e20Ted Kremenek ((uint32_t) ((uint8_t) p[0])) 3945f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 3955f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 3965f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 3975f074266cc59563036c40516c814d63825723e20Ted Kremenek 3985f074266cc59563036c40516c814d63825723e20Ted Kremenek if (TokOffset > fpos) { 3995f074266cc59563036c40516c814d63825723e20Ted Kremenek max = i; 400f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek assert(!(max == min) || (min == i)); 4015f074266cc59563036c40516c814d63825723e20Ted Kremenek continue; 4025f074266cc59563036c40516c814d63825723e20Ted Kremenek } 4035f074266cc59563036c40516c814d63825723e20Ted Kremenek 4045f074266cc59563036c40516c814d63825723e20Ted Kremenek if (TokOffset < fpos) { 4057bd88aa620406ab99547169b973de085785a0ca2Ted Kremenek if (i == min) 4067bd88aa620406ab99547169b973de085785a0ca2Ted Kremenek break; 4077bd88aa620406ab99547169b973de085785a0ca2Ted Kremenek 4085f074266cc59563036c40516c814d63825723e20Ted Kremenek min = i; 4095f074266cc59563036c40516c814d63825723e20Ted Kremenek continue; 4105f074266cc59563036c40516c814d63825723e20Ted Kremenek } 4115f074266cc59563036c40516c814d63825723e20Ted Kremenek 4125f074266cc59563036c40516c814d63825723e20Ted Kremenek uint32_t SpellingPTHOffset = 4135f074266cc59563036c40516c814d63825723e20Ted Kremenek ((uint32_t) ((uint8_t) p[4])) 4145f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[5])) << 8) 4155f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[6])) << 16) 4165f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[7])) << 24); 4175f074266cc59563036c40516c814d63825723e20Ted Kremenek 4185f074266cc59563036c40516c814d63825723e20Ted Kremenek return PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer); 4195f074266cc59563036c40516c814d63825723e20Ted Kremenek } 420f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek while (min != max); 4215f074266cc59563036c40516c814d63825723e20Ted Kremenek 4225f074266cc59563036c40516c814d63825723e20Ted Kremenek return 0; 4235f074266cc59563036c40516c814d63825723e20Ted Kremenek} 4245f074266cc59563036c40516c814d63825723e20Ted Kremenek 4252b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattnerunsigned PTHLexer::getSpelling(SourceLocation Loc, const char *&Buffer) { 4262b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner SourceManager &SM = PP->getSourceManager(); 4272b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner Loc = SM.getSpellingLoc(Loc); 4282b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner std::pair<FileID, unsigned> LocInfo = SM.getDecomposedFileLoc(Loc); 4292b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner 4302b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID FID = LocInfo.first; 4312b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner unsigned FPos = LocInfo.second; 4325f074266cc59563036c40516c814d63825723e20Ted Kremenek 4332b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner if (FID == getFileID()) 4342b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner return MySpellingSrch.getSpellingLinearSearch(FPos, Buffer); 4352b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner return PTHMgr.getSpelling(FID, FPos, Buffer); 4365f074266cc59563036c40516c814d63825723e20Ted Kremenek} 4375f074266cc59563036c40516c814d63825723e20Ted Kremenek 4380c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 4390c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek// Internal Data Structures for PTH file lookup and resolving identifiers. 4400c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 4410c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4420c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4430c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// PTHFileLookup - This internal data structure is used by the PTHManager 4440c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// to map from FileEntry objects managed by FileManager to offsets within 4450c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// the PTH file. 4460c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremeneknamespace { 4470c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekclass VISIBILITY_HIDDEN PTHFileLookup { 4480c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 4490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek class Val { 450fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t TokenOff; 451fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t PPCondOff; 452b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t SpellingOff; 4530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4540c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek public: 455fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Val() : TokenOff(~0) {} 456b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek Val(uint32_t toff, uint32_t poff, uint32_t soff) 457b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek : TokenOff(toff), PPCondOff(poff), SpellingOff(soff) {} 4580c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 459fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t getTokenOffset() const { 460fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 461fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek return TokenOff; 4620c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4630c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 464b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t getPPCondOffset() const { 465fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 466fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek return PPCondOff; 467fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 468fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 469b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t getSpellingOffset() const { 470b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 471b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek return SpellingOff; 472b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek } 473b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 474fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek bool isValid() const { return TokenOff != ~((uint32_t)0); } 4750c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek }; 4760c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4770c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekprivate: 4780c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::StringMap<Val> FileMap; 4790c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4800c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 4810c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek PTHFileLookup() {}; 4820c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4830c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek Val Lookup(const FileEntry* FE) { 4840c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* s = FE->getName(); 4850c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek unsigned size = strlen(s); 4860c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return FileMap.GetOrCreateValue(s, s+size).getValue(); 4870c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4880c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4890c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek void ReadTable(const char* D) { 4900c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek uint32_t N = Read32(D); // Read the length of the table. 4910c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4920c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek for ( ; N > 0; --N) { // The rest of the data is the table itself. 4930c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek uint32_t len = Read32(D); 4940c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* s = D; 4950c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek D += len; 496b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 497fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t TokenOff = Read32(D); 498b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t PPCondOff = Read32(D); 499b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t SpellingOff = Read32(D); 500b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 501b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek FileMap.GetOrCreateValue(s, s+len).getValue() = 502b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek Val(TokenOff, PPCondOff, SpellingOff); 5030c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5040c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5050c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek}; 5060c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} // end anonymous namespace 5070c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5080c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 5090c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek// PTHManager methods. 5100c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 5110c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5120c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup, 513cf58e6249c6b018508e34bcb76202caa42d2451aTed Kremenek const char* idDataTable, IdentifierInfo** perIDCache, 51472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* sortedIdTable, unsigned numIds) 5156183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup), 51672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IdDataTable(idDataTable), SortedIdTable(sortedIdTable), 51772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek NumIds(numIds), PP(0) {} 5180c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5190c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::~PTHManager() { 5200c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete Buf; 5210c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete (PTHFileLookup*) FileLookup; 5220e50b6e7c104d00614baa3d80df62f1630a94d9cTed Kremenek free(PerIDCache); 5230c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 5240c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 52572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted KremenekPTHManager* PTHManager::Create(const std::string& file) { 5260c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5270c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Memory map the PTH file. 5280c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::OwningPtr<llvm::MemoryBuffer> 5290c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek File(llvm::MemoryBuffer::getFile(file.c_str())); 5300c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5310c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!File) 5320c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 5330c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5340c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the buffer ranges and check if there are at least three 32-bit 5350c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // words at the end of the file. 5360c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* BufBeg = File->getBufferStart(); 5370c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* BufEnd = File->getBufferEnd(); 5380c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5390c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if(!(BufEnd > BufBeg + sizeof(uint32_t)*3)) { 5400c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 5410c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 5420c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5430c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5440c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Compute the address of the index table at the end of the PTH file. 5450c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // This table contains the offset of the file lookup table, the 5460c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // persistent ID -> identifer data table. 547293b4af04ca37576d4b228adf09acd6cee3ddb16Ted Kremenek // FIXME: We should just embed this offset in the PTH file. 548293b4af04ca37576d4b228adf09acd6cee3ddb16Ted Kremenek const char* EndTable = BufEnd - sizeof(uint32_t)*4; 5490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5500c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Construct the file lookup table. This will be used for mapping from 5510c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // FileEntry*'s to cached tokens. 552293b4af04ca37576d4b228adf09acd6cee3ddb16Ted Kremenek const char* FileTableOffset = EndTable + sizeof(uint32_t)*3; 5530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* FileTable = BufBeg + Read32(FileTableOffset); 5540c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5550c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!(FileTable > BufBeg && FileTable < BufEnd)) { 5560c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 5570c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 5580c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5590c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5600c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::OwningPtr<PTHFileLookup> FL(new PTHFileLookup()); 5610c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek FL->ReadTable(FileTable); 5620c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5630c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the location of the table mapping from persistent ids to the 5640c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // data needed to reconstruct identifiers. 5650c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IDTableOffset = EndTable + sizeof(uint32_t)*1; 5660c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IData = BufBeg + Read32(IDTableOffset); 5670c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!(IData > BufBeg && IData < BufEnd)) { 5680c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 5690c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 5700c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5710c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 57272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Get the location of the lexigraphically-sorted table of persistent IDs. 57372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* SortedIdTableOffset = EndTable + sizeof(uint32_t)*2; 57472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* SortedIdTable = BufBeg + Read32(SortedIdTableOffset); 57572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (!(SortedIdTable > BufBeg && SortedIdTable < BufEnd)) { 57672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek assert(false && "Invalid PTH file."); 57772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return 0; // FIXME: Proper error diagnostic? 57872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek } 57972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 5806183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Get the number of IdentifierInfos and pre-allocate the identifier cache. 5816183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek uint32_t NumIds = Read32(IData); 5826183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 5836183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Pre-allocate the peristent ID -> IdentifierInfo* cache. We use calloc() 5846183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // so that we in the best case only zero out memory once when the OS returns 5856183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // us new pages. 5866183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek IdentifierInfo** PerIDCache = 5876183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek (IdentifierInfo**) calloc(NumIds, sizeof(*PerIDCache)); 5886183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 5896183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek if (!PerIDCache) { 5906183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek assert(false && "Could not allocate Persistent ID cache."); 5916183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek return 0; 5926183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek } 5936183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 59472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Create the new PTHManager. 59572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return new PTHManager(File.take(), FL.take(), IData, PerIDCache, 59672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek SortedIdTable, NumIds); 5970c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 5980c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 599866bdf74547efe32c320554837ffce00fcc084feTed KremenekIdentifierInfo* PTHManager::GetIdentifierInfo(unsigned persistentID) { 600866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 6010c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Check if the IdentifierInfo has already been resolved. 60272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IdentifierInfo* II = PerIDCache[persistentID]; 6030c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (II) return II; 6040c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6050c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Look in the PTH file for the string data for the IdentifierInfo object. 6060c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* TableEntry = IdDataTable + sizeof(uint32_t) * persistentID; 6070c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IDData = Buf->getBufferStart() + Read32(TableEntry); 6080c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(IDData < Buf->getBufferEnd()); 6090c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 61072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Allocate the object. 61172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek std::pair<IdentifierInfo,const char*> *Mem = 61272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek Alloc.Allocate<std::pair<IdentifierInfo,const char*> >(); 61372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 61472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek Mem->second = IDData; 61572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek II = new ((void*) Mem) IdentifierInfo(true); 6160c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 61772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Store the new IdentifierInfo in the cache. 61872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek PerIDCache[persistentID] = II; 6190c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return II; 6200c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 6210c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 62272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted KremenekIdentifierInfo* PTHManager::get(const char *NameStart, const char *NameEnd) { 62372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned min = 0; 62472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned max = NumIds; 62572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned len = NameEnd - NameStart; 62672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 62772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek do { 62872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned i = (max - min) / 2 + min; 62972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* p = SortedIdTable + (i * 4); 63072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 63172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Read the persistentID. 63272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned perID = 63372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek ((unsigned) ((uint8_t) p[0])) 63472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek | (((unsigned) ((uint8_t) p[1])) << 8) 63572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek | (((unsigned) ((uint8_t) p[2])) << 16) 63672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek | (((unsigned) ((uint8_t) p[3])) << 24); 63772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 63872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Get the IdentifierInfo. 63972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IdentifierInfo* II = GetIdentifierInfo(perID); 64072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 64172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // First compare the lengths. 64272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned IILen = II->getLength(); 64372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (len < IILen) goto IsLess; 64472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (len > IILen) goto IsGreater; 64572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 64672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Now compare the strings! 64772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek { 64872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek signed comp = strncmp(NameStart, II->getName(), len); 64972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (comp < 0) goto IsLess; 65072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (comp > 0) goto IsGreater; 65172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek } 65272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // We found a match! 65372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return II; 65472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 65572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IsGreater: 65672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (i == min) break; 65772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek min = i; 65872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek continue; 65972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 66072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IsLess: 66172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek max = i; 66272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek assert(!(max == min) || (min == i)); 66372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek } 664e1deaac73379eeb9864215c7979f6005ebd74cefTed Kremenek while (min != max); 66572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 66672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return 0; 66772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek} 66872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 66972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 6702b2453a7d8fe732561795431f39ceb2b2a832d84Chris LattnerPTHLexer* PTHManager::CreateLexer(FileID FID, const FileEntry* FE) { 6710c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!FE) 6720c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 6730c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6740c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Lookup the FileEntry object in our file lookup data structure. It will 6750c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // return a variant that indicates whether or not there is an offset within 6760c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // the PTH file that contains cached tokens. 6772b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner PTHFileLookup::Val FileData = ((PTHFileLookup*)FileLookup)->Lookup(FE); 6780c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 679fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek if (!FileData.isValid()) // No tokens available. 6800c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 6810c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6820c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Compute the offset of the token data within the buffer. 683fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek const char* data = Buf->getBufferStart() + FileData.getTokenOffset(); 684268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 685268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Get the location of pp-conditional table. 686b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek const char* ppcond = Buf->getBufferStart() + FileData.getPPCondOffset(); 687b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t len = Read32(ppcond); 688268ee7016a2811803989487c0ad3799486092c63Ted Kremenek if (len == 0) ppcond = 0; 68932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 69032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // Get the location of the spelling table. 69132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* spellingTable = Buf->getBufferStart() + 69232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek FileData.getSpellingOffset(); 69332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 69432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek len = Read32(spellingTable); 69532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (len == 0) spellingTable = 0; 696b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 6970c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(data < Buf->getBufferEnd()); 6985f074266cc59563036c40516c814d63825723e20Ted Kremenek 6995f074266cc59563036c40516c814d63825723e20Ted Kremenek // Create the SpellingSearch object for this FileID. 7005f074266cc59563036c40516c814d63825723e20Ted Kremenek PTHSpellingSearch* ss = new PTHSpellingSearch(*this, len, spellingTable); 7012b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner SpellingMap[FID] = ss; 7025f074266cc59563036c40516c814d63825723e20Ted Kremenek 70372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek assert(PP && "No preprocessor set yet!"); 7042b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner return new PTHLexer(*PP, FID, data, ppcond, *ss, *this); 7050c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 706