Пример #1
0
line_iterator::line_iterator(const MemoryBuffer &Buffer, char CommentMarker)
    : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr),
      CommentMarker(CommentMarker), LineNumber(1),
      CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr,
                  0) {
    // Ensure that if we are constructed on a non-empty memory buffer that it is
    // a null terminated buffer.
    if (Buffer.getBufferSize()) {
        assert(Buffer.getBufferEnd()[0] == '\0');
        advance();
    }
}
Пример #2
0
line_iterator::line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks,
                             char CommentMarker)
    : Buffer(Buffer.getBufferSize() ? &Buffer : nullptr),
      CommentMarker(CommentMarker), SkipBlanks(SkipBlanks), LineNumber(1),
      CurrentLine(Buffer.getBufferSize() ? Buffer.getBufferStart() : nullptr,
                  0) {
  // Ensure that if we are constructed on a non-empty memory buffer that it is
  // a null terminated buffer.
  if (Buffer.getBufferSize()) {
    assert(Buffer.getBufferEnd()[0] == '\0');
    // Make sure we don't skip a leading newline if we're keeping blanks
    if (SkipBlanks || !isAtLineEnd(Buffer.getBufferStart()))
      advance();
  }
}
  void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
    Module *M = AuxModule.get();

    // Create the new section name, it will consist of the reserved prefix
    // concatenated with the triple.
    std::string SectionName = OFFLOAD_BUNDLER_MAGIC_STR;
    SectionName += CurrentTriple;

    // Create the constant with the content of the section. For the input we are
    // bundling into (the host input), this is just a place-holder, so a single
    // byte is sufficient.
    assert(HostInputIndex != ~0u && "Host input index undefined??");
    Constant *Content;
    if (NumberOfProcessedInputs == HostInputIndex + 1) {
      uint8_t Byte[] = {0};
      Content = ConstantDataArray::get(VMContext, Byte);
    } else
      Content = ConstantDataArray::get(
          VMContext, ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(
                                           Input.getBufferStart()),
                                       Input.getBufferSize()));

    // Create the global in the desired section. We don't want these globals in
    // the symbol table, so we mark them private.
    auto *GV = new GlobalVariable(*M, Content->getType(), /*IsConstant=*/true,
                                  GlobalVariable::PrivateLinkage, Content);
    GV->setSection(SectionName);
  }
Пример #4
0
bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
  if (DataBuffer.getBufferSize() < sizeof(uint64_t))
    return false;
  uint64_t Magic =
    *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
  return RawInstrProf::getMagic<IntPtrT>() == Magic ||
         sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
}
Пример #5
0
bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
  // Verify that this really looks like plain ASCII text by checking a
  // 'reasonable' number of characters (up to profile magic size).
  size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
  StringRef buffer = Buffer.getBufferStart();
  return count == 0 || std::all_of(buffer.begin(), buffer.begin() + count,
    [](char c) { return ::isprint(c) || ::isspace(c); });
}
Пример #6
0
bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
  if (DataBuffer.getBufferSize() < 8)
    return false;
  using namespace support;
  uint64_t Magic =
      endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
  return Magic == IndexedInstrProf::Magic;
}
static void printFile(const sys::Path *err)
{
  std::string ErrMsg;
  ErrMsg.clear();
  MemoryBuffer *buf = MemoryBuffer::getFile(err->c_str(), &ErrMsg);
  errs().write(buf->getBufferStart(), buf->getBufferSize());
  delete buf;
}
// Write one member out to the file.
bool
Archive::writeMember(
  const ArchiveMember& member,
  raw_fd_ostream& ARFile,
  std::string* ErrMsg
) {

  uint64_t filepos = ARFile.tell();
  filepos -= 8;

  // Get the data and its size either from the
  // member's in-memory data or directly from the file.
  size_t fSize = member.getSize();
  const char *data = (const char*)member.getData();
  MemoryBuffer *mFile = 0;
  if (!data) {
    ErrorOr<std::unique_ptr<MemoryBuffer> > FileOrErr =
        MemoryBuffer::getFile(member.getPath());
    if (!FileOrErr) {
      if (ErrMsg)
        *ErrMsg = FileOrErr.getError().message();
      return true;
    }
    mFile = FileOrErr.get().release();
    data = mFile->getBufferStart();
    fSize = mFile->getBufferSize();
  }

  int hdrSize = fSize;

  // Compute the fields of the header
  ArchiveMemberHeader Hdr;
  bool writeLongName = fillHeader(member,Hdr,hdrSize);

  // Write header to archive file
  ARFile.write((char*)&Hdr, sizeof(Hdr));

  // Write the long filename if its long
  if (writeLongName) {
    StringRef Name = sys::path::filename(member.getPath());
    ARFile.write(Name.data(), Name.size());
  }

  // Write the (possibly compressed) member's content to the file.
  ARFile.write(data,fSize);

  // Make sure the member is an even length
  if ((ARFile.tell() & 1) == 1)
    ARFile << ARFILE_PAD;

  // Close the mapped file if it was opened
  delete mFile;
  return false;
}
  void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
    // If the current section has size one, that means that the content we are
    // interested in is the file itself. Otherwise it is the content of the
    // section.
    //
    // TODO: Instead of copying the input file as is, deactivate the section
    // that is no longer needed.

    StringRef Content;
    CurrentSection->getContents(Content);

    if (Content.size() < 2)
      OS.write(Input.getBufferStart(), Input.getBufferSize());
    else
      OS.write(Content.data(), Content.size());
  }
Пример #10
0
void LicenseInHeaderRule::run(const ast_matchers::MatchFinder::MatchResult& result)
{
    const TranslationUnitDecl* translationUnitDeclaration = result.Nodes.getNodeAs<TranslationUnitDecl>("translationUnitDecl");
    if (translationUnitDeclaration == nullptr)
        return;

    if (m_context.licenseTemplateLines.empty())
        return;

    SourceManager& sourceManager = *result.SourceManager;

    FileID mainFileID = m_context.sourceLocationHelper.GetMainFileID(sourceManager);

    MemoryBuffer* buffer = sourceManager.getBuffer(mainFileID);
    const char* bufferChars = buffer->getBufferStart();
    int bufferSize = buffer->getBufferSize();
    if (bufferSize == 0)
        return;

    int bufferPos = 0;
    int lineNumber = 0;
    for (const auto& licenseLine : m_context.licenseTemplateLines)
    {
        ++lineNumber;
        StringRef line = GetNextBufferLine(bufferChars, bufferPos, bufferSize);
        bufferPos += line.size();
        bufferPos += 1; // newline character
        if (line != licenseLine)
        {
            StringRef fileName = m_context.sourceLocationHelper.GetCleanFilename(mainFileID, sourceManager);

            m_context.outputPrinter->PrintRuleViolation(
                "license header",
                Severity::Style,
                boost::str(boost::format("File doesn't have proper license header; expected line was '%s'")
                    % licenseLine),
                fileName,
                lineNumber);

            break;
        }
    }
}
/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
static int AnalyzeBitcode() {
  // Read the input file.
  MemoryBuffer *MemBuf = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str());

  if (MemBuf == 0)
    return Error("Error reading '" + InputFilename + "'.");

  if (MemBuf->getBufferSize() & 3)
    return Error("Bitcode stream should be a multiple of 4 bytes in length");

  unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart();
  unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize();

  // If we have a wrapper header, parse it and ignore the non-bc file contents.
  // The magic number is 0x0B17C0DE stored in little endian.
  if (isBitcodeWrapper(BufPtr, EndBufPtr))
    if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr))
      return Error("Invalid bitcode wrapper header");

  BitstreamReader StreamFile(BufPtr, EndBufPtr);
  BitstreamCursor Stream(StreamFile);
  StreamFile.CollectBlockInfoNames();

  // Read the stream signature.
  char Signature[6];
  Signature[0] = Stream.Read(8);
  Signature[1] = Stream.Read(8);
  Signature[2] = Stream.Read(4);
  Signature[3] = Stream.Read(4);
  Signature[4] = Stream.Read(4);
  Signature[5] = Stream.Read(4);

  // Autodetect the file contents, if it is one we know.
  CurStreamType = UnknownBitstream;
  if (Signature[0] == 'B' && Signature[1] == 'C' &&
      Signature[2] == 0x0 && Signature[3] == 0xC &&
      Signature[4] == 0xE && Signature[5] == 0xD)
    CurStreamType = LLVMIRBitstream;

  unsigned NumTopBlocks = 0;

  // Parse the top-level structure.  We only allow blocks at the top-level.
  while (!Stream.AtEndOfStream()) {
    unsigned Code = Stream.ReadCode();
    if (Code != bitc::ENTER_SUBBLOCK)
      return Error("Invalid record at top-level");

    if (ParseBlock(Stream, 0))
      return true;
    ++NumTopBlocks;
  }

  if (Dump) errs() << "\n\n";

  uint64_t BufferSizeBits = (EndBufPtr-BufPtr)*CHAR_BIT;
  // Print a summary of the read file.
  errs() << "Summary of " << InputFilename << ":\n";
  errs() << "         Total size: ";
  PrintSize(BufferSizeBits);
  errs() << "\n";
  errs() << "        Stream type: ";
  switch (CurStreamType) {
  default: assert(0 && "Unknown bitstream type");
  case UnknownBitstream: errs() << "unknown\n"; break;
  case LLVMIRBitstream:  errs() << "LLVM IR\n"; break;
  }
  errs() << "  # Toplevel Blocks: " << NumTopBlocks << "\n";
  errs() << "\n";

  // Emit per-block stats.
  errs() << "Per-block Summary:\n";
  for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
       E = BlockIDStats.end(); I != E; ++I) {
    errs() << "  Block ID #" << I->first;
    if (const char *BlockName = GetBlockName(I->first, StreamFile))
      errs() << " (" << BlockName << ")";
    errs() << ":\n";

    const PerBlockIDStats &Stats = I->second;
    errs() << "      Num Instances: " << Stats.NumInstances << "\n";
    errs() << "         Total Size: ";
    PrintSize(Stats.NumBits);
    errs() << "\n";
    double pct = (Stats.NumBits * 100.0) / BufferSizeBits;
    errs() << "    Percent of file: " << format("%2.4f%%", pct) << "\n";
    if (Stats.NumInstances > 1) {
      errs() << "       Average Size: ";
      PrintSize(Stats.NumBits/(double)Stats.NumInstances);
      errs() << "\n";
      errs() << "  Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
             << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
      errs() << "    Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
             << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
      errs() << "    Tot/Avg Records: " << Stats.NumRecords << "/"
             << Stats.NumRecords/(double)Stats.NumInstances << "\n";
    } else {
      errs() << "      Num SubBlocks: " << Stats.NumSubBlocks << "\n";
      errs() << "        Num Abbrevs: " << Stats.NumAbbrevs << "\n";
      errs() << "        Num Records: " << Stats.NumRecords << "\n";
    }
    if (Stats.NumRecords) {
      double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords;
      errs() << "    Percent Abbrevs: " << format("%2.4f%%", pct) << "\n";
    }
    errs() << "\n";

    // Print a histogram of the codes we see.
    if (!NoHistogram && !Stats.CodeFreq.empty()) {
      std::vector<std::pair<unsigned, unsigned> > FreqPairs;  // <freq,code>
      for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)
        if (unsigned Freq = Stats.CodeFreq[i].NumInstances)
          FreqPairs.push_back(std::make_pair(Freq, i));
      std::stable_sort(FreqPairs.begin(), FreqPairs.end());
      std::reverse(FreqPairs.begin(), FreqPairs.end());

      errs() << "\tRecord Histogram:\n";
      fprintf(stderr, "\t\t  Count    # Bits   %% Abv  Record Kind\n");
      for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
        const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];

        fprintf(stderr, "\t\t%7d %9llu ", RecStats.NumInstances,
                (unsigned long long)RecStats.TotalBits);

        if (RecStats.NumAbbrev)
          fprintf(stderr, "%7.2f  ",
                  (double)RecStats.NumAbbrev/RecStats.NumInstances*100);
        else
          fprintf(stderr, "         ");

        if (const char *CodeName =
              GetCodeName(FreqPairs[i].second, I->first, StreamFile))
          fprintf(stderr, "%s\n", CodeName);
        else
          fprintf(stderr, "UnknownCode%d\n", FreqPairs[i].second);
      }
      errs() << "\n";

    }
  }
  return 0;
}
// Write one member out to the file.
bool
Archive::writeMember(
  const ArchiveMember& member,
  std::ofstream& ARFile,
  bool CreateSymbolTable,
  bool TruncateNames,
  bool ShouldCompress,
  std::string* ErrMsg
) {

  unsigned filepos = ARFile.tellp();
  filepos -= 8;

  // Get the data and its size either from the
  // member's in-memory data or directly from the file.
  size_t fSize = member.getSize();
  const char *data = (const char*)member.getData();
  MemoryBuffer *mFile = 0;
  if (!data) {
    mFile = MemoryBuffer::getFile(member.getPath().c_str(), ErrMsg);
    if (mFile == 0)
      return true;
    data = mFile->getBufferStart();
    fSize = mFile->getBufferSize();
  }

  // Now that we have the data in memory, update the
  // symbol table if its a bitcode file.
  if (CreateSymbolTable && member.isBitcode()) {
    std::vector<std::string> symbols;
    std::string FullMemberName = archPath.str() + "(" + member.getPath().str()
      + ")";
    Module* M = 
      GetBitcodeSymbols((const unsigned char*)data,fSize,
                        FullMemberName, Context, symbols, ErrMsg);

    // If the bitcode parsed successfully
    if ( M ) {
      for (std::vector<std::string>::iterator SI = symbols.begin(),
           SE = symbols.end(); SI != SE; ++SI) {

        std::pair<SymTabType::iterator,bool> Res =
          symTab.insert(std::make_pair(*SI,filepos));

        if (Res.second) {
          symTabSize += SI->length() +
                        numVbrBytes(SI->length()) +
                        numVbrBytes(filepos);
        }
      }
      // We don't need this module any more.
      delete M;
    } else {
      delete mFile;
      if (ErrMsg)
        *ErrMsg = "Can't parse bitcode member: " + member.getPath().str()
          + ": " + *ErrMsg;
      return true;
    }
  }

  int hdrSize = fSize;

  // Compute the fields of the header
  ArchiveMemberHeader Hdr;
  bool writeLongName = fillHeader(member,Hdr,hdrSize,TruncateNames);

  // Write header to archive file
  ARFile.write((char*)&Hdr, sizeof(Hdr));

  // Write the long filename if its long
  if (writeLongName) {
    ARFile.write(member.getPath().str().data(),
                 member.getPath().str().length());
  }

  // Write the (possibly compressed) member's content to the file.
  ARFile.write(data,fSize);

  // Make sure the member is an even length
  if ((ARFile.tellp() & 1) == 1)
    ARFile << ARFILE_PAD;

  // Close the mapped file if it was opened
  delete mFile;
  return false;
}
Пример #13
0
int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  cl::ParseCommandLineOptions(argc, argv);

  SourceMgr SM;

  // Read the expected strings from the check file.
  std::vector<CheckString> CheckStrings;
  if (ReadCheckFile(SM, CheckStrings))
    return 2;

  // Open the file to check and add it to SourceMgr.
  OwningPtr<MemoryBuffer> File;
  if (error_code ec =
        MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) {
    errs() << "Could not open input file '" << InputFilename << "': "
           << ec.message() << '\n';
    return 2;
  }
  MemoryBuffer *F = File.take();

  if (F->getBufferSize() == 0) {
    errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
    return 2;
  }
  
  // Remove duplicate spaces in the input file if requested.
  // Remove DOS style line endings.
  F = CanonicalizeInputFile(F, NoCanonicalizeWhiteSpace);

  SM.AddNewSourceBuffer(F, SMLoc());

  /// VariableTable - This holds all the current filecheck variables.
  StringMap<StringRef> VariableTable;

  // Check that we have all of the expected strings, in order, in the input
  // file.
  StringRef Buffer = F->getBuffer();

  const char *LastMatch = Buffer.data();

  for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
    const CheckString &CheckStr = CheckStrings[StrNo];

    StringRef SearchFrom = Buffer;

    // Find StrNo in the file.
    size_t MatchLen = 0;
    size_t MatchPos = CheckStr.Pat.Match(Buffer, MatchLen, VariableTable);
    Buffer = Buffer.substr(MatchPos);

    // If we didn't find a match, reject the input.
    if (MatchPos == StringRef::npos) {
      PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable);
      return 1;
    }

    StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);

    // If this check is a "CHECK-NEXT", verify that the previous match was on
    // the previous line (i.e. that there is one newline between them).
    if (CheckStr.IsCheckNext) {
      // Count the number of newlines between the previous match and this one.
      assert(LastMatch != F->getBufferStart() &&
             "CHECK-NEXT can't be the first check in a file");

      unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
      if (NumNewLines == 0) {
        SM.PrintMessage(CheckStr.Loc, SourceMgr::DK_Error,
                    CheckPrefix+"-NEXT: is on the same line as previous match");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        SourceMgr::DK_Note, "'next' match was here");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch), SourceMgr::DK_Note,
                        "previous match was here");
        return 1;
      }

      if (NumNewLines != 1) {
        SM.PrintMessage(CheckStr.Loc, SourceMgr::DK_Error, CheckPrefix+
                        "-NEXT: is not on the line after the previous match");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        SourceMgr::DK_Note, "'next' match was here");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch), SourceMgr::DK_Note,
                        "previous match was here");
        return 1;
      }
    }

    // If this match had "not strings", verify that they don't exist in the
    // skipped region.
    for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size();
         ChunkNo != e; ++ChunkNo) {
      size_t MatchLen = 0;
      size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion,
                                                             MatchLen,
                                                             VariableTable);
      if (Pos == StringRef::npos) continue;

      SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos), SourceMgr::DK_Error,
                      CheckPrefix+"-NOT: string occurred!");
      SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first, SourceMgr::DK_Note,
                      CheckPrefix+"-NOT: pattern specified here");
      return 1;
    }


    // Otherwise, everything is good.  Step over the matched text and remember
    // the position after the match as the end of the last match.
    Buffer = Buffer.substr(MatchLen);
    LastMatch = Buffer.data();
  }

  return 0;
}
 void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
   OS.write(Input.getBufferStart(), Input.getBufferSize());
 }
/// LinkInFile - opens a bitcode file and links in all objects which
/// provide symbols that are currently undefined.
///
/// Inputs:
///  File - The pathname of the bitcode file.
///
/// Outputs:
///  ErrorMessage - A C++ string detailing what error occurred, if any.
///
/// Return Value:
///  TRUE  - An error occurred.
///  FALSE - No errors.
///
bool Linker::LinkInFile(const sys::Path &File, bool &is_native) {
  is_native = false;
  
  // Check for a file of name "-", which means "read standard input"
  if (File.str() == "-") {
    std::auto_ptr<Module> M;
    MemoryBuffer *Buffer = MemoryBuffer::getSTDIN();
    if (!Buffer->getBufferSize()) {
      delete Buffer;
      Error = "standard input is empty";
    } else {
      M.reset(ParseBitcodeFile(Buffer, Context, &Error));
      delete Buffer;
      if (M.get())
        if (!LinkInModule(M.get(), &Error))
          return false;
    }
    return error("Cannot link stdin: " + Error);
  }

  // Make sure we can at least read the file
  if (!File.canRead())
    return error("Cannot find linker input '" + File.str() + "'");

  // If its an archive, try to link it in
  std::string Magic;
  File.getMagicNumber(Magic, 64);
  switch (sys::IdentifyFileType(Magic.c_str(), 64)) {
    default: llvm_unreachable("Bad file type identification");
    case sys::Unknown_FileType:
      return warning("Ignoring file '" + File.str() + 
                   "' because does not contain bitcode.");

    case sys::Archive_FileType:
      // A user may specify an ar archive without -l, perhaps because it
      // is not installed as a library. Detect that and link the archive.
      if (LinkInArchive(File, is_native))
        return true;
      break;

    case sys::Bitcode_FileType: {
      verbose("Linking bitcode file '" + File.str() + "'");
      std::auto_ptr<Module> M(LoadObject(File));
      if (M.get() == 0)
        return error("Cannot load file '" + File.str() + "': " + Error);
      if (LinkInModule(M.get(), &Error))
        return error("Cannot link file '" + File.str() + "': " + Error);

      verbose("Linked in file '" + File.str() + "'");
      break;
    }

    case sys::ELF_Relocatable_FileType:
    case sys::ELF_SharedObject_FileType:
    case sys::Mach_O_Object_FileType:
    case sys::Mach_O_FixedVirtualMemorySharedLib_FileType:
    case sys::Mach_O_DynamicallyLinkedSharedLib_FileType:
    case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType:
    case sys::COFF_FileType:
      is_native = true;
      break;
  }
  return false;
}
/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
static int AnalyzeBitcode() {
  // Read the input file.
  MemoryBuffer *Buffer;
  if (InputFilename == "-")
    Buffer = MemoryBuffer::getSTDIN();
  else
    Buffer = MemoryBuffer::getFile(&InputFilename[0], InputFilename.size());

  if (Buffer == 0)
    return Error("Error reading '" + InputFilename + "'.");
  
  if (Buffer->getBufferSize() & 3)
    return Error("Bitcode stream should be a multiple of 4 bytes in length");
  
  unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
  BitstreamReader Stream(BufPtr, BufPtr+Buffer->getBufferSize());

  
  // Read the stream signature.
  char Signature[6];
  Signature[0] = Stream.Read(8);
  Signature[1] = Stream.Read(8);
  Signature[2] = Stream.Read(4);
  Signature[3] = Stream.Read(4);
  Signature[4] = Stream.Read(4);
  Signature[5] = Stream.Read(4);
  
  // Autodetect the file contents, if it is one we know.
  CurStreamType = UnknownBitstream;
  if (Signature[0] == 'B' && Signature[1] == 'C' &&
      Signature[2] == 0x0 && Signature[3] == 0xC &&
      Signature[4] == 0xE && Signature[5] == 0xD)
    CurStreamType = LLVMIRBitstream;

  unsigned NumTopBlocks = 0;
  
  // Parse the top-level structure.  We only allow blocks at the top-level.
  while (!Stream.AtEndOfStream()) {
    unsigned Code = Stream.ReadCode();
    if (Code != bitc::ENTER_SUBBLOCK)
      return Error("Invalid record at top-level");
    
    if (ParseBlock(Stream, 0))
      return true;
    ++NumTopBlocks;
  }
  
  if (Dump) std::cerr << "\n\n";
  
  uint64_t BufferSizeBits = Buffer->getBufferSize()*8;
  // Print a summary of the read file.
  std::cerr << "Summary of " << InputFilename << ":\n";
  std::cerr << "         Total size: ";
  PrintSize(BufferSizeBits);
  std::cerr << "\n";
  std::cerr << "        Stream type: ";
  switch (CurStreamType) {
  default: assert(0 && "Unknown bitstream type");
  case UnknownBitstream: std::cerr << "unknown\n"; break;
  case LLVMIRBitstream:  std::cerr << "LLVM IR\n"; break;
  }
  std::cerr << "  # Toplevel Blocks: " << NumTopBlocks << "\n";
  std::cerr << "\n";

  // Emit per-block stats.
  std::cerr << "Per-block Summary:\n";
  for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
       E = BlockIDStats.end(); I != E; ++I) {
    std::cerr << "  Block ID #" << I->first;
    if (const char *BlockName = GetBlockName(I->first))
      std::cerr << " (" << BlockName << ")";
    std::cerr << ":\n";
    
    const PerBlockIDStats &Stats = I->second;
    std::cerr << "      Num Instances: " << Stats.NumInstances << "\n";
    std::cerr << "         Total Size: ";
    PrintSize(Stats.NumBits);
    std::cerr << "\n";
    std::cerr << "          % of file: "
              << Stats.NumBits/(double)BufferSizeBits*100 << "\n";
    if (Stats.NumInstances > 1) {
      std::cerr << "       Average Size: ";
      PrintSize(Stats.NumBits/(double)Stats.NumInstances);
      std::cerr << "\n";
      std::cerr << "  Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
                << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
      std::cerr << "    Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
                << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
      std::cerr << "    Tot/Avg Records: " << Stats.NumRecords << "/"
                << Stats.NumRecords/(double)Stats.NumInstances << "\n";
    } else {
      std::cerr << "      Num SubBlocks: " << Stats.NumSubBlocks << "\n";
      std::cerr << "        Num Abbrevs: " << Stats.NumAbbrevs << "\n";
      std::cerr << "        Num Records: " << Stats.NumRecords << "\n";
    }
    if (Stats.NumRecords)
      std::cerr << "      % Abbrev Recs: " << (Stats.NumAbbreviatedRecords/
                   (double)Stats.NumRecords)*100 << "\n";
    std::cerr << "\n";
    
    // Print a histogram of the codes we see.
    if (!NoHistogram && !Stats.CodeFreq.empty()) {
      std::vector<std::pair<unsigned, unsigned> > FreqPairs;  // <freq,code>
      for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)
        if (unsigned Freq = Stats.CodeFreq[i])
          FreqPairs.push_back(std::make_pair(Freq, i));
      std::stable_sort(FreqPairs.begin(), FreqPairs.end());
      std::reverse(FreqPairs.begin(), FreqPairs.end());
      
      std::cerr << "\tCode Histogram:\n";
      for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
        std::cerr << "\t\t" << FreqPairs[i].first << "\t";
        if (const char *CodeName = GetCodeName(FreqPairs[i].second, I->first))
          std::cerr << CodeName << "\n";
        else
          std::cerr << "UnknownCode" << FreqPairs[i].second << "\n";
      }
      std::cerr << "\n";
      
    }
  }
  return 0;
}
Пример #17
0
int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " BrainF compiler\n");

  if (InputFilename == "") {
    errs() << "Error: You must specify the filename of the program to "
    "be compiled.  Use --help to see the options.\n";
    abort();
  }

  // Read the input file.
  MemoryBuffer *Code = MemoryBuffer::getFileOrSTDIN(InputFilename);
  const uint8_t *CodeBegin = (const uint8_t*)(Code->getBufferStart());
  
  // Create a new buffer to hold the preprocessed code.
  MemoryBuffer *ParsedCode =
    MemoryBuffer::getNewMemBuffer(sizeof(opcode_func_t) * 
                                  (Code->getBufferSize()+1));
  BytecodeArray = (opcode_func_t*)(ParsedCode->getBufferStart());
  size_t BytecodeOffset = 0;
  
  // Create JumpMap, a special on-the-side data array used to implement
  // efficient jumps in the interpreter.
  JumpMap = new size_t[Code->getBufferSize()];
  memset(JumpMap, 0, sizeof(size_t) * Code->getBufferSize());
  std::vector<size_t> Stack;
  
  // Preprocess the input source code, performing three tasks:
  //  1 - Remove non-instruction characters
  //  2 - Replace character literals with opcode function pointers
  //  3 - Precompute the jump targets for [ and ] instructions in JumpMap
  for (size_t i = 0; i < Code->getBufferSize(); ++i) {
    uint8_t opcode = CodeBegin[i];
    switch (opcode) {
      case '>':
        BytecodeArray[BytecodeOffset++] = &op_right;
        break;
      case '<':
        BytecodeArray[BytecodeOffset++] = &op_left;
        break;
      case '+':
        BytecodeArray[BytecodeOffset++] = &op_plus;
        break;
      case '-':
        BytecodeArray[BytecodeOffset++] = &op_minus;
        break;
      case '.':
        BytecodeArray[BytecodeOffset++] = &op_put;
        break;
      case ',':
        BytecodeArray[BytecodeOffset++] = &op_get;
        break;
      case '[':
        Stack.push_back(BytecodeOffset);
        BytecodeArray[BytecodeOffset++] = &op_if;
        break;
      case ']':
        // Special case: [-] --> 0
        if (CodeBegin[i-1] == '-' && CodeBegin[i-2] == '[') {
          Stack.pop_back();
          BytecodeOffset -= 2;
          BytecodeArray[BytecodeOffset++] = &op_set_zero;
        } else {
          JumpMap[Stack.back()] = BytecodeOffset;
          JumpMap[BytecodeOffset] = Stack.back();
          Stack.pop_back();
          BytecodeArray[BytecodeOffset++] = &op_back;
        }
        break;
      default:
        continue;
    }
  }
  
  // Fill in the suffix of the preprocessed source for op_exit.
  // Thus, if we reach the end of the source, the program will terminate.
  while (BytecodeOffset < Code->getBufferSize()+1) {
    BytecodeArray[BytecodeOffset++] = &op_end;
  }
  
  // Setup the array.
  uint8_t *BrainFArray = new uint8_t[32768];
  memset(BrainFArray, 0, 32768);
  
  // Setup the trace recorder.
  Recorder = new BrainFTraceRecorder();
  
  // Main interpreter loop.
  // Note the lack of a explicit loop: every opcode is a tail-recursive
  // function that calls its own successor by indexing into BytecodeArray.
  uint8_t* data = BrainFArray;  
  BytecodeArray[0](0, data);
  
  //Clean up
  delete Recorder;
  delete Code;
  delete ParsedCode;
  delete[] BrainFArray;
  delete[] JumpMap;

  return 0;
}