llvm-project/clang/lib/Lex/ScratchBuffer.cpp
Benjamin Kramer 040725723e MSan told me that we actually dump the entire scratch buffer into PCH files, initialize it.
Writing 4k of zeros is preferrable to 4k of random memory. Document that. While
there remove the initialization of the first byte of the buffer and start at
index zero. It was writing a literal '0' instead of a null byte at the
beginning anyways, which didn't matter since we never read it.

llvm-svn: 234202
2015-04-06 20:01:49 +00:00

77 lines
2.9 KiB
C++

//===--- ScratchBuffer.cpp - Scratch space for forming tokens -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ScratchBuffer interface.
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/ScratchBuffer.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstring>
using namespace clang;
// ScratchBufSize - The size of each chunk of scratch memory. Slightly less
//than a page, almost certainly enough for anything. :)
static const unsigned ScratchBufSize = 4060;
ScratchBuffer::ScratchBuffer(SourceManager &SM)
: SourceMgr(SM), CurBuffer(nullptr) {
// Set BytesUsed so that the first call to getToken will require an alloc.
BytesUsed = ScratchBufSize;
}
/// getToken - Splat the specified text into a temporary MemoryBuffer and
/// return a SourceLocation that refers to the token. This is just like the
/// method below, but returns a location that indicates the physloc of the
/// token.
SourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len,
const char *&DestPtr) {
if (BytesUsed+Len+2 > ScratchBufSize)
AllocScratchBuffer(Len+2);
// Prefix the token with a \n, so that it looks like it is the first thing on
// its own virtual line in caret diagnostics.
CurBuffer[BytesUsed++] = '\n';
// Return a pointer to the character data.
DestPtr = CurBuffer+BytesUsed;
// Copy the token data into the buffer.
memcpy(CurBuffer+BytesUsed, Buf, Len);
// Remember that we used these bytes.
BytesUsed += Len+1;
// Add a NUL terminator to the token. This keeps the tokens separated, in
// case they get relexed, and puts them on their own virtual lines in case a
// diagnostic points to one.
CurBuffer[BytesUsed-1] = '\0';
return BufferStartLoc.getLocWithOffset(BytesUsed-Len-1);
}
void ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
// Only pay attention to the requested length if it is larger than our default
// page size. If it is, we allocate an entire chunk for it. This is to
// support gigantic tokens, which almost certainly won't happen. :)
if (RequestLen < ScratchBufSize)
RequestLen = ScratchBufSize;
// Get scratch buffer. Zero-initialize it so it can be dumped into a PCH file
// deterministically.
std::unique_ptr<llvm::MemoryBuffer> OwnBuf =
llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
llvm::MemoryBuffer &Buf = *OwnBuf;
FileID FID = SourceMgr.createFileID(std::move(OwnBuf));
BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
CurBuffer = const_cast<char*>(Buf.getBufferStart());
BytesUsed = 0;
}