PTHLexer.cpp revision 72b1b15ee88aac0a63e2c1dc53fe22f5ab297b20
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" 260c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 27274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenekusing namespace clang; 28274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 2918d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek#define DISK_TOKEN_SIZE (1+1+3+4+2) 30268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 31e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 32e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// Utility methods for reading from the mmap'ed PTH file. 33e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 34e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 35e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenekstatic inline uint8_t Read8(const char*& data) { 36e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek return (uint8_t) *(data++); 37e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek} 38e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 39e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenekstatic inline uint32_t Read32(const char*& data) { 40e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek uint32_t V = (uint32_t) Read8(data); 41e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek V |= (((uint32_t) Read8(data)) << 8); 42e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek V |= (((uint32_t) Read8(data)) << 16); 43e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek V |= (((uint32_t) Read8(data)) << 24); 44e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek return V; 45e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek} 46e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 47e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 48e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// PTHLexer methods. 49e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek//===----------------------------------------------------------------------===// 50e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 510c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D, 5232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* ppcond, 535f074266cc59563036c40516c814d63825723e20Ted Kremenek PTHSpellingSearch& mySpellingSrch, 5432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek PTHManager& PM) 55cd223444d1680290efe11da657faafc9a1ac14baTed Kremenek : PreprocessorLexer(&pp, fileloc), TokBuf(D), CurPtr(D), LastHashTokPtr(0), 565f074266cc59563036c40516c814d63825723e20Ted Kremenek PPCond(ppcond), CurPPCondPtr(ppcond), MySpellingSrch(mySpellingSrch), 575f074266cc59563036c40516c814d63825723e20Ted Kremenek PTHMgr(PM) 585f074266cc59563036c40516c814d63825723e20Ted Kremenek{ 595f074266cc59563036c40516c814d63825723e20Ted Kremenek FileID = fileloc.getFileID(); 605f074266cc59563036c40516c814d63825723e20Ted Kremenek} 61274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 62e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenekvoid PTHLexer::Lex(Token& Tok) { 63e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted KremenekLexNextToken: 64866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 65866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 66866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Read the raw token data. 67866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 68e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 69866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Shadow CurPtr into an automatic variable. 70866bdf74547efe32c320554837ffce00fcc084feTed Kremenek const unsigned char *CurPtrShadow = (const unsigned char*) CurPtr; 71866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 72866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Read in the data for the token. 14 bytes in total. 73866bdf74547efe32c320554837ffce00fcc084feTed Kremenek tok::TokenKind k = (tok::TokenKind) CurPtrShadow[0]; 74866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Token::TokenFlags flags = (Token::TokenFlags) CurPtrShadow[1]; 75866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 766b1c9708c8fca3786c766b6d1869721656b31322Ted Kremenek uint32_t perID = ((uint32_t) CurPtrShadow[2]) 77866bdf74547efe32c320554837ffce00fcc084feTed Kremenek | (((uint32_t) CurPtrShadow[3]) << 8) 7818d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[4]) << 16); 790c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 8018d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek uint32_t FileOffset = ((uint32_t) CurPtrShadow[5]) 8118d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[6]) << 8) 8218d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[7]) << 16) 8318d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[8]) << 24); 84e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 8518d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek uint32_t Len = ((uint32_t) CurPtrShadow[9]) 8618d9afb815bd8aff885dd64c5078760b3398d7beTed Kremenek | (((uint32_t) CurPtrShadow[10]) << 8); 87e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 88866bdf74547efe32c320554837ffce00fcc084feTed Kremenek CurPtr = (const char*) (CurPtrShadow + DISK_TOKEN_SIZE); 89e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 90866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 91866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Construct the token itself. 92866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 93e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 94866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.startToken(); 95866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setKind(k); 9659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek Tok.setFlag(flags); 9759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 986b1c9708c8fca3786c766b6d1869721656b31322Ted Kremenek Tok.setIdentifierInfo(perID ? PTHMgr.GetIdentifierInfo(perID-1) : 0); 99866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setLocation(SourceLocation::getFileLoc(FileID, FileOffset)); 100866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setLength(Len); 10189d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 102866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 103866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Process the token. 104866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 1055f074266cc59563036c40516c814d63825723e20Ted Kremenek#if 0 1065f074266cc59563036c40516c814d63825723e20Ted Kremenek SourceManager& SM = PP->getSourceManager(); 1075f074266cc59563036c40516c814d63825723e20Ted Kremenek llvm::cerr << SM.getFileEntryForID(FileID)->getName() 1085f074266cc59563036c40516c814d63825723e20Ted Kremenek << ':' << SM.getLogicalLineNumber(Tok.getLocation()) 1095f074266cc59563036c40516c814d63825723e20Ted Kremenek << ':' << SM.getLogicalColumnNumber(Tok.getLocation()) 1105f074266cc59563036c40516c814d63825723e20Ted Kremenek << '\n'; 1115f074266cc59563036c40516c814d63825723e20Ted Kremenek#endif 11289d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 11359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::identifier) { 11459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek MIOpt.ReadToken(); 11559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return PP->HandleIdentifier(Tok); 11659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek } 11759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 11859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::eof) { 119e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Save the end-of-file token. 120e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek EofToken = Tok; 121e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 122cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek Preprocessor *PPCache = PP; 12359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 12459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!ParsingPreprocessorDirective); 12559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 12659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 12759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek // FIXME: Issue diagnostics similar to Lexer. 12859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->HandleEndOfFile(Tok, false)) 129d6f53dc4951aace69014619761760addac9e59ecTed Kremenek return; 13059d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 131cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek assert(PPCache && "Raw buffer::LexEndOfFile should return a token"); 132cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek return PPCache->Lex(Tok); 133cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek } 134d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 13559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::hash && Tok.isAtStartOfLine()) { 13659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE; 13759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 13859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek PP->HandleDirective(Tok); 139d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 14059d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->isCurrentLexer(this)) 14159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek goto LexNextToken; 142e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 14359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return PP->Lex(Tok); 144e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 145e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 14659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::eom) { 14759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(ParsingPreprocessorDirective); 14859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek ParsingPreprocessorDirective = false; 14959d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return; 15059d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek } 151274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 15259d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek MIOpt.ReadToken(); 153cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek} 154cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek 155e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// FIXME: We can just grab the last token instead of storing a copy 156e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// into EofToken. 15759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenekvoid PTHLexer::getEOF(Token& Tok) { 158defb7094c835998bb821e894253287625ce8c74dTed Kremenek assert(EofToken.is(tok::eof)); 1590c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek Tok = EofToken; 160274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek} 16117ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek 16217ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenekvoid PTHLexer::DiscardToEndOfLine() { 16317ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek assert(ParsingPreprocessorDirective && ParsingFilename == false && 16417ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek "Must be in a preprocessing directive!"); 1654d35da2e41941965bbee8ed7e8c30e7c21000d71Ted Kremenek 166e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // We assume that if the preprocessor wishes to discard to the end of 167e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // the line that it also means to end the current preprocessor directive. 168e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 169e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 17074c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip tokens by only peeking at their token kind and the flags. 17174c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // We don't need to actually reconstruct full tokens from the token buffer. 17274c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // This saves some copies and it also reduces IdentifierInfo* lookup. 17374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek const char* p = CurPtr; 17474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek while (1) { 17574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token kind. Are we at the end of the file? 17674c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek tok::TokenKind x = (tok::TokenKind) (uint8_t) *p; 17774c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek if (x == tok::eof) break; 178e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 17974c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token flags. Are we at the start of the next line? 18074c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek Token::TokenFlags y = (Token::TokenFlags) (uint8_t) p[1]; 18180d2f3059326f99ebf7c867db1c7f106ec9485f5Ted Kremenek if (y & Token::StartOfLine) break; 18274c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 18374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip to the next token. 18474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek p += DISK_TOKEN_SIZE; 18574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek } 18674c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 18774c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek CurPtr = p; 18817ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek} 1890c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 190268ee7016a2811803989487c0ad3799486092c63Ted Kremenek/// SkipBlock - Used by Preprocessor to skip the current conditional block. 191268ee7016a2811803989487c0ad3799486092c63Ted Kremenekbool PTHLexer::SkipBlock() { 192268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(CurPPCondPtr && "No cached PP conditional information."); 193268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(LastHashTokPtr && "No known '#' token."); 194268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 19541a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* HashEntryI = 0; 196268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t Offset; 197268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t TableIdx; 198268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 199268ee7016a2811803989487c0ad3799486092c63Ted Kremenek do { 20041a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the token offset from the side-table. 201268ee7016a2811803989487c0ad3799486092c63Ted Kremenek Offset = Read32(CurPPCondPtr); 20241a2660377d215d004fe413c03874bd066b5384cTed Kremenek 20341a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the target table index from the side-table. 204268ee7016a2811803989487c0ad3799486092c63Ted Kremenek TableIdx = Read32(CurPPCondPtr); 20541a2660377d215d004fe413c03874bd066b5384cTed Kremenek 20641a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Compute the actual memory address of the '#' token data for this entry. 20741a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = TokBuf + Offset; 20841a2660377d215d004fe413c03874bd066b5384cTed Kremenek 20941a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Optmization: "Sibling jumping". #if...#else...#endif blocks can 21041a2660377d215d004fe413c03874bd066b5384cTed Kremenek // contain nested blocks. In the side-table we can jump over these 21141a2660377d215d004fe413c03874bd066b5384cTed Kremenek // nested blocks instead of doing a linear search if the next "sibling" 21241a2660377d215d004fe413c03874bd066b5384cTed Kremenek // entry is not at a location greater than LastHashTokPtr. 21341a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryI < LastHashTokPtr && TableIdx) { 21441a2660377d215d004fe413c03874bd066b5384cTed Kremenek // In the side-table we are still at an entry for a '#' token that 21541a2660377d215d004fe413c03874bd066b5384cTed Kremenek // is earlier than the last one we saw. Check if the location we would 21641a2660377d215d004fe413c03874bd066b5384cTed Kremenek // stride gets us closer. 21741a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2); 21841a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 21941a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read where we should jump to. 22041a2660377d215d004fe413c03874bd066b5384cTed Kremenek uint32_t TmpOffset = Read32(NextPPCondPtr); 22141a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* HashEntryJ = TokBuf + TmpOffset; 22241a2660377d215d004fe413c03874bd066b5384cTed Kremenek 22341a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryJ <= LastHashTokPtr) { 22441a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Jump directly to the next entry in the side table. 22541a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = HashEntryJ; 22641a2660377d215d004fe413c03874bd066b5384cTed Kremenek Offset = TmpOffset; 22741a2660377d215d004fe413c03874bd066b5384cTed Kremenek TableIdx = Read32(NextPPCondPtr); 22841a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPPCondPtr = NextPPCondPtr; 22941a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 23041a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 231268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 23241a2660377d215d004fe413c03874bd066b5384cTed Kremenek while (HashEntryI < LastHashTokPtr); 23341a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'"); 234268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(TableIdx && "No jumping from #endifs."); 235268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 236268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update our side-table iterator. 237268ee7016a2811803989487c0ad3799486092c63Ted Kremenek const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2); 238268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 239268ee7016a2811803989487c0ad3799486092c63Ted Kremenek CurPPCondPtr = NextPPCondPtr; 240268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 241268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Read where we should jump to. 24241a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = TokBuf + Read32(NextPPCondPtr); 243268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t NextIdx = Read32(NextPPCondPtr); 244268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 245268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // By construction NextIdx will be zero if this is a #endif. This is useful 246268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // to know to obviate lexing another token. 247268ee7016a2811803989487c0ad3799486092c63Ted Kremenek bool isEndif = NextIdx == 0; 248268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 249268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // This case can occur when we see something like this: 250268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 251268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #if ... 252268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // /* a comment or nothing */ 253268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #elif 254268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 255268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // If we are skipping the first #if block it will be the case that CurPtr 256268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // already points 'elif'. Just return. 257268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 25841a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (CurPtr > HashEntryI) { 25941a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE); 260268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 261268ee7016a2811803989487c0ad3799486092c63Ted Kremenek if (isEndif) 262e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE*2; 263268ee7016a2811803989487c0ad3799486092c63Ted Kremenek else 26441a2660377d215d004fe413c03874bd066b5384cTed Kremenek LastHashTokPtr = HashEntryI; 265268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 266268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 267268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 268268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 269268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Otherwise, we need to advance. Update CurPtr to point to the '#' token. 27041a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPtr = HashEntryI; 271268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 272268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update the location of the last observed '#'. This is useful if we 273268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // are skipping multiple blocks. 274268ee7016a2811803989487c0ad3799486092c63Ted Kremenek LastHashTokPtr = CurPtr; 275268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 276e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Skip the '#' token. 277e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(((tok::TokenKind) (unsigned char) *CurPtr) == tok::hash); 278e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE; 279e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 280268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 281e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if (isEndif) { CurPtr += DISK_TOKEN_SIZE*2; } 282268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 283268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 284268ee7016a2811803989487c0ad3799486092c63Ted Kremenek} 285268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 28630a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed KremenekSourceLocation PTHLexer::getSourceLocation() { 28730a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // getLocation is not on the hot path. It is used to get the location of 28830a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // the next token when transitioning back to this lexer when done 28930a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // handling a #included file. Just read the necessary data from the token 29030a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // data buffer to construct the SourceLocation object. 29130a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // NOTE: This is a virtual function; hence it is defined out-of-line. 29259d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek const char* p = CurPtr + (1 + 1 + 3); 29330a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek uint32_t offset = 29430a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek ((uint32_t) ((uint8_t) p[0])) 29530a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 29630a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 29730a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 29830a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek return SourceLocation::getFileLoc(FileID, offset); 29930a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek} 30030a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek 3015f074266cc59563036c40516c814d63825723e20Ted Kremenek//===----------------------------------------------------------------------===// 3025f074266cc59563036c40516c814d63825723e20Ted Kremenek// getSpelling() - Use cached data in PTH files for getSpelling(). 3035f074266cc59563036c40516c814d63825723e20Ted Kremenek//===----------------------------------------------------------------------===// 3045f074266cc59563036c40516c814d63825723e20Ted Kremenek 3055f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHManager::getSpelling(unsigned FileID, unsigned fpos, 3065f074266cc59563036c40516c814d63825723e20Ted Kremenek const char *& Buffer) { 3075f074266cc59563036c40516c814d63825723e20Ted Kremenek 3085f074266cc59563036c40516c814d63825723e20Ted Kremenek llvm::DenseMap<unsigned,PTHSpellingSearch*>::iterator I = 3095f074266cc59563036c40516c814d63825723e20Ted Kremenek SpellingMap.find(FileID); 3105f074266cc59563036c40516c814d63825723e20Ted Kremenek 3115f074266cc59563036c40516c814d63825723e20Ted Kremenek if (I == SpellingMap.end()) 3125f074266cc59563036c40516c814d63825723e20Ted Kremenek return 0; 313f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek 314f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek return I->second->getSpellingBinarySearch(fpos, Buffer); 3155f074266cc59563036c40516c814d63825723e20Ted Kremenek} 3165f074266cc59563036c40516c814d63825723e20Ted Kremenek 3175f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHManager::getSpellingAtPTHOffset(unsigned PTHOffset, 3185f074266cc59563036c40516c814d63825723e20Ted Kremenek const char *& Buffer) { 3195f074266cc59563036c40516c814d63825723e20Ted Kremenek 32032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* p = Buf->getBufferStart() + PTHOffset; 32132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek assert(p < Buf->getBufferEnd()); 32232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 32332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // The string is prefixed by 16 bits for its length, followed by the string 32432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // itself. 32532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek unsigned len = ((unsigned) ((uint8_t) p[0])) 32632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((unsigned) ((uint8_t) p[1])) << 8); 32732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 32832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek Buffer = p + 2; 32932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek return len; 33032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek} 33132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 3325f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHSpellingSearch::getSpellingLinearSearch(unsigned fpos, 3335f074266cc59563036c40516c814d63825723e20Ted Kremenek const char *&Buffer) { 3345f074266cc59563036c40516c814d63825723e20Ted Kremenek const char* p = LinearItr; 33532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek unsigned len = 0; 3365f074266cc59563036c40516c814d63825723e20Ted Kremenek 337f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek if (p == TableEnd) 3385f074266cc59563036c40516c814d63825723e20Ted Kremenek return getSpellingBinarySearch(fpos, Buffer); 3395f074266cc59563036c40516c814d63825723e20Ted Kremenek 3405f074266cc59563036c40516c814d63825723e20Ted Kremenek do { 34132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek uint32_t TokOffset = 34232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek ((uint32_t) ((uint8_t) p[0])) 34332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 34432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 34532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 34632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 34732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (TokOffset > fpos) 3485f074266cc59563036c40516c814d63825723e20Ted Kremenek return getSpellingBinarySearch(fpos, Buffer); 34932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 35032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // Did we find a matching token offset for this spelling? 35132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (TokOffset == fpos) { 35232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek uint32_t SpellingPTHOffset = 35332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek ((uint32_t) ((uint8_t) p[4])) 35432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[5])) << 8) 35532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[6])) << 16) 35632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[7])) << 24); 35732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 358f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek p += SpellingEntrySize; 3595f074266cc59563036c40516c814d63825723e20Ted Kremenek len = PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer); 36032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek break; 36132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek } 36232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 36332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // No match. Keep on looking. 364f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek p += SpellingEntrySize; 36532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek } 366f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek while (p != TableEnd); 36732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 3685f074266cc59563036c40516c814d63825723e20Ted Kremenek LinearItr = p; 36932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek return len; 370b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek} 371b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 3725f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHSpellingSearch::getSpellingBinarySearch(unsigned fpos, 3735f074266cc59563036c40516c814d63825723e20Ted Kremenek const char *& Buffer) { 3745f074266cc59563036c40516c814d63825723e20Ted Kremenek 375f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek assert((TableEnd - TableBeg) % SpellingEntrySize == 0); 376f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek 377f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek if (TableEnd == TableBeg) 378f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek return 0; 379f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek 380f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek assert(TableEnd > TableBeg); 3815f074266cc59563036c40516c814d63825723e20Ted Kremenek 3825f074266cc59563036c40516c814d63825723e20Ted Kremenek unsigned min = 0; 3835f074266cc59563036c40516c814d63825723e20Ted Kremenek const char* tb = TableBeg; 384f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek unsigned max = NumSpellings; 3855f074266cc59563036c40516c814d63825723e20Ted Kremenek 386f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek do { 3875f074266cc59563036c40516c814d63825723e20Ted Kremenek unsigned i = (max - min) / 2 + min; 3885f074266cc59563036c40516c814d63825723e20Ted Kremenek const char* p = tb + (i * SpellingEntrySize); 3895f074266cc59563036c40516c814d63825723e20Ted Kremenek 3905f074266cc59563036c40516c814d63825723e20Ted Kremenek uint32_t TokOffset = 3915f074266cc59563036c40516c814d63825723e20Ted Kremenek ((uint32_t) ((uint8_t) p[0])) 3925f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 3935f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 3945f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 3955f074266cc59563036c40516c814d63825723e20Ted Kremenek 3965f074266cc59563036c40516c814d63825723e20Ted Kremenek if (TokOffset > fpos) { 3975f074266cc59563036c40516c814d63825723e20Ted Kremenek max = i; 398f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek assert(!(max == min) || (min == i)); 3995f074266cc59563036c40516c814d63825723e20Ted Kremenek continue; 4005f074266cc59563036c40516c814d63825723e20Ted Kremenek } 4015f074266cc59563036c40516c814d63825723e20Ted Kremenek 4025f074266cc59563036c40516c814d63825723e20Ted Kremenek if (TokOffset < fpos) { 4037bd88aa620406ab99547169b973de085785a0ca2Ted Kremenek if (i == min) 4047bd88aa620406ab99547169b973de085785a0ca2Ted Kremenek break; 4057bd88aa620406ab99547169b973de085785a0ca2Ted Kremenek 4065f074266cc59563036c40516c814d63825723e20Ted Kremenek min = i; 4075f074266cc59563036c40516c814d63825723e20Ted Kremenek continue; 4085f074266cc59563036c40516c814d63825723e20Ted Kremenek } 4095f074266cc59563036c40516c814d63825723e20Ted Kremenek 4105f074266cc59563036c40516c814d63825723e20Ted Kremenek uint32_t SpellingPTHOffset = 4115f074266cc59563036c40516c814d63825723e20Ted Kremenek ((uint32_t) ((uint8_t) p[4])) 4125f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[5])) << 8) 4135f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[6])) << 16) 4145f074266cc59563036c40516c814d63825723e20Ted Kremenek | (((uint32_t) ((uint8_t) p[7])) << 24); 4155f074266cc59563036c40516c814d63825723e20Ted Kremenek 4165f074266cc59563036c40516c814d63825723e20Ted Kremenek return PTHMgr.getSpellingAtPTHOffset(SpellingPTHOffset, Buffer); 4175f074266cc59563036c40516c814d63825723e20Ted Kremenek } 418f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek while (min != max); 4195f074266cc59563036c40516c814d63825723e20Ted Kremenek 4205f074266cc59563036c40516c814d63825723e20Ted Kremenek return 0; 4215f074266cc59563036c40516c814d63825723e20Ted Kremenek} 4225f074266cc59563036c40516c814d63825723e20Ted Kremenek 4235f074266cc59563036c40516c814d63825723e20Ted Kremenekunsigned PTHLexer::getSpelling(SourceLocation sloc, const char *&Buffer) { 4245f074266cc59563036c40516c814d63825723e20Ted Kremenek SourceManager& SM = PP->getSourceManager(); 4255f074266cc59563036c40516c814d63825723e20Ted Kremenek sloc = SM.getPhysicalLoc(sloc); 42628396608ec20d44e9d1470e1ea51689bb504d0deTed Kremenek unsigned fid = SM.getCanonicalFileID(sloc); 4275f074266cc59563036c40516c814d63825723e20Ted Kremenek unsigned fpos = SM.getFullFilePos(sloc); 4285f074266cc59563036c40516c814d63825723e20Ted Kremenek 429f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek return (fid == FileID ) ? MySpellingSrch.getSpellingLinearSearch(fpos, Buffer) 430f02f6f0ee3e05b958bcf67f00f4503671d67eccdTed Kremenek : PTHMgr.getSpelling(fid, fpos, Buffer); 4315f074266cc59563036c40516c814d63825723e20Ted Kremenek} 4325f074266cc59563036c40516c814d63825723e20Ted Kremenek 4330c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 4340c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek// Internal Data Structures for PTH file lookup and resolving identifiers. 4350c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 4360c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4370c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4380c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// PTHFileLookup - This internal data structure is used by the PTHManager 4390c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// to map from FileEntry objects managed by FileManager to offsets within 4400c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// the PTH file. 4410c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremeneknamespace { 4420c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekclass VISIBILITY_HIDDEN PTHFileLookup { 4430c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 4440c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek class Val { 445fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t TokenOff; 446fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t PPCondOff; 447b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t SpellingOff; 4480c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek public: 450fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Val() : TokenOff(~0) {} 451b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek Val(uint32_t toff, uint32_t poff, uint32_t soff) 452b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek : TokenOff(toff), PPCondOff(poff), SpellingOff(soff) {} 4530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 454fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t getTokenOffset() const { 455fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 456fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek return TokenOff; 4570c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4580c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 459b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t getPPCondOffset() const { 460fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 461fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek return PPCondOff; 462fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 463fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 464b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t getSpellingOffset() const { 465b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 466b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek return SpellingOff; 467b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek } 468b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 469fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek bool isValid() const { return TokenOff != ~((uint32_t)0); } 4700c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek }; 4710c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4720c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekprivate: 4730c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::StringMap<Val> FileMap; 4740c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4750c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 4760c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek PTHFileLookup() {}; 4770c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4780c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek Val Lookup(const FileEntry* FE) { 4790c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* s = FE->getName(); 4800c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek unsigned size = strlen(s); 4810c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return FileMap.GetOrCreateValue(s, s+size).getValue(); 4820c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4830c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4840c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek void ReadTable(const char* D) { 4850c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek uint32_t N = Read32(D); // Read the length of the table. 4860c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4870c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek for ( ; N > 0; --N) { // The rest of the data is the table itself. 4880c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek uint32_t len = Read32(D); 4890c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* s = D; 4900c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek D += len; 491b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 492fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t TokenOff = Read32(D); 493b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t PPCondOff = Read32(D); 494b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t SpellingOff = Read32(D); 495b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 496b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek FileMap.GetOrCreateValue(s, s+len).getValue() = 497b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek Val(TokenOff, PPCondOff, SpellingOff); 4980c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4990c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5000c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek}; 5010c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} // end anonymous namespace 5020c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5030c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 5040c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek// PTHManager methods. 5050c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 5060c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5070c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup, 508cf58e6249c6b018508e34bcb76202caa42d2451aTed Kremenek const char* idDataTable, IdentifierInfo** perIDCache, 50972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* sortedIdTable, unsigned numIds) 5106183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup), 51172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IdDataTable(idDataTable), SortedIdTable(sortedIdTable), 51272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek NumIds(numIds), PP(0) {} 5130c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5140c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::~PTHManager() { 5150c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete Buf; 5160c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete (PTHFileLookup*) FileLookup; 5170e50b6e7c104d00614baa3d80df62f1630a94d9cTed Kremenek free(PerIDCache); 5180c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 5190c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 52072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted KremenekPTHManager* PTHManager::Create(const std::string& file) { 5210c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5220c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Memory map the PTH file. 5230c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::OwningPtr<llvm::MemoryBuffer> 5240c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek File(llvm::MemoryBuffer::getFile(file.c_str())); 5250c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5260c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!File) 5270c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 5280c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5290c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the buffer ranges and check if there are at least three 32-bit 5300c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // words at the end of the file. 5310c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* BufBeg = File->getBufferStart(); 5320c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* BufEnd = File->getBufferEnd(); 5330c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5340c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if(!(BufEnd > BufBeg + sizeof(uint32_t)*3)) { 5350c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 5360c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 5370c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5380c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5390c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Compute the address of the index table at the end of the PTH file. 5400c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // This table contains the offset of the file lookup table, the 5410c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // persistent ID -> identifer data table. 542293b4af04ca37576d4b228adf09acd6cee3ddb16Ted Kremenek // FIXME: We should just embed this offset in the PTH file. 543293b4af04ca37576d4b228adf09acd6cee3ddb16Ted Kremenek const char* EndTable = BufEnd - sizeof(uint32_t)*4; 5440c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5450c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Construct the file lookup table. This will be used for mapping from 5460c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // FileEntry*'s to cached tokens. 547293b4af04ca37576d4b228adf09acd6cee3ddb16Ted Kremenek const char* FileTableOffset = EndTable + sizeof(uint32_t)*3; 5480c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* FileTable = BufBeg + Read32(FileTableOffset); 5490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5500c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!(FileTable > BufBeg && FileTable < BufEnd)) { 5510c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 5520c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 5530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5540c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5550c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::OwningPtr<PTHFileLookup> FL(new PTHFileLookup()); 5560c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek FL->ReadTable(FileTable); 5570c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5580c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the location of the table mapping from persistent ids to the 5590c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // data needed to reconstruct identifiers. 5600c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IDTableOffset = EndTable + sizeof(uint32_t)*1; 5610c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IData = BufBeg + Read32(IDTableOffset); 5620c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!(IData > BufBeg && IData < BufEnd)) { 5630c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 5640c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 5650c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 5660c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 56772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Get the location of the lexigraphically-sorted table of persistent IDs. 56872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* SortedIdTableOffset = EndTable + sizeof(uint32_t)*2; 56972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* SortedIdTable = BufBeg + Read32(SortedIdTableOffset); 57072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (!(SortedIdTable > BufBeg && SortedIdTable < BufEnd)) { 57172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek assert(false && "Invalid PTH file."); 57272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return 0; // FIXME: Proper error diagnostic? 57372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek } 57472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 5756183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Get the number of IdentifierInfos and pre-allocate the identifier cache. 5766183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek uint32_t NumIds = Read32(IData); 5776183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 5786183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Pre-allocate the peristent ID -> IdentifierInfo* cache. We use calloc() 5796183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // so that we in the best case only zero out memory once when the OS returns 5806183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // us new pages. 5816183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek IdentifierInfo** PerIDCache = 5826183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek (IdentifierInfo**) calloc(NumIds, sizeof(*PerIDCache)); 5836183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 5846183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek if (!PerIDCache) { 5856183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek assert(false && "Could not allocate Persistent ID cache."); 5866183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek return 0; 5876183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek } 5886183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 58972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Create the new PTHManager. 59072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return new PTHManager(File.take(), FL.take(), IData, PerIDCache, 59172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek SortedIdTable, NumIds); 5920c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 5930c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 594866bdf74547efe32c320554837ffce00fcc084feTed KremenekIdentifierInfo* PTHManager::GetIdentifierInfo(unsigned persistentID) { 595866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 5960c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Check if the IdentifierInfo has already been resolved. 59772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IdentifierInfo* II = PerIDCache[persistentID]; 5980c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (II) return II; 5990c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6000c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Look in the PTH file for the string data for the IdentifierInfo object. 6010c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* TableEntry = IdDataTable + sizeof(uint32_t) * persistentID; 6020c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IDData = Buf->getBufferStart() + Read32(TableEntry); 6030c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(IDData < Buf->getBufferEnd()); 6040c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 60572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Allocate the object. 60672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek std::pair<IdentifierInfo,const char*> *Mem = 60772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek Alloc.Allocate<std::pair<IdentifierInfo,const char*> >(); 60872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 60972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek Mem->second = IDData; 61072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek II = new ((void*) Mem) IdentifierInfo(true); 6110c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 61272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Store the new IdentifierInfo in the cache. 61372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek PerIDCache[persistentID] = II; 6140c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return II; 6150c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 6160c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 61772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted KremenekIdentifierInfo* PTHManager::get(const char *NameStart, const char *NameEnd) { 61872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned min = 0; 61972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned max = NumIds; 62072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned len = NameEnd - NameStart; 62172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 62272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek do { 62372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned i = (max - min) / 2 + min; 62472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek const char* p = SortedIdTable + (i * 4); 62572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 62672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Read the persistentID. 62772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned perID = 62872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek ((unsigned) ((uint8_t) p[0])) 62972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek | (((unsigned) ((uint8_t) p[1])) << 8) 63072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek | (((unsigned) ((uint8_t) p[2])) << 16) 63172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek | (((unsigned) ((uint8_t) p[3])) << 24); 63272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 63372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Get the IdentifierInfo. 63472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IdentifierInfo* II = GetIdentifierInfo(perID); 63572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 63672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // First compare the lengths. 63772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek unsigned IILen = II->getLength(); 63872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (len < IILen) goto IsLess; 63972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (len > IILen) goto IsGreater; 64072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 64172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // Now compare the strings! 64272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek { 64372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek signed comp = strncmp(NameStart, II->getName(), len); 64472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (comp < 0) goto IsLess; 64572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (comp > 0) goto IsGreater; 64672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek } 64772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek // We found a match! 64872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return II; 64972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 65072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IsGreater: 65172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek if (i == min) break; 65272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek min = i; 65372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek continue; 65472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 65572b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek IsLess: 65672b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek max = i; 65772b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek assert(!(max == min) || (min == i)); 65872b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek } 65972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek while (1); 66072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 66172b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return 0; 66272b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek} 66372b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 66472b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek 6650c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHLexer* PTHManager::CreateLexer(unsigned FileID, const FileEntry* FE) { 6660c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6670c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!FE) 6680c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 6690c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6700c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Lookup the FileEntry object in our file lookup data structure. It will 6710c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // return a variant that indicates whether or not there is an offset within 6720c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // the PTH file that contains cached tokens. 673fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PTHFileLookup::Val FileData = ((PTHFileLookup*) FileLookup)->Lookup(FE); 6740c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 675fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek if (!FileData.isValid()) // No tokens available. 6760c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 6770c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 6780c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Compute the offset of the token data within the buffer. 679fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek const char* data = Buf->getBufferStart() + FileData.getTokenOffset(); 680268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 681268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Get the location of pp-conditional table. 682b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek const char* ppcond = Buf->getBufferStart() + FileData.getPPCondOffset(); 683b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t len = Read32(ppcond); 684268ee7016a2811803989487c0ad3799486092c63Ted Kremenek if (len == 0) ppcond = 0; 68532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 68632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // Get the location of the spelling table. 68732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* spellingTable = Buf->getBufferStart() + 68832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek FileData.getSpellingOffset(); 68932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 69032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek len = Read32(spellingTable); 69132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (len == 0) spellingTable = 0; 692b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 6930c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(data < Buf->getBufferEnd()); 6945f074266cc59563036c40516c814d63825723e20Ted Kremenek 6955f074266cc59563036c40516c814d63825723e20Ted Kremenek // Create the SpellingSearch object for this FileID. 6965f074266cc59563036c40516c814d63825723e20Ted Kremenek PTHSpellingSearch* ss = new PTHSpellingSearch(*this, len, spellingTable); 6975f074266cc59563036c40516c814d63825723e20Ted Kremenek SpellingMap[FileID] = ss; 6985f074266cc59563036c40516c814d63825723e20Ted Kremenek 69972b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek assert(PP && "No preprocessor set yet!"); 70072b1b15ee88aac0a63e2c1dc53fe22f5ab297b20Ted Kremenek return new PTHLexer(*PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond, 7015f074266cc59563036c40516c814d63825723e20Ted Kremenek *ss, *this); 7020c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 703