diff options
Diffstat (limited to 'include/llvm/Bytecode')
-rw-r--r-- | include/llvm/Bytecode/Format.h | 33 | ||||
-rw-r--r-- | include/llvm/Bytecode/Primitives.h | 237 | ||||
-rw-r--r-- | include/llvm/Bytecode/Reader.h | 24 | ||||
-rw-r--r-- | include/llvm/Bytecode/Writer.h | 25 |
4 files changed, 319 insertions, 0 deletions
diff --git a/include/llvm/Bytecode/Format.h b/include/llvm/Bytecode/Format.h new file mode 100644 index 0000000000..a87f8d18a6 --- /dev/null +++ b/include/llvm/Bytecode/Format.h @@ -0,0 +1,33 @@ +//===-- llvm/Bytecode/Format.h - VM bytecode file format info ----*- C++ -*--=// +// +// This header defines intrinsic constants that are useful to libraries that +// need to hack on bytecode files directly, like the reader and writer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BYTECODE_FORMAT_H +#define LLVM_BYTECODE_FORMAT_H + +class BytecodeFormat { // Throw the constants into a poorman's namespace... + BytecodeFormat(); // do not implement +public: + + // ID Numbers that are used in bytecode files... + enum FileBlockIDs { + // File level identifiers... + Module = 0x01, + + // Module subtypes: + Method = 0x11, + ConstantPool, + SymbolTable, + ModuleGlobalInfo, + + // Method subtypes: + MethodInfo = 0x21, + // Can also have ConstantPool block + // Can also have SymbolTable block + BasicBlock = 0x31, // May contain many basic blocks + }; +}; +#endif diff --git a/include/llvm/Bytecode/Primitives.h b/include/llvm/Bytecode/Primitives.h new file mode 100644 index 0000000000..f4b232b368 --- /dev/null +++ b/include/llvm/Bytecode/Primitives.h @@ -0,0 +1,237 @@ +//===-- llvm/Bytecode/Primitives.h - Bytecode file format prims --*- C++ -*--=// +// +// This header defines some basic functions for reading and writing basic +// primitive types to a bytecode stream. +// +// Using the routines defined in this file does not require linking to any +// libraries, as all of the services are small self contained units that are to +// be inlined as neccesary. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BYTECODE_PRIMITIVES_H +#define LLVM_BYTECODE_PRIMITIVES_H + +#include "llvm/Tools/DataTypes.h" +#include <string> +#include <vector> + +//===----------------------------------------------------------------------===// +// Reading Primitives +//===----------------------------------------------------------------------===// + +static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf, + unsigned &Result) { + if (Buf+4 > EndBuf) return true; +#ifdef LITTLE_ENDIAN + Result = *(unsigned*)Buf; +#else + Result = Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24); +#endif + Buf += 4; + return false; +} + +static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf, + uint64_t &Result) { + if (Buf+8 > EndBuf) return true; + +#ifdef LITTLE_ENDIAN + Result = *(uint64_t*)Buf; +#else + Result = Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24) | + ((uint64_t)(Buf[4] | (Buf[5] << 8) | (Buf[6] << 16) | (Buf[7] << 24)) <<32); +#endif + Buf += 8; + return false; +} + +static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf, + int &Result) { + return read(Buf, EndBuf, (unsigned &)Result); +} + +static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf, + int64_t &Result) { + return read(Buf, EndBuf, (uint64_t &)Result); +} + + +// read_vbr - Read an unsigned integer encoded in variable bitrate format. +// +static inline bool read_vbr(const unsigned char *&Buf, + const unsigned char *EndBuf, unsigned &Result) { + unsigned Shift = Result = 0; + + do { + Result |= (unsigned)((*Buf++) & 0x7F) << Shift; + Shift += 7; + } while (Buf[-1] & 0x80 && Buf < EndBuf); + + return Buf > EndBuf; +} + +static inline bool read_vbr(const unsigned char *&Buf, + const unsigned char *EndBuf, uint64_t &Result) { + unsigned Shift = 0; Result = 0; + + do { + Result |= (uint64_t)((*Buf++) & 0x7F) << Shift; + Shift += 7; + } while (Buf[-1] & 0x80 && Buf < EndBuf); + return Buf > EndBuf; +} + +// read_vbr (signed) - Read a signed number stored in sign-magnitude format +static inline bool read_vbr(const unsigned char *&Buf, + const unsigned char *EndBuf, int &Result) { + unsigned R; + if (read_vbr(Buf, EndBuf, R)) return true; + if (R & 1) + Result = -(int)(R >> 1); + else + Result = (int)(R >> 1); + + return false; +} + + +static inline bool read_vbr(const unsigned char *&Buf, + const unsigned char *EndBuf, int64_t &Result) { + uint64_t R; + if (read_vbr(Buf, EndBuf, R)) return true; + if (R & 1) + Result = -(int64_t)(R >> 1); + else + Result = (int64_t)(R >> 1); + + return false; +} + +// align32 - Round up to multiple of 32 bits... +static inline bool align32(const unsigned char *&Buf, + const unsigned char *EndBuf) { + Buf = (const unsigned char *)((unsigned long)(Buf+3) & (~3UL)); + return Buf > EndBuf; +} + +static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf, + string &Result, bool Aligned = true) { + unsigned Size; + if (read_vbr(Buf, EndBuf, Size)) return true; // Failure reading size? + if (Buf+Size > EndBuf) return true; // Size invalid? + + Result = string((char*)Buf, Size); + Buf += Size; + + if (Aligned) // If we should stay aligned do so... + if (align32(Buf, EndBuf)) return true; // Failure aligning? + + return false; +} + + +//===----------------------------------------------------------------------===// +// Writing Primitives +//===----------------------------------------------------------------------===// + +// output - If a position is specified, it must be in the valid portion of the +// string... note that this should be inlined always so only the relevant IF +// body should be included... +// +static inline void output(unsigned i, vector<unsigned char> &Out, int pos = -1){ +#ifdef LITTLE_ENDIAN + if (pos == -1) + Out.insert(Out.end(), (unsigned char*)&i, (unsigned char*)&i+4); + else + *(unsigned*)&Out[pos] = i; +#else + if (pos == -1) { // Be endian clean, little endian is our friend + Out.push_back((unsigned char)i); + Out.push_back((unsigned char)(i >> 8)); + Out.push_back((unsigned char)(i >> 16)); + Out.push_back((unsigned char)(i >> 24)); + } else { + Out[pos ] = (unsigned char)i; + Out[pos+1] = (unsigned char)(i >> 8); + Out[pos+2] = (unsigned char)(i >> 16); + Out[pos+3] = (unsigned char)(i >> 24); + } +#endif +} + +static inline void output(int i, vector<unsigned char> &Out) { + output((unsigned)i, Out); +} + +// output_vbr - Output an unsigned value, by using the least number of bytes +// possible. This is useful because many of our "infinite" values are really +// very small most of the time... but can be large a few times... +// +// Data format used: If you read a byte with the night bit set, use the low +// seven bits as data and then read another byte... +// +// Note that using this may cause the output buffer to become unaligned... +// +static inline void output_vbr(uint64_t i, vector<unsigned char> &out) { + while (1) { + if (i < 0x80) { // done? + out.push_back((unsigned char)i); // We know the high bit is clear... + return; + } + + // Nope, we are bigger than a character, output the next 7 bits and set the + // high bit to say that there is more coming... + out.push_back(0x80 | (i & 0x7F)); + i >>= 7; // Shift out 7 bits now... + } +} + +static inline void output_vbr(unsigned i, vector<unsigned char> &out) { + while (1) { + if (i < 0x80) { // done? + out.push_back((unsigned char)i); // We know the high bit is clear... + return; + } + + // Nope, we are bigger than a character, output the next 7 bits and set the + // high bit to say that there is more coming... + out.push_back(0x80 | (i & 0x7F)); + i >>= 7; // Shift out 7 bits now... + } +} + +static inline void output_vbr(int64_t i, vector<unsigned char> &out) { + if (i < 0) + output_vbr(((uint64_t)(-i) << 1) | 1, out); // Set low order sign bit... + else + output_vbr((uint64_t)i << 1, out); // Low order bit is clear. +} + + +static inline void output_vbr(int i, vector<unsigned char> &out) { + if (i < 0) + output_vbr(((unsigned)(-i) << 1) | 1, out); // Set low order sign bit... + else + output_vbr((unsigned)i << 1, out); // Low order bit is clear. +} + +// align32 - emit the minimal number of bytes that will bring us to 32 bit +// alignment... +// +static inline void align32(vector<unsigned char> &Out) { + int NumPads = (4-(Out.size() & 3)) & 3; // Bytes to get padding to 32 bits + while (NumPads--) Out.push_back((unsigned char)0xAB); +} + +static inline void output(const string &s, vector<unsigned char> &Out, + bool Aligned = true) { + unsigned Len = s.length(); + output_vbr(Len, Out); // Strings may have an arbitrary length... + Out.insert(Out.end(), s.begin(), s.end()); + + if (Aligned) + align32(Out); // Make sure we are now aligned... +} + +#endif diff --git a/include/llvm/Bytecode/Reader.h b/include/llvm/Bytecode/Reader.h new file mode 100644 index 0000000000..17ddfc8fb8 --- /dev/null +++ b/include/llvm/Bytecode/Reader.h @@ -0,0 +1,24 @@ +//===-- llvm/Bytecode/Reader.h - Reader for VM bytecode files ----*- C++ -*--=// +// +// This functionality is implemented by the lib/BytecodeReader library. +// This library is used to read VM bytecode files from an iostream. +// +// Note that performance of this library is _crucial_ for performance of the +// JIT type applications, so we have designed the bytecode format to support +// quick reading. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BYTECODE_READER_H +#define LLVM_BYTECODE_READER_H + +#include <string> + +class Module; + +// Parse and return a class... +// +Module *ParseBytecodeFile(const string &Filename); +Module *ParseBytecodeBuffer(const char *Buffer, unsigned BufferSize); + +#endif diff --git a/include/llvm/Bytecode/Writer.h b/include/llvm/Bytecode/Writer.h new file mode 100644 index 0000000000..e28ea77f07 --- /dev/null +++ b/include/llvm/Bytecode/Writer.h @@ -0,0 +1,25 @@ +//===-- llvm/Bytecode/Writer.h - Writer for VM bytecode files ----*- C++ -*--=// +// +// This functionality is implemented by the lib/BytecodeWriter library. +// This library is used to write VM bytecode files to an iostream. First, you +// have to make a BytecodeStream object, which you can then put a class into +// by using operator <<. +// +// This library uses the Analysis library to figure out offsets for +// variables in the method tables... +// +// Note that performance of this library is not as crucial as performance of the +// bytecode reader (which is to be used in JIT type applications), so we have +// designed the bytecode format to support quick reading. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BYTECODE_WRITER_H +#define LLVM_BYTECODE_WRITER_H + +#include <iostream.h> + +class Module; +void WriteBytecodeToFile(const Module *C, ostream &Out); + +#endif |