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