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