PTHLexer.cpp revision defb7094c835998bb821e894253287625ce8c74d
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, 5332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* spellingTable, unsigned NumSpellings, 5432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek PTHManager& PM) 55cd223444d1680290efe11da657faafc9a1ac14baTed Kremenek : PreprocessorLexer(&pp, fileloc), TokBuf(D), CurPtr(D), LastHashTokPtr(0), 5632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek PPCond(ppcond), CurPPCondPtr(ppcond), 5732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek SpellingTable(spellingTable), SpellingsLeft(NumSpellings), 5832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek PTHMgr(PM) {} 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); 97866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setLocation(SourceLocation::getFileLoc(FileID, FileOffset)); 98866bdf74547efe32c320554837ffce00fcc084feTed Kremenek Tok.setLength(Len); 9989d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 100866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 101866bdf74547efe32c320554837ffce00fcc084feTed Kremenek // Process the token. 102866bdf74547efe32c320554837ffce00fcc084feTed Kremenek //===--------------------------------------==// 10389d7ee9619d2dbdfa8d956a695c612a104a92cadTed Kremenek 10459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::identifier) { 10559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek MIOpt.ReadToken(); 10659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return PP->HandleIdentifier(Tok); 10759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek } 10859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 10959d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::eof) { 110e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Save the end-of-file token. 111e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek EofToken = Tok; 112e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 113cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek Preprocessor *PPCache = PP; 11459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 11559d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!ParsingPreprocessorDirective); 11659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 11759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 11859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek // FIXME: Issue diagnostics similar to Lexer. 11959d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->HandleEndOfFile(Tok, false)) 120d6f53dc4951aace69014619761760addac9e59ecTed Kremenek return; 12159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek 122cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek assert(PPCache && "Raw buffer::LexEndOfFile should return a token"); 123cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek return PPCache->Lex(Tok); 124cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek } 125d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 12659d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::hash && Tok.isAtStartOfLine()) { 12759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE; 12859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(!LexingRawMode); 12959d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek PP->HandleDirective(Tok); 130d6f53dc4951aace69014619761760addac9e59ecTed Kremenek 13159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (PP->isCurrentLexer(this)) 13259d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek goto LexNextToken; 133e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 13459d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return PP->Lex(Tok); 135e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek } 136e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 13759d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek if (k == tok::eom) { 13859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek assert(ParsingPreprocessorDirective); 13959d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek ParsingPreprocessorDirective = false; 14059d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek return; 14159d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek } 142274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek 14359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek MIOpt.ReadToken(); 144cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek} 145cd4e2aecde5bb7810715d5d5a88ac63ce7946f34Ted Kremenek 146e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// FIXME: We can just grab the last token instead of storing a copy 147e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek// into EofToken. 14859d08cb672136322375e5400578ee1fbd0947de2Ted Kremenekvoid PTHLexer::getEOF(Token& Tok) { 149defb7094c835998bb821e894253287625ce8c74dTed Kremenek assert(EofToken.is(tok::eof)); 1500c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek Tok = EofToken; 151274b20863a728cc6a31ee75c670e3733600c1531Ted Kremenek} 15217ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek 15317ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenekvoid PTHLexer::DiscardToEndOfLine() { 15417ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek assert(ParsingPreprocessorDirective && ParsingFilename == false && 15517ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek "Must be in a preprocessing directive!"); 1564d35da2e41941965bbee8ed7e8c30e7c21000d71Ted Kremenek 157e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // We assume that if the preprocessor wishes to discard to the end of 158e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // the line that it also means to end the current preprocessor directive. 159e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek ParsingPreprocessorDirective = false; 160e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 16174c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip tokens by only peeking at their token kind and the flags. 16274c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // We don't need to actually reconstruct full tokens from the token buffer. 16374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // This saves some copies and it also reduces IdentifierInfo* lookup. 16474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek const char* p = CurPtr; 16574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek while (1) { 16674c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token kind. Are we at the end of the file? 16774c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek tok::TokenKind x = (tok::TokenKind) (uint8_t) *p; 16874c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek if (x == tok::eof) break; 169e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 17074c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Read the token flags. Are we at the start of the next line? 17174c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek Token::TokenFlags y = (Token::TokenFlags) (uint8_t) p[1]; 17280d2f3059326f99ebf7c867db1c7f106ec9485f5Ted Kremenek if (y & Token::StartOfLine) break; 17374c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 17474c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek // Skip to the next token. 17574c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek p += DISK_TOKEN_SIZE; 17674c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek } 17774c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek 17874c3e6e5e95af08096aab415d1ce15f15ffff02aTed Kremenek CurPtr = p; 17917ff58a63197b398ae52697b088dc0fb8b255519Ted Kremenek} 1800c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 181268ee7016a2811803989487c0ad3799486092c63Ted Kremenek/// SkipBlock - Used by Preprocessor to skip the current conditional block. 182268ee7016a2811803989487c0ad3799486092c63Ted Kremenekbool PTHLexer::SkipBlock() { 183268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(CurPPCondPtr && "No cached PP conditional information."); 184268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(LastHashTokPtr && "No known '#' token."); 185268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 18641a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* HashEntryI = 0; 187268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t Offset; 188268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t TableIdx; 189268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 190268ee7016a2811803989487c0ad3799486092c63Ted Kremenek do { 19141a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the token offset from the side-table. 192268ee7016a2811803989487c0ad3799486092c63Ted Kremenek Offset = Read32(CurPPCondPtr); 19341a2660377d215d004fe413c03874bd066b5384cTed Kremenek 19441a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read the target table index from the side-table. 195268ee7016a2811803989487c0ad3799486092c63Ted Kremenek TableIdx = Read32(CurPPCondPtr); 19641a2660377d215d004fe413c03874bd066b5384cTed Kremenek 19741a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Compute the actual memory address of the '#' token data for this entry. 19841a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = TokBuf + Offset; 19941a2660377d215d004fe413c03874bd066b5384cTed Kremenek 20041a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Optmization: "Sibling jumping". #if...#else...#endif blocks can 20141a2660377d215d004fe413c03874bd066b5384cTed Kremenek // contain nested blocks. In the side-table we can jump over these 20241a2660377d215d004fe413c03874bd066b5384cTed Kremenek // nested blocks instead of doing a linear search if the next "sibling" 20341a2660377d215d004fe413c03874bd066b5384cTed Kremenek // entry is not at a location greater than LastHashTokPtr. 20441a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryI < LastHashTokPtr && TableIdx) { 20541a2660377d215d004fe413c03874bd066b5384cTed Kremenek // In the side-table we are still at an entry for a '#' token that 20641a2660377d215d004fe413c03874bd066b5384cTed Kremenek // is earlier than the last one we saw. Check if the location we would 20741a2660377d215d004fe413c03874bd066b5384cTed Kremenek // stride gets us closer. 20841a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2); 20941a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 21041a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Read where we should jump to. 21141a2660377d215d004fe413c03874bd066b5384cTed Kremenek uint32_t TmpOffset = Read32(NextPPCondPtr); 21241a2660377d215d004fe413c03874bd066b5384cTed Kremenek const char* HashEntryJ = TokBuf + TmpOffset; 21341a2660377d215d004fe413c03874bd066b5384cTed Kremenek 21441a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (HashEntryJ <= LastHashTokPtr) { 21541a2660377d215d004fe413c03874bd066b5384cTed Kremenek // Jump directly to the next entry in the side table. 21641a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = HashEntryJ; 21741a2660377d215d004fe413c03874bd066b5384cTed Kremenek Offset = TmpOffset; 21841a2660377d215d004fe413c03874bd066b5384cTed Kremenek TableIdx = Read32(NextPPCondPtr); 21941a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPPCondPtr = NextPPCondPtr; 22041a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 22141a2660377d215d004fe413c03874bd066b5384cTed Kremenek } 222268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 22341a2660377d215d004fe413c03874bd066b5384cTed Kremenek while (HashEntryI < LastHashTokPtr); 22441a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'"); 225268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(TableIdx && "No jumping from #endifs."); 226268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 227268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update our side-table iterator. 228268ee7016a2811803989487c0ad3799486092c63Ted Kremenek const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2); 229268ee7016a2811803989487c0ad3799486092c63Ted Kremenek assert(NextPPCondPtr >= CurPPCondPtr); 230268ee7016a2811803989487c0ad3799486092c63Ted Kremenek CurPPCondPtr = NextPPCondPtr; 231268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 232268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Read where we should jump to. 23341a2660377d215d004fe413c03874bd066b5384cTed Kremenek HashEntryI = TokBuf + Read32(NextPPCondPtr); 234268ee7016a2811803989487c0ad3799486092c63Ted Kremenek uint32_t NextIdx = Read32(NextPPCondPtr); 235268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 236268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // By construction NextIdx will be zero if this is a #endif. This is useful 237268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // to know to obviate lexing another token. 238268ee7016a2811803989487c0ad3799486092c63Ted Kremenek bool isEndif = NextIdx == 0; 239268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 240268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // This case can occur when we see something like this: 241268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 242268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #if ... 243268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // /* a comment or nothing */ 244268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // #elif 245268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // 246268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // If we are skipping the first #if block it will be the case that CurPtr 247268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // already points 'elif'. Just return. 248268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 24941a2660377d215d004fe413c03874bd066b5384cTed Kremenek if (CurPtr > HashEntryI) { 25041a2660377d215d004fe413c03874bd066b5384cTed Kremenek assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE); 251268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 252268ee7016a2811803989487c0ad3799486092c63Ted Kremenek if (isEndif) 253e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE*2; 254268ee7016a2811803989487c0ad3799486092c63Ted Kremenek else 25541a2660377d215d004fe413c03874bd066b5384cTed Kremenek LastHashTokPtr = HashEntryI; 256268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 257268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 258268ee7016a2811803989487c0ad3799486092c63Ted Kremenek } 259268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 260268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Otherwise, we need to advance. Update CurPtr to point to the '#' token. 26141a2660377d215d004fe413c03874bd066b5384cTed Kremenek CurPtr = HashEntryI; 262268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 263268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Update the location of the last observed '#'. This is useful if we 264268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // are skipping multiple blocks. 265268ee7016a2811803989487c0ad3799486092c63Ted Kremenek LastHashTokPtr = CurPtr; 266268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 267e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek // Skip the '#' token. 268e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek assert(((tok::TokenKind) (unsigned char) *CurPtr) == tok::hash); 269e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek CurPtr += DISK_TOKEN_SIZE; 270e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek 271268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Did we reach a #endif? If so, go ahead and consume that token as well. 272e5680f3cd678014cf0872d34726dc804b0cbbdd4Ted Kremenek if (isEndif) { CurPtr += DISK_TOKEN_SIZE*2; } 273268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 274268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return isEndif; 275268ee7016a2811803989487c0ad3799486092c63Ted Kremenek} 276268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 27730a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed KremenekSourceLocation PTHLexer::getSourceLocation() { 27830a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // getLocation is not on the hot path. It is used to get the location of 27930a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // the next token when transitioning back to this lexer when done 28030a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // handling a #included file. Just read the necessary data from the token 28130a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // data buffer to construct the SourceLocation object. 28230a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek // NOTE: This is a virtual function; hence it is defined out-of-line. 28359d08cb672136322375e5400578ee1fbd0947de2Ted Kremenek const char* p = CurPtr + (1 + 1 + 3); 28430a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek uint32_t offset = 28530a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek ((uint32_t) ((uint8_t) p[0])) 28630a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 28730a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 28830a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 28930a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek return SourceLocation::getFileLoc(FileID, offset); 29030a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek} 29130a12ec2a7f331d9e08acabe7cda853aaa7ba54bTed Kremenek 29232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenekunsigned PTHManager::GetSpelling(unsigned PTHOffset, const char *& Buffer) { 29332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* p = Buf->getBufferStart() + PTHOffset; 29432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek assert(p < Buf->getBufferEnd()); 29532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 29632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // The string is prefixed by 16 bits for its length, followed by the string 29732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // itself. 29832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek unsigned len = ((unsigned) ((uint8_t) p[0])) 29932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((unsigned) ((uint8_t) p[1])) << 8); 30032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 30132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek Buffer = p + 2; 30232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek return len; 30332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek} 30432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 305b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenekunsigned PTHLexer::getSpelling(SourceLocation sloc, const char *&Buffer) { 30632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* p = SpellingTable; 30732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek SourceManager& SM = PP->getSourceManager(); 30832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek unsigned fpos = SM.getFullFilePos(SM.getPhysicalLoc(sloc)); 30932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek unsigned len = 0; 31032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 31132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek while (SpellingsLeft) { 31232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek uint32_t TokOffset = 31332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek ((uint32_t) ((uint8_t) p[0])) 31432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[1])) << 8) 31532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[2])) << 16) 31632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[3])) << 24); 31732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 31832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (TokOffset > fpos) 31932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek break; 32032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 32132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek --SpellingsLeft; 32232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 32332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // Did we find a matching token offset for this spelling? 32432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (TokOffset == fpos) { 32532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek uint32_t SpellingPTHOffset = 32632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek ((uint32_t) ((uint8_t) p[4])) 32732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[5])) << 8) 32832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[6])) << 16) 32932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek | (((uint32_t) ((uint8_t) p[7])) << 24); 33032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 33132a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek len = PTHMgr.GetSpelling(SpellingPTHOffset, Buffer); 33232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek break; 33332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek } 33432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 33532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // No match. Keep on looking. 33632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek p += sizeof(uint32_t)*2; 33732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek } 33832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 33932a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek SpellingTable = p; 34032a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek return len; 341b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek} 342b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 3430c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 3440c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek// Internal Data Structures for PTH file lookup and resolving identifiers. 3450c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 3460c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3470c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3480c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// PTHFileLookup - This internal data structure is used by the PTHManager 3490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// to map from FileEntry objects managed by FileManager to offsets within 3500c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek/// the PTH file. 3510c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremeneknamespace { 3520c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekclass VISIBILITY_HIDDEN PTHFileLookup { 3530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 3540c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek class Val { 355fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t TokenOff; 356fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t PPCondOff; 357b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t SpellingOff; 3580c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3590c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek public: 360fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek Val() : TokenOff(~0) {} 361b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek Val(uint32_t toff, uint32_t poff, uint32_t soff) 362b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek : TokenOff(toff), PPCondOff(poff), SpellingOff(soff) {} 3630c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 364fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t getTokenOffset() const { 365fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 366fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek return TokenOff; 3670c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 3680c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 369b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t getPPCondOffset() const { 370fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 371fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek return PPCondOff; 372fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek } 373fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek 374b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t getSpellingOffset() const { 375b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized."); 376b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek return SpellingOff; 377b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek } 378b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 379fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek bool isValid() const { return TokenOff != ~((uint32_t)0); } 3800c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek }; 3810c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3820c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekprivate: 3830c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::StringMap<Val> FileMap; 3840c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3850c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenekpublic: 3860c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek PTHFileLookup() {}; 3870c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3880c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek Val Lookup(const FileEntry* FE) { 3890c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* s = FE->getName(); 3900c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek unsigned size = strlen(s); 3910c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return FileMap.GetOrCreateValue(s, s+size).getValue(); 3920c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 3930c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3940c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek void ReadTable(const char* D) { 3950c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek uint32_t N = Read32(D); // Read the length of the table. 3960c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 3970c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek for ( ; N > 0; --N) { // The rest of the data is the table itself. 3980c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek uint32_t len = Read32(D); 3990c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* s = D; 4000c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek D += len; 401b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 402fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek uint32_t TokenOff = Read32(D); 403b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t PPCondOff = Read32(D); 404b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t SpellingOff = Read32(D); 405b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 406b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek FileMap.GetOrCreateValue(s, s+len).getValue() = 407b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek Val(TokenOff, PPCondOff, SpellingOff); 4080c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4090c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4100c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek}; 4110c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} // end anonymous namespace 4120c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4130c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 4140c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek// PTHManager methods. 4150c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek//===----------------------------------------------------------------------===// 4160c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4170c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup, 418cf58e6249c6b018508e34bcb76202caa42d2451aTed Kremenek const char* idDataTable, IdentifierInfo** perIDCache, 4196183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek Preprocessor& pp) 4206183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup), 4216183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek IdDataTable(idDataTable), ITable(pp.getIdentifierTable()), PP(pp) {} 4220c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4230c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager::~PTHManager() { 4240c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete Buf; 4250c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek delete (PTHFileLookup*) FileLookup; 4260e50b6e7c104d00614baa3d80df62f1630a94d9cTed Kremenek free(PerIDCache); 4270c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 4280c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4290c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHManager* PTHManager::Create(const std::string& file, Preprocessor& PP) { 4300c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4310c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Memory map the PTH file. 4320c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::OwningPtr<llvm::MemoryBuffer> 4330c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek File(llvm::MemoryBuffer::getFile(file.c_str())); 4340c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4350c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!File) 4360c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 4370c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4380c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the buffer ranges and check if there are at least three 32-bit 4390c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // words at the end of the file. 4400c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* BufBeg = File->getBufferStart(); 4410c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* BufEnd = File->getBufferEnd(); 4420c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4430c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if(!(BufEnd > BufBeg + sizeof(uint32_t)*3)) { 4440c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 4450c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 4460c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4470c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4480c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Compute the address of the index table at the end of the PTH file. 4490c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // This table contains the offset of the file lookup table, the 4500c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // persistent ID -> identifer data table. 4510c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* EndTable = BufEnd - sizeof(uint32_t)*3; 4520c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4530c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Construct the file lookup table. This will be used for mapping from 4540c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // FileEntry*'s to cached tokens. 4550c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* FileTableOffset = EndTable + sizeof(uint32_t)*2; 4560c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* FileTable = BufBeg + Read32(FileTableOffset); 4570c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4580c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!(FileTable > BufBeg && FileTable < BufEnd)) { 4590c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 4600c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 4610c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4620c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4630c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek llvm::OwningPtr<PTHFileLookup> FL(new PTHFileLookup()); 4640c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek FL->ReadTable(FileTable); 4650c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4660c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the location of the table mapping from persistent ids to the 4670c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // data needed to reconstruct identifiers. 4680c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IDTableOffset = EndTable + sizeof(uint32_t)*1; 4690c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IData = BufBeg + Read32(IDTableOffset); 4700c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!(IData > BufBeg && IData < BufEnd)) { 4710c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(false && "Invalid PTH file."); 4720c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; // FIXME: Proper error diagnostic? 4730c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek } 4740c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4756183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Get the number of IdentifierInfos and pre-allocate the identifier cache. 4766183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek uint32_t NumIds = Read32(IData); 4776183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 4786183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Pre-allocate the peristent ID -> IdentifierInfo* cache. We use calloc() 4796183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // so that we in the best case only zero out memory once when the OS returns 4806183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // us new pages. 4816183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek IdentifierInfo** PerIDCache = 4826183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek (IdentifierInfo**) calloc(NumIds, sizeof(*PerIDCache)); 4836183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 4846183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek if (!PerIDCache) { 4856183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek assert(false && "Could not allocate Persistent ID cache."); 4866183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek return 0; 4876183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek } 4886183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek 4896183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek // Create the new lexer. 4906183e4815a4019e97ad01bd880f12355599b75fdTed Kremenek return new PTHManager(File.take(), FL.take(), IData, PerIDCache, PP); 4910c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 4920c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 493866bdf74547efe32c320554837ffce00fcc084feTed KremenekIdentifierInfo* PTHManager::GetIdentifierInfo(unsigned persistentID) { 494866bdf74547efe32c320554837ffce00fcc084feTed Kremenek 4950c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Check if the IdentifierInfo has already been resolved. 496cf58e6249c6b018508e34bcb76202caa42d2451aTed Kremenek IdentifierInfo*& II = PerIDCache[persistentID]; 4970c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (II) return II; 4980c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 4990c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Look in the PTH file for the string data for the IdentifierInfo object. 5000c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* TableEntry = IdDataTable + sizeof(uint32_t) * persistentID; 5010c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek const char* IDData = Buf->getBufferStart() + Read32(TableEntry); 5020c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(IDData < Buf->getBufferEnd()); 5030c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5040c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Read the length of the string. 5050c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek uint32_t len = Read32(IDData); 5060c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5070c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Get the IdentifierInfo* with the specified string. 5080c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek II = &ITable.get(IDData, IDData+len); 5090c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return II; 5100c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 5110c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5120c6a77bc1f52f282a969538f139ebde429076ed3Ted KremenekPTHLexer* PTHManager::CreateLexer(unsigned FileID, const FileEntry* FE) { 5130c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5140c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek if (!FE) 5150c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 5160c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5170c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Lookup the FileEntry object in our file lookup data structure. It will 5180c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // return a variant that indicates whether or not there is an offset within 5190c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // the PTH file that contains cached tokens. 520fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek PTHFileLookup::Val FileData = ((PTHFileLookup*) FileLookup)->Lookup(FE); 5210c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 522fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek if (!FileData.isValid()) // No tokens available. 5230c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek return 0; 5240c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek 5250c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek // Compute the offset of the token data within the buffer. 526fb645b6547b75ddc2e3c7ab2126ad8beeefca62dTed Kremenek const char* data = Buf->getBufferStart() + FileData.getTokenOffset(); 527268ee7016a2811803989487c0ad3799486092c63Ted Kremenek 528268ee7016a2811803989487c0ad3799486092c63Ted Kremenek // Get the location of pp-conditional table. 529b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek const char* ppcond = Buf->getBufferStart() + FileData.getPPCondOffset(); 530b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek uint32_t len = Read32(ppcond); 531268ee7016a2811803989487c0ad3799486092c63Ted Kremenek if (len == 0) ppcond = 0; 53232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 53332a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek // Get the location of the spelling table. 53432a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek const char* spellingTable = Buf->getBufferStart() + 53532a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek FileData.getSpellingOffset(); 53632a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek 53732a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek len = Read32(spellingTable); 53832a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek if (len == 0) spellingTable = 0; 539b70e3dafb9618f34017061400dc19ac5e3539a6dTed Kremenek 5400c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek assert(data < Buf->getBufferEnd()); 541268ee7016a2811803989487c0ad3799486092c63Ted Kremenek return new PTHLexer(PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond, 54232a8ad526f9bc00539f000a2dd1ac3e167db61c1Ted Kremenek spellingTable, len, *this); 5430c6a77bc1f52f282a969538f139ebde429076ed3Ted Kremenek} 544