15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- ScratchBuffer.cpp - Scratch space for forming tokens -------------===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  This file implements the ScratchBuffer interface.
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Lex/ScratchBuffer.h"
155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/SourceManager.h"
165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/Support/MemoryBuffer.h"
1787cf5ac1b046a1db874b77dcb6e35f9c4b88c386Chris Lattner#include <cstring>
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang;
195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// ScratchBufSize - The size of each chunk of scratch memory.  Slightly less
215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//than a page, almost certainly enough for anything. :)
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic const unsigned ScratchBufSize = 4060;
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerScratchBuffer::ScratchBuffer(SourceManager &SM) : SourceMgr(SM), CurBuffer(0) {
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Set BytesUsed so that the first call to getToken will require an alloc.
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  BytesUsed = ScratchBufSize;
275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getToken - Splat the specified text into a temporary MemoryBuffer and
305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// return a SourceLocation that refers to the token.  This is just like the
315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// method below, but returns a location that indicates the physloc of the
325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// token.
3347246be8ac5b0ddde6c402b8fc6946b6135487b5Chris LattnerSourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len,
3447246be8ac5b0ddde6c402b8fc6946b6135487b5Chris Lattner                                       const char *&DestPtr) {
352bc69bdb29c4912e90bd213608bd98e1fc73707aChris Lattner  if (BytesUsed+Len+2 > ScratchBufSize)
362bc69bdb29c4912e90bd213608bd98e1fc73707aChris Lattner    AllocScratchBuffer(Len+2);
372bc69bdb29c4912e90bd213608bd98e1fc73707aChris Lattner
382bc69bdb29c4912e90bd213608bd98e1fc73707aChris Lattner  // Prefix the token with a \n, so that it looks like it is the first thing on
392bc69bdb29c4912e90bd213608bd98e1fc73707aChris Lattner  // its own virtual line in caret diagnostics.
402bc69bdb29c4912e90bd213608bd98e1fc73707aChris Lattner  CurBuffer[BytesUsed++] = '\n';
411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4247246be8ac5b0ddde6c402b8fc6946b6135487b5Chris Lattner  // Return a pointer to the character data.
4347246be8ac5b0ddde6c402b8fc6946b6135487b5Chris Lattner  DestPtr = CurBuffer+BytesUsed;
441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Copy the token data into the buffer.
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  memcpy(CurBuffer+BytesUsed, Buf, Len);
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Remember that we used these bytes.
491fa495304c81e03f07f278a47b5efe9317104aabChris Lattner  BytesUsed += Len+1;
501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
511fa495304c81e03f07f278a47b5efe9317104aabChris Lattner  // Add a NUL terminator to the token.  This keeps the tokens separated, in
521fa495304c81e03f07f278a47b5efe9317104aabChris Lattner  // case they get relexed, and puts them on their own virtual lines in case a
531fa495304c81e03f07f278a47b5efe9317104aabChris Lattner  // diagnostic points to one.
541fa495304c81e03f07f278a47b5efe9317104aabChris Lattner  CurBuffer[BytesUsed-1] = '\0';
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
56a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis  return BufferStartLoc.getLocWithOffset(BytesUsed-Len-1);
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Only pay attention to the requested length if it is larger than our default
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // page size.  If it is, we allocate an entire chunk for it.  This is to
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // support gigantic tokens, which almost certainly won't happen. :)
632bc69bdb29c4912e90bd213608bd98e1fc73707aChris Lattner  if (RequestLen < ScratchBufSize)
645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    RequestLen = ScratchBufSize;
651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  llvm::MemoryBuffer *Buf =
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
682b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  FileID FID = SourceMgr.createFileIDForMemBuffer(Buf);
692b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  CurBuffer = const_cast<char*>(Buf->getBufferStart());
711fa495304c81e03f07f278a47b5efe9317104aabChris Lattner  BytesUsed = 1;
721fa495304c81e03f07f278a47b5efe9317104aabChris Lattner  CurBuffer[0] = '0';  // Start out with a \0 for cleanliness.
735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
74