| Index: pnacl-llvm/NaClBitCodes.cpp
|
| diff --git a/pnacl-llvm/NaClBitCodes.cpp b/pnacl-llvm/NaClBitCodes.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7267411519425b6122d987840389f4fa50b54836
|
| --- /dev/null
|
| +++ b/pnacl-llvm/NaClBitCodes.cpp
|
| @@ -0,0 +1,131 @@
|
| +//===- NaClBitcodeHeader.cpp ----------------------------------------------===//
|
| +// PNaCl bitcode header reader.
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// Implementation of Bitcode abbrevations.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#include "llvm/Bitcode/NaCl/NaClBitCodes.h"
|
| +#include "llvm/Support/raw_ostream.h"
|
| +#include "llvm/Support/ErrorHandling.h"
|
| +
|
| +using namespace llvm;
|
| +
|
| +const bool NaClBitCodeAbbrevOp::HasValueArray[] = {
|
| + true, // Literal
|
| + true, // Fixed
|
| + true, // VBR
|
| + false, // Array
|
| + false // Char6
|
| +};
|
| +
|
| +const char *NaClBitCodeAbbrevOp::EncodingNameArray[] = {
|
| + "Literal",
|
| + "Fixed",
|
| + "VBR",
|
| + "Array",
|
| + "Char6"
|
| +};
|
| +
|
| +NaClBitCodeAbbrevOp::NaClBitCodeAbbrevOp(Encoding E, uint64_t Data)
|
| + : Enc(E), Val(Data) {
|
| + if (isValid(E, Data)) return;
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Invalid NaClBitCodeAbbrevOp(" << E << ", " << Data << ")";
|
| + report_fatal_error(StrBuf.str());
|
| +}
|
| +
|
| +bool NaClBitCodeAbbrevOp::isValid(Encoding E, uint64_t Val) {
|
| + switch (NaClBitCodeAbbrevOp::Encoding(E)) {
|
| + case Literal:
|
| + return true;
|
| + case Fixed:
|
| + case VBR:
|
| + return Val <= naclbitc::MaxAbbrevWidth;
|
| + case Char6:
|
| + case Array:
|
| + return Val == 0;
|
| + }
|
| + llvm_unreachable("unhandled abbreviation");
|
| +}
|
| +
|
| +void NaClBitCodeAbbrevOp::Print(raw_ostream& Stream) const {
|
| + if (Enc == Literal) {
|
| + Stream << getValue();
|
| + return;
|
| + }
|
| + Stream << getEncodingName(Enc);
|
| + if (!hasValue())
|
| + return;
|
| + Stream << "(" << Val << ")";
|
| +}
|
| +
|
| +static void PrintExpression(raw_ostream &Stream,
|
| + const NaClBitCodeAbbrev *Abbrev,
|
| + unsigned &Index) {
|
| + // Bail out early, in case we are incrementally building the
|
| + // expression and the argument is not available yet.
|
| + if (Index >= Abbrev->getNumOperandInfos()) return;
|
| +
|
| + const NaClBitCodeAbbrevOp &Op = Abbrev->getOperandInfo(Index);
|
| + Op.Print(Stream);
|
| + if (unsigned NumArgs = Op.NumArguments()) {
|
| + Stream << "(";
|
| + for (unsigned i = 0; i < NumArgs; ++i) {
|
| + ++Index;
|
| + if (i > 0) Stream << ",";
|
| + PrintExpression(Stream, Abbrev, Index);
|
| + }
|
| + Stream << ")";
|
| + }
|
| +}
|
| +
|
| +void NaClBitCodeAbbrev::Print(raw_ostream &Stream, bool AddNewLine) const {
|
| + Stream << "[";
|
| + for (unsigned i = 0; i < getNumOperandInfos(); ++i) {
|
| + if (i > 0) Stream << ", ";
|
| + PrintExpression(Stream, this, i);
|
| + }
|
| + Stream << "]";
|
| + if (AddNewLine) Stream << "\n";
|
| +}
|
| +
|
| +NaClBitCodeAbbrev *NaClBitCodeAbbrev::Simplify() const {
|
| + NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
|
| + for (unsigned i = 0; i < OperandList.size(); ++i) {
|
| + const NaClBitCodeAbbrevOp &Op = OperandList[i];
|
| + // Simplify if possible. Currently, the only simplification known
|
| + // is to remove unnecessary operands appearing immediately before an
|
| + // array operator. That is, apply the simplification:
|
| + // Op Array(Op) -> Array(Op)
|
| + assert(!Op.isArrayOp() || i == OperandList.size()-2);
|
| + while (Op.isArrayOp() && !Abbrev->OperandList.empty() &&
|
| + Abbrev->OperandList.back() == OperandList[i+1]) {
|
| + Abbrev->OperandList.pop_back();
|
| + }
|
| + Abbrev->OperandList.push_back(Op);
|
| + }
|
| + return Abbrev;
|
| +}
|
| +
|
| +bool NaClBitCodeAbbrev::isValid() const {
|
| + // Verify that an array op appears can only appear if it is the
|
| + // second to last element.
|
| + unsigned NumOperands = getNumOperandInfos();
|
| + if (NumOperands == 0) return false;
|
| + for (unsigned i = 0; i < NumOperands; ++i) {
|
| + const NaClBitCodeAbbrevOp &Op = getOperandInfo(i);
|
| + if (Op.isArrayOp() && i + 2 != NumOperands)
|
| + // Note: Unlike LLVM bitcode, we allow literals in arrays!
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
|
|