Home | History | Annotate | Download | only in pnacl-llvm
      1 //===- NaClBitcodeHeader.cpp ----------------------------------------------===//
      2 //     PNaCl bitcode header reader.
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is distributed under the University of Illinois Open Source
      7 // License. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 //
     11 // Implementation of Bitcode abbrevations.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/Bitcode/NaCl/NaClBitCodes.h"
     16 #include "llvm/Support/raw_ostream.h"
     17 #include "llvm/Support/ErrorHandling.h"
     18 
     19 using namespace llvm;
     20 
     21 const bool NaClBitCodeAbbrevOp::HasValueArray[] = {
     22   true,  // Literal
     23   true,  // Fixed
     24   true,  // VBR
     25   false, // Array
     26   false  // Char6
     27 };
     28 
     29 const char *NaClBitCodeAbbrevOp::EncodingNameArray[] = {
     30   "Literal",
     31   "Fixed",
     32   "VBR",
     33   "Array",
     34   "Char6"
     35 };
     36 
     37 NaClBitCodeAbbrevOp::NaClBitCodeAbbrevOp(Encoding E, uint64_t Data)
     38     : Enc(E), Val(Data) {
     39   if (isValid(E, Data)) return;
     40   std::string Buffer;
     41   raw_string_ostream StrBuf(Buffer);
     42   StrBuf << "Invalid NaClBitCodeAbbrevOp(" << E << ", " << Data << ")";
     43   report_fatal_error(StrBuf.str());
     44 }
     45 
     46 bool NaClBitCodeAbbrevOp::isValid(Encoding E, uint64_t Val) {
     47   switch (NaClBitCodeAbbrevOp::Encoding(E)) {
     48   case Literal:
     49     return true;
     50   case Fixed:
     51   case VBR:
     52     return Val <= naclbitc::MaxAbbrevWidth;
     53   case Char6:
     54   case Array:
     55     return Val == 0;
     56   }
     57   llvm_unreachable("unhandled abbreviation");
     58 }
     59 
     60 void NaClBitCodeAbbrevOp::Print(raw_ostream& Stream) const {
     61   if (Enc == Literal) {
     62     Stream << getValue();
     63     return;
     64   }
     65   Stream << getEncodingName(Enc);
     66   if (!hasValue())
     67     return;
     68   Stream << "(" << Val << ")";
     69 }
     70 
     71 static void PrintExpression(raw_ostream &Stream,
     72                             const NaClBitCodeAbbrev *Abbrev,
     73                             unsigned &Index) {
     74   // Bail out early, in case we are incrementally building the
     75   // expression and the argument is not available yet.
     76   if (Index >= Abbrev->getNumOperandInfos()) return;
     77 
     78   const NaClBitCodeAbbrevOp &Op = Abbrev->getOperandInfo(Index);
     79   Op.Print(Stream);
     80   if (unsigned NumArgs = Op.NumArguments()) {
     81     Stream << "(";
     82     for (unsigned i = 0; i < NumArgs; ++i) {
     83       ++Index;
     84       if (i > 0) Stream << ",";
     85       PrintExpression(Stream, Abbrev, Index);
     86     }
     87     Stream << ")";
     88   }
     89 }
     90 
     91 void NaClBitCodeAbbrev::Print(raw_ostream &Stream, bool AddNewLine) const {
     92   Stream << "[";
     93   for (unsigned i = 0; i < getNumOperandInfos(); ++i) {
     94     if (i > 0) Stream << ", ";
     95     PrintExpression(Stream, this, i);
     96   }
     97   Stream << "]";
     98   if (AddNewLine) Stream << "\n";
     99 }
    100 
    101 NaClBitCodeAbbrev *NaClBitCodeAbbrev::Simplify() const {
    102   NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
    103   for (unsigned i = 0; i < OperandList.size(); ++i) {
    104     const NaClBitCodeAbbrevOp &Op = OperandList[i];
    105     // Simplify if possible.  Currently, the only simplification known
    106     // is to remove unnecessary operands appearing immediately before an
    107     // array operator. That is, apply the simplification:
    108     //    Op Array(Op) -> Array(Op)
    109     assert(!Op.isArrayOp() || i == OperandList.size()-2);
    110     while (Op.isArrayOp() && !Abbrev->OperandList.empty() &&
    111            Abbrev->OperandList.back() == OperandList[i+1]) {
    112       Abbrev->OperandList.pop_back();
    113     }
    114     Abbrev->OperandList.push_back(Op);
    115   }
    116   return Abbrev;
    117 }
    118 
    119 bool NaClBitCodeAbbrev::isValid() const {
    120   // Verify that an array op appears can only appear if it is the
    121   // second to last element.
    122   unsigned NumOperands = getNumOperandInfos();
    123   if (NumOperands == 0) return false;
    124   for (unsigned i = 0; i < NumOperands; ++i) {
    125     const NaClBitCodeAbbrevOp &Op = getOperandInfo(i);
    126     if (Op.isArrayOp() && i + 2 != NumOperands)
    127       // Note: Unlike LLVM bitcode, we allow literals in arrays!
    128       return false;
    129   }
    130   return true;
    131 }
    132