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