blob: f914cc24988b427c5373be0088733206bbfb4955 [file] [log] [blame]
//===- NaClBitCodes.h - Enum values for the bitcode format ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header Bitcode enum values.
//
// The enum values defined in this file should be considered permanent. If
// new features are added, they should have values added at the end of the
// respective lists.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_BITCODE_NACL_NACLBITCODES_H
#define LLVM_BITCODE_NACL_NACLBITCODES_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <climits>
namespace llvm {
class raw_ostream;
namespace naclbitc {
enum StandardWidths {
BlockIDWidth = 8, // We use VBR-8 for block IDs.
CodeLenWidth = 4, // Codelen are VBR-4.
BlockSizeWidth = 32, // BlockSize up to 2^32 32-bit words = 16GB per block.
MaxAbbrevWidth = 32, // Maximum value allowed for Fixed and VBR.
BitstreamWordSize = sizeof(uint32_t), // Number of bytes in bitstream word.
MinRecordBitSize = 2 // Minimum number of bits needed to represent a record.
};
// The standard abbrev namespace always has a way to exit a block, enter a
// nested block, define abbrevs, and define an unabbreviated record.
enum FixedAbbrevIDs {
END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode.
ENTER_SUBBLOCK = 1,
/// DEFINE_ABBREV - Defines an abbrev for the current block. It consists
/// of a vbr5 for # operand infos. Each operand info is emitted with a
/// single bit to indicate if it is a literal encoding. If so, the value is
/// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed
/// by the info value as a vbr5 if needed.
DEFINE_ABBREV = 2,
// UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by
// a vbr6 for the # operands, followed by vbr6's for each operand.
UNABBREV_RECORD = 3,
// This is not a code, this is a marker for the first abbrev assignment.
// In addition, we assume up to two additional enumerated constants are
// added for each extension. These constants are:
//
// PREFIX_MAX_FIXED_ABBREV
// PREFIX_MAX_ABBREV
//
// PREFIX_MAX_ABBREV defines the maximal enumeration value used for
// the code selector of a block. If Both PREFIX_MAX_FIXED_ABBREV
// and PREFIX_MAX_ABBREV is defined, then PREFIX_MAX_FIXED_ABBREV
// defines the last code selector of the block that must be read using
// a single read (i.e. a FIXED read, or the first chunk of a VBR read.
FIRST_APPLICATION_ABBREV = 4,
// Defines default values for code length, if no additional selectors
// are added.
DEFAULT_MAX_ABBREV = FIRST_APPLICATION_ABBREV - 1
};
/// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO
/// block, which contains metadata about other blocks in the file.
enum StandardBlockIDs {
/// BLOCKINFO_BLOCK is used to define metadata about blocks, for example,
/// standard abbrevs that should be available to all blocks of a specified
/// ID.
BLOCKINFO_BLOCK_ID = 0,
// Block IDs 1-6 are reserved for future expansion.
// Dummy block added around all records in a bitcode file. Allows the code
// to treat top-level records like all other records (i.e. all records
// appear in a block).
TOP_LEVEL_BLOCKID = 7,
FIRST_APPLICATION_BLOCKID = 8
};
/// BlockInfoCodes - The blockinfo block contains metadata about user-defined
/// blocks.
enum BlockInfoCodes {
// DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd
// block, instead of the BlockInfo block.
BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#]
// The following two codes were removed
// because the PNaCl reader could read
// them, but couldn't be generated by
// the writer.
BLOCKINFO_CODE_BLOCKNAME = 2, // Not used in PNaCl.
BLOCKINFO_CODE_SETRECORDNAME = 3 // Not used in PNaCl.
};
} // namespace naclbitc
/// NaClBitCodeAbbrevOp - This describes one or more operands in an
/// abbreviation. This is actually a union of two different things:
/// 1. It could be a literal integer value ("the operand is always 17").
/// 2. It could be an encoding specification ("this operand encoded like so").
///
class NaClBitCodeAbbrevOp {
public:
enum Encoding {
Literal = 0, // Value is literal value.
Fixed = 1, // A fixed width field, Val specifies number of bits.
VBR = 2, // A VBR field where Val specifies the width of each chunk.
Array = 3, // A sequence of fields, next field species elt encoding.
Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._].
Encoding_MAX = Char6
};
explicit NaClBitCodeAbbrevOp(uint64_t V) : Enc(Literal), Val(V) {}
explicit NaClBitCodeAbbrevOp(Encoding E, uint64_t Data = 0);
Encoding getEncoding() const { return Enc; }
static bool isValidEncoding(uint64_t Enc) { return Enc <= Encoding_MAX; }
uint64_t getValue() const { return Val; }
bool hasValue() const { return hasValue(Enc); }
static bool hasValue(Encoding E) {
return E <= Encoding_MAX && HasValueArray[E];
}
bool isValid() const { return isValid(Enc, Val); }
static bool isValid(Encoding E, uint64_t Val);
static bool isValid(Encoding E) { return isValid(E, 0); }
bool isLiteral() const { return Enc == Literal; }
bool isArrayOp() const { return Enc == Array; }
/// Returns the number of arguments expected by this abbrevation operator.
unsigned NumArguments() const {
if (isArrayOp())
return 1;
else
return 0;
}
// Returns the name of the encoding
static const char *getEncodingName(Encoding E) {
if (E > Encoding_MAX)
return "???";
return EncodingNameArray[E];
}
/// Prints out the abbreviation operator to the given stream.
void Print(raw_ostream &Stream) const;
/// isChar6 - Return true if this character is legal in the Char6 encoding.
static bool isChar6(char C) {
if (C >= 'a' && C <= 'z')
return true;
if (C >= 'A' && C <= 'Z')
return true;
if (C >= '0' && C <= '9')
return true;
if (C == '.' || C == '_')
return true;
return false;
}
static unsigned EncodeChar6(char C) {
if (C >= 'a' && C <= 'z')
return C - 'a';
if (C >= 'A' && C <= 'Z')
return C - 'A' + 26;
if (C >= '0' && C <= '9')
return C - '0' + 26 + 26;
if (C == '.')
return 62;
if (C == '_')
return 63;
llvm_unreachable("Not a value Char6 character!");
}
static char DecodeChar6(unsigned V) {
assert((V & ~63) == 0 && "Not a Char6 encoded character!");
if (V < 26)
return V + 'a';
if (V < 26 + 26)
return V - 26 + 'A';
if (V < 26 + 26 + 10)
return V - 26 - 26 + '0';
if (V == 62)
return '.';
if (V == 63)
return '_';
llvm_unreachable("Not a value Char6 character!");
}
/// \brief Compares this to Op. Returns <0 if this is less than Op,
/// Returns 0 if they are equal, and >0 if this is greater than Op.
int Compare(const NaClBitCodeAbbrevOp &Op) const {
// Compare encoding values.
int EncodingDiff = static_cast<int>(Enc) - static_cast<int>(Op.Enc);
if (EncodingDiff != 0)
return EncodingDiff;
// Encodings don't differ, so now base on data associated with the
// encoding.
return ValCompare(Op);
}
private:
Encoding Enc; // The encoding to use.
uint64_t Val; // Data associated with encoding (if any).
int ValCompare(const NaClBitCodeAbbrevOp &Op) const {
if (Val < Op.Val)
return -1;
else if (Val > Op.Val)
return 1;
else
return 0;
}
static const bool HasValueArray[];
static const char *EncodingNameArray[];
};
template <> struct isPodLike<NaClBitCodeAbbrevOp> {
static const bool value = true;
};
static inline bool operator<(const NaClBitCodeAbbrevOp &Op1,
const NaClBitCodeAbbrevOp &Op2) {
return Op1.Compare(Op2) < 0;
}
static inline bool operator<=(const NaClBitCodeAbbrevOp &Op1,
const NaClBitCodeAbbrevOp &Op2) {
return Op1.Compare(Op2) <= 0;
}
static inline bool operator==(const NaClBitCodeAbbrevOp &Op1,
const NaClBitCodeAbbrevOp &Op2) {
return Op1.Compare(Op2) == 0;
}
static inline bool operator!=(const NaClBitCodeAbbrevOp &Op1,
const NaClBitCodeAbbrevOp &Op2) {
return Op1.Compare(Op2) != 0;
}
static inline bool operator>=(const NaClBitCodeAbbrevOp &Op1,
const NaClBitCodeAbbrevOp &Op2) {
return Op1.Compare(Op2) >= 0;
}
static inline bool operator>(const NaClBitCodeAbbrevOp &Op1,
const NaClBitCodeAbbrevOp &Op2) {
return Op1.Compare(Op2) > 0;
}
/// NaClBitCodeAbbrev - This class represents an abbreviation record. An
/// abbreviation allows a complex record that has redundancy to be stored in a
/// specialized format instead of the fully-general, fully-vbr, format.
class NaClBitCodeAbbrev {
SmallVector<NaClBitCodeAbbrevOp, 8> OperandList;
unsigned char RefCount; // Number of things using this.
~NaClBitCodeAbbrev() {}
public:
NaClBitCodeAbbrev() : RefCount(1) {}
void addRef() { ++RefCount; }
void dropRef() {
if (--RefCount == 0)
delete this;
}
unsigned getNumOperandInfos() const {
return static_cast<unsigned>(OperandList.size());
}
const NaClBitCodeAbbrevOp &getOperandInfo(unsigned N) const {
return OperandList[N];
}
void Add(const NaClBitCodeAbbrevOp &OpInfo) { OperandList.push_back(OpInfo); }
// Returns a simplified version of the abbreviation. Used
// to recognize equivalent abbrevations.
NaClBitCodeAbbrev *Simplify() const;
// Returns true if the abbreviation is valid wrt to the bitcode reader.
bool isValid() const;
int Compare(const NaClBitCodeAbbrev &Abbrev) const {
// First order based on number of operands.
size_t OperandListSize = OperandList.size();
size_t AbbrevOperandListSize = Abbrev.OperandList.size();
if (OperandListSize < AbbrevOperandListSize)
return -1;
else if (OperandListSize > AbbrevOperandListSize)
return 1;
// Same number of operands, so compare element by element.
for (size_t I = 0; I < OperandListSize; ++I) {
if (int Diff = OperandList[I].Compare(Abbrev.OperandList[I]))
return Diff;
}
return 0;
}
// Returns true if all records matching the abbreviation must be
// of fixed length.
bool IsFixedSize() const {
unsigned Size = getNumOperandInfos();
if (Size < 2)
return true;
return !OperandList[Size - 2].isArrayOp();
}
// Returns the smallest record size that will match this
// abbreviation.
size_t GetMinRecordSize() const {
size_t Min = getNumOperandInfos();
if (!IsFixedSize())
Min -= 2;
return Min;
}
void Print(raw_ostream &Stream, bool AddNewline = true) const;
NaClBitCodeAbbrev *Copy() const {
NaClBitCodeAbbrev *AbbrevCopy = new NaClBitCodeAbbrev();
for (unsigned I = 0, IEnd = getNumOperandInfos(); I != IEnd; ++I) {
AbbrevCopy->Add(NaClBitCodeAbbrevOp(getOperandInfo(I)));
}
return AbbrevCopy;
}
};
static inline bool operator<(const NaClBitCodeAbbrev &A1,
const NaClBitCodeAbbrev &A2) {
return A1.Compare(A2) < 0;
}
static inline bool operator<=(const NaClBitCodeAbbrev &A1,
const NaClBitCodeAbbrev &A2) {
return A1.Compare(A2) <= 0;
}
static inline bool operator==(const NaClBitCodeAbbrev &A1,
const NaClBitCodeAbbrev &A2) {
return A1.Compare(A2) == 0;
}
static inline bool operator!=(const NaClBitCodeAbbrev &A1,
const NaClBitCodeAbbrev &A2) {
return A1.Compare(A2) != 0;
}
static inline bool operator>=(const NaClBitCodeAbbrev &A1,
const NaClBitCodeAbbrev &A2) {
return A1.Compare(A2) >= 0;
}
static inline bool operator>(const NaClBitCodeAbbrev &A1,
const NaClBitCodeAbbrev &A2) {
return A1.Compare(A2) > 0;
}
/// \brief Returns number of bits needed to encode
/// value for dense FIXED encoding.
inline unsigned NaClBitsNeededForValue(unsigned Value) {
// Note: Need to handle case where Value=0xFFFFFFFF as special case,
// since we can't add 1 to it.
if (Value >= 0x80000000)
return 32;
return Log2_32_Ceil(Value + 1);
}
/// \brief Encode a signed value by moving the sign to the LSB for dense
/// VBR encoding.
inline uint64_t NaClEncodeSignRotatedValue(int64_t V) {
return (V >= 0) ? (V << 1) : ((-V << 1) | 1);
}
/// \brief Decode a signed value stored with the sign bit in
/// the LSB for dense VBR encoding.
inline uint64_t NaClDecodeSignRotatedValue(uint64_t V) {
if ((V & 1) == 0)
return V >> 1;
if (V != 1)
return -(V >> 1);
// There is no such thing as -0 with integers. "-0" really means MININT.
return 1ULL << 63;
}
/// \brief This class determines whether a FIXED or VBR
/// abbreviation should be used for the selector, and the number of bits
/// needed to capture such selectors.
class NaClBitcodeSelectorAbbrev {
public:
// If true, use a FIXED abbreviation. Otherwise, use a VBR abbreviation.
bool IsFixed;
// Number of bits needed for selector.
unsigned NumBits;
// Creates a selector range for the given values.
NaClBitcodeSelectorAbbrev(bool IF, unsigned NB) : IsFixed(IF), NumBits(NB) {}
// Creates a selector range when no abbreviations are defined.
NaClBitcodeSelectorAbbrev()
: IsFixed(true),
NumBits(NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV)) {}
// Creates a selector range to handle fixed abbrevations up to
// the specified value.
explicit NaClBitcodeSelectorAbbrev(unsigned MaxAbbrev)
: IsFixed(true), NumBits(NaClBitsNeededForValue(MaxAbbrev)) {}
};
} // namespace llvm
#endif