xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Lex/ScratchBuffer.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- ScratchBuffer.cpp - Scratch space for forming tokens -------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg //  This file implements the ScratchBuffer interface.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/Lex/ScratchBuffer.h"
147330f729Sjoerg #include "clang/Basic/SourceManager.h"
157330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
167330f729Sjoerg #include <cstring>
177330f729Sjoerg using namespace clang;
187330f729Sjoerg 
197330f729Sjoerg // ScratchBufSize - The size of each chunk of scratch memory.  Slightly less
207330f729Sjoerg //than a page, almost certainly enough for anything. :)
217330f729Sjoerg static const unsigned ScratchBufSize = 4060;
227330f729Sjoerg 
ScratchBuffer(SourceManager & SM)237330f729Sjoerg ScratchBuffer::ScratchBuffer(SourceManager &SM)
247330f729Sjoerg     : SourceMgr(SM), CurBuffer(nullptr) {
257330f729Sjoerg   // Set BytesUsed so that the first call to getToken will require an alloc.
267330f729Sjoerg   BytesUsed = ScratchBufSize;
277330f729Sjoerg }
287330f729Sjoerg 
297330f729Sjoerg /// getToken - Splat the specified text into a temporary MemoryBuffer and
307330f729Sjoerg /// return a SourceLocation that refers to the token.  This is just like the
317330f729Sjoerg /// method below, but returns a location that indicates the physloc of the
327330f729Sjoerg /// token.
getToken(const char * Buf,unsigned Len,const char * & DestPtr)337330f729Sjoerg SourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len,
347330f729Sjoerg                                        const char *&DestPtr) {
357330f729Sjoerg   if (BytesUsed+Len+2 > ScratchBufSize)
367330f729Sjoerg     AllocScratchBuffer(Len+2);
377330f729Sjoerg   else {
387330f729Sjoerg     // Clear out the source line cache if it's already been computed.
397330f729Sjoerg     // FIXME: Allow this to be incrementally extended.
407330f729Sjoerg     SourceMgr.getSLocEntry(SourceMgr.getFileID(BufferStartLoc))
41*e038c9c4Sjoerg         .getFile()
42*e038c9c4Sjoerg         .getContentCache()
43*e038c9c4Sjoerg         .SourceLineCache = SrcMgr::LineOffsetMapping();
447330f729Sjoerg   }
457330f729Sjoerg 
467330f729Sjoerg   // Prefix the token with a \n, so that it looks like it is the first thing on
477330f729Sjoerg   // its own virtual line in caret diagnostics.
487330f729Sjoerg   CurBuffer[BytesUsed++] = '\n';
497330f729Sjoerg 
507330f729Sjoerg   // Return a pointer to the character data.
517330f729Sjoerg   DestPtr = CurBuffer+BytesUsed;
527330f729Sjoerg 
537330f729Sjoerg   // Copy the token data into the buffer.
547330f729Sjoerg   memcpy(CurBuffer+BytesUsed, Buf, Len);
557330f729Sjoerg 
567330f729Sjoerg   // Remember that we used these bytes.
577330f729Sjoerg   BytesUsed += Len+1;
587330f729Sjoerg 
597330f729Sjoerg   // Add a NUL terminator to the token.  This keeps the tokens separated, in
607330f729Sjoerg   // case they get relexed, and puts them on their own virtual lines in case a
617330f729Sjoerg   // diagnostic points to one.
627330f729Sjoerg   CurBuffer[BytesUsed-1] = '\0';
637330f729Sjoerg 
647330f729Sjoerg   return BufferStartLoc.getLocWithOffset(BytesUsed-Len-1);
657330f729Sjoerg }
667330f729Sjoerg 
AllocScratchBuffer(unsigned RequestLen)677330f729Sjoerg void ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
687330f729Sjoerg   // Only pay attention to the requested length if it is larger than our default
697330f729Sjoerg   // page size.  If it is, we allocate an entire chunk for it.  This is to
707330f729Sjoerg   // support gigantic tokens, which almost certainly won't happen. :)
717330f729Sjoerg   if (RequestLen < ScratchBufSize)
727330f729Sjoerg     RequestLen = ScratchBufSize;
737330f729Sjoerg 
747330f729Sjoerg   // Get scratch buffer. Zero-initialize it so it can be dumped into a PCH file
757330f729Sjoerg   // deterministically.
767330f729Sjoerg   std::unique_ptr<llvm::WritableMemoryBuffer> OwnBuf =
777330f729Sjoerg       llvm::WritableMemoryBuffer::getNewMemBuffer(RequestLen,
787330f729Sjoerg                                                   "<scratch space>");
797330f729Sjoerg   CurBuffer = OwnBuf->getBufferStart();
807330f729Sjoerg   FileID FID = SourceMgr.createFileID(std::move(OwnBuf));
817330f729Sjoerg   BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
827330f729Sjoerg   BytesUsed = 0;
837330f729Sjoerg }
84