Merge pull request #263 from joshuawarner32/compiler-types

Introduce stronger typing in compiler
This commit is contained in:
Joel Dice 2014-06-01 20:08:44 -06:00
commit 86648ea054
26 changed files with 4049 additions and 2859 deletions

View File

@ -11,6 +11,8 @@
#ifndef AVIAN_CODEGEN_ARCHITECTURE_H
#define AVIAN_CODEGEN_ARCHITECTURE_H
#include "ir.h"
namespace vm {
class Zone;
}
@ -57,6 +59,8 @@ virtual int returnHigh() = 0;
virtual int virtualCallTarget() = 0;
virtual int virtualCallIndex() = 0;
virtual ir::TargetInfo targetInfo() = 0;
virtual bool bigEndian() = 0;
virtual uintptr_t maximumImmediateJump() = 0;

View File

@ -12,8 +12,10 @@
#define AVIAN_CODEGEN_COMPILER_H
#include <avian/system/system.h>
#include <avian/util/slice.h>
#include "avian/zone.h"
#include "assembler.h"
#include "ir.h"
namespace avian {
namespace codegen {
@ -33,35 +35,22 @@ class Compiler {
virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size,
unsigned resultSize, bool* threadParameter) = 0;
};
static const unsigned Aligned = 1 << 0;
static const unsigned NoReturn = 1 << 1;
static const unsigned TailJump = 1 << 2;
static const unsigned LongJumpOrCall = 1 << 3;
enum OperandType {
ObjectType,
AddressType,
IntegerType,
FloatType,
VoidType
};
class Operand { };
class State { };
class Subroutine { };
virtual State* saveState() = 0;
virtual void restoreState(State* state) = 0;
virtual Subroutine* startSubroutine() = 0;
virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address)
= 0;
virtual void linkSubroutine(Subroutine* subroutine) = 0;
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
unsigned localFootprint, unsigned alignedFrameSize) = 0;
virtual void extendLogicalCode(unsigned more) = 0;
virtual void visitLogicalIp(unsigned logicalIp) = 0;
virtual void startLogicalIp(unsigned logicalIp) = 0;
@ -70,73 +59,82 @@ class Compiler {
virtual Promise* poolAppend(intptr_t value) = 0;
virtual Promise* poolAppendPromise(Promise* value) = 0;
virtual Operand* constant(int64_t value, OperandType type) = 0;
virtual Operand* promiseConstant(Promise* value, OperandType type) = 0;
virtual Operand* address(Promise* address) = 0;
virtual Operand* memory(Operand* base,
OperandType type,
int displacement = 0,
Operand* index = 0,
unsigned scale = 1) = 0;
virtual ir::Value* constant(int64_t value, ir::Type type) = 0;
virtual ir::Value* promiseConstant(Promise* value, ir::Type type) = 0;
virtual ir::Value* address(ir::Type type, Promise* address) = 0;
virtual ir::Value* memory(ir::Value* base,
ir::Type type,
int displacement = 0,
ir::Value* index = 0) = 0;
virtual Operand* register_(int number) = 0;
virtual ir::Value* threadRegister() = 0;
virtual void push(unsigned footprint) = 0;
virtual void push(unsigned footprint, Operand* value) = 0;
virtual void save(unsigned footprint, Operand* value) = 0;
virtual Operand* pop(unsigned footprint) = 0;
virtual void pushed() = 0;
virtual void push(ir::Type type, ir::Value* value) = 0;
virtual void save(ir::Type type, ir::Value* value) = 0;
virtual ir::Value* pop(ir::Type type) = 0;
virtual void pushed(ir::Type type) = 0;
virtual void popped(unsigned footprint) = 0;
virtual unsigned topOfStack() = 0;
virtual Operand* peek(unsigned footprint, unsigned index) = 0;
virtual ir::Value* peek(unsigned footprint, unsigned index) = 0;
virtual Operand* call(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
OperandType resultType,
unsigned argumentCount,
...) = 0;
virtual ir::Value* call(ir::Value* address,
unsigned flags,
TraceHandler* traceHandler,
ir::Type resultType,
unsigned argumentCount,
...) = 0;
virtual Operand* stackCall(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
OperandType resultType,
unsigned argumentFootprint) = 0;
virtual ir::Value* stackCall(ir::Value* address,
unsigned flags,
TraceHandler* traceHandler,
ir::Type resultType,
util::Slice<ir::Value*> arguments) = 0;
virtual void return_(unsigned size, Operand* value) = 0;
virtual void return_(ir::Value* value) = 0;
virtual void return_() = 0;
virtual void initLocal(unsigned size, unsigned index, OperandType type) = 0;
virtual void initLocal(unsigned index, ir::Type type) = 0;
virtual void initLocalsFromLogicalIp(unsigned logicalIp) = 0;
virtual void storeLocal(unsigned footprint, Operand* src,
unsigned index) = 0;
virtual Operand* loadLocal(unsigned footprint, unsigned index) = 0;
virtual void storeLocal(ir::Value* src, unsigned index) = 0;
virtual ir::Value* loadLocal(ir::Type type, unsigned index) = 0;
virtual void saveLocals() = 0;
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler) = 0;
virtual void checkBounds(ir::Value* object,
unsigned lengthOffset,
ir::Value* index,
intptr_t handler) = 0;
virtual void store(unsigned srcSize, Operand* src, unsigned dstSize,
Operand* dst) = 0;
virtual Operand* load(unsigned srcSize, unsigned srcSelectSize, Operand* src,
unsigned dstSize) = 0;
virtual Operand* loadz(unsigned size, unsigned srcSelectSize, Operand* src,
unsigned dstSize) = 0;
virtual ir::Value* truncateThenExtend(ir::SignExtendMode signExtend,
ir::Type extendType,
ir::Type truncateType,
ir::Value* src) = 0;
virtual ir::Value* truncate(ir::Type type, ir::Value* src) = 0;
virtual void condJump(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b, Operand* address) = 0;
virtual void store(ir::Value* src, ir::Value* dst) = 0;
virtual ir::Value* load(ir::SignExtendMode signExtend,
ir::Value* src,
ir::Type dstType) = 0;
virtual void jmp(Operand* address) = 0;
virtual void exit(Operand* address) = 0;
virtual void condJump(lir::TernaryOperation op,
ir::Value* a,
ir::Value* b,
ir::Value* address) = 0;
virtual Operand* binaryOp(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b) = 0;
virtual Operand* unaryOp(lir::BinaryOperation type, unsigned size, Operand* a) = 0;
virtual void nullaryOp(lir::Operation type) = 0;
virtual void jmp(ir::Value* address) = 0;
virtual void exit(ir::Value* address) = 0;
virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0;
virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0;
virtual ir::Value* binaryOp(lir::TernaryOperation op,
ir::Type type,
ir::Value* a,
ir::Value* b) = 0;
virtual ir::Value* unaryOp(lir::BinaryOperation op,
ir::Value* a) = 0;
virtual void nullaryOp(lir::Operation op) = 0;
virtual ir::Value* f2f(ir::Type resType, ir::Value* a) = 0;
virtual ir::Value* f2i(ir::Type resType, ir::Value* a) = 0;
virtual ir::Value* i2f(ir::Type resType, ir::Value* a) = 0;
virtual void compile(uintptr_t stackOverflowHandler,
unsigned stackLimitOffset) = 0;

157
include/avian/codegen/ir.h Normal file
View File

@ -0,0 +1,157 @@
/* Copyright (c) 2008-2014, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_CODEGEN_IR_H
#define AVIAN_CODEGEN_IR_H
namespace avian {
namespace codegen {
namespace ir {
class TargetInfo {
public:
unsigned pointerSize;
explicit TargetInfo(unsigned pointerSize) : pointerSize(pointerSize)
{
}
};
class Type {
public:
enum Flavor {
// A GC-visiible reference
Object,
// GC-invisible types
Integer,
Float,
Address,
// Represents individual halves of two-word types
// (double/long on 32-bit systems)
// TODO: remove when possible
Half,
// Represents the lack of a return value
// TODO: remove when possible
Void,
};
typedef int16_t TypeDesc;
#define TY_DESC(flavor, size) ((flavor & 0xff) | ((size & 0xff) << 8))
// TODO: once we upgrade to c++11, these should become plain constants (rather
// than function calls).
// The constructor will need to be declared 'constexpr'.
static inline Type void_()
{
return TY_DESC(Void, 0);
}
static inline Type object()
{
return TY_DESC(Object, -1);
}
static inline Type iptr()
{
return TY_DESC(Integer, -1);
}
static inline Type i1()
{
return TY_DESC(Integer, 1);
}
static inline Type i2()
{
return TY_DESC(Integer, 2);
}
static inline Type i4()
{
return TY_DESC(Integer, 4);
}
static inline Type i8()
{
return TY_DESC(Integer, 8);
}
static inline Type f4()
{
return TY_DESC(Float, 4);
}
static inline Type f8()
{
return TY_DESC(Float, 8);
}
static inline Type addr()
{
return TY_DESC(Address, -1);
}
#undef TY_DESC
private:
TypeDesc desc;
friend class Types;
// TODO: once we move to c++11, declare this 'constexpr', to allow
// compile-time constants of this type.
/* constexpr */ Type(TypeDesc desc) : desc(desc)
{
}
public:
inline Flavor flavor() const
{
return (Flavor)(desc & 0xff);
}
// If the size isn't known without inspecting the TargetInfo, returns -1.
// Otherwise, matches size(TargetInfo).
inline int rawSize() const
{
return desc >> 8;
}
inline unsigned size(const TargetInfo& t) const
{
int s = rawSize();
if (s < 0) {
return t.pointerSize;
}
return (unsigned)s;
}
inline bool operator==(const Type& other) const
{
return desc == other.desc;
}
inline bool operator!=(const Type& other) const
{
return !(*this == other);
}
};
enum SignExtendMode { SignExtend, ZeroExtend };
enum CallingConvention { NativeCallingConvention, AvianCallingConvention };
class Value {
public:
ir::Type type;
Value(ir::Type type) : type(type)
{
}
};
} // namespace ir
} // namespace codegen
} // namespace avian
#endif // AVIAN_CODEGEN_IR_H

View File

@ -0,0 +1,32 @@
/* Copyright (c) 2008-2013, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef AVIAN_UTIL_ASSERT_H
#define AVIAN_UTIL_ASSERT_H
#include <stdlib.h>
namespace avian {
namespace util {
#define UNREACHABLE_ ::abort()
// TODO: print msg in debug mode
#define UNREACHABLE(msg) ::abort()
#define ASSERT(that) \
if (!(that)) { \
UNREACHABLE(#that); \
}
} // namespace util
} // namespace avian
#endif // AVIAN_UTIL_ASSERT_H

View File

@ -13,6 +13,7 @@
#include "allocator.h"
#include "math.h"
#include "assert.h"
namespace avian {
namespace util {
@ -33,6 +34,7 @@ class Slice {
inline T& operator[](size_t index)
{
ASSERT(index < count);
return items[index];
}
@ -51,20 +53,36 @@ class Slice {
return Slice<T>((T*)a->allocate(sizeof(T) * count), count);
}
Slice<T> clone(Allocator* a)
static Slice<T> allocAndSet(Allocator* a, size_t count, const T& item)
{
Slice<T> ret((T*)a->allocate(count * sizeof(T)), count);
memcpy(ret.items, items, count * sizeof(T));
return ret;
Slice<T> slice(alloc(a, count));
for (size_t i = 0; i < count; i++) {
slice[i] = item;
}
return slice;
}
Slice<T> clone(Allocator* a, size_t newCount)
{
T* newItems = (T*)a->allocate(newCount * sizeof(T));
memcpy(newItems, items, min(count, newCount) * sizeof(T));
return Slice<T>(newItems, newCount);
}
Slice<T> cloneAndSet(Allocator* a, size_t newCount, const T& item)
{
Slice<T> slice(clone(a, newCount));
for (size_t i = count; i < newCount; i++) {
slice[i] = item;
}
return slice;
}
void resize(Allocator* a, size_t newCount)
{
T* newItems = (T*)a->allocate(newCount * sizeof(T));
memcpy(newItems, items, min(count, newCount));
Slice<T> slice(clone(a, newCount));
a->free(items, count);
items = newItems;
count = newCount;
*this = slice;
}
};

View File

@ -1125,6 +1125,7 @@ embed-objects = $(call cpp-objects,$(embed-sources),$(src),$(build-embed))
compiler-sources = \
$(src)/codegen/compiler.cpp \
$(wildcard $(src)/codegen/compiler/*.cpp) \
$(src)/debug-util.cpp \
$(src)/codegen/registers.cpp \
$(src)/codegen/runtime.cpp \
$(src)/codegen/targets.cpp \

View File

@ -156,7 +156,7 @@ popRead(Context* c, Event* e UNUSED, Value* v)
if (valid(nextWord->reads)) {
deadWord(c, v);
} else {
deadWord(c, nextWord);
deadWord(c, nextWord);
}
}
@ -186,22 +186,6 @@ addBuddy(Value* original, Value* buddy)
}
}
lir::ValueType
valueType(Context* c, Compiler::OperandType type)
{
switch (type) {
case Compiler::ObjectType:
case Compiler::AddressType:
case Compiler::IntegerType:
case Compiler::VoidType:
return lir::ValueGeneral;
case Compiler::FloatType:
return lir::ValueFloat;
default:
abort(c);
}
}
void
move(Context* c, Value* value, Site* src, Site* dst);
@ -751,10 +735,14 @@ saveLocals(Context* c, Event* e)
}
}
void
maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
unsigned srcSelectSize, Value* srcValue, unsigned dstSize, Value* dstValue,
const SiteMask& dstMask)
void maybeMove(Context* c,
lir::BinaryOperation op,
unsigned srcSize,
unsigned srcSelectSize,
Value* srcValue,
unsigned dstSize,
Value* dstValue,
const SiteMask& dstMask)
{
Read* read = live(c, dstValue);
bool isStore = read == 0;
@ -806,8 +794,14 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
srcValue->source->freeze(c, srcValue);
apply(c, type, min(srcSelectSize, dstSize), srcValue->source, srcValue->source,
dstSize, target, target);
apply(c,
op,
min(srcSelectSize, dstSize),
srcValue->source,
srcValue->source,
dstSize,
target,
target);
srcValue->source->thaw(c, srcValue);
} else {
@ -819,9 +813,9 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
bool thunk;
OperandMask src;
c->arch->planSource(type, dstSize, src, dstSize, &thunk);
c->arch->planSource(op, dstSize, src, dstSize, &thunk);
if (srcValue->type == lir::ValueGeneral) {
if (isGeneralValue(srcValue)) {
src.registerMask &= c->regFile->generalRegisters.mask;
}
@ -844,8 +838,14 @@ maybeMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
srcb, dstb, srcValue, dstValue);
}
apply(c, type, srcSelectSize, srcValue->source, srcValue->source,
dstSize, tmpTarget, tmpTarget);
apply(c,
op,
srcSelectSize,
srcValue->source,
srcValue->source,
dstSize,
tmpTarget,
tmpTarget);
tmpTarget->thaw(c, dstValue);
@ -1214,9 +1214,27 @@ storeLocal(Context* c, unsigned footprint, Value* v, unsigned index, bool copy)
return v;
}
Value*
loadLocal(Context* c, unsigned footprint, unsigned index)
unsigned typeFootprint(Context* c, ir::Type type)
{
// TODO: this function is very Java-specific in nature. Generalize.
switch (type.flavor()) {
case ir::Type::Float:
case ir::Type::Integer:
return type.rawSize() / 4;
case ir::Type::Object:
case ir::Type::Address:
case ir::Type::Half:
return 1;
case ir::Type::Void:
return 0;
default:
abort(c);
}
}
Value* loadLocal(Context* c, ir::Type type, unsigned index)
{
unsigned footprint = typeFootprint(c, type);
assert(c, index + footprint <= c->localFootprint);
if (footprint > 1) {
@ -1237,17 +1255,10 @@ loadLocal(Context* c, unsigned footprint, unsigned index)
return c->locals[index].value;
}
Value*
register_(Context* c, int number)
Value* threadRegister(Context* c)
{
assert(c, (1 << number) & (c->regFile->generalRegisters.mask
| c->regFile->floatRegisters.mask));
Site* s = registerSite(c, number);
lir::ValueType type = ((1 << number) & c->regFile->floatRegisters.mask)
? lir::ValueFloat: lir::ValueGeneral;
return value(c, type, s, s);
Site* s = registerSite(c, c->arch->thread());
return value(c, ir::Type::addr(), s, s);
}
unsigned
@ -1506,8 +1517,8 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen,
fprintf(stderr, "freeze original %s for %p local %d frame %d\n",
buffer, v, el.localIndex, el.frameIndex(c));
}
Value dummy(0, 0, lir::ValueGeneral);
Value dummy(0, 0, ir::Type::addr());
dummy.addSite(c, s);
dummy.removeSite(c, s);
freeze(c, frozen, s, 0);
@ -2129,26 +2140,9 @@ class MyCompiler: public Compiler {
compiler::restoreState(&c, static_cast<ForkState*>(state));
}
virtual Subroutine* startSubroutine() {
return c.subroutine = new(c.zone) MySubroutine;
}
virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) {
appendSaveLocals(&c);
appendJump(&c, lir::Jump, static_cast<Value*>(address), false, true);
static_cast<MySubroutine*>(subroutine)->forkState = compiler::saveState(&c);
}
virtual void linkSubroutine(Subroutine* subroutine) {
Local* oldLocals = c.locals;
restoreState(static_cast<MySubroutine*>(subroutine)->forkState);
linkLocals(&c, oldLocals, c.locals);
}
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
unsigned localFootprint, unsigned alignedFrameSize)
{
c.logicalCodeLength = logicalCodeLength;
c.parameterFootprint = parameterFootprint;
c.localFootprint = localFootprint;
c.alignedFrameSize = alignedFrameSize;
@ -2167,23 +2161,23 @@ class MyCompiler: public Compiler {
c.frameResources[base + c.arch->framePointerOffset()].reserved
= UseFramePointer;
// leave room for logical instruction -1
unsigned codeSize = sizeof(LogicalInstruction*) * (logicalCodeLength + 1);
c.logicalCode = static_cast<LogicalInstruction**>
(c.zone->allocate(codeSize));
memset(c.logicalCode, 0, codeSize);
c.logicalCode++;
c.logicalCode.init(c.zone, logicalCodeLength);
c.logicalCode[-1] = new (c.zone) LogicalInstruction(-1, c.stack, c.locals);
c.locals = static_cast<Local*>
(c.zone->allocate(sizeof(Local) * localFootprint));
memset(c.locals, 0, sizeof(Local) * localFootprint);
}
c.logicalCode[-1] = new(c.zone) LogicalInstruction(-1, c.stack, c.locals);
virtual void extendLogicalCode(unsigned more)
{
c.logicalCode.extend(c.zone, more);
}
virtual void visitLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
assert(&c, logicalIp < c.logicalCode.count());
if (c.logicalCode[c.logicalIp]->lastEvent == 0) {
appendDummy(&c);
@ -2215,17 +2209,11 @@ class MyCompiler: public Compiler {
populateJunctionReads(&c, link);
}
if (c.subroutine) {
c.subroutine->forkState
= c.logicalCode[logicalIp]->subroutine->forkState;
c.subroutine = 0;
}
c.forkState = 0;
}
virtual void startLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
assert(&c, logicalIp < c.logicalCode.count());
assert(&c, c.logicalCode[logicalIp] == 0);
if (c.logicalCode[c.logicalIp]->lastEvent == 0) {
@ -2240,30 +2228,7 @@ class MyCompiler: public Compiler {
c.logicalCode[logicalIp] = new(c.zone) LogicalInstruction(logicalIp, c.stack, c.locals);
bool startSubroutine = c.subroutine != 0;
if (startSubroutine) {
c.logicalCode[logicalIp]->subroutine = c.subroutine;
c.subroutine = 0;
}
c.logicalIp = logicalIp;
if (startSubroutine) {
// assume all local variables are initialized on entry to a
// subroutine, since other calls to the subroutine may
// initialize them:
unsigned sizeInBytes = sizeof(Local) * c.localFootprint;
Local* newLocals = static_cast<Local*>(c.zone->allocate(sizeInBytes));
memcpy(newLocals, c.locals, sizeInBytes);
c.locals = newLocals;
for (unsigned li = 0; li < c.localFootprint; ++li) {
Local* local = c.locals + li;
if (local->value == 0) {
initLocal(1, li, IntegerType);
}
}
}
}
virtual Promise* machineIp(unsigned logicalIp) {
@ -2290,71 +2255,82 @@ class MyCompiler: public Compiler {
return p;
}
virtual Operand* constant(int64_t value, Compiler::OperandType type) {
virtual ir::Value* constant(int64_t value, ir::Type type)
{
return promiseConstant(resolvedPromise(&c, value), type);
}
virtual Operand* promiseConstant(Promise* value, Compiler::OperandType type) {
return compiler::value
(&c, valueType(&c, type), compiler::constantSite(&c, value));
}
virtual Operand* address(Promise* address) {
return value(&c, lir::ValueGeneral, compiler::addressSite(&c, address));
}
virtual Operand* memory(Operand* base,
OperandType type,
int displacement = 0,
Operand* index = 0,
unsigned scale = 1)
virtual ir::Value* promiseConstant(Promise* value, ir::Type type)
{
Value* result = value(&c, valueType(&c, type));
return compiler::value(&c, type, compiler::constantSite(&c, value));
}
appendMemory(&c, static_cast<Value*>(base), displacement,
static_cast<Value*>(index), scale, result);
virtual ir::Value* address(ir::Type type, Promise* address)
{
return value(&c, type, compiler::addressSite(&c, address));
}
virtual ir::Value* memory(ir::Value* base,
ir::Type type,
int displacement = 0,
ir::Value* index = 0)
{
Value* result = value(&c, type);
appendMemory(&c,
static_cast<Value*>(base),
displacement,
static_cast<Value*>(index),
index == 0 ? 1 : type.size(c.targetInfo),
result);
return result;
}
virtual Operand* register_(int number) {
return compiler::register_(&c, number);
virtual ir::Value* threadRegister()
{
return compiler::threadRegister(&c);
}
Promise* machineIp() {
return c.logicalCode[c.logicalIp]->lastEvent->makeCodePromise(&c);
}
virtual void push(unsigned footprint UNUSED) {
assert(&c, footprint == 1);
Value* v = value(&c, lir::ValueGeneral);
Stack* s = compiler::stack(&c, v, c.stack);
v->home = frameIndex(&c, s->index + c.localFootprint);
c.stack = s;
virtual void push(ir::Type type, ir::Value* value)
{
// TODO: once type information is flowed properly, enable this assert.
// Some time later, we can remove the parameter.
// assert(&c, value->type == type);
compiler::push(&c, typeFootprint(&c, type), static_cast<Value*>(value));
}
virtual void push(unsigned footprint, Operand* value) {
compiler::push(&c, footprint, static_cast<Value*>(value));
}
virtual void save(unsigned footprint, Operand* value) {
virtual void save(ir::Type type, ir::Value* value)
{
// TODO: once type information is flowed properly, enable this assert.
// Some time later, we can remove the parameter.
// assert(&c, value->type == type);
unsigned footprint = typeFootprint(&c, type);
c.saved = cons(&c, static_cast<Value*>(value), c.saved);
if (TargetBytesPerWord == 4 and footprint > 1) {
assert(&c, footprint == 2);
assert(&c, static_cast<Value*>(value)->nextWord);
save(1, static_cast<Value*>(value)->nextWord);
save(ir::Type::i4(), static_cast<Value*>(value)->nextWord);
}
}
virtual Operand* pop(unsigned footprint) {
return compiler::pop(&c, footprint);
virtual ir::Value* pop(ir::Type type)
{
ir::Value* value = compiler::pop(&c, typeFootprint(&c, type));
// TODO: once type information is flowed properly, enable this assert.
// Some time later, we can remove the parameter.
// assert(&c, static_cast<Value*>(value)->type == type);
return value;
}
virtual void pushed() {
Value* v = value(&c, lir::ValueGeneral);
virtual void pushed(ir::Type type)
{
Value* v = value(&c, type);
appendFrameSite
(&c, v, frameIndex
(&c, (c.stack ? c.stack->index : 0) + c.localFootprint));
@ -2380,7 +2356,8 @@ class MyCompiler: public Compiler {
return c.stack->index;
}
virtual Operand* peek(unsigned footprint, unsigned index) {
virtual ir::Value* peek(unsigned footprint, unsigned index)
{
Stack* s = c.stack;
for (unsigned i = index; i > 0; --i) {
s = s->next;
@ -2416,13 +2393,12 @@ class MyCompiler: public Compiler {
return s->value;
}
virtual Operand* call(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
OperandType resultType,
unsigned argumentCount,
...)
virtual ir::Value* call(ir::Value* address,
unsigned flags,
TraceHandler* traceHandler,
ir::Type resultType,
unsigned argumentCount,
...)
{
va_list a; va_start(a, argumentCount);
@ -2430,7 +2406,7 @@ class MyCompiler: public Compiler {
unsigned footprint = 0;
unsigned size = TargetBytesPerWord;
RUNTIME_ARRAY(Value*, arguments, argumentCount);
RUNTIME_ARRAY(ir::Value*, arguments, argumentCount);
int index = 0;
for (unsigned i = 0; i < argumentCount; ++i) {
Value* o = va_arg(a, Value*);
@ -2452,41 +2428,74 @@ class MyCompiler: public Compiler {
va_end(a);
Stack* argumentStack = c.stack;
for (int i = index - 1; i >= 0; --i) {
argumentStack = compiler::stack
(&c, RUNTIME_ARRAY_BODY(arguments)[i], argumentStack);
Value* result = value(&c, resultType);
appendCall(&c,
static_cast<Value*>(address),
ir::NativeCallingConvention,
flags,
traceHandler,
result,
util::Slice<ir::Value*>(RUNTIME_ARRAY_BODY(arguments), index));
return result;
}
virtual ir::Value* stackCall(ir::Value* address,
unsigned flags,
TraceHandler* traceHandler,
ir::Type resultType,
Slice<ir::Value*> arguments)
{
Value* result = value(&c, resultType);
Stack* b UNUSED = c.stack;
appendCall(&c,
static_cast<Value*>(address),
ir::AvianCallingConvention,
flags,
traceHandler,
result,
arguments);
assert(&c, c.stack == b);
return result;
}
virtual void return_(ir::Value* a)
{
assert(&c, a);
appendReturn(&c, static_cast<Value*>(a));
}
virtual void return_()
{
appendReturn(&c, 0);
}
void initLocalPart(unsigned index, ir::Type type)
{
Value* v = value(&c, type);
if (DebugFrame) {
fprintf(stderr,
"init local %p at %d (%d)\n",
v,
index,
frameIndex(&c, index));
}
Value* result = value(&c, valueType(&c, resultType));
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
resultSize, argumentStack, index, 0);
appendFrameSite(&c, v, frameIndex(&c, index));
return result;
Local* local = c.locals + index;
local->value = v;
v->home = frameIndex(&c, index);
}
virtual Operand* stackCall(Operand* address,
unsigned flags,
TraceHandler* traceHandler,
unsigned resultSize,
OperandType resultType,
unsigned argumentFootprint)
virtual void initLocal(unsigned index, ir::Type type)
{
Value* result = value(&c, valueType(&c, resultType));
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
resultSize, c.stack, 0, argumentFootprint);
return result;
}
unsigned footprint = typeFootprint(&c, type);
virtual void return_(unsigned size, Operand* value) {
appendReturn(&c, size, static_cast<Value*>(value));
}
virtual void initLocal(unsigned footprint, unsigned index, OperandType type)
{
assert(&c, index + footprint <= c.localFootprint);
Value* v = value(&c, valueType(&c, type));
Value* v = value(&c, type);
if (footprint > 1) {
assert(&c, footprint == 2);
@ -2498,11 +2507,11 @@ class MyCompiler: public Compiler {
lowIndex = index;
} else {
lowIndex = index + 1;
highIndex = index;
highIndex = index;
}
if (TargetBytesPerWord == 4) {
initLocal(1, highIndex, type);
initLocalPart(highIndex, type);
Value* next = c.locals[highIndex].value;
v->nextWord = next;
next->nextWord = v;
@ -2525,7 +2534,7 @@ class MyCompiler: public Compiler {
}
virtual void initLocalsFromLogicalIp(unsigned logicalIp) {
assert(&c, logicalIp < c.logicalCodeLength);
assert(&c, logicalIp < c.logicalCode.count());
unsigned footprint = sizeof(Local) * c.localFootprint;
Local* newLocals = static_cast<Local*>(c.zone->allocate(footprint));
@ -2536,127 +2545,203 @@ class MyCompiler: public Compiler {
for (int i = 0; i < static_cast<int>(c.localFootprint); ++i) {
Local* local = e->locals() + i;
if (local->value) {
initLocal
(1, i, local->value->type == lir::ValueGeneral ? IntegerType : FloatType);
initLocalPart(i, local->value->type);
}
}
linkLocals(&c, e->locals(), newLocals);
}
virtual void storeLocal(unsigned footprint, Operand* src, unsigned index) {
compiler::storeLocal(&c, footprint, static_cast<Value*>(src), index, true);
virtual void storeLocal(ir::Value* src, unsigned index)
{
compiler::storeLocal(&c, typeFootprint(&c, src->type), static_cast<Value*>(src), index, true);
}
virtual Operand* loadLocal(unsigned footprint, unsigned index) {
return compiler::loadLocal(&c, footprint, index);
virtual ir::Value* loadLocal(ir::Type type, unsigned index)
{
return compiler::loadLocal(&c, type, index);
}
virtual void saveLocals() {
int oldIp UNUSED = c.logicalIp;
appendSaveLocals(&c);
assert(&c, oldIp == c.logicalIp);
}
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler)
virtual void checkBounds(ir::Value* object,
unsigned lengthOffset,
ir::Value* index,
intptr_t handler)
{
appendBoundsCheck(&c, static_cast<Value*>(object), lengthOffset,
static_cast<Value*>(index), handler);
}
virtual void store(unsigned srcSize, Operand* src, unsigned dstSize,
Operand* dst)
virtual ir::Value* truncate(ir::Type type, ir::Value* src)
{
appendMove(&c, lir::Move, srcSize, srcSize, static_cast<Value*>(src),
dstSize, static_cast<Value*>(dst));
}
virtual Operand* load(unsigned srcSize, unsigned srcSelectSize, Operand* src,
unsigned dstSize)
{
assert(&c, dstSize >= TargetBytesPerWord);
Value* dst = value(&c, static_cast<Value*>(src)->type);
appendMove(&c, lir::Move, srcSize, srcSelectSize, static_cast<Value*>(src),
dstSize, dst);
assert(&c, src->type.flavor() == type.flavor());
assert(&c, type.flavor() != ir::Type::Float);
assert(&c, type.rawSize() < src->type.rawSize());
Value* dst = value(&c, type);
appendMove(&c,
lir::Move,
src->type.size(c.targetInfo),
src->type.size(c.targetInfo),
static_cast<Value*>(src),
type.size(c.targetInfo),
dst);
return dst;
}
virtual Operand* loadz(unsigned srcSize, unsigned srcSelectSize,
Operand* src, unsigned dstSize)
virtual ir::Value* truncateThenExtend(ir::SignExtendMode signExtend,
ir::Type extendType,
ir::Type truncateType,
ir::Value* src)
{
assert(&c, dstSize >= TargetBytesPerWord);
Value* dst = value(&c, static_cast<Value*>(src)->type);
appendMove(&c, lir::MoveZ, srcSize, srcSelectSize, static_cast<Value*>(src),
dstSize, dst);
Value* dst = value(&c, extendType);
appendMove(&c,
signExtend == ir::SignExtend ? lir::Move : lir::MoveZ,
TargetBytesPerWord,
truncateType.size(c.targetInfo),
static_cast<Value*>(src),
extendType.size(c.targetInfo) < TargetBytesPerWord
? TargetBytesPerWord
: extendType.size(c.targetInfo),
dst);
return dst;
}
virtual void condJump(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b,
Operand* address)
virtual void store(ir::Value* src, ir::Value* dst)
{
assert(&c, src->type.flavor() == dst->type.flavor());
appendMove(&c,
lir::Move,
src->type.size(c.targetInfo),
src->type.size(c.targetInfo),
static_cast<Value*>(src),
dst->type.size(c.targetInfo),
static_cast<Value*>(dst));
}
virtual ir::Value* load(ir::SignExtendMode signExtend,
ir::Value* src,
ir::Type dstType)
{
assert(&c, src->type.flavor() == dstType.flavor());
Value* dst = value(&c, dstType);
appendMove(&c,
signExtend == ir::SignExtend ? lir::Move : lir::MoveZ,
src->type.size(c.targetInfo),
src->type.size(c.targetInfo),
static_cast<Value*>(src),
dstType.size(c.targetInfo) < TargetBytesPerWord
? TargetBytesPerWord
: dstType.size(c.targetInfo),
dst);
return dst;
}
virtual void condJump(lir::TernaryOperation op,
ir::Value* a,
ir::Value* b,
ir::Value* addr)
{
assert(&c,
(isGeneralBranch(type) and isGeneralValue(a) and isGeneralValue(b))
or (isFloatBranch(type) and isFloatValue(a) and isFloatValue(b)));
(isGeneralBranch(op) and isGeneralValue(a) and isGeneralValue(b))or(
isFloatBranch(op) and isFloatValue(a) and isFloatValue(b)));
appendBranch(&c, type, size, static_cast<Value*>(a),
static_cast<Value*>(b), static_cast<Value*>(address));
assert(&c, a->type == b->type);
assert(&c, addr->type == ir::Type::iptr());
appendBranch(&c,
op,
static_cast<Value*>(a),
static_cast<Value*>(b),
static_cast<Value*>(addr));
}
virtual void jmp(Operand* address) {
appendJump(&c, lir::Jump, static_cast<Value*>(address));
virtual void jmp(ir::Value* addr)
{
appendJump(&c, lir::Jump, static_cast<Value*>(addr));
}
virtual void exit(Operand* address) {
appendJump(&c, lir::Jump, static_cast<Value*>(address), true);
virtual void exit(ir::Value* addr)
{
appendJump(&c, lir::Jump, static_cast<Value*>(addr), true);
}
virtual Operand* binaryOp(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b) {
virtual ir::Value* binaryOp(lir::TernaryOperation op,
ir::Type type,
ir::Value* a,
ir::Value* b)
{
assert(&c,
(isGeneralBinaryOp(type) and isGeneralValue(a) and isGeneralValue(b))
or (isFloatBinaryOp(type) and isFloatValue(a) and isFloatValue(b)));
(isGeneralBinaryOp(op) and isGeneralValue(a) and isGeneralValue(b))
or(isFloatBinaryOp(op) and isFloatValue(a) and isFloatValue(b)));
Value* result = value(&c, static_cast<Value*>(a)->type);
appendCombine(&c, type, size, static_cast<Value*>(a),
size, static_cast<Value*>(b), size, result);
Value* result = value(&c, type);
appendCombine(&c,
op,
static_cast<Value*>(a),
static_cast<Value*>(b),
result);
return result;
}
virtual Operand* unaryOp(lir::BinaryOperation type, unsigned size, Operand* a) {
assert(&c, (isGeneralUnaryOp(type) and isGeneralValue(a))or(
isFloatUnaryOp(type) and isFloatValue(a)));
Value* result = value(&c, static_cast<Value*>(a)->type);
appendTranslate(&c, type, size, static_cast<Value*>(a), size, result);
return result;
}
virtual Operand* f2f(unsigned aSize, unsigned resSize, Operand* a) {
assert(&c, static_cast<Value*>(a)->type == lir::ValueFloat);
Value* result = value(&c, lir::ValueFloat);
appendTranslate
(&c, lir::Float2Float, aSize, static_cast<Value*>(a), resSize, result);
return result;
}
virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) {
assert(&c, static_cast<Value*>(a)->type == lir::ValueFloat);
Value* result = value(&c, lir::ValueGeneral);
appendTranslate
(&c, lir::Float2Int, aSize, static_cast<Value*>(a), resSize, result);
return result;
}
virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) {
assert(&c, static_cast<Value*>(a)->type == lir::ValueGeneral);
Value* result = value(&c, lir::ValueFloat);
appendTranslate
(&c, lir::Int2Float, aSize, static_cast<Value*>(a), resSize, result);
virtual ir::Value* unaryOp(lir::BinaryOperation op,
ir::Value* a)
{
assert(&c,
(isGeneralUnaryOp(op) and isGeneralValue(a))or(isFloatUnaryOp(op)
and isFloatValue(a)));
Value* result = value(&c, a->type);
appendTranslate(
&c, op, static_cast<Value*>(a), result);
return result;
}
virtual void nullaryOp(lir::Operation type) {
appendOperation(&c, type);
virtual ir::Value* f2f(ir::Type resType, ir::Value* a)
{
assert(&c, isFloatValue(a));
assert(&c, resType.flavor() == ir::Type::Float);
Value* result = value(&c, resType);
appendTranslate(&c,
lir::Float2Float,
static_cast<Value*>(a),
result);
return result;
}
virtual ir::Value* f2i(ir::Type resType, ir::Value* a)
{
assert(&c, isFloatValue(a));
assert(&c, resType.flavor() != ir::Type::Float);
Value* result = value(&c, resType);
appendTranslate(&c,
lir::Float2Int,
static_cast<Value*>(a),
result);
return result;
}
virtual ir::Value* i2f(ir::Type resType, ir::Value* a)
{
assert(&c, isGeneralValue(a));
assert(&c, resType.flavor() == ir::Type::Float);
Value* result = value(&c, resType);
appendTranslate(&c,
lir::Int2Float,
static_cast<Value*>(a),
result);
return result;
}
virtual void nullaryOp(lir::Operation op)
{
appendOperation(&c, op);
}
virtual void compile(uintptr_t stackOverflowHandler,

View File

@ -17,41 +17,41 @@ namespace avian {
namespace codegen {
namespace compiler {
Context::Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
Compiler::Client* client):
system(system),
assembler(assembler),
arch(assembler->arch()),
zone(zone),
client(client),
stack(0),
locals(0),
saved(0),
predecessor(0),
logicalCode(0),
regFile(arch->registerFile()),
regAlloc(system, arch->registerFile()),
registerResources
(static_cast<RegisterResource*>
(zone->allocate(sizeof(RegisterResource) * regFile->allRegisters.limit))),
frameResources(0),
acquiredResources(0),
firstConstant(0),
lastConstant(0),
machineCode(0),
firstEvent(0),
lastEvent(0),
forkState(0),
subroutine(0),
firstBlock(0),
logicalIp(-1),
constantCount(0),
logicalCodeLength(0),
parameterFootprint(0),
localFootprint(0),
machineCodeSize(0),
alignedFrameSize(0),
availableGeneralRegisterCount(regFile->generalRegisters.limit - regFile->generalRegisters.start)
Context::Context(vm::System* system,
Assembler* assembler,
vm::Zone* zone,
Compiler::Client* client)
: system(system),
assembler(assembler),
arch(assembler->arch()),
zone(zone),
client(client),
stack(0),
locals(0),
saved(0),
predecessor(0),
regFile(arch->registerFile()),
regAlloc(system, arch->registerFile()),
registerResources(static_cast<RegisterResource*>(zone->allocate(
sizeof(RegisterResource) * regFile->allRegisters.limit))),
frameResources(0),
acquiredResources(0),
firstConstant(0),
lastConstant(0),
machineCode(0),
firstEvent(0),
lastEvent(0),
forkState(0),
firstBlock(0),
logicalIp(-1),
constantCount(0),
parameterFootprint(0),
localFootprint(0),
machineCodeSize(0),
alignedFrameSize(0),
availableGeneralRegisterCount(regFile->generalRegisters.limit
- regFile->generalRegisters.start),
targetInfo(arch->targetInfo())
{
for (unsigned i = regFile->generalRegisters.start; i < regFile->generalRegisters.limit; ++i) {
new (registerResources + i) RegisterResource(arch->reserved(i));

View File

@ -35,7 +35,6 @@ class FrameResource;
class ConstantPoolNode;
class ForkState;
class MySubroutine;
class Block;
template<class T>
@ -50,6 +49,48 @@ List<T>* reverseDestroy(List<T>* cell) {
return previous;
}
class LogicalCode {
private:
util::Slice<LogicalInstruction*> logicalCode;
public:
LogicalCode() : logicalCode(0, 0)
{
}
void init(vm::Zone* zone, size_t count)
{
// leave room for logical instruction -1
size_t realCount = count + 1;
logicalCode
= util::Slice<LogicalInstruction*>::allocAndSet(zone, realCount, 0);
}
void extend(vm::Zone* zone, size_t more)
{
util::Slice<LogicalInstruction*> newCode
= logicalCode.cloneAndSet(zone, logicalCode.count + more, 0);
for (size_t i = 0; i < logicalCode.count; i++) {
assert((vm::System*)0, logicalCode[i] == newCode[i]);
}
logicalCode = newCode;
}
size_t count()
{
return logicalCode.count - 1;
}
LogicalInstruction*& operator[](int index)
{
// leave room for logical instruction -1
return logicalCode[index + 1];
}
};
class Context {
public:
Context(vm::System* system, Assembler* assembler, vm::Zone* zone,
@ -64,7 +105,7 @@ class Context {
Local* locals;
List<Value*>* saved;
Event* predecessor;
LogicalInstruction** logicalCode;
LogicalCode logicalCode;
const RegisterFile* regFile;
RegisterAllocator regAlloc;
RegisterResource* registerResources;
@ -76,16 +117,15 @@ class Context {
Event* firstEvent;
Event* lastEvent;
ForkState* forkState;
MySubroutine* subroutine;
Block* firstBlock;
int logicalIp;
unsigned constantCount;
unsigned logicalCodeLength;
unsigned parameterFootprint;
unsigned localFootprint;
unsigned machineCodeSize;
unsigned alignedFrameSize;
unsigned availableGeneralRegisterCount;
ir::TargetInfo targetInfo;
};
inline Aborter* getAborter(Context* c) {

File diff suppressed because it is too large Load Diff

View File

@ -113,28 +113,34 @@ Link*
link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor,
Link* nextSuccessor, ForkState* forkState);
void
appendCall(Context* c, Value* address, unsigned flags,
TraceHandler* traceHandler, Value* result, unsigned resultSize,
Stack* argumentStack, unsigned argumentCount,
unsigned stackArgumentFootprint);
void appendCall(Context* c,
Value* address,
ir::CallingConvention callingConvention,
unsigned flags,
TraceHandler* traceHandler,
Value* result,
util::Slice<ir::Value*> arguments);
void
appendReturn(Context* c, unsigned size, Value* value);
void appendReturn(Context* c, Value* value);
void
appendMove(Context* c, lir::BinaryOperation type, unsigned srcSize,
unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst);
void appendMove(Context* c,
lir::BinaryOperation op,
unsigned srcSize,
unsigned srcSelectSize,
Value* src,
unsigned dstSize,
Value* dst);
void
appendCombine(Context* c, lir::TernaryOperation type,
unsigned firstSize, Value* first,
unsigned secondSize, Value* second,
unsigned resultSize, Value* result);
void appendCombine(Context* c,
lir::TernaryOperation op,
Value* first,
Value* second,
Value* result);
void
appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize,
Value* first, unsigned resultSize, Value* result);
void appendTranslate(Context* c,
lir::BinaryOperation op,
Value* first,
Value* result);
void
appendOperation(Context* c, lir::Operation op);
@ -143,13 +149,17 @@ void
appendMemory(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result);
void
appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first,
Value* second, Value* address);
void appendBranch(Context* c,
lir::TernaryOperation op,
Value* first,
Value* second,
Value* address);
void
appendJump(Context* c, lir::UnaryOperation type, Value* address, bool exit = false,
bool cleanLocals = false);
void appendJump(Context* c,
lir::UnaryOperation op,
Value* address,
bool exit = false,
bool cleanLocals = false);
void
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
@ -164,6 +174,8 @@ appendSaveLocals(Context* c);
void
appendDummy(Context* c);
void appendBuddy(Context* c, Value* original, Value* buddy);
} // namespace compiler
} // namespace codegen
} // namespace avian

View File

@ -45,16 +45,18 @@ int frameIndex(Context* c, int localIndex) {
unsigned frameIndexToOffset(Context* c, unsigned frameIndex) {
assert(c, frameIndex < totalFrameSize(c));
return (frameIndex + c->arch->frameFooterSize()) * vm::TargetBytesPerWord;
return (frameIndex + c->arch->frameFooterSize()) * c->targetInfo.pointerSize;
}
unsigned offsetToFrameIndex(Context* c, unsigned offset) {
assert(c, static_cast<int>
((offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize()) >= 0);
assert(c, ((offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize())
assert(c,
static_cast<int>((offset / c->targetInfo.pointerSize)
- c->arch->frameFooterSize()) >= 0);
assert(c,
((offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize())
< totalFrameSize(c));
return (offset / vm::TargetBytesPerWord) - c->arch->frameFooterSize();
return (offset / c->targetInfo.pointerSize) - c->arch->frameFooterSize();
}
unsigned frameBase(Context* c) {

View File

@ -15,14 +15,19 @@ namespace avian {
namespace codegen {
namespace compiler {
LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals):
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack),
locals(locals), machineOffset(0), subroutine(0), index(index)
LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals)
: firstEvent(0),
lastEvent(0),
immediatePredecessor(0),
stack(stack),
locals(locals),
machineOffset(0),
/*subroutine(0), */ index(index)
{ }
LogicalInstruction* LogicalInstruction::next(Context* c) {
LogicalInstruction* i = this;
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
for (size_t n = i->index + 1; n < c->logicalCode.count(); ++n) {
i = c->logicalCode[n];
if (i) return i;
}

View File

@ -57,17 +57,9 @@ class LogicalInstruction {
Stack* stack;
Local* locals;
Promise* machineOffset;
MySubroutine* subroutine;
int index;
};
class MySubroutine: public Compiler::Subroutine {
public:
MySubroutine(): forkState(0) { }
ForkState* forkState;
};
class Block {
public:
Block(Event* head);

View File

@ -90,9 +90,10 @@ class PoolPromise: public Promise {
virtual int64_t value() {
if (resolved()) {
return reinterpret_cast<int64_t>
(c->machineCode + vm::pad(c->machineCodeSize, vm::TargetBytesPerWord)
+ (key * vm::TargetBytesPerWord));
return reinterpret_cast<int64_t>(
c->machineCode
+ vm::pad(c->machineCodeSize, c->targetInfo.pointerSize)
+ (key * c->targetInfo.pointerSize));
}
abort(c);

View File

@ -215,12 +215,12 @@ pickTarget(Context* c, Read* read, bool intersectRead,
Value* value = read->value;
uint32_t registerMask
= (value->type == lir::ValueFloat ? ~0 : c->regFile->generalRegisters.mask);
= (isFloatValue(value) ? ~0 : c->regFile->generalRegisters.mask);
SiteMask mask(~0, registerMask, AnyFrameIndex);
read->intersect(&mask);
if (value->type == lir::ValueFloat) {
if (isFloatValue(value)) {
uint32_t floatMask = mask.registerMask & c->regFile->floatRegisters.mask;
if (floatMask) {
mask.registerMask = floatMask;

View File

@ -52,7 +52,7 @@ SiteIterator::SiteIterator(Context* c, Value* v, bool includeBuddies,
Site** SiteIterator::findNext(Site** p) {
while (true) {
if (*p) {
if (pass == 0 or (*p)->registerSize(c) > vm::TargetBytesPerWord) {
if (pass == 0 or (*p)->registerSize(c) > c->targetInfo.pointerSize) {
return p;
} else {
p = &((*p)->next);
@ -103,14 +103,11 @@ void SiteIterator::remove(Context* c) {
previous = 0;
}
unsigned Site::registerSize(Context*) {
return vm::TargetBytesPerWord;
unsigned Site::registerSize(Context* c)
{
return c->targetInfo.pointerSize;
}
Site* constantSite(Context* c, Promise* value) {
return new(c->zone) ConstantSite(value);
}
@ -250,7 +247,7 @@ bool RegisterSite::matchNextWord(Context* c, Site* s, unsigned) {
RegisterSite* rs = static_cast<RegisterSite*>(s);
unsigned size = rs->registerSize(c);
if (size > vm::TargetBytesPerWord) {
if (size > c->targetInfo.pointerSize) {
assert(c, number != lir::NoRegister);
return number == rs->number;
} else {
@ -352,7 +349,7 @@ SiteMask RegisterSite::mask(Context* c UNUSED) {
SiteMask RegisterSite::nextWordMask(Context* c, unsigned) {
assert(c, number != lir::NoRegister);
if (registerSize(c) > vm::TargetBytesPerWord) {
if (registerSize(c) > c->targetInfo.pointerSize) {
return SiteMask
(1 << lir::RegisterOperand, number, NoFrameIndex);
} else {
@ -367,7 +364,7 @@ unsigned RegisterSite::registerSize(Context* c) {
if ((1 << number) & c->regFile->floatRegisters.mask) {
return c->arch->floatRegisterSize();
} else {
return vm::TargetBytesPerWord;
return c->targetInfo.pointerSize;
}
}
@ -469,12 +466,15 @@ bool MemorySite::matchNextWord(Context* c, Site* s, unsigned index) {
if (s->type(c) == lir::MemoryOperand) {
MemorySite* ms = static_cast<MemorySite*>(s);
return ms->base == this->base
and ((index == 1 and ms->offset == static_cast<int>
(this->offset + vm::TargetBytesPerWord))
or (index == 0 and this->offset == static_cast<int>
(ms->offset + vm::TargetBytesPerWord)))
and ms->index == this->index
and ms->scale == this->scale;
and ((index == 1
and ms->offset
== static_cast<int>(this->offset
+ c->targetInfo.pointerSize))
or (index == 0
and this->offset
== static_cast<int>(ms->offset
+ c->targetInfo.pointerSize)))
and ms->index == this->index and ms->scale == this->scale;
} else {
return false;
}
@ -551,10 +551,11 @@ void MemorySite::asAssemblerOperand(Context* c UNUSED, Site* high UNUSED,
lir::Operand* result)
{
// todo: endianness?
assert(c, high == this
assert(c,
high == this
or (static_cast<MemorySite*>(high)->base == base
and static_cast<MemorySite*>(high)->offset
== static_cast<int>(offset + vm::TargetBytesPerWord)
== static_cast<int>(offset + c->targetInfo.pointerSize)
and static_cast<MemorySite*>(high)->index == index
and static_cast<MemorySite*>(high)->scale == scale));
@ -569,7 +570,8 @@ Site* MemorySite::copy(Context* c) {
Site* MemorySite::copyHalf(Context* c, bool add) {
if (add) {
return memorySite(c, base, offset + vm::TargetBytesPerWord, index, scale);
return memorySite(
c, base, offset + c->targetInfo.pointerSize, index, scale);
} else {
return copy(c);
}
@ -584,10 +586,13 @@ Site* MemorySite::copyHigh(Context* c) {
}
Site* MemorySite::makeNextWord(Context* c, unsigned index) {
return memorySite
(c, base, offset + ((index == 1) xor c->arch->bigEndian()
? vm::TargetBytesPerWord : -vm::TargetBytesPerWord),
this->index, scale);
return memorySite(c,
base,
offset + ((index == 1) xor c->arch->bigEndian()
? c->targetInfo.pointerSize
: -c->targetInfo.pointerSize),
this->index,
scale);
}
SiteMask MemorySite::mask(Context* c) {

View File

@ -17,10 +17,19 @@ namespace avian {
namespace codegen {
namespace compiler {
Value::Value(Site* site, Site* target, lir::ValueType type):
reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this),
nextWord(this), home(NoFrameIndex), type(type), wordIndex(0)
{ }
Value::Value(Site* site, Site* target, ir::Type type)
: ir::Value(type),
reads(0),
lastRead(0),
sites(site),
source(0),
target(target),
buddy(this),
nextWord(this),
home(NoFrameIndex),
wordIndex(0)
{
}
bool Value::findSite(Site* site) {
for (Site* s = this->sites; s; s = s->next) {
@ -106,7 +115,8 @@ bool Value::uniqueSite(Context* c, Site* s) {
if (it.hasMore()) {
// the site is not this word's only site, but if the site is
// shared with the next word, it may be that word's only site
if (this->nextWord != this and s->registerSize(c) > vm::TargetBytesPerWord) {
if (this->nextWord != this
and s->registerSize(c) > c->targetInfo.pointerSize) {
SiteIterator nit(c, this->nextWord);
Site* p = nit.next();
if (nit.hasMore()) {
@ -154,8 +164,8 @@ bool Value::hasBuddy(Context* c, Value* b) {
}
#endif // not NDEBUG
Value* value(Context* c, lir::ValueType type, Site* site, Site* target) {
Value* value(Context* c, ir::Type type, Site* site, Site* target)
{
return new(c->zone) Value(site, target, type);
}

View File

@ -26,7 +26,7 @@ const int NoFrameIndex = -1;
const bool DebugSites = false;
class Value: public Compiler::Operand {
class Value : public ir::Value {
public:
Read* reads;
Read* lastRead;
@ -36,10 +36,9 @@ class Value: public Compiler::Operand {
Value* buddy;
Value* nextWord;
int16_t home;
lir::ValueType type;
uint8_t wordIndex;
Value(Site* site, Site* target, lir::ValueType type);
Value(Site* site, Site* target, ir::Type type);
bool findSite(Site* site);
@ -67,15 +66,17 @@ class Value: public Compiler::Operand {
};
inline bool isGeneralValue(Compiler::Operand* a) {
return static_cast<Value*>(a)->type == lir::ValueGeneral;
inline bool isFloatValue(ir::Value* a)
{
return static_cast<Value*>(a)->type.flavor() == ir::Type::Float;
}
inline bool isFloatValue(Compiler::Operand* a) {
return static_cast<Value*>(a)->type == lir::ValueFloat;
inline bool isGeneralValue(ir::Value* a)
{
return !isFloatValue(a);
}
Value* value(Context* c, lir::ValueType type, Site* site = 0, Site* target = 0);
Value* value(Context* c, ir::Type type, Site* site = 0, Site* target = 0);
} // namespace compiler
} // namespace codegen

View File

@ -180,6 +180,11 @@ class MyArchitecture: public Architecture {
return 3;
}
virtual ir::TargetInfo targetInfo()
{
return ir::TargetInfo(TargetBytesPerWord);
}
virtual bool bigEndian() {
return false;
}

View File

@ -204,6 +204,11 @@ class MyArchitecture: public Architecture {
return rdx;
}
virtual ir::TargetInfo targetInfo()
{
return ir::TargetInfo(TargetBytesPerWord);
}
virtual bool bigEndian() {
return false;
}

File diff suppressed because it is too large Load Diff

612
src/debug-util.cpp Normal file
View File

@ -0,0 +1,612 @@
/* Copyright (c) 2008-2013, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include <avian/machine.h>
#include "debug-util.h"
namespace avian {
namespace jvm {
namespace debug {
uint16_t read16(uint8_t* code, unsigned& ip)
{
uint16_t a = code[ip++];
uint16_t b = code[ip++];
return (a << 8) | b;
}
uint32_t read32(uint8_t* code, unsigned& ip)
{
uint32_t b = code[ip++];
uint32_t a = code[ip++];
uint32_t c = code[ip++];
uint32_t d = code[ip++];
return (a << 24) | (b << 16) | (c << 8) | d;
}
using namespace vm;
int printInstruction(uint8_t* code, unsigned& ip, const char* prefix)
{
unsigned startIp = ip;
uint8_t instr = code[ip++];
switch (instr) {
case aaload:
return fprintf(stderr, "aaload");
case aastore:
return fprintf(stderr, "aastore");
case aconst_null:
return fprintf(stderr, "aconst_null");
case aload:
return fprintf(stderr, "aload %2d", code[ip++]);
case aload_0:
return fprintf(stderr, "aload_0");
case aload_1:
return fprintf(stderr, "aload_1");
case aload_2:
return fprintf(stderr, "aload_2");
case aload_3:
return fprintf(stderr, "aload_3");
case anewarray:
return fprintf(stderr, "anewarray %4d", read16(code, ip));
case areturn:
return fprintf(stderr, "areturn");
case arraylength:
return fprintf(stderr, "arraylength");
case astore:
return fprintf(stderr, "astore %2d", code[ip++]);
case astore_0:
return fprintf(stderr, "astore_0");
case astore_1:
return fprintf(stderr, "astore_1");
case astore_2:
return fprintf(stderr, "astore_2");
case astore_3:
return fprintf(stderr, "astore_3");
case athrow:
return fprintf(stderr, "athrow");
case baload:
return fprintf(stderr, "baload");
case bastore:
return fprintf(stderr, "bastore");
case bipush:
return fprintf(stderr, "bipush %2d", code[ip++]);
case caload:
return fprintf(stderr, "caload");
case castore:
return fprintf(stderr, "castore");
case checkcast:
return fprintf(stderr, "checkcast %4d", read16(code, ip));
case d2f:
return fprintf(stderr, "d2f");
case d2i:
return fprintf(stderr, "d2i");
case d2l:
return fprintf(stderr, "d2l");
case dadd:
return fprintf(stderr, "dadd");
case daload:
return fprintf(stderr, "daload");
case dastore:
return fprintf(stderr, "dastore");
case dcmpg:
return fprintf(stderr, "dcmpg");
case dcmpl:
return fprintf(stderr, "dcmpl");
case dconst_0:
return fprintf(stderr, "dconst_0");
case dconst_1:
return fprintf(stderr, "dconst_1");
case ddiv:
return fprintf(stderr, "ddiv");
case dmul:
return fprintf(stderr, "dmul");
case dneg:
return fprintf(stderr, "dneg");
case vm::drem:
return fprintf(stderr, "drem");
case dsub:
return fprintf(stderr, "dsub");
case dup:
return fprintf(stderr, "dup");
case dup_x1:
return fprintf(stderr, "dup_x1");
case dup_x2:
return fprintf(stderr, "dup_x2");
case dup2:
return fprintf(stderr, "dup2");
case dup2_x1:
return fprintf(stderr, "dup2_x1");
case dup2_x2:
return fprintf(stderr, "dup2_x2");
case f2d:
return fprintf(stderr, "f2d");
case f2i:
return fprintf(stderr, "f2i");
case f2l:
return fprintf(stderr, "f2l");
case fadd:
return fprintf(stderr, "fadd");
case faload:
return fprintf(stderr, "faload");
case fastore:
return fprintf(stderr, "fastore");
case fcmpg:
return fprintf(stderr, "fcmpg");
case fcmpl:
return fprintf(stderr, "fcmpl");
case fconst_0:
return fprintf(stderr, "fconst_0");
case fconst_1:
return fprintf(stderr, "fconst_1");
case fconst_2:
return fprintf(stderr, "fconst_2");
case fdiv:
return fprintf(stderr, "fdiv");
case fmul:
return fprintf(stderr, "fmul");
case fneg:
return fprintf(stderr, "fneg");
case frem:
return fprintf(stderr, "frem");
case fsub:
return fprintf(stderr, "fsub");
case getfield:
return fprintf(stderr, "getfield %4d", read16(code, ip));
case getstatic:
return fprintf(stderr, "getstatic %4d", read16(code, ip));
case goto_: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "goto %4d", offset + ip - 3);
}
case goto_w: {
int32_t offset = read32(code, ip);
return fprintf(stderr, "goto_w %08x", offset + ip - 5);
}
case i2b:
return fprintf(stderr, "i2b");
case i2c:
return fprintf(stderr, "i2c");
case i2d:
return fprintf(stderr, "i2d");
case i2f:
return fprintf(stderr, "i2f");
case i2l:
return fprintf(stderr, "i2l");
case i2s:
return fprintf(stderr, "i2s");
case iadd:
return fprintf(stderr, "iadd");
case iaload:
return fprintf(stderr, "iaload");
case iand:
return fprintf(stderr, "iand");
case iastore:
return fprintf(stderr, "iastore");
case iconst_m1:
return fprintf(stderr, "iconst_m1");
case iconst_0:
return fprintf(stderr, "iconst_0");
case iconst_1:
return fprintf(stderr, "iconst_1");
case iconst_2:
return fprintf(stderr, "iconst_2");
case iconst_3:
return fprintf(stderr, "iconst_3");
case iconst_4:
return fprintf(stderr, "iconst_4");
case iconst_5:
return fprintf(stderr, "iconst_5");
case idiv:
return fprintf(stderr, "idiv");
case if_acmpeq: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_acmpeq %4d", offset + ip - 3);
}
case if_acmpne: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_acmpne %4d", offset + ip - 3);
}
case if_icmpeq: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_icmpeq %4d", offset + ip - 3);
}
case if_icmpne: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_icmpne %4d", offset + ip - 3);
}
case if_icmpgt: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_icmpgt %4d", offset + ip - 3);
}
case if_icmpge: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_icmpge %4d", offset + ip - 3);
}
case if_icmplt: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_icmplt %4d", offset + ip - 3);
}
case if_icmple: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "if_icmple %4d", offset + ip - 3);
}
case ifeq: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "ifeq %4d", offset + ip - 3);
}
case ifne: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "ifne %4d", offset + ip - 3);
}
case ifgt: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "ifgt %4d", offset + ip - 3);
}
case ifge: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "ifge %4d", offset + ip - 3);
}
case iflt: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "iflt %4d", offset + ip - 3);
}
case ifle: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "ifle %4d", offset + ip - 3);
}
case ifnonnull: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "ifnonnull %4d", offset + ip - 3);
}
case ifnull: {
int16_t offset = read16(code, ip);
return fprintf(stderr, "ifnull %4d", offset + ip - 3);
}
case iinc: {
uint8_t a = code[ip++];
uint8_t b = code[ip++];
return fprintf(stderr, "iinc %2d %2d", a, b);
}
case iload:
return fprintf(stderr, "iload %2d", code[ip++]);
case fload:
return fprintf(stderr, "fload %2d", code[ip++]);
case iload_0:
return fprintf(stderr, "iload_0");
case fload_0:
return fprintf(stderr, "fload_0");
case iload_1:
return fprintf(stderr, "iload_1");
case fload_1:
return fprintf(stderr, "fload_1");
case iload_2:
return fprintf(stderr, "iload_2");
case fload_2:
return fprintf(stderr, "fload_2");
case iload_3:
return fprintf(stderr, "iload_3");
case fload_3:
return fprintf(stderr, "fload_3");
case imul:
return fprintf(stderr, "imul");
case ineg:
return fprintf(stderr, "ineg");
case instanceof:
return fprintf(stderr, "instanceof %4d", read16(code, ip));
case invokeinterface:
return fprintf(stderr, "invokeinterface %4d", read16(code, ip));
case invokespecial:
return fprintf(stderr, "invokespecial %4d", read16(code, ip));
case invokestatic:
return fprintf(stderr, "invokestatic %4d", read16(code, ip));
case invokevirtual:
return fprintf(stderr, "invokevirtual %4d", read16(code, ip));
case ior:
return fprintf(stderr, "ior");
case irem:
return fprintf(stderr, "irem");
case ireturn:
return fprintf(stderr, "ireturn");
case freturn:
return fprintf(stderr, "freturn");
case ishl:
return fprintf(stderr, "ishl");
case ishr:
return fprintf(stderr, "ishr");
case istore:
return fprintf(stderr, "istore %2d", code[ip++]);
case fstore:
return fprintf(stderr, "fstore %2d", code[ip++]);
case istore_0:
return fprintf(stderr, "istore_0");
case fstore_0:
return fprintf(stderr, "fstore_0");
case istore_1:
return fprintf(stderr, "istore_1");
case fstore_1:
return fprintf(stderr, "fstore_1");
case istore_2:
return fprintf(stderr, "istore_2");
case fstore_2:
return fprintf(stderr, "fstore_2");
case istore_3:
return fprintf(stderr, "istore_3");
case fstore_3:
return fprintf(stderr, "fstore_3");
case isub:
return fprintf(stderr, "isub");
case iushr:
return fprintf(stderr, "iushr");
case ixor:
return fprintf(stderr, "ixor");
case jsr:
return fprintf(stderr, "jsr %4d", read16(code, ip) + startIp);
case jsr_w:
return fprintf(stderr, "jsr_w %08x", read32(code, ip) + startIp);
case l2d:
return fprintf(stderr, "l2d");
case l2f:
return fprintf(stderr, "l2f");
case l2i:
return fprintf(stderr, "l2i");
case ladd:
return fprintf(stderr, "ladd");
case laload:
return fprintf(stderr, "laload");
case land:
return fprintf(stderr, "land");
case lastore:
return fprintf(stderr, "lastore");
case lcmp:
return fprintf(stderr, "lcmp");
case lconst_0:
return fprintf(stderr, "lconst_0");
case lconst_1:
return fprintf(stderr, "lconst_1");
case ldc:
return fprintf(stderr, "ldc %4d", read16(code, ip));
case ldc_w:
return fprintf(stderr, "ldc_w %08x", read32(code, ip));
case ldc2_w:
return fprintf(stderr, "ldc2_w %4d", read16(code, ip));
case ldiv_:
return fprintf(stderr, "ldiv_");
case lload:
return fprintf(stderr, "lload %2d", code[ip++]);
case dload:
return fprintf(stderr, "dload %2d", code[ip++]);
case lload_0:
return fprintf(stderr, "lload_0");
case dload_0:
return fprintf(stderr, "dload_0");
case lload_1:
return fprintf(stderr, "lload_1");
case dload_1:
return fprintf(stderr, "dload_1");
case lload_2:
return fprintf(stderr, "lload_2");
case dload_2:
return fprintf(stderr, "dload_2");
case lload_3:
return fprintf(stderr, "lload_3");
case dload_3:
return fprintf(stderr, "dload_3");
case lmul:
return fprintf(stderr, "lmul");
case lneg:
return fprintf(stderr, "lneg");
case lookupswitch: {
while (ip & 0x3) {
ip++;
}
int32_t default_ = read32(code, ip) + startIp;
int32_t pairCount = read32(code, ip);
fprintf(
stderr, "lookupswitch default: %d pairCount: %d", default_, pairCount);
for (int i = 0; i < pairCount; i++) {
int32_t k = read32(code, ip);
int32_t d = read32(code, ip) + startIp;
fprintf(stderr, "\n%s key: %2d dest: %d", prefix, k, d);
}
fprintf(stderr, "\n");
fflush(stderr);
return 0;
}
case lor:
return fprintf(stderr, "lor");
case lrem:
return fprintf(stderr, "lrem");
case lreturn:
return fprintf(stderr, "lreturn");
case dreturn:
return fprintf(stderr, "dreturn");
case lshl:
return fprintf(stderr, "lshl");
case lshr:
return fprintf(stderr, "lshr");
case lstore:
return fprintf(stderr, "lstore %2d", code[ip++]);
case dstore:
return fprintf(stderr, "dstore %2d", code[ip++]);
case lstore_0:
return fprintf(stderr, "lstore_0");
case dstore_0:
return fprintf(stderr, "dstore_0");
case lstore_1:
return fprintf(stderr, "lstore_1");
case dstore_1:
return fprintf(stderr, "dstore_1");
case lstore_2:
return fprintf(stderr, "lstore_2");
case dstore_2:
return fprintf(stderr, "dstore_2");
case lstore_3:
return fprintf(stderr, "lstore_3");
case dstore_3:
return fprintf(stderr, "dstore_3");
case lsub:
return fprintf(stderr, "lsub");
case lushr:
return fprintf(stderr, "lushr");
case lxor:
return fprintf(stderr, "lxor");
case monitorenter:
return fprintf(stderr, "monitorenter");
case monitorexit:
return fprintf(stderr, "monitorexit");
case multianewarray: {
unsigned type = read16(code, ip);
return fprintf(stderr, "multianewarray %4d %2d", type, code[ip++]);
}
case new_:
return fprintf(stderr, "new %4d", read16(code, ip));
case newarray:
return fprintf(stderr, "newarray %2d", code[ip++]);
case nop:
return fprintf(stderr, "nop");
case pop_:
return fprintf(stderr, "pop");
case pop2:
return fprintf(stderr, "pop2");
case putfield:
return fprintf(stderr, "putfield %4d", read16(code, ip));
case putstatic:
return fprintf(stderr, "putstatic %4d", read16(code, ip));
case ret:
return fprintf(stderr, "ret %2d", code[ip++]);
case return_:
return fprintf(stderr, "return_");
case saload:
return fprintf(stderr, "saload");
case sastore:
return fprintf(stderr, "sastore");
case sipush:
return fprintf(stderr, "sipush %4d", read16(code, ip));
case swap:
return fprintf(stderr, "swap");
case tableswitch: {
while (ip & 0x3) {
ip++;
}
int32_t default_ = read32(code, ip) + startIp;
int32_t bottom = read32(code, ip);
int32_t top = read32(code, ip);
fprintf(stderr,
"tableswitch default: %d bottom: %d top: %d",
default_,
bottom,
top);
for (int i = 0; i < top - bottom + 1; i++) {
int32_t d = read32(code, ip) + startIp;
fprintf(stderr, "%s key: %d dest: %d", prefix, i + bottom, d);
}
return 0;
}
case wide: {
switch (code[ip++]) {
case aload:
return fprintf(stderr, "wide aload %4d", read16(code, ip));
case astore:
return fprintf(stderr, "wide astore %4d", read16(code, ip));
case iinc:
fprintf(stderr, "wide iinc %4d %4d", read16(code, ip), read16(code, ip));
case iload:
return fprintf(stderr, "wide iload %4d", read16(code, ip));
case istore:
return fprintf(stderr, "wide istore %4d", read16(code, ip));
case lload:
return fprintf(stderr, "wide lload %4d", read16(code, ip));
case lstore:
return fprintf(stderr, "wide lstore %4d", read16(code, ip));
case ret:
return fprintf(stderr, "wide ret %4d", read16(code, ip));
default: {
fprintf(
stderr, "unknown wide instruction %2d %4d", instr, read16(code, ip));
}
}
}
default: {
return fprintf(stderr, "unknown instruction %2d", instr);
}
}
return ip;
}
void disassembleCode(const char* prefix, uint8_t* code, unsigned length)
{
unsigned ip = 0;
while (ip < length) {
fprintf(stderr, "%s%x:\t", prefix, ip);
printInstruction(code, ip, prefix);
fprintf(stderr, "\n");
}
}
} // namespace debug
} // namespace jvm
} // namespace avian

24
src/debug-util.h Normal file
View File

@ -0,0 +1,24 @@
/* Copyright (c) 2008-2013, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#include <stdint.h>
namespace avian {
namespace jvm {
namespace debug {
// print out a single instruction (no newline)
// returns number of characters printed
int printInstruction(uint8_t* code, unsigned& ip, const char* prefix = "");
void disassembleCode(const char* prefix, uint8_t* code, unsigned length);
} // namespace debug
} // namespace jvm
} // namespace avian

View File

@ -253,6 +253,16 @@ public class Subroutine {
return true;
}
private static int test6(boolean predicate) {
try {
if (predicate) {
return -2;
}
} finally {
return new Throwable().getStackTrace()[0].getLineNumber();
}
}
public static void main(String[] args) throws Exception {
test(false, false);
test(false, true);
@ -311,6 +321,15 @@ public class Subroutine {
(null, new Object[0]);
stackMap(new Object());
{
int f = test6(false);
int t = test6(true);
System.out.println("line: " + f);
expect(f > 0);
expect(f == t);
}
}
private static class DummyException extends RuntimeException { }

View File

@ -24,6 +24,7 @@ run make ${flags} process=interpret ${test_target}
# bootimage and openjdk builds without openjdk-src don't work:
if [ -z "${openjdk}" ]; then
run make ${flags} bootimage=true ${test_target}
run make ${flags} mode=debug bootimage=true ${test_target}
# might as well do an openjdk test while we're here:
run make openjdk=$JAVA_HOME ${flags} ${test_target}
fi