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