blob: e20e961a56cb709afd285e370436867517e6992f [file] [log] [blame]
Jim Stichnotha5b16ab2016-05-10 11:20:41 -07001//===- 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"
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070016#include "llvm/Support/ErrorHandling.h"
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050017#include "llvm/Support/raw_ostream.h"
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070018
19using namespace llvm;
20
21const bool NaClBitCodeAbbrevOp::HasValueArray[] = {
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050022 true, // Literal
23 true, // Fixed
24 true, // VBR
25 false, // Array
26 false // Char6
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070027};
28
29const char *NaClBitCodeAbbrevOp::EncodingNameArray[] = {
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050030 "Literal", "Fixed", "VBR", "Array", "Char6"};
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070031
32NaClBitCodeAbbrevOp::NaClBitCodeAbbrevOp(Encoding E, uint64_t Data)
33 : Enc(E), Val(Data) {
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050034 if (isValid(E, Data))
35 return;
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070036 std::string Buffer;
37 raw_string_ostream StrBuf(Buffer);
38 StrBuf << "Invalid NaClBitCodeAbbrevOp(" << E << ", " << Data << ")";
39 report_fatal_error(StrBuf.str());
40}
41
42bool 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
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050056void NaClBitCodeAbbrevOp::Print(raw_ostream &Stream) const {
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070057 if (Enc == Literal) {
58 Stream << getValue();
59 return;
60 }
61 Stream << getEncodingName(Enc);
62 if (!hasValue())
63 return;
64 Stream << "(" << Val << ")";
65}
66
67static void PrintExpression(raw_ostream &Stream,
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050068 const NaClBitCodeAbbrev *Abbrev, unsigned &Index) {
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070069 // Bail out early, in case we are incrementally building the
70 // expression and the argument is not available yet.
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050071 if (Index >= Abbrev->getNumOperandInfos())
72 return;
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070073
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;
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050080 if (i > 0)
81 Stream << ",";
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070082 PrintExpression(Stream, Abbrev, Index);
83 }
84 Stream << ")";
85 }
86}
87
88void NaClBitCodeAbbrev::Print(raw_ostream &Stream, bool AddNewLine) const {
89 Stream << "[";
90 for (unsigned i = 0; i < getNumOperandInfos(); ++i) {
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050091 if (i > 0)
92 Stream << ", ";
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070093 PrintExpression(Stream, this, i);
94 }
95 Stream << "]";
Antonio Maioranoca8a16e2020-11-10 16:56:20 -050096 if (AddNewLine)
97 Stream << "\n";
Jim Stichnotha5b16ab2016-05-10 11:20:41 -070098}
99
100NaClBitCodeAbbrev *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)
Antonio Maioranoca8a16e2020-11-10 16:56:20 -0500108 assert(!Op.isArrayOp() || i == OperandList.size() - 2);
Jim Stichnotha5b16ab2016-05-10 11:20:41 -0700109 while (Op.isArrayOp() && !Abbrev->OperandList.empty() &&
Antonio Maioranoca8a16e2020-11-10 16:56:20 -0500110 Abbrev->OperandList.back() == OperandList[i + 1]) {
Jim Stichnotha5b16ab2016-05-10 11:20:41 -0700111 Abbrev->OperandList.pop_back();
112 }
113 Abbrev->OperandList.push_back(Op);
114 }
115 return Abbrev;
116}
117
118bool 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();
Antonio Maioranoca8a16e2020-11-10 16:56:20 -0500122 if (NumOperands == 0)
123 return false;
Jim Stichnotha5b16ab2016-05-10 11:20:41 -0700124 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}