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/ErrorHandling.h"
17 #include "llvm/Support/raw_ostream.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", "Fixed", "VBR", "Array", "Char6"};
31
NaClBitCodeAbbrevOp(Encoding E,uint64_t Data)32 NaClBitCodeAbbrevOp::NaClBitCodeAbbrevOp(Encoding E, uint64_t Data)
33 : Enc(E), Val(Data) {
34 if (isValid(E, Data))
35 return;
36 std::string Buffer;
37 raw_string_ostream StrBuf(Buffer);
38 StrBuf << "Invalid NaClBitCodeAbbrevOp(" << E << ", " << Data << ")";
39 report_fatal_error(StrBuf.str());
40 }
41
isValid(Encoding E,uint64_t Val)42 bool NaClBitCodeAbbrevOp::isValid(Encoding E, uint64_t Val) {
43 switch (NaClBitCodeAbbrevOp::Encoding(E)) {
44 case Literal:
45 return true;
46 case Fixed:
47 case VBR:
48 return Val <= naclbitc::MaxAbbrevWidth;
49 case Char6:
50 case Array:
51 return Val == 0;
52 }
53 llvm_unreachable("unhandled abbreviation");
54 }
55
Print(raw_ostream & Stream) const56 void NaClBitCodeAbbrevOp::Print(raw_ostream &Stream) const {
57 if (Enc == Literal) {
58 Stream << getValue();
59 return;
60 }
61 Stream << getEncodingName(Enc);
62 if (!hasValue())
63 return;
64 Stream << "(" << Val << ")";
65 }
66
PrintExpression(raw_ostream & Stream,const NaClBitCodeAbbrev * Abbrev,unsigned & Index)67 static void PrintExpression(raw_ostream &Stream,
68 const NaClBitCodeAbbrev *Abbrev, unsigned &Index) {
69 // Bail out early, in case we are incrementally building the
70 // expression and the argument is not available yet.
71 if (Index >= Abbrev->getNumOperandInfos())
72 return;
73
74 const NaClBitCodeAbbrevOp &Op = Abbrev->getOperandInfo(Index);
75 Op.Print(Stream);
76 if (unsigned NumArgs = Op.NumArguments()) {
77 Stream << "(";
78 for (unsigned i = 0; i < NumArgs; ++i) {
79 ++Index;
80 if (i > 0)
81 Stream << ",";
82 PrintExpression(Stream, Abbrev, Index);
83 }
84 Stream << ")";
85 }
86 }
87
Print(raw_ostream & Stream,bool AddNewLine) const88 void NaClBitCodeAbbrev::Print(raw_ostream &Stream, bool AddNewLine) const {
89 Stream << "[";
90 for (unsigned i = 0; i < getNumOperandInfos(); ++i) {
91 if (i > 0)
92 Stream << ", ";
93 PrintExpression(Stream, this, i);
94 }
95 Stream << "]";
96 if (AddNewLine)
97 Stream << "\n";
98 }
99
Simplify() const100 NaClBitCodeAbbrev *NaClBitCodeAbbrev::Simplify() const {
101 NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
102 for (unsigned i = 0; i < OperandList.size(); ++i) {
103 const NaClBitCodeAbbrevOp &Op = OperandList[i];
104 // Simplify if possible. Currently, the only simplification known
105 // is to remove unnecessary operands appearing immediately before an
106 // array operator. That is, apply the simplification:
107 // Op Array(Op) -> Array(Op)
108 assert(!Op.isArrayOp() || i == OperandList.size() - 2);
109 while (Op.isArrayOp() && !Abbrev->OperandList.empty() &&
110 Abbrev->OperandList.back() == OperandList[i + 1]) {
111 Abbrev->OperandList.pop_back();
112 }
113 Abbrev->OperandList.push_back(Op);
114 }
115 return Abbrev;
116 }
117
isValid() const118 bool NaClBitCodeAbbrev::isValid() const {
119 // Verify that an array op appears can only appear if it is the
120 // second to last element.
121 unsigned NumOperands = getNumOperandInfos();
122 if (NumOperands == 0)
123 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