mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-25 21:18:19 +00:00
Initial revision
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user