2013-07-03 02:52:38 +00:00
|
|
|
/* Copyright (c) 2008-2013, Avian Contributors
|
2008-02-19 18:06:52 +00:00
|
|
|
|
|
|
|
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. */
|
|
|
|
|
2013-02-12 04:31:19 +00:00
|
|
|
#ifndef AVIAN_CODEGEN_COMPILER_H
|
|
|
|
#define AVIAN_CODEGEN_COMPILER_H
|
2007-11-20 16:21:17 +00:00
|
|
|
|
2013-02-21 03:42:09 +00:00
|
|
|
#include <avian/vm/system/system.h>
|
2013-02-27 20:25:50 +00:00
|
|
|
#include "avian/zone.h"
|
2008-02-11 17:21:41 +00:00
|
|
|
#include "assembler.h"
|
2007-11-21 22:15:33 +00:00
|
|
|
|
2013-02-11 15:07:46 +00:00
|
|
|
namespace avian {
|
|
|
|
namespace codegen {
|
2007-11-20 16:21:17 +00:00
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
class TraceHandler {
|
|
|
|
public:
|
|
|
|
virtual void handleTrace(Promise* address, unsigned argumentIndex) = 0;
|
|
|
|
};
|
|
|
|
|
2007-11-20 16:21:17 +00:00
|
|
|
class Compiler {
|
|
|
|
public:
|
2008-05-31 22:14:27 +00:00
|
|
|
class Client {
|
|
|
|
public:
|
2013-02-11 15:07:46 +00:00
|
|
|
virtual intptr_t getThunk(lir::UnaryOperation op, unsigned size) = 0;
|
|
|
|
virtual intptr_t getThunk(lir::BinaryOperation op, unsigned size,
|
2009-09-20 21:43:32 +00:00
|
|
|
unsigned resultSize) = 0;
|
2013-02-11 15:07:46 +00:00
|
|
|
virtual intptr_t getThunk(lir::TernaryOperation op, unsigned size,
|
2010-12-20 00:47:21 +00:00
|
|
|
unsigned resultSize, bool* threadParameter) = 0;
|
2008-05-31 22:14:27 +00:00
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
static const unsigned Aligned = 1 << 0;
|
|
|
|
static const unsigned NoReturn = 1 << 1;
|
2009-04-22 01:39:25 +00:00
|
|
|
static const unsigned TailJump = 1 << 2;
|
2009-10-18 00:18:03 +00:00
|
|
|
static const unsigned LongJumpOrCall = 1 << 3;
|
2007-12-30 22:24:48 +00:00
|
|
|
|
2009-09-20 21:43:32 +00:00
|
|
|
enum OperandType {
|
|
|
|
ObjectType,
|
|
|
|
AddressType,
|
|
|
|
IntegerType,
|
|
|
|
FloatType,
|
|
|
|
VoidType
|
|
|
|
};
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class Operand { };
|
2008-09-13 21:09:26 +00:00
|
|
|
class State { };
|
2008-11-14 00:59:21 +00:00
|
|
|
class Subroutine { };
|
2007-12-30 22:24:48 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
virtual State* saveState() = 0;
|
|
|
|
virtual void restoreState(State* state) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-11-14 00:59:21 +00:00
|
|
|
virtual Subroutine* startSubroutine() = 0;
|
2010-01-05 00:17:16 +00:00
|
|
|
virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address)
|
|
|
|
= 0;
|
2009-07-20 14:26:01 +00:00
|
|
|
virtual void linkSubroutine(Subroutine* subroutine) = 0;
|
2008-11-14 00:59:21 +00:00
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
|
2008-09-28 19:00:52 +00:00
|
|
|
unsigned localFootprint, unsigned alignedFrameSize) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
virtual void visitLogicalIp(unsigned logicalIp) = 0;
|
|
|
|
virtual void startLogicalIp(unsigned logicalIp) = 0;
|
|
|
|
|
2007-12-16 00:24:15 +00:00
|
|
|
virtual Promise* machineIp(unsigned logicalIp) = 0;
|
2007-11-26 23:15:53 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Promise* poolAppend(intptr_t value) = 0;
|
|
|
|
virtual Promise* poolAppendPromise(Promise* value) = 0;
|
2007-11-21 22:15:33 +00:00
|
|
|
|
2009-09-20 21:43:32 +00:00
|
|
|
virtual Operand* constant(int64_t value, OperandType type) = 0;
|
|
|
|
virtual Operand* promiseConstant(Promise* value, OperandType type) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* address(Promise* address) = 0;
|
2007-12-30 22:24:48 +00:00
|
|
|
virtual Operand* memory(Operand* base,
|
2009-09-20 21:43:32 +00:00
|
|
|
OperandType type,
|
2007-12-30 22:24:48 +00:00
|
|
|
int displacement = 0,
|
|
|
|
Operand* index = 0,
|
2008-04-09 19:08:13 +00:00
|
|
|
unsigned scale = 1) = 0;
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
virtual Operand* register_(int number) = 0;
|
2009-04-05 21:42:10 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual void push(unsigned footprint) = 0;
|
|
|
|
virtual void push(unsigned footprint, Operand* value) = 0;
|
2008-11-07 00:39:38 +00:00
|
|
|
virtual void save(unsigned footprint, Operand* value) = 0;
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual Operand* pop(unsigned footprint) = 0;
|
2008-07-05 20:21:13 +00:00
|
|
|
virtual void pushed() = 0;
|
2009-01-30 01:36:19 +00:00
|
|
|
virtual void popped(unsigned footprint) = 0;
|
2009-05-15 02:08:01 +00:00
|
|
|
virtual unsigned topOfStack() = 0;
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual Operand* peek(unsigned footprint, unsigned index) = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
virtual Operand* call(Operand* address,
|
|
|
|
unsigned flags,
|
|
|
|
TraceHandler* traceHandler,
|
|
|
|
unsigned resultSize,
|
2009-09-20 21:43:32 +00:00
|
|
|
OperandType resultType,
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned argumentCount,
|
|
|
|
...) = 0;
|
2008-02-12 02:06:12 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
virtual Operand* stackCall(Operand* address,
|
|
|
|
unsigned flags,
|
|
|
|
TraceHandler* traceHandler,
|
|
|
|
unsigned resultSize,
|
2009-09-20 21:43:32 +00:00
|
|
|
OperandType resultType,
|
2008-07-05 20:21:13 +00:00
|
|
|
unsigned argumentFootprint) = 0;
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void return_(unsigned size, Operand* value) = 0;
|
|
|
|
|
2009-09-20 21:43:32 +00:00
|
|
|
virtual void initLocal(unsigned size, unsigned index, OperandType type) = 0;
|
2008-09-25 00:48:32 +00:00
|
|
|
virtual void initLocalsFromLogicalIp(unsigned logicalIp) = 0;
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual void storeLocal(unsigned footprint, Operand* src,
|
|
|
|
unsigned index) = 0;
|
|
|
|
virtual Operand* loadLocal(unsigned footprint, unsigned index) = 0;
|
2008-11-25 17:34:48 +00:00
|
|
|
virtual void saveLocals() = 0;
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
virtual void checkBounds(Operand* object, unsigned lengthOffset,
|
|
|
|
Operand* index, intptr_t handler) = 0;
|
|
|
|
|
2009-02-28 23:17:24 +00:00
|
|
|
virtual void store(unsigned srcSize, Operand* src, unsigned dstSize,
|
|
|
|
Operand* dst) = 0;
|
2009-03-06 17:56:11 +00:00
|
|
|
virtual Operand* load(unsigned srcSize, unsigned srcSelectSize, Operand* src,
|
|
|
|
unsigned dstSize) = 0;
|
|
|
|
virtual Operand* loadz(unsigned size, unsigned srcSelectSize, Operand* src,
|
|
|
|
unsigned dstSize) = 0;
|
2009-10-07 00:50:32 +00:00
|
|
|
|
2013-12-18 21:38:05 +00:00
|
|
|
|
|
|
|
virtual void condJump(lir::TernaryOperation type, unsigned size, Operand* a, Operand* b, Operand* address) = 0;
|
2009-10-07 00:50:32 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jmp(Operand* address) = 0;
|
2009-04-26 02:54:36 +00:00
|
|
|
virtual void exit(Operand* address) = 0;
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* add(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* sub(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* mul(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* div(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* rem(unsigned size, Operand* a, Operand* b) = 0;
|
2009-08-06 14:48:15 +00:00
|
|
|
virtual Operand* fadd(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* fsub(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* fmul(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* fdiv(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* frem(unsigned size, Operand* a, Operand* b) = 0;
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* shl(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* shr(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* ushr(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* and_(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* or_(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) = 0;
|
|
|
|
virtual Operand* neg(unsigned size, Operand* a) = 0;
|
2009-08-06 14:48:15 +00:00
|
|
|
virtual Operand* fneg(unsigned size, Operand* a) = 0;
|
2009-10-18 01:26:14 +00:00
|
|
|
virtual Operand* abs(unsigned size, Operand* a) = 0;
|
|
|
|
virtual Operand* fabs(unsigned size, Operand* a) = 0;
|
|
|
|
virtual Operand* fsqrt(unsigned size, Operand* a) = 0;
|
2009-08-06 14:48:15 +00:00
|
|
|
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;
|
2008-02-11 17:21:41 +00:00
|
|
|
|
fix a couple of subtle Thread.getStackTrace bugs
The first problem was that, on x86, we failed to properly keep track
of whether to expect the return address to be on the stack or not when
unwinding through a frame. We were relying on a "stackLimit" pointer
to tell us whether we were looking at the most recently-called frame
by comparing it with the stack pointer for that frame. That was
inaccurate in the case of a thread executing at the beginning of a
method before a new frame is allocated, in which case the most recent
two frames share a stack pointer, confusing the unwinder. The
solution involves keeping track of how many frames we've looked at
while walking the stack.
The other problem was that compareIpToMethodBounds assumed every
method was followed by at least one byte of padding before the next
method started. That assumption was usually valid because we were
storing the size following method code prior to the code itself.
However, the last method of an AOT-compiled code image is not followed
by any such method header and may instead be followed directly by
native code with no intervening padding. In that case, we risk
interpreting that native code as part of the preceding method, with
potentially bizarre results.
The reason for the compareIpToMethodBounds assumption was that methods
which throw exceptions as their last instruction generate a
non-returning call, which nonetheless push a return address on the
stack which points past the end of the method, and the unwinder needs
to know that return address belongs to that method. A better solution
is to add an extra trap instruction to the end of such methods, which
is what this patch does.
2012-05-05 00:35:13 +00:00
|
|
|
virtual void trap() = 0;
|
|
|
|
|
2009-03-03 03:18:15 +00:00
|
|
|
virtual void loadBarrier() = 0;
|
|
|
|
virtual void storeStoreBarrier() = 0;
|
|
|
|
virtual void storeLoadBarrier() = 0;
|
|
|
|
|
2011-02-28 06:03:13 +00:00
|
|
|
virtual void compile(uintptr_t stackOverflowHandler,
|
|
|
|
unsigned stackLimitOffset) = 0;
|
|
|
|
virtual unsigned resolve(uint8_t* dst) = 0;
|
2007-12-11 23:52:28 +00:00
|
|
|
virtual unsigned poolSize() = 0;
|
2011-02-28 06:03:13 +00:00
|
|
|
virtual void write() = 0;
|
2007-11-26 23:15:53 +00:00
|
|
|
|
2007-11-21 22:15:33 +00:00
|
|
|
virtual void dispose() = 0;
|
2007-11-20 16:21:17 +00:00
|
|
|
};
|
|
|
|
|
2007-11-21 22:15:33 +00:00
|
|
|
Compiler*
|
2013-02-11 15:07:46 +00:00
|
|
|
makeCompiler(vm::System* system, Assembler* assembler, vm::Zone* zone,
|
2008-05-31 22:14:27 +00:00
|
|
|
Compiler::Client* client);
|
2007-11-21 22:15:33 +00:00
|
|
|
|
2013-02-11 15:07:46 +00:00
|
|
|
} // namespace codegen
|
|
|
|
} // namespace avian
|
2007-11-20 16:21:17 +00:00
|
|
|
|
2013-02-12 04:31:19 +00:00
|
|
|
#endif // AVIAN_CODEGEN_COMPILER_H
|