2008-02-19 18:06:52 +00:00
|
|
|
/* Copyright (c) 2008, 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. */
|
|
|
|
|
2008-02-12 00:20:32 +00:00
|
|
|
#include "compiler.h"
|
2008-02-11 17:21:41 +00:00
|
|
|
#include "assembler.h"
|
2007-12-08 23:22:13 +00:00
|
|
|
|
|
|
|
using namespace vm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
const bool DebugAppend = true;
|
|
|
|
const bool DebugCompile = true;
|
2008-04-27 20:15:18 +00:00
|
|
|
const bool DebugStack = false;
|
2008-09-27 22:01:39 +00:00
|
|
|
const bool DebugRegisters = true;
|
2008-04-19 21:52:45 +00:00
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
const int AnyFrameIndex = -2;
|
|
|
|
const int NoFrameIndex = -1;
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class Context;
|
2008-04-16 20:58:21 +00:00
|
|
|
class Value;
|
2008-04-17 22:07:32 +00:00
|
|
|
class Stack;
|
|
|
|
class Site;
|
2008-05-15 23:19:23 +00:00
|
|
|
class RegisterSite;
|
2008-04-17 22:07:32 +00:00
|
|
|
class Event;
|
2008-04-18 03:47:42 +00:00
|
|
|
class PushEvent;
|
2008-04-18 00:39:41 +00:00
|
|
|
class Read;
|
2008-09-13 21:09:26 +00:00
|
|
|
class MultiRead;
|
2008-09-22 14:28:18 +00:00
|
|
|
class StubRead;
|
2008-08-30 20:12:27 +00:00
|
|
|
class Block;
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
void NO_RETURN abort(Context*);
|
2008-03-15 23:54:20 +00:00
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
void
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(Context* c, UnaryOperation op,
|
|
|
|
unsigned s1Size, Site* s1);
|
2008-04-17 22:07:32 +00:00
|
|
|
|
|
|
|
void
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(Context* c, BinaryOperation op,
|
|
|
|
unsigned s1Size, Site* s1,
|
|
|
|
unsigned s2Size, Site* s2);
|
|
|
|
|
|
|
|
void
|
|
|
|
apply(Context* c, TernaryOperation op,
|
|
|
|
unsigned s1Size, Site* s1,
|
|
|
|
unsigned s2Size, Site* s2,
|
|
|
|
unsigned s3Size, Site* s3);
|
2008-04-17 22:07:32 +00:00
|
|
|
|
2008-06-11 00:17:44 +00:00
|
|
|
enum ConstantCompare {
|
|
|
|
CompareNone,
|
|
|
|
CompareLess,
|
|
|
|
CompareGreater,
|
|
|
|
CompareEqual
|
|
|
|
};
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
class Cell {
|
|
|
|
public:
|
|
|
|
Cell(Cell* next, void* value): next(next), value(value) { }
|
|
|
|
|
|
|
|
Cell* next;
|
|
|
|
void* value;
|
|
|
|
};
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
class Local {
|
|
|
|
public:
|
|
|
|
Value* value;
|
|
|
|
unsigned size;
|
|
|
|
};
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class Site {
|
|
|
|
public:
|
|
|
|
Site(): next(0) { }
|
|
|
|
|
|
|
|
virtual ~Site() { }
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Site* readTarget(Context*, Read*) { return this; }
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual unsigned copyCost(Context*, Site*) = 0;
|
2008-08-23 18:04:36 +00:00
|
|
|
|
|
|
|
virtual bool match(Context*, uint8_t, uint64_t, int) = 0;
|
2008-04-16 20:58:21 +00:00
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
virtual void acquire(Context*, Stack*, Local*, unsigned, Value*) { }
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
virtual void release(Context*) { }
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual void freeze(Context*) { }
|
|
|
|
|
|
|
|
virtual void thaw(Context*) { }
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
virtual OperandType type(Context*) = 0;
|
2008-04-16 20:58:21 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context*) = 0;
|
2008-04-16 20:58:21 +00:00
|
|
|
|
|
|
|
Site* next;
|
|
|
|
};
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
class Stack: public Compiler::StackElement {
|
2008-04-17 22:07:32 +00:00
|
|
|
public:
|
2008-08-28 22:43:35 +00:00
|
|
|
Stack(unsigned index, unsigned size, Value* value, Stack* next):
|
|
|
|
index(index), size(size), padding(0), value(value), next(next)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
unsigned index;
|
2008-08-28 22:43:35 +00:00
|
|
|
unsigned size;
|
|
|
|
unsigned padding;
|
2008-07-05 20:21:13 +00:00
|
|
|
Value* value;
|
2008-04-17 22:07:32 +00:00
|
|
|
Stack* next;
|
|
|
|
};
|
|
|
|
|
2008-09-22 14:28:18 +00:00
|
|
|
class MultiReadPair {
|
|
|
|
public:
|
|
|
|
Value* value;
|
|
|
|
MultiRead* read;
|
|
|
|
};
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
class MyState: public Compiler::State {
|
2008-04-17 22:07:32 +00:00
|
|
|
public:
|
2008-09-24 00:01:42 +00:00
|
|
|
MyState(Stack* stack, Local* locals, Event* predecessor,
|
2008-09-20 23:42:46 +00:00
|
|
|
unsigned logicalIp):
|
2008-04-27 21:58:29 +00:00
|
|
|
stack(stack),
|
2008-07-05 20:21:13 +00:00
|
|
|
locals(locals),
|
2008-09-20 23:42:46 +00:00
|
|
|
predecessor(predecessor),
|
|
|
|
logicalIp(logicalIp),
|
|
|
|
readCount(0)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
Stack* stack;
|
2008-09-24 00:01:42 +00:00
|
|
|
Local* locals;
|
2008-09-20 23:42:46 +00:00
|
|
|
Event* predecessor;
|
|
|
|
unsigned logicalIp;
|
|
|
|
unsigned readCount;
|
2008-09-22 00:58:54 +00:00
|
|
|
MultiReadPair reads[0];
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class LogicalInstruction {
|
|
|
|
public:
|
2008-09-24 00:01:42 +00:00
|
|
|
LogicalInstruction(int index, Stack* stack, Local* locals):
|
2008-09-15 02:28:42 +00:00
|
|
|
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack),
|
|
|
|
locals(locals), machineOffset(0), index(index)
|
2008-09-07 20:12:11 +00:00
|
|
|
{ }
|
2008-09-07 01:37:12 +00:00
|
|
|
|
2008-04-19 07:03:59 +00:00
|
|
|
Event* firstEvent;
|
2008-04-17 22:07:32 +00:00
|
|
|
Event* lastEvent;
|
2008-04-20 19:35:36 +00:00
|
|
|
LogicalInstruction* immediatePredecessor;
|
|
|
|
Stack* stack;
|
2008-09-24 00:01:42 +00:00
|
|
|
Local* locals;
|
2008-09-09 00:31:19 +00:00
|
|
|
Promise* machineOffset;
|
2008-08-30 20:12:27 +00:00
|
|
|
int index;
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Register {
|
|
|
|
public:
|
2008-05-12 13:54:47 +00:00
|
|
|
Register(int number):
|
2008-05-15 23:19:23 +00:00
|
|
|
value(0), site(0), number(number), size(0), refCount(0),
|
2008-05-15 20:00:57 +00:00
|
|
|
freezeCount(0), reserved(false), pushed(false)
|
2008-05-12 13:54:47 +00:00
|
|
|
{ }
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
Value* value;
|
2008-05-15 23:19:23 +00:00
|
|
|
RegisterSite* site;
|
2008-05-12 13:54:47 +00:00
|
|
|
int number;
|
2008-04-17 22:07:32 +00:00
|
|
|
unsigned size;
|
2008-04-20 00:43:12 +00:00
|
|
|
unsigned refCount;
|
2008-05-12 13:54:47 +00:00
|
|
|
unsigned freezeCount;
|
2008-04-17 22:07:32 +00:00
|
|
|
bool reserved;
|
2008-04-27 20:15:18 +00:00
|
|
|
bool pushed;
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ConstantPoolNode {
|
|
|
|
public:
|
|
|
|
ConstantPoolNode(Promise* promise): promise(promise), next(0) { }
|
|
|
|
|
|
|
|
Promise* promise;
|
|
|
|
ConstantPoolNode* next;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Read {
|
|
|
|
public:
|
2008-09-24 00:01:42 +00:00
|
|
|
Read(unsigned size):
|
|
|
|
value(0), event(0), eventNext(0), size(size)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
2008-07-05 20:21:13 +00:00
|
|
|
|
2008-09-06 21:25:41 +00:00
|
|
|
virtual ~Read() { }
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
virtual Site* pickSite(Context* c, Value* v) = 0;
|
|
|
|
|
|
|
|
virtual Site* allocateSite(Context* c) = 0;
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
|
2008-07-05 20:21:13 +00:00
|
|
|
int* frameIndex) = 0;
|
|
|
|
|
|
|
|
virtual bool valid() = 0;
|
2008-08-30 20:12:27 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
virtual void append(Context* c, Read* r) = 0;
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual Read* next(Context* c) = 0;
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
Value* value;
|
|
|
|
Event* event;
|
|
|
|
Read* eventNext;
|
2008-09-24 00:01:42 +00:00
|
|
|
unsigned size;
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
int
|
|
|
|
intersectFrameIndexes(int a, int b)
|
|
|
|
{
|
|
|
|
if (a == NoFrameIndex or b == NoFrameIndex) return NoFrameIndex;
|
|
|
|
if (a == AnyFrameIndex) return b;
|
|
|
|
if (b == AnyFrameIndex) return a;
|
|
|
|
if (a == b) return a;
|
|
|
|
return NoFrameIndex;
|
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
class Value: public Compiler::Operand {
|
|
|
|
public:
|
2008-04-26 20:56:03 +00:00
|
|
|
Value(Site* site, Site* target):
|
2008-09-20 23:42:46 +00:00
|
|
|
reads(0), lastRead(0), sites(site), source(0), target(target),
|
|
|
|
visited(false)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
2008-09-13 21:09:26 +00:00
|
|
|
|
|
|
|
virtual ~Value() { }
|
|
|
|
|
|
|
|
virtual void addPredecessor(Context*, Event*) { }
|
2008-04-17 22:07:32 +00:00
|
|
|
|
|
|
|
Read* reads;
|
|
|
|
Read* lastRead;
|
|
|
|
Site* sites;
|
|
|
|
Site* source;
|
2008-04-19 20:41:31 +00:00
|
|
|
Site* target;
|
2008-09-20 23:42:46 +00:00
|
|
|
bool visited;
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
enum Pass {
|
|
|
|
ScanPass,
|
|
|
|
CompilePass
|
|
|
|
};
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
class Context {
|
|
|
|
public:
|
2008-05-31 22:14:27 +00:00
|
|
|
Context(System* system, Assembler* assembler, Zone* zone,
|
|
|
|
Compiler::Client* client):
|
2008-04-17 22:07:32 +00:00
|
|
|
system(system),
|
|
|
|
assembler(assembler),
|
2008-08-23 18:04:36 +00:00
|
|
|
arch(assembler->arch()),
|
2008-04-17 22:07:32 +00:00
|
|
|
zone(zone),
|
2008-05-31 22:14:27 +00:00
|
|
|
client(client),
|
2008-09-13 21:09:26 +00:00
|
|
|
stack(0),
|
|
|
|
locals(0),
|
2008-09-20 23:42:46 +00:00
|
|
|
predecessor(0),
|
2008-04-17 22:07:32 +00:00
|
|
|
logicalCode(0),
|
2008-05-12 13:54:47 +00:00
|
|
|
registers
|
|
|
|
(static_cast<Register**>
|
2008-08-23 18:04:36 +00:00
|
|
|
(zone->allocate(sizeof(Register*) * arch->registerCount()))),
|
2008-04-17 22:07:32 +00:00
|
|
|
firstConstant(0),
|
|
|
|
lastConstant(0),
|
2008-08-30 20:12:27 +00:00
|
|
|
machineCode(0),
|
|
|
|
firstEvent(0),
|
2008-09-07 01:37:12 +00:00
|
|
|
lastEvent(0),
|
2008-09-15 02:28:42 +00:00
|
|
|
state(0),
|
2008-08-30 20:12:27 +00:00
|
|
|
logicalIp(-1),
|
2008-04-17 22:07:32 +00:00
|
|
|
constantCount(0),
|
2008-08-30 20:12:27 +00:00
|
|
|
logicalCodeLength(0),
|
|
|
|
parameterFootprint(0),
|
|
|
|
localFootprint(0),
|
|
|
|
maxStackFootprint(0),
|
|
|
|
stackPadding(0),
|
2008-09-23 21:18:41 +00:00
|
|
|
machineCodeSize(0),
|
2008-09-27 22:01:39 +00:00
|
|
|
availableRegisterCount(arch->registerCount()),
|
2008-07-05 20:21:13 +00:00
|
|
|
constantCompare(CompareNone),
|
2008-08-30 20:12:27 +00:00
|
|
|
pass(ScanPass)
|
2008-04-17 22:07:32 +00:00
|
|
|
{
|
2008-08-23 18:04:36 +00:00
|
|
|
for (unsigned i = 0; i < arch->registerCount(); ++i) {
|
2008-05-12 13:54:47 +00:00
|
|
|
registers[i] = new (zone->allocate(sizeof(Register))) Register(i);
|
2008-09-27 22:01:39 +00:00
|
|
|
if (arch->reserved(i)) {
|
|
|
|
registers[i]->reserved = true;
|
|
|
|
-- availableRegisterCount;
|
|
|
|
}
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-17 22:07:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
System* system;
|
|
|
|
Assembler* assembler;
|
2008-08-23 18:04:36 +00:00
|
|
|
Assembler::Architecture* arch;
|
2008-04-17 22:07:32 +00:00
|
|
|
Zone* zone;
|
2008-05-31 22:14:27 +00:00
|
|
|
Compiler::Client* client;
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* stack;
|
2008-09-24 00:01:42 +00:00
|
|
|
Local* locals;
|
2008-09-20 23:42:46 +00:00
|
|
|
Event* predecessor;
|
2008-08-16 17:45:36 +00:00
|
|
|
LogicalInstruction** logicalCode;
|
2008-05-12 13:54:47 +00:00
|
|
|
Register** registers;
|
2008-04-17 22:07:32 +00:00
|
|
|
ConstantPoolNode* firstConstant;
|
|
|
|
ConstantPoolNode* lastConstant;
|
2008-08-30 20:12:27 +00:00
|
|
|
uint8_t* machineCode;
|
|
|
|
Event* firstEvent;
|
2008-09-07 01:37:12 +00:00
|
|
|
Event* lastEvent;
|
2008-09-15 02:28:42 +00:00
|
|
|
MyState* state;
|
2008-08-30 20:12:27 +00:00
|
|
|
int logicalIp;
|
2008-04-17 22:07:32 +00:00
|
|
|
unsigned constantCount;
|
2008-08-30 20:12:27 +00:00
|
|
|
unsigned logicalCodeLength;
|
|
|
|
unsigned parameterFootprint;
|
|
|
|
unsigned localFootprint;
|
|
|
|
unsigned maxStackFootprint;
|
|
|
|
unsigned stackPadding;
|
2008-09-23 21:18:41 +00:00
|
|
|
unsigned machineCodeSize;
|
2008-09-27 22:01:39 +00:00
|
|
|
unsigned availableRegisterCount;
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantCompare constantCompare;
|
2008-07-05 20:21:13 +00:00
|
|
|
Pass pass;
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
class PoolPromise: public Promise {
|
|
|
|
public:
|
|
|
|
PoolPromise(Context* c, int key): c(c), key(key) { }
|
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
if (resolved()) {
|
|
|
|
return reinterpret_cast<intptr_t>
|
2008-09-23 21:18:41 +00:00
|
|
|
(c->machineCode + pad(c->machineCodeSize) + (key * BytesPerWord));
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return c->machineCode != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Context* c;
|
|
|
|
int key;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CodePromise: public Promise {
|
|
|
|
public:
|
2008-08-30 20:12:27 +00:00
|
|
|
CodePromise(Context* c, CodePromise* next):
|
|
|
|
c(c), offset(0), next(next)
|
|
|
|
{ }
|
2008-04-18 17:00:55 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
CodePromise(Context* c, Promise* offset):
|
2008-08-30 20:12:27 +00:00
|
|
|
c(c), offset(offset), next(0)
|
|
|
|
{ }
|
2008-04-18 17:00:55 +00:00
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
if (resolved()) {
|
2008-08-30 20:12:27 +00:00
|
|
|
return reinterpret_cast<intptr_t>(c->machineCode + offset->value());
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
2008-08-30 20:12:27 +00:00
|
|
|
return c->machineCode != 0 and offset and offset->resolved();
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Context* c;
|
2008-09-09 00:31:19 +00:00
|
|
|
Promise* offset;
|
2008-04-18 17:00:55 +00:00
|
|
|
CodePromise* next;
|
|
|
|
};
|
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
unsigned
|
|
|
|
machineOffset(Context* c, int logicalIp)
|
|
|
|
{
|
2008-09-22 14:28:18 +00:00
|
|
|
return c->logicalCode[logicalIp]->machineOffset->value();
|
2008-09-07 20:12:11 +00:00
|
|
|
}
|
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
class IpPromise: public Promise {
|
|
|
|
public:
|
|
|
|
IpPromise(Context* c, int logicalIp):
|
|
|
|
c(c),
|
|
|
|
logicalIp(logicalIp)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
if (resolved()) {
|
|
|
|
return reinterpret_cast<intptr_t>
|
2008-09-07 20:12:11 +00:00
|
|
|
(c->machineCode + machineOffset(c, logicalIp));
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return c->machineCode != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Context* c;
|
|
|
|
int logicalIp;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline void NO_RETURN
|
|
|
|
abort(Context* c)
|
|
|
|
{
|
|
|
|
abort(c->system);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
inline void
|
|
|
|
assert(Context* c, bool v)
|
|
|
|
{
|
|
|
|
assert(c->system, v);
|
|
|
|
}
|
|
|
|
#endif // not NDEBUG
|
|
|
|
|
|
|
|
inline void
|
|
|
|
expect(Context* c, bool v)
|
|
|
|
{
|
|
|
|
expect(c->system, v);
|
|
|
|
}
|
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
Cell*
|
|
|
|
cons(Context* c, void* value, Cell* next)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Cell))) Cell(next, value);
|
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
Cell*
|
|
|
|
append(Context* c, Cell* first, Cell* second)
|
|
|
|
{
|
|
|
|
if (first) {
|
|
|
|
if (second) {
|
|
|
|
Cell* start = cons(c, first->value, second);
|
|
|
|
Cell* end = start;
|
|
|
|
for (Cell* cell = first->next; cell; cell = cell->next) {
|
|
|
|
Cell* n = cons(c, cell->value, second);
|
|
|
|
end->next = n;
|
|
|
|
end = n;
|
|
|
|
}
|
|
|
|
return start;
|
|
|
|
} else {
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
unsigned
|
|
|
|
count(Cell* c)
|
|
|
|
{
|
|
|
|
unsigned n = 0;
|
|
|
|
for (; c; c = c->next) ++ n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2008-09-22 14:28:18 +00:00
|
|
|
class StubReadPair {
|
|
|
|
public:
|
|
|
|
Value* value;
|
|
|
|
StubRead* read;
|
|
|
|
};
|
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
class Event {
|
|
|
|
public:
|
|
|
|
Event(Context* c):
|
2008-09-13 21:09:26 +00:00
|
|
|
next(0), stack(c->stack), locals(c->locals), promises(0),
|
2008-09-20 23:42:46 +00:00
|
|
|
reads(0), junctionSites(0), savedSites(0), predecessors(0),
|
2008-09-15 02:28:42 +00:00
|
|
|
successors(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
|
2008-09-22 14:28:18 +00:00
|
|
|
state(c->state), junctionReads(0), readCount(0)
|
2008-04-18 17:00:55 +00:00
|
|
|
{
|
|
|
|
assert(c, c->logicalIp >= 0);
|
|
|
|
|
2008-09-07 01:37:12 +00:00
|
|
|
if (c->lastEvent) {
|
|
|
|
c->lastEvent->next = this;
|
2008-04-18 17:00:55 +00:00
|
|
|
} else {
|
2008-09-07 01:37:12 +00:00
|
|
|
c->firstEvent = this;
|
|
|
|
}
|
|
|
|
c->lastEvent = this;
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
Event* p = c->predecessor;
|
|
|
|
if (p) {
|
|
|
|
predecessors = cons(c, p, 0);
|
2008-09-15 02:28:42 +00:00
|
|
|
p->successors = cons(c, this, p->successors);
|
|
|
|
}
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
c->predecessor = this;
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-09-07 01:37:12 +00:00
|
|
|
if (logicalInstruction->firstEvent == 0) {
|
2008-08-30 20:12:27 +00:00
|
|
|
logicalInstruction->firstEvent = this;
|
2008-04-20 05:23:08 +00:00
|
|
|
}
|
2008-08-30 20:12:27 +00:00
|
|
|
logicalInstruction->lastEvent = this;
|
2008-04-18 17:00:55 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
c->state = 0;
|
|
|
|
}
|
2008-04-18 17:00:55 +00:00
|
|
|
|
|
|
|
virtual ~Event() { }
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() = 0;
|
2008-04-18 17:00:55 +00:00
|
|
|
virtual void compile(Context* c) = 0;
|
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
virtual void compilePostsync(Context*) { }
|
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
Event* next;
|
|
|
|
Stack* stack;
|
2008-09-24 00:01:42 +00:00
|
|
|
Local* locals;
|
2008-04-18 17:00:55 +00:00
|
|
|
CodePromise* promises;
|
|
|
|
Read* reads;
|
2008-08-30 20:12:27 +00:00
|
|
|
Site** junctionSites;
|
|
|
|
Site** savedSites;
|
|
|
|
Cell* predecessors;
|
|
|
|
Cell* successors;
|
|
|
|
Block* block;
|
|
|
|
LogicalInstruction* logicalInstruction;
|
2008-09-15 02:28:42 +00:00
|
|
|
MyState* state;
|
2008-09-22 00:58:54 +00:00
|
|
|
StubReadPair* junctionReads;
|
2008-05-15 14:29:19 +00:00
|
|
|
unsigned readCount;
|
2008-04-18 17:00:55 +00:00
|
|
|
};
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
unsigned
|
|
|
|
alignedFrameSize(Context* c)
|
|
|
|
{
|
|
|
|
return c->arch->alignFrameSize
|
|
|
|
(c->localFootprint
|
|
|
|
- c->parameterFootprint
|
|
|
|
+ c->maxStackFootprint);
|
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
int
|
|
|
|
localOffset(Context* c, int v)
|
|
|
|
{
|
2008-09-08 02:21:11 +00:00
|
|
|
int parameterFootprint = c->parameterFootprint;
|
|
|
|
int frameSize = alignedFrameSize(c);
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
int offset = ((v < parameterFootprint) ?
|
|
|
|
(frameSize
|
|
|
|
+ parameterFootprint
|
|
|
|
+ (c->arch->frameFooterSize() * 2)
|
|
|
|
+ c->arch->frameHeaderSize()
|
2008-09-15 02:28:42 +00:00
|
|
|
- v - 1) :
|
2008-09-09 00:31:19 +00:00
|
|
|
(frameSize
|
|
|
|
+ parameterFootprint
|
|
|
|
+ c->arch->frameFooterSize()
|
2008-09-15 02:28:42 +00:00
|
|
|
- v - 1)) * BytesPerWord;
|
2008-09-09 00:31:19 +00:00
|
|
|
|
|
|
|
assert(c, offset >= 0);
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
return offset;
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-04-18 00:39:41 +00:00
|
|
|
bool
|
|
|
|
findSite(Context*, Value* v, Site* site)
|
|
|
|
{
|
|
|
|
for (Site* s = v->sites; s; s = s->next) {
|
|
|
|
if (s == site) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
void
|
2008-09-24 00:01:42 +00:00
|
|
|
addSite(Context* c, Stack* stack, Local* locals, unsigned size, Value* v,
|
2008-07-17 23:34:38 +00:00
|
|
|
Site* s)
|
2008-04-19 00:19:45 +00:00
|
|
|
{
|
|
|
|
if (not findSite(c, v, s)) {
|
2008-04-29 16:25:20 +00:00
|
|
|
// fprintf(stderr, "add site %p (%d) to %p\n", s, s->type(c), v);
|
2008-07-17 23:34:38 +00:00
|
|
|
s->acquire(c, stack, locals, size, v);
|
2008-05-12 13:54:47 +00:00
|
|
|
s->next = v->sites;
|
|
|
|
v->sites = s;
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-18 00:39:41 +00:00
|
|
|
void
|
2008-04-19 07:03:59 +00:00
|
|
|
removeSite(Context* c, Value* v, Site* s)
|
2008-04-18 00:39:41 +00:00
|
|
|
{
|
|
|
|
for (Site** p = &(v->sites); *p;) {
|
|
|
|
if (s == *p) {
|
2008-04-29 16:25:20 +00:00
|
|
|
// fprintf(stderr, "remove site %p (%d) from %p\n", s, s->type(c), v);
|
2008-04-19 07:03:59 +00:00
|
|
|
s->release(c);
|
2008-04-18 00:39:41 +00:00
|
|
|
*p = (*p)->next;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
p = &((*p)->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-30 15:44:17 +00:00
|
|
|
void
|
|
|
|
removeMemorySites(Context* c, Value* v)
|
|
|
|
{
|
|
|
|
for (Site** p = &(v->sites); *p;) {
|
|
|
|
if ((*p)->type(c) == MemoryOperand) {
|
2008-05-15 20:00:57 +00:00
|
|
|
// fprintf(stderr, "remove site %p (%d) from %p\n", *p, (*p)->type(c), v);
|
2008-04-30 15:44:17 +00:00
|
|
|
(*p)->release(c);
|
|
|
|
*p = (*p)->next;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
p = &((*p)->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-19 07:03:59 +00:00
|
|
|
void
|
|
|
|
clearSites(Context* c, Value* v)
|
|
|
|
{
|
2008-09-25 00:48:32 +00:00
|
|
|
//fprintf(stderr, "clear sites for %p\n", v);
|
2008-04-19 07:03:59 +00:00
|
|
|
for (Site* s = v->sites; s; s = s->next) {
|
|
|
|
s->release(c);
|
|
|
|
}
|
|
|
|
v->sites = 0;
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
bool
|
|
|
|
valid(Read* r)
|
|
|
|
{
|
|
|
|
return r and r->valid();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
live(Value* v)
|
|
|
|
{
|
|
|
|
return valid(v->reads);
|
|
|
|
}
|
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
void
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(Context* c, Event* e, Value* v)
|
2008-04-19 00:19:45 +00:00
|
|
|
{
|
2008-09-25 00:48:32 +00:00
|
|
|
assert(c, e == v->reads->event);
|
|
|
|
|
|
|
|
// fprintf(stderr, "pop read %p from %p; next: %p\n",
|
|
|
|
// v->reads, v, v->reads->next(c));
|
2008-04-19 07:03:59 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
v->reads = v->reads->next(c);
|
2008-07-05 20:21:13 +00:00
|
|
|
if (not live(v)) {
|
2008-04-19 07:03:59 +00:00
|
|
|
clearSites(c, v);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class ConstantSite: public Site {
|
|
|
|
public:
|
|
|
|
ConstantSite(Promise* value): value(value) { }
|
|
|
|
|
2008-04-18 18:36:57 +00:00
|
|
|
virtual unsigned copyCost(Context*, Site* s) {
|
|
|
|
return (s == this ? 0 : 1);
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual bool match(Context*, uint8_t typeMask, uint64_t, int) {
|
|
|
|
return typeMask & (1 << ConstantOperand);
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return ConstantOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context*) {
|
|
|
|
return &value;
|
|
|
|
}
|
|
|
|
|
|
|
|
Assembler::Constant value;
|
|
|
|
};
|
|
|
|
|
|
|
|
ConstantSite*
|
|
|
|
constantSite(Context* c, Promise* value)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ResolvedPromise*
|
|
|
|
resolved(Context* c, int64_t value)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(ResolvedPromise)))
|
|
|
|
ResolvedPromise(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstantSite*
|
|
|
|
constantSite(Context* c, int64_t value)
|
|
|
|
{
|
|
|
|
return constantSite(c, resolved(c, value));
|
|
|
|
}
|
|
|
|
|
|
|
|
class AddressSite: public Site {
|
|
|
|
public:
|
|
|
|
AddressSite(Promise* address): address(address) { }
|
|
|
|
|
2008-04-18 18:36:57 +00:00
|
|
|
virtual unsigned copyCost(Context*, Site* s) {
|
|
|
|
return (s == this ? 0 : 3);
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual bool match(Context*, uint8_t typeMask, uint64_t, int) {
|
|
|
|
return typeMask & (1 << AddressOperand);
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return AddressOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context*) {
|
|
|
|
return &address;
|
|
|
|
}
|
|
|
|
|
|
|
|
Assembler::Address address;
|
|
|
|
};
|
|
|
|
|
|
|
|
AddressSite*
|
|
|
|
addressSite(Context* c, Promise* address)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address);
|
|
|
|
}
|
|
|
|
|
2008-05-15 00:04:25 +00:00
|
|
|
void
|
2008-09-27 22:01:39 +00:00
|
|
|
freeze(Context* c, Register* r)
|
2008-05-15 00:04:25 +00:00
|
|
|
{
|
2008-09-27 22:01:39 +00:00
|
|
|
assert(c, c->availableRegisterCount);
|
|
|
|
|
2008-05-15 00:04:25 +00:00
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "freeze %d to %d\n", r->number, r->freezeCount + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
++ r->freezeCount;
|
2008-09-27 22:01:39 +00:00
|
|
|
-- c->availableRegisterCount;
|
2008-05-15 00:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-27 22:01:39 +00:00
|
|
|
thaw(Context* c, Register* r)
|
2008-05-15 00:04:25 +00:00
|
|
|
{
|
2008-09-27 22:01:39 +00:00
|
|
|
assert(c, r->freezeCount);
|
|
|
|
|
2008-05-15 00:04:25 +00:00
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "thaw %d to %d\n", r->number, r->freezeCount - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
-- r->freezeCount;
|
2008-09-27 22:01:39 +00:00
|
|
|
++ c->availableRegisterCount;
|
2008-05-15 00:04:25 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Register*
|
2008-09-24 00:01:42 +00:00
|
|
|
acquire(Context* c, uint32_t mask, Stack* stack, Local* locals,
|
2008-07-17 23:34:38 +00:00
|
|
|
unsigned newSize, Value* newValue, RegisterSite* newSite);
|
2008-04-16 20:58:21 +00:00
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
void
|
2008-05-12 13:54:47 +00:00
|
|
|
release(Context* c, Register* r);
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-15 20:00:57 +00:00
|
|
|
Register*
|
2008-09-24 00:01:42 +00:00
|
|
|
validate(Context* c, uint32_t mask, Stack* stack, Local* locals,
|
2008-08-23 18:04:36 +00:00
|
|
|
unsigned size, Value* value, RegisterSite* site, Register* current);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class RegisterSite: public Site {
|
|
|
|
public:
|
2008-05-13 17:27:57 +00:00
|
|
|
RegisterSite(uint64_t mask, Register* low = 0, Register* high = 0):
|
|
|
|
mask(mask), low(low), high(high), register_(NoRegister, NoRegister)
|
2008-05-12 13:54:47 +00:00
|
|
|
{ }
|
|
|
|
|
2008-05-14 23:19:41 +00:00
|
|
|
void sync(Context* c UNUSED) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
|
|
|
register_.low = low->number;
|
|
|
|
register_.high = (high? high->number : NoRegister);
|
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
|
|
|
|
virtual unsigned copyCost(Context* c, Site* s) {
|
2008-05-12 13:54:47 +00:00
|
|
|
sync(c);
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
if (s and
|
|
|
|
(this == s or
|
2008-04-17 22:07:32 +00:00
|
|
|
(s->type(c) == RegisterOperand
|
2008-05-12 13:54:47 +00:00
|
|
|
and (static_cast<RegisterSite*>(s)->mask
|
|
|
|
& (static_cast<uint64_t>(1) << register_.low))
|
|
|
|
and (register_.high == NoRegister
|
|
|
|
or (static_cast<RegisterSite*>(s)->mask
|
|
|
|
& (static_cast<uint64_t>(1) << (register_.high + 32)))))))
|
2008-04-16 20:58:21 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual bool match(Context* c, uint8_t typeMask, uint64_t registerMask, int)
|
|
|
|
{
|
|
|
|
if ((typeMask & (1 << RegisterOperand)) and low) {
|
|
|
|
sync(c);
|
|
|
|
return ((static_cast<uint64_t>(1) << register_.low) & registerMask)
|
|
|
|
and (register_.high == NoRegister
|
|
|
|
or ((static_cast<uint64_t>(1) << (register_.high + 32))
|
|
|
|
& registerMask));
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
virtual void acquire(Context* c, Stack* stack, Local* locals, unsigned size,
|
2008-07-17 23:34:38 +00:00
|
|
|
Value* v)
|
|
|
|
{
|
|
|
|
low = ::validate(c, mask, stack, locals, size, v, this, low);
|
2008-05-20 22:47:53 +00:00
|
|
|
if (size > BytesPerWord) {
|
2008-09-27 22:01:39 +00:00
|
|
|
::freeze(c, low);
|
2008-07-17 23:34:38 +00:00
|
|
|
high = ::validate(c, mask >> 32, stack, locals, size, v, this, high);
|
2008-09-27 22:01:39 +00:00
|
|
|
::thaw(c, low);
|
2008-05-20 22:47:53 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void release(Context* c) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
|
|
|
::release(c, low);
|
|
|
|
if (high) {
|
|
|
|
::release(c, high);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-14 23:19:41 +00:00
|
|
|
virtual void freeze(Context* c UNUSED) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
2008-09-27 22:01:39 +00:00
|
|
|
::freeze(c, low);
|
2008-05-12 13:54:47 +00:00
|
|
|
if (high) {
|
2008-09-27 22:01:39 +00:00
|
|
|
::freeze(c, high);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-14 23:19:41 +00:00
|
|
|
virtual void thaw(Context* c UNUSED) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
2008-09-27 22:01:39 +00:00
|
|
|
::thaw(c, low);
|
2008-05-12 13:54:47 +00:00
|
|
|
if (high) {
|
2008-09-27 22:01:39 +00:00
|
|
|
::thaw(c, high);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return RegisterOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
|
|
|
|
sync(c);
|
2008-04-16 20:58:21 +00:00
|
|
|
return ®ister_;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
uint64_t mask;
|
|
|
|
Register* low;
|
|
|
|
Register* high;
|
2008-04-16 20:58:21 +00:00
|
|
|
Assembler::Register register_;
|
|
|
|
};
|
|
|
|
|
|
|
|
RegisterSite*
|
|
|
|
registerSite(Context* c, int low, int high = NoRegister)
|
|
|
|
{
|
2008-04-19 00:19:45 +00:00
|
|
|
assert(c, low != NoRegister);
|
2008-08-23 18:04:36 +00:00
|
|
|
assert(c, low < static_cast<int>(c->arch->registerCount()));
|
2008-04-19 00:19:45 +00:00
|
|
|
assert(c, high == NoRegister
|
2008-08-23 18:04:36 +00:00
|
|
|
or high < static_cast<int>(c->arch->registerCount()));
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-13 17:27:57 +00:00
|
|
|
Register* hr;
|
2008-05-12 13:54:47 +00:00
|
|
|
if (high == NoRegister) {
|
2008-05-13 17:27:57 +00:00
|
|
|
hr = 0;
|
2008-05-12 13:54:47 +00:00
|
|
|
} else {
|
2008-05-13 17:27:57 +00:00
|
|
|
hr = c->registers[high];
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
return new (c->zone->allocate(sizeof(RegisterSite)))
|
2008-05-15 23:19:23 +00:00
|
|
|
RegisterSite(~static_cast<uint64_t>(0), c->registers[low], hr);
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
RegisterSite*
|
2008-05-15 23:19:23 +00:00
|
|
|
freeRegisterSite(Context* c, uint64_t mask = ~static_cast<uint64_t>(0))
|
2008-05-12 13:54:47 +00:00
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(RegisterSite)))
|
|
|
|
RegisterSite(mask);
|
|
|
|
}
|
2008-04-17 22:07:32 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Register*
|
|
|
|
increment(Context* c, int i)
|
2008-04-20 00:43:12 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
Register* r = c->registers[i];
|
|
|
|
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-05-12 13:54:47 +00:00
|
|
|
fprintf(stderr, "increment %d to %d\n", r->number, r->refCount + 1);
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
2008-05-12 13:54:47 +00:00
|
|
|
|
|
|
|
++ r->refCount;
|
|
|
|
|
|
|
|
return r;
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-05-14 23:19:41 +00:00
|
|
|
decrement(Context* c UNUSED, Register* r)
|
2008-04-20 00:43:12 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, r->refCount > 0);
|
|
|
|
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-05-15 00:04:25 +00:00
|
|
|
fprintf(stderr, "decrement %d to %d\n", r->number, r->refCount - 1);
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
2008-05-12 13:54:47 +00:00
|
|
|
|
|
|
|
-- r->refCount;
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class MemorySite: public Site {
|
|
|
|
public:
|
2008-04-17 02:55:38 +00:00
|
|
|
MemorySite(int base, int offset, int index, unsigned scale):
|
2008-08-23 18:04:36 +00:00
|
|
|
base(0), index(0), value(base, offset, index, scale)
|
2008-04-16 20:58:21 +00:00
|
|
|
{ }
|
|
|
|
|
2008-05-14 23:19:41 +00:00
|
|
|
void sync(Context* c UNUSED) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, base);
|
|
|
|
|
|
|
|
value.base = base->number;
|
|
|
|
value.index = (index? index->number : NoRegister);
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual unsigned copyCost(Context* c, Site* s) {
|
2008-05-12 13:54:47 +00:00
|
|
|
sync(c);
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
if (s and
|
|
|
|
(this == s or
|
2008-04-17 22:07:32 +00:00
|
|
|
(s->type(c) == MemoryOperand
|
|
|
|
and static_cast<MemorySite*>(s)->value.base == value.base
|
|
|
|
and static_cast<MemorySite*>(s)->value.offset == value.offset
|
|
|
|
and static_cast<MemorySite*>(s)->value.index == value.index
|
|
|
|
and static_cast<MemorySite*>(s)->value.scale == value.scale)))
|
2008-04-16 20:58:21 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual bool match(Context* c, uint8_t typeMask, uint64_t, int frameIndex) {
|
|
|
|
if (typeMask & (1 << MemoryOperand)) {
|
|
|
|
sync(c);
|
|
|
|
if (value.base == c->arch->stack()) {
|
|
|
|
assert(c, value.index == NoRegister);
|
|
|
|
return frameIndex == AnyFrameIndex
|
|
|
|
|| (frameIndex != NoFrameIndex
|
|
|
|
&& localOffset(c, frameIndex) == value.offset);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
virtual void acquire(Context* c, Stack*, Local*, unsigned, Value*) {
|
2008-05-12 13:54:47 +00:00
|
|
|
base = increment(c, value.base);
|
2008-04-19 00:19:45 +00:00
|
|
|
if (value.index != NoRegister) {
|
2008-05-12 13:54:47 +00:00
|
|
|
index = increment(c, value.index);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void release(Context* c) {
|
2008-05-12 13:54:47 +00:00
|
|
|
decrement(c, base);
|
|
|
|
if (index) {
|
|
|
|
decrement(c, index);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
virtual OperandType type(Context*) {
|
2008-04-17 22:07:32 +00:00
|
|
|
return MemoryOperand;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
|
|
|
|
sync(c);
|
2008-04-16 20:58:21 +00:00
|
|
|
return &value;
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Register* base;
|
|
|
|
Register* index;
|
2008-04-16 20:58:21 +00:00
|
|
|
Assembler::Memory value;
|
|
|
|
};
|
|
|
|
|
|
|
|
MemorySite*
|
2008-05-19 04:31:52 +00:00
|
|
|
memorySite(Context* c, int base, int offset = 0, int index = NoRegister,
|
|
|
|
unsigned scale = 1)
|
2008-04-16 20:58:21 +00:00
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(MemorySite)))
|
|
|
|
MemorySite(base, offset, index, scale);
|
|
|
|
}
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
MemorySite*
|
|
|
|
frameSite(Context* c, int frameIndex)
|
|
|
|
{
|
|
|
|
assert(c, frameIndex >= 0);
|
|
|
|
return memorySite(c, c->arch->stack(), localOffset(c, frameIndex));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
Site*
|
|
|
|
targetOrNull(Context* c, Value* v, Read* r)
|
2008-05-04 20:55:34 +00:00
|
|
|
{
|
2008-07-05 20:21:13 +00:00
|
|
|
if (v->target) {
|
|
|
|
return v->target;
|
2008-05-22 17:15:18 +00:00
|
|
|
} else {
|
2008-07-05 20:21:13 +00:00
|
|
|
Site* s = r->pickSite(c, v);
|
|
|
|
if (s) return s;
|
|
|
|
return r->allocateSite(c);
|
2008-05-22 17:15:18 +00:00
|
|
|
}
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
Site*
|
|
|
|
targetOrNull(Context* c, Value* v)
|
2008-05-04 20:55:34 +00:00
|
|
|
{
|
2008-07-05 20:21:13 +00:00
|
|
|
if (v->target) {
|
|
|
|
return v->target;
|
|
|
|
} else if (live(v)) {
|
2008-08-23 18:04:36 +00:00
|
|
|
Read* r = v->reads;
|
2008-07-05 20:21:13 +00:00
|
|
|
Site* s = r->pickSite(c, v);
|
|
|
|
if (s) return s;
|
|
|
|
return r->allocateSite(c);
|
|
|
|
}
|
|
|
|
return 0;
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
2008-05-06 21:13:02 +00:00
|
|
|
Site*
|
2008-07-05 20:21:13 +00:00
|
|
|
pickSite(Context* c, Value* value, uint8_t typeMask, uint64_t registerMask,
|
|
|
|
int frameIndex)
|
2008-05-06 21:13:02 +00:00
|
|
|
{
|
2008-07-05 20:21:13 +00:00
|
|
|
Site* site = 0;
|
|
|
|
unsigned copyCost = 0xFFFFFFFF;
|
|
|
|
for (Site* s = value->sites; s; s = s->next) {
|
|
|
|
if (s->match(c, typeMask, registerMask, frameIndex)) {
|
|
|
|
unsigned v = s->copyCost(c, 0);
|
|
|
|
if (v < copyCost) {
|
|
|
|
site = s;
|
|
|
|
copyCost = v;
|
|
|
|
}
|
|
|
|
}
|
2008-05-06 21:13:02 +00:00
|
|
|
}
|
2008-07-05 20:21:13 +00:00
|
|
|
return site;
|
2008-05-06 21:13:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Site*
|
2008-07-05 20:21:13 +00:00
|
|
|
allocateSite(Context* c, uint8_t typeMask, uint64_t registerMask,
|
|
|
|
int frameIndex)
|
2008-05-06 21:13:02 +00:00
|
|
|
{
|
2008-07-05 20:21:13 +00:00
|
|
|
if ((typeMask & (1 << RegisterOperand)) and registerMask) {
|
|
|
|
return freeRegisterSite(c, registerMask);
|
|
|
|
} else if (frameIndex >= 0) {
|
|
|
|
return frameSite(c, frameIndex);
|
|
|
|
} else {
|
2008-09-24 00:01:42 +00:00
|
|
|
return 0;
|
2008-05-06 21:13:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
class SingleRead: public Read {
|
|
|
|
public:
|
|
|
|
SingleRead(unsigned size, uint8_t typeMask, uint64_t registerMask,
|
|
|
|
int frameIndex):
|
2008-09-24 00:01:42 +00:00
|
|
|
Read(size), next_(0), typeMask(typeMask), registerMask(registerMask),
|
2008-08-28 22:43:35 +00:00
|
|
|
frameIndex(frameIndex)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual Site* pickSite(Context* c, Value* value) {
|
|
|
|
return ::pickSite(c, value, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Site* allocateSite(Context* c) {
|
|
|
|
return ::allocateSite(c, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
|
2008-08-28 22:43:35 +00:00
|
|
|
int* frameIndex)
|
|
|
|
{
|
|
|
|
*typeMask &= this->typeMask;
|
|
|
|
*registerMask &= this->registerMask;
|
|
|
|
*frameIndex = intersectFrameIndexes(*frameIndex, this->frameIndex);
|
2008-09-15 02:28:42 +00:00
|
|
|
return true;
|
2008-08-28 22:43:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool valid() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
virtual void append(Context* c, Read* r) {
|
|
|
|
assert(c, next_ == 0);
|
|
|
|
next_ = r;
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual Read* next(Context*) {
|
2008-09-13 21:09:26 +00:00
|
|
|
return next_;
|
|
|
|
}
|
|
|
|
|
|
|
|
Read* next_;
|
2008-08-28 22:43:35 +00:00
|
|
|
uint8_t typeMask;
|
|
|
|
uint64_t registerMask;
|
|
|
|
int frameIndex;
|
|
|
|
};
|
|
|
|
|
|
|
|
Read*
|
|
|
|
read(Context* c, unsigned size, uint8_t typeMask, uint64_t registerMask,
|
|
|
|
int frameIndex)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(SingleRead)))
|
|
|
|
SingleRead(size, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
Read*
|
|
|
|
anyRegisterRead(Context* c, unsigned size)
|
|
|
|
{
|
|
|
|
return read(c, size, 1 << RegisterOperand, ~static_cast<uint64_t>(0),
|
|
|
|
NoFrameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
Read*
|
|
|
|
registerOrConstantRead(Context* c, unsigned size)
|
|
|
|
{
|
|
|
|
return read(c, size, (1 << RegisterOperand) | (1 << ConstantOperand),
|
|
|
|
~static_cast<uint64_t>(0), NoFrameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
Read*
|
|
|
|
fixedRegisterRead(Context* c, unsigned size, int low, int high = NoRegister)
|
|
|
|
{
|
|
|
|
uint64_t mask;
|
|
|
|
if (high == NoRegister) {
|
|
|
|
mask = (~static_cast<uint64_t>(0) << 32)
|
|
|
|
| (static_cast<uint64_t>(1) << low);
|
|
|
|
} else {
|
|
|
|
mask = (static_cast<uint64_t>(1) << (high + 32))
|
|
|
|
| (static_cast<uint64_t>(1) << low);
|
|
|
|
}
|
|
|
|
|
|
|
|
return read(c, size, 1 << RegisterOperand, mask, NoFrameIndex);
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
class MultiRead: public Read {
|
2008-05-06 21:13:02 +00:00
|
|
|
public:
|
2008-09-24 00:01:42 +00:00
|
|
|
MultiRead(unsigned size):
|
|
|
|
Read(size), reads(0), lastRead(0), firstTarget(0), lastTarget(0),
|
|
|
|
visited(false)
|
2008-05-04 20:55:34 +00:00
|
|
|
{ }
|
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
virtual Site* pickSite(Context* c, Value* value) {
|
2008-07-05 20:21:13 +00:00
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0);
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
intersect(&typeMask, ®isterMask, &frameIndex);
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
return ::pickSite(c, value, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Site* allocateSite(Context* c) {
|
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0);
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
intersect(&typeMask, ®isterMask, &frameIndex);
|
|
|
|
|
|
|
|
return ::allocateSite(c, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
|
2008-07-05 20:21:13 +00:00
|
|
|
int* frameIndex)
|
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
bool result = false;
|
2008-09-13 21:09:26 +00:00
|
|
|
if (not visited) {
|
|
|
|
visited = true;
|
2008-09-15 02:28:42 +00:00
|
|
|
for (Cell** cell = &reads; *cell;) {
|
|
|
|
Read* r = static_cast<Read*>((*cell)->value);
|
|
|
|
bool valid = r->intersect(typeMask, registerMask, frameIndex);
|
|
|
|
if (valid) {
|
|
|
|
result = true;
|
|
|
|
cell = &((*cell)->next);
|
|
|
|
} else {
|
|
|
|
*cell = (*cell)->next;
|
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
}
|
|
|
|
visited = false;
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
return result;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
virtual bool valid() {
|
2008-09-15 02:28:42 +00:00
|
|
|
bool result = false;
|
2008-09-13 21:09:26 +00:00
|
|
|
if (not visited) {
|
|
|
|
visited = true;
|
2008-09-15 02:28:42 +00:00
|
|
|
for (Cell** cell = &reads; *cell;) {
|
|
|
|
Read* r = static_cast<Read*>((*cell)->value);
|
2008-09-13 21:09:26 +00:00
|
|
|
if (r->valid()) {
|
2008-09-15 02:28:42 +00:00
|
|
|
result = true;
|
|
|
|
cell = &((*cell)->next);
|
|
|
|
} else {
|
|
|
|
*cell = (*cell)->next;
|
2008-09-13 21:09:26 +00:00
|
|
|
}
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
visited = false;
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
return result;
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
virtual void append(Context* c, Read* r) {
|
|
|
|
Cell* cell = cons(c, r, 0);
|
|
|
|
if (lastRead == 0) {
|
|
|
|
reads = cell;
|
|
|
|
} else {
|
|
|
|
lastRead->next = cell;
|
|
|
|
}
|
|
|
|
lastRead = cell;
|
2008-09-15 02:28:42 +00:00
|
|
|
|
|
|
|
lastTarget->value = r;
|
2008-09-13 21:09:26 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual Read* next(Context* c) {
|
|
|
|
abort(c);
|
2008-09-13 21:09:26 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
void allocateTarget(Context* c) {
|
|
|
|
Cell* cell = cons(c, 0, 0);
|
|
|
|
if (lastTarget == 0) {
|
|
|
|
firstTarget = cell;
|
|
|
|
} else {
|
|
|
|
lastTarget->next = cell;
|
|
|
|
}
|
|
|
|
lastTarget = cell;
|
|
|
|
}
|
|
|
|
|
|
|
|
Read* nextTarget() {
|
|
|
|
Read* r = static_cast<Read*>(firstTarget->value);
|
|
|
|
firstTarget = firstTarget->next;
|
|
|
|
return r;
|
2008-09-13 21:09:26 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
Cell* reads;
|
2008-09-13 21:09:26 +00:00
|
|
|
Cell* lastRead;
|
2008-09-15 02:28:42 +00:00
|
|
|
Cell* firstTarget;
|
|
|
|
Cell* lastTarget;
|
2008-09-13 21:09:26 +00:00
|
|
|
bool visited;
|
2008-04-16 20:58:21 +00:00
|
|
|
};
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
MultiRead*
|
2008-09-24 00:01:42 +00:00
|
|
|
multiRead(Context* c, unsigned size)
|
2008-05-04 20:55:34 +00:00
|
|
|
{
|
2008-09-24 00:01:42 +00:00
|
|
|
return new (c->zone->allocate(sizeof(MultiRead))) MultiRead(size);
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
2008-09-22 00:58:54 +00:00
|
|
|
class StubRead: public Read {
|
|
|
|
public:
|
2008-09-24 00:01:42 +00:00
|
|
|
StubRead(unsigned size):
|
|
|
|
Read(size), read(0), visited(false)
|
2008-09-22 00:58:54 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual Site* pickSite(Context* c, Value* value) {
|
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0);
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
intersect(&typeMask, ®isterMask, &frameIndex);
|
|
|
|
|
|
|
|
return ::pickSite(c, value, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Site* allocateSite(Context* c) {
|
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0);
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
intersect(&typeMask, ®isterMask, &frameIndex);
|
|
|
|
|
|
|
|
return ::allocateSite(c, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
|
|
|
|
int* frameIndex)
|
|
|
|
{
|
|
|
|
if (not visited) {
|
|
|
|
visited = true;
|
|
|
|
if (read) {
|
|
|
|
bool valid = read->intersect(typeMask, registerMask, frameIndex);
|
|
|
|
if (not valid) {
|
|
|
|
read = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
visited = false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool valid() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void append(Context*, Read* r) {
|
|
|
|
read = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Read* next(Context* c) {
|
|
|
|
abort(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
Read* read;
|
|
|
|
bool visited;
|
|
|
|
};
|
|
|
|
|
|
|
|
StubRead*
|
2008-09-24 00:01:42 +00:00
|
|
|
stubRead(Context* c, unsigned size)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
2008-09-24 00:01:42 +00:00
|
|
|
return new (c->zone->allocate(sizeof(StubRead))) StubRead(size);
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
Site*
|
2008-05-12 13:54:47 +00:00
|
|
|
targetOrRegister(Context* c, Value* v)
|
2008-04-18 17:00:55 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
Site* s = targetOrNull(c, v);
|
|
|
|
if (s) {
|
2008-04-18 17:00:55 +00:00
|
|
|
return s;
|
|
|
|
} else {
|
2008-05-15 23:19:23 +00:00
|
|
|
return freeRegisterSite(c);
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
Site*
|
|
|
|
pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
|
|
|
|
{
|
|
|
|
Site* site = 0;
|
|
|
|
unsigned copyCost = 0xFFFFFFFF;
|
|
|
|
for (Site* s = sites; s; s = s->next) {
|
|
|
|
unsigned v = s->copyCost(c, target);
|
|
|
|
if (v < copyCost) {
|
|
|
|
site = s;
|
|
|
|
copyCost = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cost) *cost = copyCost;
|
|
|
|
return site;
|
|
|
|
}
|
|
|
|
|
2008-04-27 20:15:18 +00:00
|
|
|
bool
|
2008-09-24 00:01:42 +00:00
|
|
|
trySteal(Context* c, Register* r, Stack* stack, Local* locals)
|
2008-04-27 20:15:18 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, r->refCount == 0);
|
2008-04-27 20:15:18 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Value* v = r->value;
|
2008-07-17 23:34:38 +00:00
|
|
|
assert(c, v->reads);
|
2008-04-27 20:15:18 +00:00
|
|
|
|
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "try steal %d from %p: next: %p\n",
|
2008-05-12 13:54:47 +00:00
|
|
|
r->number, v, v->sites->next);
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (v->sites->next == 0) {
|
2008-07-17 23:34:38 +00:00
|
|
|
Site* saveSite = 0;
|
2008-08-23 18:04:36 +00:00
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-24 00:01:42 +00:00
|
|
|
if (locals[i].value == v) {
|
2008-07-17 23:34:38 +00:00
|
|
|
saveSite = frameSite(c, i);
|
|
|
|
break;
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-17 23:34:38 +00:00
|
|
|
if (saveSite == 0) {
|
2008-08-23 18:04:36 +00:00
|
|
|
for (Stack* s = stack; s; s = s->next) {
|
2008-07-17 23:34:38 +00:00
|
|
|
if (s->value == v) {
|
|
|
|
uint8_t typeMask;
|
|
|
|
uint64_t registerMask;
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
v->reads->intersect(&typeMask, ®isterMask, &frameIndex);
|
|
|
|
|
|
|
|
if (frameIndex >= 0) {
|
|
|
|
saveSite = frameSite(c, frameIndex);
|
|
|
|
} else {
|
2008-08-28 22:43:35 +00:00
|
|
|
saveSite = frameSite(c, s->index + c->localFootprint);
|
2008-07-17 23:34:38 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2008-05-18 01:26:36 +00:00
|
|
|
}
|
2008-07-17 23:34:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (saveSite) {
|
|
|
|
addSite(c, 0, 0, r->size, v, saveSite);
|
2008-09-24 00:01:42 +00:00
|
|
|
apply(c, Move, r->size, r->site, r->size, saveSite);
|
2008-04-27 20:15:18 +00:00
|
|
|
} else {
|
2008-05-18 01:26:36 +00:00
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "unable to steal %d from %p\n", r->number, v);
|
|
|
|
}
|
2008-04-27 20:15:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
removeSite(c, v, r->site);
|
2008-04-27 20:15:18 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-04-21 00:21:48 +00:00
|
|
|
bool
|
2008-05-12 13:54:47 +00:00
|
|
|
used(Context* c, Register* r)
|
|
|
|
{
|
|
|
|
Value* v = r->value;
|
|
|
|
return v and findSite(c, v, r->site);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
usedExclusively(Context* c, Register* r)
|
|
|
|
{
|
|
|
|
return used(c, r) and r->value->sites->next == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
registerCost(Context* c, Register* r)
|
|
|
|
{
|
|
|
|
if (r->reserved or r->freezeCount) {
|
|
|
|
return 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned cost = 0;
|
|
|
|
|
|
|
|
if (used(c, r)) {
|
|
|
|
++ cost;
|
|
|
|
if (usedExclusively(c, r)) {
|
|
|
|
cost += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r->refCount) {
|
|
|
|
cost += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cost;
|
|
|
|
}
|
|
|
|
|
|
|
|
Register*
|
|
|
|
pickRegister(Context* c, uint32_t mask)
|
|
|
|
{
|
|
|
|
Register* register_ = 0;
|
|
|
|
unsigned cost = 5;
|
2008-08-23 18:04:36 +00:00
|
|
|
for (int i = c->arch->registerCount() - 1; i >= 0; --i) {
|
2008-05-12 13:54:47 +00:00
|
|
|
if ((1 << i) & mask) {
|
|
|
|
Register* r = c->registers[i];
|
|
|
|
if ((static_cast<uint32_t>(1) << i) == mask) {
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned myCost = registerCost(c, r);
|
|
|
|
if (myCost < cost) {
|
|
|
|
register_ = r;
|
|
|
|
cost = myCost;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expect(c, register_);
|
|
|
|
|
|
|
|
return register_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
swap(Context* c, Register* a, Register* b)
|
|
|
|
{
|
2008-05-15 23:19:23 +00:00
|
|
|
assert(c, a != b);
|
|
|
|
assert(c, a->number != b->number);
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
Assembler::Register ar(a->number);
|
|
|
|
Assembler::Register br(b->number);
|
|
|
|
c->assembler->apply
|
2008-08-16 17:45:36 +00:00
|
|
|
(Swap, BytesPerWord, RegisterOperand, &ar,
|
|
|
|
BytesPerWord, RegisterOperand, &br);
|
2008-05-12 13:54:47 +00:00
|
|
|
|
|
|
|
c->registers[a->number] = b;
|
|
|
|
c->registers[b->number] = a;
|
|
|
|
|
|
|
|
int t = a->number;
|
|
|
|
a->number = b->number;
|
|
|
|
b->number = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
Register*
|
2008-09-24 00:01:42 +00:00
|
|
|
replace(Context* c, Stack* stack, Local* locals, Register* r)
|
2008-05-12 13:54:47 +00:00
|
|
|
{
|
2008-05-15 23:19:23 +00:00
|
|
|
uint32_t mask = (r->freezeCount? r->site->mask : ~0);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-09-27 22:01:39 +00:00
|
|
|
freeze(c, r);
|
2008-07-17 23:34:38 +00:00
|
|
|
Register* s = acquire(c, mask, stack, locals, r->size, r->value, r->site);
|
2008-09-27 22:01:39 +00:00
|
|
|
thaw(c, r);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-05-18 01:26:36 +00:00
|
|
|
if (DebugRegisters) {
|
|
|
|
fprintf(stderr, "replace %d with %d\n", r->number, s->number);
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
swap(c, r, s);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
Register*
|
2008-09-24 00:01:42 +00:00
|
|
|
acquire(Context* c, uint32_t mask, Stack* stack, Local* locals,
|
2008-07-17 23:34:38 +00:00
|
|
|
unsigned newSize, Value* newValue, RegisterSite* newSite)
|
2008-04-17 22:07:32 +00:00
|
|
|
{
|
2008-05-12 13:54:47 +00:00
|
|
|
Register* r = pickRegister(c, mask);
|
|
|
|
|
|
|
|
if (r->reserved) return r;
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-07-17 23:34:38 +00:00
|
|
|
fprintf(stderr, "acquire %d, value %p, site %p freeze count %d "
|
|
|
|
"ref count %d used %d used exclusively %d\n",
|
|
|
|
r->number, newValue, newSite, r->freezeCount, r->refCount,
|
|
|
|
used(c, r), usedExclusively(c, r));
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
if (r->refCount) {
|
2008-08-28 22:43:35 +00:00
|
|
|
r = replace(c, stack, locals, r);
|
2008-05-12 13:54:47 +00:00
|
|
|
} else {
|
|
|
|
Value* oldValue = r->value;
|
|
|
|
if (oldValue
|
|
|
|
and oldValue != newValue
|
|
|
|
and findSite(c, oldValue, r->site))
|
|
|
|
{
|
2008-07-17 23:34:38 +00:00
|
|
|
if (not trySteal(c, r, stack, locals)) {
|
2008-08-28 22:43:35 +00:00
|
|
|
r = replace(c, stack, locals, r);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-17 22:07:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
r->size = newSize;
|
|
|
|
r->value = newValue;
|
|
|
|
r->site = newSite;
|
2008-04-21 00:21:48 +00:00
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
return r;
|
2008-04-17 22:07:32 +00:00
|
|
|
}
|
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
void
|
2008-05-12 13:54:47 +00:00
|
|
|
release(Context*, Register* r)
|
2008-04-19 00:19:45 +00:00
|
|
|
{
|
2008-04-20 00:43:12 +00:00
|
|
|
if (DebugRegisters) {
|
2008-05-12 13:54:47 +00:00
|
|
|
fprintf(stderr, "release %d\n", r->number);
|
2008-04-20 00:43:12 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
r->size = 0;
|
|
|
|
r->value = 0;
|
|
|
|
r->site = 0;
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
|
2008-05-15 20:00:57 +00:00
|
|
|
Register*
|
2008-09-24 00:01:42 +00:00
|
|
|
validate(Context* c, uint32_t mask, Stack* stack, Local* locals,
|
2008-07-17 23:34:38 +00:00
|
|
|
unsigned size, Value* value, RegisterSite* site, Register* current)
|
2008-05-15 20:00:57 +00:00
|
|
|
{
|
2008-05-15 23:19:23 +00:00
|
|
|
if (current and (mask & (1 << current->number))) {
|
|
|
|
if (current->reserved or current->value == value) {
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current->value == 0) {
|
|
|
|
current->size = size;
|
|
|
|
current->value = value;
|
|
|
|
current->site = site;
|
|
|
|
return current;
|
2008-05-18 01:26:36 +00:00
|
|
|
} else {
|
|
|
|
abort(c);
|
2008-05-15 23:19:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-17 23:34:38 +00:00
|
|
|
Register* r = acquire(c, mask, stack, locals, size, value, site);
|
2008-05-15 23:19:23 +00:00
|
|
|
|
|
|
|
if (current and current != r) {
|
2008-05-15 20:00:57 +00:00
|
|
|
release(c, current);
|
|
|
|
|
|
|
|
Assembler::Register rr(r->number);
|
|
|
|
Assembler::Register cr(current->number);
|
|
|
|
c->assembler->apply
|
2008-08-16 17:45:36 +00:00
|
|
|
(Move, BytesPerWord, RegisterOperand, &cr,
|
|
|
|
BytesPerWord, RegisterOperand, &rr);
|
2008-05-15 20:00:57 +00:00
|
|
|
}
|
2008-05-15 23:19:23 +00:00
|
|
|
|
|
|
|
return r;
|
2008-05-15 20:00:57 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
void
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(Context* c, UnaryOperation op,
|
|
|
|
unsigned s1Size, Site* s1)
|
|
|
|
{
|
|
|
|
OperandType s1Type = s1->type(c);
|
|
|
|
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
|
|
|
|
|
|
|
|
c->assembler->apply(op, s1Size, s1Type, s1Operand);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
apply(Context* c, BinaryOperation op,
|
|
|
|
unsigned s1Size, Site* s1,
|
|
|
|
unsigned s2Size, Site* s2)
|
2008-04-17 02:55:38 +00:00
|
|
|
{
|
2008-08-16 17:45:36 +00:00
|
|
|
OperandType s1Type = s1->type(c);
|
|
|
|
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
|
|
|
|
|
|
|
|
OperandType s2Type = s2->type(c);
|
|
|
|
Assembler::Operand* s2Operand = s2->asAssemblerOperand(c);
|
2008-03-15 20:24:04 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
c->assembler->apply(op, s1Size, s1Type, s1Operand,
|
|
|
|
s2Size, s2Type, s2Operand);
|
2008-04-17 02:55:38 +00:00
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
void
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(Context* c, TernaryOperation op,
|
|
|
|
unsigned s1Size, Site* s1,
|
|
|
|
unsigned s2Size, Site* s2,
|
|
|
|
unsigned s3Size, Site* s3)
|
2008-04-17 02:55:38 +00:00
|
|
|
{
|
2008-08-16 17:45:36 +00:00
|
|
|
OperandType s1Type = s1->type(c);
|
|
|
|
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
OperandType s2Type = s2->type(c);
|
|
|
|
Assembler::Operand* s2Operand = s2->asAssemblerOperand(c);
|
2008-02-17 22:29:04 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
OperandType s3Type = s3->type(c);
|
|
|
|
Assembler::Operand* s3Operand = s3->asAssemblerOperand(c);
|
|
|
|
|
|
|
|
c->assembler->apply(op, s1Size, s1Type, s1Operand,
|
|
|
|
s2Size, s2Type, s2Operand,
|
|
|
|
s3Size, s3Type, s3Operand);
|
2008-04-17 02:55:38 +00:00
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-03-11 16:40:28 +00:00
|
|
|
void
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(Context* c, Event* e, Value* v, Read* r)
|
2008-03-11 16:40:28 +00:00
|
|
|
{
|
2008-09-25 00:48:32 +00:00
|
|
|
// fprintf(stderr, "add read %p to %p\n", r, v);
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
r->value = v;
|
2008-09-15 02:28:42 +00:00
|
|
|
if (e) {
|
|
|
|
r->event = e;
|
|
|
|
r->eventNext = e->reads;
|
|
|
|
e->reads = r;
|
|
|
|
++ e->readCount;
|
|
|
|
}
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
if (v->lastRead) {
|
2008-09-15 02:28:42 +00:00
|
|
|
//fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v);
|
2008-09-13 21:09:26 +00:00
|
|
|
v->lastRead->append(c, r);
|
|
|
|
} else {
|
|
|
|
v->reads = r;
|
2008-04-17 02:55:38 +00:00
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
v->lastRead = r;
|
2008-03-11 16:40:28 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void
|
2008-08-23 18:04:36 +00:00
|
|
|
clean(Context* c, Value* v)
|
2008-07-05 20:21:13 +00:00
|
|
|
{
|
2008-08-23 18:04:36 +00:00
|
|
|
for (Site** s = &(v->sites); *s;) {
|
|
|
|
if ((*s)->match(c, 1 << MemoryOperand, 0, AnyFrameIndex)) {
|
|
|
|
s = &((*s)->next);
|
|
|
|
} else {
|
|
|
|
(*s)->release(c);
|
|
|
|
*s = (*s)->next;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
void
|
2008-09-25 00:48:32 +00:00
|
|
|
clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads)
|
2008-05-19 04:31:52 +00:00
|
|
|
{
|
2008-08-28 22:43:35 +00:00
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-24 00:01:42 +00:00
|
|
|
if (locals[i].value) clean(c, locals[i].value);
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Stack* s = stack; s; s = s->next) {
|
2008-08-23 18:04:36 +00:00
|
|
|
clean(c, s->value);
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Read* r = reads; r; r = r->eventNext) {
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, e, r->value);
|
2008-08-28 22:43:35 +00:00
|
|
|
}
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-31 22:24:04 +00:00
|
|
|
CodePromise*
|
|
|
|
codePromise(Context* c, Event* e)
|
|
|
|
{
|
|
|
|
return e->promises = new (c->zone->allocate(sizeof(CodePromise)))
|
|
|
|
CodePromise(c, e->promises);
|
|
|
|
}
|
|
|
|
|
|
|
|
CodePromise*
|
2008-09-09 00:31:19 +00:00
|
|
|
codePromise(Context* c, Promise* offset)
|
2008-05-31 22:24:04 +00:00
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset);
|
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
class CallEvent: public Event {
|
2008-02-11 17:21:41 +00:00
|
|
|
public:
|
2008-05-06 21:13:02 +00:00
|
|
|
CallEvent(Context* c, Value* address, unsigned flags,
|
2008-04-18 04:16:20 +00:00
|
|
|
TraceHandler* traceHandler, Value* result, unsigned resultSize,
|
2008-08-23 18:04:36 +00:00
|
|
|
Stack* argumentStack, unsigned argumentCount,
|
|
|
|
unsigned stackArgumentFootprint):
|
2008-04-17 02:55:38 +00:00
|
|
|
Event(c),
|
|
|
|
address(address),
|
|
|
|
traceHandler(traceHandler),
|
2008-04-17 20:48:26 +00:00
|
|
|
result(result),
|
|
|
|
flags(flags),
|
2008-08-23 18:04:36 +00:00
|
|
|
resultSize(resultSize)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-05-15 20:00:57 +00:00
|
|
|
uint32_t mask = ~0;
|
2008-04-19 00:19:45 +00:00
|
|
|
Stack* s = argumentStack;
|
2008-04-21 00:21:48 +00:00
|
|
|
unsigned index = 0;
|
2008-08-23 18:04:36 +00:00
|
|
|
unsigned frameIndex = alignedFrameSize(c) + c->parameterFootprint;
|
2008-04-19 00:19:45 +00:00
|
|
|
for (unsigned i = 0; i < argumentCount; ++i) {
|
2008-08-23 18:04:36 +00:00
|
|
|
Read* target;
|
2008-08-28 22:43:35 +00:00
|
|
|
if (index < c->arch->argumentRegisterCount()) {
|
|
|
|
int r = c->arch->argumentRegister(index);
|
|
|
|
target = fixedRegisterRead(c, s->size * BytesPerWord, r);
|
2008-05-15 20:00:57 +00:00
|
|
|
mask &= ~(1 << r);
|
2008-04-19 00:19:45 +00:00
|
|
|
} else {
|
2008-08-28 22:43:35 +00:00
|
|
|
frameIndex -= s->size;
|
|
|
|
target = read(c, s->size * BytesPerWord, 1 << MemoryOperand, 0,
|
|
|
|
frameIndex);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, s->value, target);
|
2008-08-28 22:43:35 +00:00
|
|
|
index += s->size;
|
2008-04-19 00:19:45 +00:00
|
|
|
s = s->next;
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, address, read
|
2008-08-28 22:43:35 +00:00
|
|
|
(c, BytesPerWord, ~0, (static_cast<uint64_t>(mask) << 32) | mask,
|
2008-08-23 18:04:36 +00:00
|
|
|
AnyFrameIndex));
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-08-23 18:04:36 +00:00
|
|
|
int footprint = stackArgumentFootprint;
|
2008-05-15 20:00:57 +00:00
|
|
|
for (Stack* s = stack; s; s = s->next) {
|
2008-09-15 02:28:42 +00:00
|
|
|
frameIndex -= s->size;
|
2008-09-23 21:18:41 +00:00
|
|
|
if (footprint > 0) {
|
2008-09-25 00:48:32 +00:00
|
|
|
addRead(c, this, s->value, read
|
|
|
|
(c, s->size * BytesPerWord,
|
|
|
|
1 << MemoryOperand, 0, frameIndex));
|
2008-08-23 18:04:36 +00:00
|
|
|
} else {
|
2008-08-28 22:43:35 +00:00
|
|
|
unsigned index = s->index + c->localFootprint;
|
2008-08-23 18:04:36 +00:00
|
|
|
if (footprint == 0) {
|
|
|
|
assert(c, index <= frameIndex);
|
2008-08-28 22:43:35 +00:00
|
|
|
s->padding = frameIndex - index;
|
2008-08-23 18:04:36 +00:00
|
|
|
}
|
2008-09-23 21:18:41 +00:00
|
|
|
addRead(c, this, s->value, read
|
|
|
|
(c, s->size * BytesPerWord, 1 << MemoryOperand, 0, index));
|
2008-08-23 18:04:36 +00:00
|
|
|
}
|
2008-08-28 22:43:35 +00:00
|
|
|
footprint -= s->size;
|
2008-05-15 20:00:57 +00:00
|
|
|
}
|
2008-09-25 00:48:32 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
|
|
|
Local* local = locals + i;
|
|
|
|
if (local->value) {
|
|
|
|
addRead(c, this, local->value, read
|
|
|
|
(c, local->size, 1 << MemoryOperand, 0, i));
|
|
|
|
}
|
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "CallEvent";
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-08-23 18:04:36 +00:00
|
|
|
apply(c, (flags & Compiler::Aligned) ? AlignedCall : Call, BytesPerWord,
|
|
|
|
address->source);
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-05-15 23:19:23 +00:00
|
|
|
if (traceHandler) {
|
2008-08-30 20:12:27 +00:00
|
|
|
traceHandler->handleTrace(codePromise(c, c->assembler->offset()));
|
2008-05-15 23:19:23 +00:00
|
|
|
}
|
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
clean(c, this, stack, locals, reads);
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
if (resultSize and live(result)) {
|
2008-07-17 23:34:38 +00:00
|
|
|
addSite(c, 0, 0, resultSize, result, registerSite
|
2008-08-28 22:43:35 +00:00
|
|
|
(c, c->arch->returnLow(),
|
2008-04-19 00:19:45 +00:00
|
|
|
resultSize > BytesPerWord ?
|
2008-08-28 22:43:35 +00:00
|
|
|
c->arch->returnHigh() : NoRegister));
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* address;
|
|
|
|
TraceHandler* traceHandler;
|
|
|
|
Value* result;
|
2008-04-17 20:48:26 +00:00
|
|
|
unsigned flags;
|
2008-04-18 04:16:20 +00:00
|
|
|
unsigned resultSize;
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-05-06 21:13:02 +00:00
|
|
|
appendCall(Context* c, Value* address, unsigned flags,
|
2008-04-18 04:16:20 +00:00
|
|
|
TraceHandler* traceHandler, Value* result, unsigned resultSize,
|
2008-08-23 18:04:36 +00:00
|
|
|
Stack* argumentStack, unsigned argumentCount,
|
|
|
|
unsigned stackArgumentFootprint)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-04-17 02:55:38 +00:00
|
|
|
new (c->zone->allocate(sizeof(CallEvent)))
|
2008-05-06 21:13:02 +00:00
|
|
|
CallEvent(c, address, flags, traceHandler, result,
|
2008-08-23 18:04:36 +00:00
|
|
|
resultSize, argumentStack, argumentCount,
|
|
|
|
stackArgumentFootprint);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
class ReturnEvent: public Event {
|
2008-02-17 20:57:40 +00:00
|
|
|
public:
|
2008-04-17 02:55:38 +00:00
|
|
|
ReturnEvent(Context* c, unsigned size, Value* value):
|
|
|
|
Event(c), value(value)
|
|
|
|
{
|
|
|
|
if (value) {
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, value, fixedRegisterRead
|
2008-08-28 22:43:35 +00:00
|
|
|
(c, size, c->arch->returnLow(),
|
2008-04-17 02:55:38 +00:00
|
|
|
size > BytesPerWord ?
|
2008-08-28 22:43:35 +00:00
|
|
|
c->arch->returnHigh() : NoRegister));
|
2008-04-17 02:55:38 +00:00
|
|
|
}
|
2008-03-15 20:24:04 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "ReturnEvent";
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-04-19 00:19:45 +00:00
|
|
|
if (value) {
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, value);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
c->assembler->popFrame();
|
2008-04-17 02:55:38 +00:00
|
|
|
c->assembler->apply(Return);
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* value;
|
2008-02-17 20:57:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2008-04-17 22:07:32 +00:00
|
|
|
appendReturn(Context* c, unsigned size, Value* value)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-04-17 02:55:38 +00:00
|
|
|
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
class MoveEvent: public Event {
|
2008-02-11 17:21:41 +00:00
|
|
|
public:
|
2008-08-16 17:45:36 +00:00
|
|
|
MoveEvent(Context* c, BinaryOperation type, unsigned srcSize, Value* src,
|
2008-08-28 22:43:35 +00:00
|
|
|
unsigned dstSize, Value* dst, Read* srcRead, Read* dstRead):
|
2008-08-16 17:45:36 +00:00
|
|
|
Event(c), type(type), srcSize(srcSize), src(src), dstSize(dstSize),
|
2008-08-28 22:43:35 +00:00
|
|
|
dst(dst), dstRead(dstRead)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, src, srcRead);
|
2008-03-15 20:24:04 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "MoveEvent";
|
|
|
|
}
|
2008-03-15 20:24:04 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
|
|
|
bool isLoad = not valid(src->reads->next(c));
|
2008-07-05 20:21:13 +00:00
|
|
|
bool isStore = not valid(dst->reads);
|
2008-05-19 13:44:39 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
Site* target = targetOrRegister(c, dst);
|
|
|
|
unsigned cost = src->source->copyCost(c, target);
|
|
|
|
if (cost == 0 and (isLoad or isStore)) {
|
2008-04-18 17:30:54 +00:00
|
|
|
target = src->source;
|
2008-04-18 17:00:55 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-19 14:53:40 +00:00
|
|
|
assert(c, isLoad or isStore or target != src->source);
|
|
|
|
|
2008-05-18 01:26:36 +00:00
|
|
|
if (target == src->source) {
|
2008-05-19 14:53:40 +00:00
|
|
|
removeSite(c, src, target);
|
2008-05-18 01:26:36 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
if (not isStore) {
|
2008-08-16 17:45:36 +00:00
|
|
|
addSite(c, stack, locals, dstSize, dst, target);
|
2008-04-28 22:08:31 +00:00
|
|
|
}
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
if (cost or type != Move) {
|
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0);
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
dstRead->intersect(&typeMask, ®isterMask, &frameIndex);
|
|
|
|
|
|
|
|
if (target->match(c, typeMask, registerMask, frameIndex)) {
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(c, type, srcSize, src->source, dstSize, target);
|
2008-05-16 16:01:24 +00:00
|
|
|
} else {
|
2008-08-28 22:43:35 +00:00
|
|
|
assert(c, typeMask & (1 << RegisterOperand));
|
2008-05-16 16:01:24 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
Site* tmpTarget = freeRegisterSite(c, registerMask);
|
2008-05-16 16:01:24 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
addSite(c, stack, locals, dstSize, dst, tmpTarget);
|
2008-05-16 16:01:24 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(c, type, srcSize, src->source, dstSize, tmpTarget);
|
2008-05-16 16:01:24 +00:00
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
if (isStore) {
|
2008-05-18 01:26:36 +00:00
|
|
|
removeSite(c, dst, tmpTarget);
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(c, Move, dstSize, tmpTarget, dstSize, target);
|
2008-05-18 01:26:36 +00:00
|
|
|
} else {
|
|
|
|
removeSite(c, dst, target);
|
|
|
|
}
|
2008-05-16 16:01:24 +00:00
|
|
|
}
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
if (isStore) {
|
2008-04-20 19:35:36 +00:00
|
|
|
removeSite(c, dst, target);
|
|
|
|
}
|
2008-05-18 01:26:36 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, src);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
BinaryOperation type;
|
2008-08-16 17:45:36 +00:00
|
|
|
unsigned srcSize;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* src;
|
2008-08-16 17:45:36 +00:00
|
|
|
unsigned dstSize;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* dst;
|
2008-08-28 22:43:35 +00:00
|
|
|
Read* dstRead;
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-11 21:26:59 +00:00
|
|
|
|
|
|
|
void
|
2008-08-28 22:43:35 +00:00
|
|
|
appendMove(Context* c, BinaryOperation type, unsigned srcSize, Value* src,
|
|
|
|
unsigned dstSize, Value* dst)
|
2007-12-11 21:26:59 +00:00
|
|
|
{
|
2008-05-31 22:14:27 +00:00
|
|
|
bool thunk;
|
2008-08-28 22:43:35 +00:00
|
|
|
uint8_t srcTypeMask;
|
|
|
|
uint64_t srcRegisterMask;
|
|
|
|
uint8_t dstTypeMask;
|
|
|
|
uint64_t dstRegisterMask;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
c->arch->plan(type, srcSize, &srcTypeMask, &srcRegisterMask,
|
|
|
|
dstSize, &dstTypeMask, &dstRegisterMask,
|
|
|
|
&thunk);
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
assert(c, not thunk); // todo
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
new (c->zone->allocate(sizeof(MoveEvent)))
|
2008-08-28 22:43:35 +00:00
|
|
|
MoveEvent(c, type, srcSize, src, dstSize, dst,
|
|
|
|
read(c, srcSize, srcTypeMask, srcRegisterMask, AnyFrameIndex),
|
|
|
|
read(c, dstSize, dstTypeMask, dstRegisterMask, AnyFrameIndex));
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantSite*
|
|
|
|
findConstantSite(Context* c, Value* v)
|
|
|
|
{
|
|
|
|
for (Site* s = v->sites; s; s = s->next) {
|
|
|
|
if (s->type(c) == ConstantOperand) {
|
|
|
|
return static_cast<ConstantSite*>(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
class CompareEvent: public Event {
|
2008-02-11 17:21:41 +00:00
|
|
|
public:
|
2008-05-19 13:27:05 +00:00
|
|
|
CompareEvent(Context* c, unsigned size, Value* first, Value* second,
|
2008-08-28 22:43:35 +00:00
|
|
|
Read* firstRead, Read* secondRead):
|
2008-04-17 02:55:38 +00:00
|
|
|
Event(c), size(size), first(first), second(second)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, first, firstRead);
|
|
|
|
addRead(c, this, second, secondRead);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 01:42:12 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "CompareEvent";
|
|
|
|
}
|
2008-03-15 20:24:04 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantSite* firstConstant = findConstantSite(c, first);
|
|
|
|
ConstantSite* secondConstant = findConstantSite(c, second);
|
|
|
|
|
|
|
|
if (firstConstant and secondConstant) {
|
|
|
|
int64_t d = firstConstant->value.value->value()
|
|
|
|
- secondConstant->value.value->value();
|
|
|
|
|
|
|
|
if (d < 0) {
|
|
|
|
c->constantCompare = CompareLess;
|
|
|
|
} else if (d > 0) {
|
|
|
|
c->constantCompare = CompareGreater;
|
|
|
|
} else {
|
|
|
|
c->constantCompare = CompareEqual;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
c->constantCompare = CompareNone;
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(c, Compare, size, first->source, size, second->source);
|
2008-06-11 00:17:44 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, first);
|
|
|
|
nextRead(c, this, second);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
unsigned size;
|
|
|
|
Value* first;
|
|
|
|
Value* second;
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-11 21:26:59 +00:00
|
|
|
|
|
|
|
void
|
2008-04-17 02:55:38 +00:00
|
|
|
appendCompare(Context* c, unsigned size, Value* first, Value* second)
|
2007-12-11 21:26:59 +00:00
|
|
|
{
|
2008-05-31 22:14:27 +00:00
|
|
|
bool thunk;
|
2008-08-28 22:43:35 +00:00
|
|
|
uint8_t firstTypeMask;
|
|
|
|
uint64_t firstRegisterMask;
|
|
|
|
uint8_t secondTypeMask;
|
|
|
|
uint64_t secondRegisterMask;
|
2008-05-19 13:27:05 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
c->arch->plan(Compare, size, &firstTypeMask, &firstRegisterMask,
|
|
|
|
size, &secondTypeMask, &secondRegisterMask,
|
|
|
|
&thunk);
|
2008-05-19 13:27:05 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
assert(c, not thunk); // todo
|
2008-05-19 13:27:05 +00:00
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
new (c->zone->allocate(sizeof(CompareEvent)))
|
2008-08-28 22:43:35 +00:00
|
|
|
CompareEvent
|
|
|
|
(c, size, first, second,
|
|
|
|
read(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
|
|
|
read(c, size, secondTypeMask, secondRegisterMask, AnyFrameIndex));
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 14:53:40 +00:00
|
|
|
void
|
2008-09-24 00:01:42 +00:00
|
|
|
preserve(Context* c, Stack* stack, Local* locals, unsigned size, Value* v,
|
2008-08-28 22:43:35 +00:00
|
|
|
Site* s, Read* read)
|
2008-05-19 14:53:40 +00:00
|
|
|
{
|
|
|
|
assert(c, v->sites == s);
|
2008-08-28 22:43:35 +00:00
|
|
|
Site* r = targetOrNull(c, v, read);
|
2008-05-19 14:53:40 +00:00
|
|
|
if (r == 0 or r == s) r = freeRegisterSite(c);
|
2008-07-17 23:34:38 +00:00
|
|
|
addSite(c, stack, locals, size, v, r);
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(c, Move, size, s, size, r);
|
2008-05-19 14:53:40 +00:00
|
|
|
}
|
|
|
|
|
2008-04-29 16:25:20 +00:00
|
|
|
void
|
2008-09-24 00:01:42 +00:00
|
|
|
maybePreserve(Context* c, Stack* stack, Local* locals, unsigned size,
|
2008-08-28 22:43:35 +00:00
|
|
|
Value* v, Site* s)
|
2008-04-29 16:25:20 +00:00
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
if (valid(v->reads->next(c)) and v->sites->next == 0) {
|
|
|
|
preserve(c, stack, locals, size, v, s, v->reads->next(c));
|
2008-04-29 16:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class CombineEvent: public Event {
|
|
|
|
public:
|
2008-08-16 17:45:36 +00:00
|
|
|
CombineEvent(Context* c, TernaryOperation type,
|
|
|
|
unsigned firstSize, Value* first,
|
|
|
|
unsigned secondSize, Value* second,
|
|
|
|
unsigned resultSize, Value* result,
|
2008-09-07 20:12:11 +00:00
|
|
|
Read* firstRead,
|
|
|
|
Read* secondRead,
|
|
|
|
Read* resultRead):
|
2008-08-16 17:45:36 +00:00
|
|
|
Event(c), type(type), firstSize(firstSize), first(first),
|
|
|
|
secondSize(secondSize), second(second), resultSize(resultSize),
|
2008-09-07 20:12:11 +00:00
|
|
|
result(result), resultRead(resultRead)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, first, firstRead);
|
|
|
|
addRead(c, this, second, secondRead);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-16 23:52:38 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "CombineEvent";
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-09-07 20:12:11 +00:00
|
|
|
Site* target;
|
|
|
|
if (c->arch->condensedAddressing()) {
|
|
|
|
maybePreserve(c, stack, locals, secondSize, second, second->source);
|
|
|
|
target = second->source;
|
|
|
|
} else {
|
|
|
|
target = resultRead->allocateSite(c);
|
|
|
|
addSite(c, stack, locals, resultSize, result, target);
|
|
|
|
}
|
2008-04-29 16:25:20 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
fprintf(stderr, "combine %p and %p into %p\n", first, second, result);
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(c, type, firstSize, first->source, secondSize, second->source,
|
|
|
|
resultSize, target);
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, first);
|
|
|
|
nextRead(c, this, second);
|
2008-09-23 21:18:41 +00:00
|
|
|
|
|
|
|
if (c->arch->condensedAddressing()) {
|
|
|
|
removeSite(c, second, second->source);
|
|
|
|
if (result->reads) {
|
|
|
|
addSite(c, 0, 0, resultSize, result, second->source);
|
|
|
|
}
|
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-23 18:48:22 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
TernaryOperation type;
|
2008-08-16 17:45:36 +00:00
|
|
|
unsigned firstSize;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* first;
|
2008-08-16 17:45:36 +00:00
|
|
|
unsigned secondSize;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* second;
|
2008-08-16 17:45:36 +00:00
|
|
|
unsigned resultSize;
|
2008-04-17 22:07:32 +00:00
|
|
|
Value* result;
|
2008-09-07 20:12:11 +00:00
|
|
|
Read* resultRead;
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-05-06 21:13:02 +00:00
|
|
|
Value*
|
|
|
|
value(Context* c, Site* site = 0, Site* target = 0)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Value))) Value(site, target);
|
|
|
|
}
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
Stack*
|
|
|
|
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Stack)))
|
|
|
|
Stack(index, size, value, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
Stack*
|
|
|
|
stack(Context* c, Value* value, unsigned size, Stack* next)
|
|
|
|
{
|
|
|
|
return stack
|
|
|
|
(c, value, size, (next ? next->index + next->size : 0), next);
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-08-28 22:43:35 +00:00
|
|
|
push(Context* c, unsigned size, Value* v)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-08-28 22:43:35 +00:00
|
|
|
assert(c, ceiling(size, BytesPerWord));
|
2008-04-28 22:08:31 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
c->stack = stack(c, v, ceiling(size, BytesPerWord), c->stack);
|
2008-08-28 22:43:35 +00:00
|
|
|
}
|
2008-04-28 22:08:31 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
Value*
|
|
|
|
pop(Context* c, unsigned size UNUSED)
|
|
|
|
{
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* s = c->stack;
|
2008-08-28 22:43:35 +00:00
|
|
|
assert(c, ceiling(size, BytesPerWord) == s->size);
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
c->stack = s->next;
|
2008-08-28 22:43:35 +00:00
|
|
|
return s->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
appendCombine(Context* c, TernaryOperation type,
|
|
|
|
unsigned firstSize, Value* first,
|
|
|
|
unsigned secondSize, Value* second,
|
|
|
|
unsigned resultSize, Value* result)
|
|
|
|
{
|
|
|
|
bool thunk;
|
|
|
|
uint8_t firstTypeMask;
|
|
|
|
uint64_t firstRegisterMask;
|
|
|
|
uint8_t secondTypeMask;
|
|
|
|
uint64_t secondRegisterMask;
|
|
|
|
uint8_t resultTypeMask;
|
|
|
|
uint64_t resultRegisterMask;
|
|
|
|
|
|
|
|
c->arch->plan(type, firstSize, &firstTypeMask, &firstRegisterMask,
|
|
|
|
secondSize, &secondTypeMask, &secondRegisterMask,
|
|
|
|
resultSize, &resultTypeMask, &resultRegisterMask,
|
|
|
|
&thunk);
|
2008-05-16 00:35:17 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
if (thunk) {
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* oldStack = c->stack;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
::push(c, secondSize, second);
|
|
|
|
::push(c, firstSize, first);
|
2008-04-18 03:47:42 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* argumentStack = c->stack;
|
|
|
|
c->stack = oldStack;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
appendCall
|
|
|
|
(c, value(c, constantSite(c, c->client->getThunk(type, resultSize))),
|
|
|
|
0, 0, result, resultSize, argumentStack, 2, 0);
|
2008-05-04 20:55:34 +00:00
|
|
|
} else {
|
2008-09-07 20:12:11 +00:00
|
|
|
Read* resultRead = read
|
|
|
|
(c, resultSize, resultTypeMask, resultRegisterMask, AnyFrameIndex);
|
|
|
|
Read* secondRead;
|
|
|
|
if (c->arch->condensedAddressing()) {
|
|
|
|
secondRead = resultRead;
|
|
|
|
} else {
|
|
|
|
secondRead = read
|
|
|
|
(c, secondSize, secondTypeMask, secondRegisterMask, AnyFrameIndex);
|
|
|
|
}
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-05-04 20:55:34 +00:00
|
|
|
new (c->zone->allocate(sizeof(CombineEvent)))
|
2008-08-28 22:43:35 +00:00
|
|
|
CombineEvent
|
|
|
|
(c, type,
|
|
|
|
firstSize, first,
|
|
|
|
secondSize, second,
|
|
|
|
resultSize, result,
|
|
|
|
read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
2008-09-07 20:12:11 +00:00
|
|
|
secondRead,
|
|
|
|
resultRead);
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class TranslateEvent: public Event {
|
|
|
|
public:
|
2008-08-28 22:43:35 +00:00
|
|
|
TranslateEvent(Context* c, BinaryOperation type, unsigned size, Value* value,
|
|
|
|
Value* result, Read* read):
|
2008-04-17 02:55:38 +00:00
|
|
|
Event(c), type(type), size(size), value(value), result(result)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, value, read);
|
2008-03-15 20:24:04 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "TranslateEvent";
|
|
|
|
}
|
2008-02-17 20:57:40 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-08-28 22:43:35 +00:00
|
|
|
maybePreserve(c, stack, locals, size, value, value->source);
|
2008-04-29 16:25:20 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
Site* target = targetOrRegister(c, result);
|
|
|
|
apply(c, type, size, value->source, size, target);
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, value);
|
2008-04-19 00:19:45 +00:00
|
|
|
|
2008-04-18 00:39:41 +00:00
|
|
|
removeSite(c, value, value->source);
|
2008-07-05 20:21:13 +00:00
|
|
|
if (live(result)) {
|
2008-07-17 23:34:38 +00:00
|
|
|
addSite(c, 0, 0, size, result, value->source);
|
2008-04-21 00:21:48 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
BinaryOperation type;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* value;
|
|
|
|
Value* result;
|
2008-02-11 17:21:41 +00:00
|
|
|
};
|
2007-12-12 18:59:45 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-08-28 22:43:35 +00:00
|
|
|
appendTranslate(Context* c, BinaryOperation type, unsigned size, Value* value,
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* result)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-05-31 22:14:27 +00:00
|
|
|
bool thunk;
|
2008-08-28 22:43:35 +00:00
|
|
|
uint8_t firstTypeMask;
|
|
|
|
uint64_t firstRegisterMask;
|
|
|
|
uint8_t resultTypeMask;
|
|
|
|
uint64_t resultRegisterMask;
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
c->arch->plan(type, size, &firstTypeMask, &firstRegisterMask,
|
|
|
|
size, &resultTypeMask, &resultRegisterMask,
|
|
|
|
&thunk);
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
assert(c, not thunk); // todo
|
2008-05-04 20:55:34 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
// todo: respect resultTypeMask and resultRegisterMask
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
new (c->zone->allocate(sizeof(TranslateEvent)))
|
2008-08-28 22:43:35 +00:00
|
|
|
TranslateEvent
|
|
|
|
(c, type, size, value, result,
|
|
|
|
read(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex));
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-20 16:02:00 +00:00
|
|
|
|
2008-03-15 23:54:20 +00:00
|
|
|
class MemoryEvent: public Event {
|
|
|
|
public:
|
2008-04-17 20:48:26 +00:00
|
|
|
MemoryEvent(Context* c, Value* base, int displacement, Value* index,
|
|
|
|
unsigned scale, Value* result):
|
|
|
|
Event(c), base(base), displacement(displacement), index(index),
|
|
|
|
scale(scale), result(result)
|
2008-03-15 23:54:20 +00:00
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, base, anyRegisterRead(c, BytesPerWord));
|
|
|
|
if (index) addRead(c, this, index, registerOrConstantRead(c, BytesPerWord));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const char* name() {
|
|
|
|
return "MemoryEvent";
|
2008-03-15 23:54:20 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-04-17 20:48:26 +00:00
|
|
|
int indexRegister;
|
2008-06-10 14:49:13 +00:00
|
|
|
int displacement = this->displacement;
|
|
|
|
unsigned scale = this->scale;
|
2008-04-17 20:48:26 +00:00
|
|
|
if (index) {
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantSite* constant = findConstantSite(c, index);
|
2008-06-10 14:49:13 +00:00
|
|
|
|
|
|
|
if (constant) {
|
|
|
|
indexRegister = NoRegister;
|
|
|
|
displacement += (constant->value.value->value() * scale);
|
|
|
|
scale = 1;
|
|
|
|
} else {
|
|
|
|
assert(c, index->source->type(c) == RegisterOperand);
|
|
|
|
indexRegister = static_cast<RegisterSite*>
|
|
|
|
(index->source)->register_.low;
|
|
|
|
}
|
2008-04-17 20:48:26 +00:00
|
|
|
} else {
|
|
|
|
indexRegister = NoRegister;
|
|
|
|
}
|
2008-04-18 00:39:41 +00:00
|
|
|
assert(c, base->source->type(c) == RegisterOperand);
|
|
|
|
int baseRegister = static_cast<RegisterSite*>(base->source)->register_.low;
|
2008-04-17 20:48:26 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, base);
|
2008-04-19 00:19:45 +00:00
|
|
|
if (index) {
|
2008-06-10 14:49:13 +00:00
|
|
|
if (BytesPerWord == 8 and indexRegister != NoRegister) {
|
2008-08-28 22:43:35 +00:00
|
|
|
apply(c, Move, 4, index->source, 8, index->source);
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
2008-05-13 17:27:57 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, index);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
|
2008-04-19 21:52:45 +00:00
|
|
|
result->target = memorySite
|
|
|
|
(c, baseRegister, displacement, indexRegister, scale);
|
2008-07-17 23:34:38 +00:00
|
|
|
addSite(c, 0, 0, 0, result, result->target);
|
2008-03-15 23:54:20 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* base;
|
2008-04-17 20:48:26 +00:00
|
|
|
int displacement;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* index;
|
2008-04-17 20:48:26 +00:00
|
|
|
unsigned scale;
|
2008-04-17 02:55:38 +00:00
|
|
|
Value* result;
|
2008-03-15 23:54:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2008-04-17 20:48:26 +00:00
|
|
|
appendMemory(Context* c, Value* base, int displacement, Value* index,
|
|
|
|
unsigned scale, Value* result)
|
2008-04-17 02:55:38 +00:00
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(MemoryEvent)))
|
2008-04-17 20:48:26 +00:00
|
|
|
MemoryEvent(c, base, displacement, index, scale, result);
|
|
|
|
}
|
|
|
|
|
2008-04-20 05:23:08 +00:00
|
|
|
class BranchEvent: public Event {
|
|
|
|
public:
|
|
|
|
BranchEvent(Context* c, UnaryOperation type, Value* address):
|
|
|
|
Event(c), type(type), address(address)
|
|
|
|
{
|
2008-09-20 23:42:46 +00:00
|
|
|
address->addPredecessor(c, this);
|
|
|
|
|
|
|
|
addRead(c, this, address, read
|
|
|
|
(c, BytesPerWord, ~0, ~static_cast<uint64_t>(0), AnyFrameIndex));
|
2008-04-20 05:23:08 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "BranchEvent";
|
|
|
|
}
|
2008-04-20 05:23:08 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-06-11 00:17:44 +00:00
|
|
|
bool jump;
|
|
|
|
UnaryOperation type = this->type;
|
|
|
|
if (type != Jump) {
|
|
|
|
switch (c->constantCompare) {
|
|
|
|
case CompareLess:
|
|
|
|
switch (type) {
|
|
|
|
case JumpIfLess:
|
|
|
|
case JumpIfLessOrEqual:
|
|
|
|
case JumpIfNotEqual:
|
|
|
|
jump = true;
|
|
|
|
type = Jump;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
jump = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CompareGreater:
|
|
|
|
switch (type) {
|
|
|
|
case JumpIfGreater:
|
|
|
|
case JumpIfGreaterOrEqual:
|
|
|
|
case JumpIfNotEqual:
|
|
|
|
jump = true;
|
|
|
|
type = Jump;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
jump = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CompareEqual:
|
|
|
|
switch (type) {
|
|
|
|
case JumpIfEqual:
|
|
|
|
case JumpIfLessOrEqual:
|
|
|
|
case JumpIfGreaterOrEqual:
|
|
|
|
jump = true;
|
|
|
|
type = Jump;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
jump = false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CompareNone:
|
|
|
|
jump = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(c);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
jump = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (jump) {
|
|
|
|
apply(c, type, BytesPerWord, address->source);
|
|
|
|
}
|
2008-04-20 05:23:08 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, address);
|
2008-04-20 05:23:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UnaryOperation type;
|
|
|
|
Value* address;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendBranch(Context* c, UnaryOperation type, Value* address)
|
|
|
|
{
|
2008-09-13 21:09:26 +00:00
|
|
|
new (c->zone->allocate(sizeof(BranchEvent)))
|
|
|
|
BranchEvent(c, type, address);
|
2008-04-18 03:47:42 +00:00
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
class BoundsCheckEvent: public Event {
|
|
|
|
public:
|
|
|
|
BoundsCheckEvent(Context* c, Value* object, unsigned lengthOffset,
|
|
|
|
Value* index, intptr_t handler):
|
|
|
|
Event(c), object(object), lengthOffset(lengthOffset), index(index),
|
|
|
|
handler(handler)
|
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
addRead(c, this, object, anyRegisterRead(c, BytesPerWord));
|
|
|
|
addRead(c, this, index, registerOrConstantRead(c, BytesPerWord));
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
|
|
|
return "BoundsCheckEvent";
|
|
|
|
}
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-05-31 22:14:27 +00:00
|
|
|
Assembler* a = c->assembler;
|
|
|
|
|
2008-06-11 00:17:44 +00:00
|
|
|
ConstantSite* constant = findConstantSite(c, index);
|
2008-08-30 20:12:27 +00:00
|
|
|
CodePromise* nextPromise = codePromise
|
2008-09-09 00:31:19 +00:00
|
|
|
(c, static_cast<Promise*>(0));
|
2008-05-31 23:06:45 +00:00
|
|
|
CodePromise* outOfBoundsPromise = 0;
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
if (constant) {
|
|
|
|
expect(c, constant->value.value->value() >= 0);
|
|
|
|
} else {
|
2008-09-09 00:31:19 +00:00
|
|
|
outOfBoundsPromise = codePromise(c, static_cast<Promise*>(0));
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
apply(c, Compare, 4, constantSite(c, resolved(c, 0)), 4, index->source);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
Assembler::Constant outOfBoundsConstant(outOfBoundsPromise);
|
|
|
|
a->apply
|
|
|
|
(JumpIfLess, BytesPerWord, ConstantOperand, &outOfBoundsConstant);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(c, object->source->type(c) == RegisterOperand);
|
|
|
|
int base = static_cast<RegisterSite*>(object->source)->register_.low;
|
|
|
|
|
|
|
|
Site* length = memorySite(c, base, lengthOffset);
|
2008-08-30 20:12:27 +00:00
|
|
|
length->acquire(c, 0, 0, 0, 0);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
apply(c, Compare, 4, index->source, 4, length);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
length->release(c);
|
|
|
|
|
|
|
|
Assembler::Constant nextConstant(nextPromise);
|
|
|
|
a->apply(JumpIfGreater, BytesPerWord, ConstantOperand, &nextConstant);
|
|
|
|
|
|
|
|
if (constant == 0) {
|
2008-08-30 20:12:27 +00:00
|
|
|
outOfBoundsPromise->offset = a->offset();
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
2008-05-31 22:53:37 +00:00
|
|
|
Assembler::Constant handlerConstant(resolved(c, handler));
|
2008-05-31 22:14:27 +00:00
|
|
|
a->apply(Call, BytesPerWord, ConstantOperand, &handlerConstant);
|
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
nextPromise->offset = a->offset();
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, object);
|
|
|
|
nextRead(c, this, index);
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Value* object;
|
|
|
|
unsigned lengthOffset;
|
|
|
|
Value* index;
|
|
|
|
intptr_t handler;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset,
|
|
|
|
Value* index, intptr_t handler)
|
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(BoundsCheckEvent))) BoundsCheckEvent
|
|
|
|
(c, object, lengthOffset, index, handler);
|
|
|
|
}
|
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
class FrameSiteEvent: public Event {
|
2008-09-09 00:31:19 +00:00
|
|
|
public:
|
2008-09-25 00:48:32 +00:00
|
|
|
FrameSiteEvent(Context* c, Value* value, unsigned size, int index):
|
2008-09-09 00:31:19 +00:00
|
|
|
Event(c), value(value), size(size), index(index)
|
|
|
|
{ }
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() {
|
2008-09-25 00:48:32 +00:00
|
|
|
return "FrameSiteEvent";
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
2008-09-09 00:31:19 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual void compile(Context* c) {
|
2008-09-09 00:31:19 +00:00
|
|
|
addSite(c, stack, locals, size, value, frameSite(c, index));
|
|
|
|
}
|
|
|
|
|
|
|
|
Value* value;
|
|
|
|
unsigned size;
|
|
|
|
int index;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2008-09-25 00:48:32 +00:00
|
|
|
appendFrameSite(Context* c, Value* value, unsigned size, int index)
|
2008-09-09 00:31:19 +00:00
|
|
|
{
|
2008-09-25 00:48:32 +00:00
|
|
|
new (c->zone->allocate(sizeof(FrameSiteEvent))) FrameSiteEvent
|
2008-09-09 00:31:19 +00:00
|
|
|
(c, value, size, index);
|
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
class DummyEvent: public Event {
|
|
|
|
public:
|
|
|
|
DummyEvent(Context* c):
|
|
|
|
Event(c)
|
2008-09-15 02:28:42 +00:00
|
|
|
{
|
|
|
|
stack = logicalInstruction->stack;
|
|
|
|
locals = logicalInstruction->locals;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const char* name() {
|
|
|
|
return "DummyEvent";
|
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
|
|
|
|
virtual void compile(Context*) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendDummy(Context* c)
|
|
|
|
{
|
|
|
|
new (c->zone->allocate(sizeof(DummyEvent))) DummyEvent(c);
|
|
|
|
}
|
|
|
|
|
2008-04-18 03:47:42 +00:00
|
|
|
Site*
|
2008-09-24 00:01:42 +00:00
|
|
|
readSource(Context* c, Stack* stack, Local* locals, Read* r)
|
2008-04-18 03:47:42 +00:00
|
|
|
{
|
2008-05-15 20:00:57 +00:00
|
|
|
if (r->value->sites == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
Site* site = r->pickSite(c, r->value);
|
2008-04-18 03:47:42 +00:00
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
if (site) {
|
2008-04-18 00:39:41 +00:00
|
|
|
return site;
|
2008-08-30 20:12:27 +00:00
|
|
|
} else {
|
|
|
|
Site* target = r->allocateSite(c);
|
|
|
|
unsigned copyCost;
|
|
|
|
site = pick(c, r->value->sites, target, ©Cost);
|
|
|
|
assert(c, copyCost);
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
addSite(c, stack, locals, r->size, r->value, target);
|
|
|
|
apply(c, Move, r->size, site, r->size, target);
|
2008-08-30 20:12:27 +00:00
|
|
|
return target;
|
2008-04-17 02:55:38 +00:00
|
|
|
}
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2008-07-23 23:58:29 +00:00
|
|
|
Site*
|
2008-09-27 22:01:39 +00:00
|
|
|
pickJunctionSite(Context* c, Value* v, Read* r, unsigned index)
|
2008-07-23 23:58:29 +00:00
|
|
|
{
|
2008-09-27 22:01:39 +00:00
|
|
|
if (c->availableRegisterCount > 1) {
|
|
|
|
Site* s = r->pickSite(c, v);
|
|
|
|
if (s) return s;
|
|
|
|
s = r->allocateSite(c);
|
|
|
|
if (s) return s;
|
|
|
|
return freeRegisterSite(c);
|
|
|
|
} else {
|
|
|
|
return frameSite(c, index);
|
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
unsigned
|
|
|
|
frameFootprint(Context* c, Stack* s)
|
|
|
|
{
|
|
|
|
return c->localFootprint + (s ? (s->index + s->size) : 0);
|
|
|
|
}
|
|
|
|
|
2008-07-23 23:58:29 +00:00
|
|
|
unsigned
|
|
|
|
resolveJunctionSite(Context* c, Event* e, Event* successor, Value* v,
|
|
|
|
unsigned index, Site** frozenSites,
|
|
|
|
unsigned frozenSiteIndex)
|
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
assert(c, index < frameFootprint(c, successor->stack));
|
|
|
|
|
2008-07-23 23:58:29 +00:00
|
|
|
if (live(v)) {
|
2008-09-25 00:48:32 +00:00
|
|
|
assert(c, v->sites);
|
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
Read* r = v->reads;
|
2008-07-23 23:58:29 +00:00
|
|
|
Site* original = e->junctionSites[index];
|
|
|
|
|
|
|
|
if (original == 0) {
|
2008-09-27 22:01:39 +00:00
|
|
|
e->junctionSites[index] = pickJunctionSite(c, v, r, index);
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Site* target = e->junctionSites[index];
|
|
|
|
unsigned copyCost;
|
|
|
|
Site* site = pick(c, v->sites, target, ©Cost);
|
|
|
|
if (copyCost) {
|
2008-09-24 00:01:42 +00:00
|
|
|
addSite(c, successor->stack, successor->locals, r->size, v, target);
|
|
|
|
apply(c, Move, r->size, site, r->size, target);
|
2008-09-25 00:48:32 +00:00
|
|
|
} else {
|
|
|
|
target = site;
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (original == 0) {
|
|
|
|
frozenSites[frozenSiteIndex++] = target;
|
|
|
|
target->freeze(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return frozenSiteIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
propagateJunctionSites(Context* c, Event* e, Site** sites)
|
|
|
|
{
|
|
|
|
for (Cell* pc = e->predecessors; pc; pc = pc->next) {
|
|
|
|
Event* p = static_cast<Event*>(pc->value);
|
|
|
|
if (p->junctionSites == 0) {
|
|
|
|
p->junctionSites = sites;
|
|
|
|
for (Cell* sc = p->successors; sc; sc = sc->next) {
|
|
|
|
Event* s = static_cast<Event*>(sc->value);
|
2008-08-30 20:12:27 +00:00
|
|
|
propagateJunctionSites(c, s, sites);
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
void
|
|
|
|
populateSiteTables(Context* c, Event* e)
|
|
|
|
{
|
|
|
|
Event* successor = static_cast<Event*>(e->successors->value);
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
unsigned frameFootprint = ::frameFootprint(c, successor->stack);
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
{ Site* frozenSites[frameFootprint];
|
2008-08-16 17:45:36 +00:00
|
|
|
unsigned frozenSiteIndex = 0;
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
if (e->junctionSites) {
|
2008-08-30 20:12:27 +00:00
|
|
|
for (unsigned i = 0; i < frameFootprint; ++i) {
|
2008-08-16 17:45:36 +00:00
|
|
|
Site* site = e->junctionSites[i];
|
|
|
|
if (site) {
|
|
|
|
frozenSites[frozenSiteIndex++] = site;
|
|
|
|
site->freeze(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (Cell* sc = e->successors; sc; sc = sc->next) {
|
|
|
|
Event* s = static_cast<Event*>(sc->value);
|
|
|
|
if (s->predecessors->next) {
|
2008-08-30 20:12:27 +00:00
|
|
|
unsigned size = sizeof(Site*) * frameFootprint;
|
2008-08-16 17:45:36 +00:00
|
|
|
Site** junctionSites = static_cast<Site**>
|
|
|
|
(c->zone->allocate(size));
|
|
|
|
memset(junctionSites, 0, size);
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
propagateJunctionSites(c, s, junctionSites);
|
|
|
|
break;
|
2008-04-20 05:23:08 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
if (e->junctionSites) {
|
2008-08-30 20:12:27 +00:00
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-24 00:01:42 +00:00
|
|
|
if (successor->locals[i].value) {
|
2008-09-23 21:18:41 +00:00
|
|
|
frozenSiteIndex = resolveJunctionSite
|
2008-09-24 00:01:42 +00:00
|
|
|
(c, e, successor, successor->locals[i].value, i, frozenSites,
|
2008-09-23 21:18:41 +00:00
|
|
|
frozenSiteIndex);
|
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
if (successor->stack) {
|
|
|
|
unsigned i = successor->stack->index + c->localFootprint;
|
|
|
|
for (Stack* stack = successor->stack; stack; stack = stack->next) {
|
|
|
|
frozenSiteIndex = resolveJunctionSite
|
|
|
|
(c, e, successor, stack->value, i, frozenSites, frozenSiteIndex);
|
|
|
|
|
|
|
|
i -= stack->size;
|
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
while (frozenSiteIndex) {
|
|
|
|
frozenSites[--frozenSiteIndex]->thaw(c);
|
|
|
|
}
|
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
if (e->successors->next) {
|
2008-08-30 20:12:27 +00:00
|
|
|
unsigned size = sizeof(Site*) * frameFootprint;
|
2008-08-16 17:45:36 +00:00
|
|
|
Site** savedSites = static_cast<Site**>(c->zone->allocate(size));
|
2008-09-23 21:18:41 +00:00
|
|
|
memset(savedSites, 0, size);
|
2008-04-20 05:23:08 +00:00
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-25 00:48:32 +00:00
|
|
|
Value* v = successor->locals[i].value;
|
|
|
|
if (v) {
|
|
|
|
savedSites[i] = v->sites;
|
|
|
|
|
|
|
|
// fprintf(stderr, "save %p for %p at %d\n", savedSites[i], v, i);
|
2008-09-23 21:18:41 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-05-15 14:29:19 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
if (successor->stack) {
|
|
|
|
unsigned i = successor->stack->index + c->localFootprint;
|
|
|
|
for (Stack* stack = successor->stack; stack; stack = stack->next) {
|
2008-09-25 00:48:32 +00:00
|
|
|
savedSites[i] = stack->value->sites;
|
|
|
|
// fprintf(stderr, "save %p for %p at %d\n",
|
|
|
|
// savedSites[i], stack->value, i);
|
2008-05-12 13:54:47 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
i -= stack->size;
|
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
|
|
|
|
e->savedSites = savedSites;
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
}
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
void
|
|
|
|
setSites(Context* c, Event* e, Site** sites)
|
|
|
|
{
|
2008-08-30 20:12:27 +00:00
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-24 00:01:42 +00:00
|
|
|
Value* v = e->locals[i].value;
|
2008-09-23 21:18:41 +00:00
|
|
|
if (v) {
|
|
|
|
clearSites(c, v);
|
|
|
|
if (live(v)) {
|
2008-09-25 00:48:32 +00:00
|
|
|
// fprintf(stderr, "set sites %p for %p at %d\n", sites[i], v, i);
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
addSite(c, 0, 0, v->reads->size, v, sites[i]);
|
2008-09-23 21:18:41 +00:00
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
if (e->stack) {
|
|
|
|
unsigned i = e->stack->index + c->localFootprint;
|
|
|
|
for (Stack* stack = e->stack; stack; stack = stack->next) {
|
|
|
|
Value* v = stack->value;
|
|
|
|
clearSites(c, v);
|
|
|
|
if (live(v)) {
|
2008-09-25 00:48:32 +00:00
|
|
|
// fprintf(stderr, "set sites %p for %p at %d\n", sites[i], v, i);
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
addSite(c, 0, 0, v->reads->size, v, sites[i]);
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
|
|
|
i -= stack->size;
|
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
void
|
|
|
|
populateSources(Context* c, Event* e)
|
|
|
|
{
|
|
|
|
Site* frozenSites[e->readCount];
|
|
|
|
unsigned frozenSiteIndex = 0;
|
|
|
|
for (Read* r = e->reads; r; r = r->eventNext) {
|
|
|
|
r->value->source = readSource(c, e->stack, e->locals, r);
|
|
|
|
|
|
|
|
if (r->value->source) {
|
|
|
|
assert(c, frozenSiteIndex < e->readCount);
|
|
|
|
frozenSites[frozenSiteIndex++] = r->value->source;
|
|
|
|
r->value->source->freeze(c);
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (frozenSiteIndex) {
|
|
|
|
frozenSites[--frozenSiteIndex]->thaw(c);
|
|
|
|
}
|
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-09-22 00:58:54 +00:00
|
|
|
void
|
2008-09-24 00:01:42 +00:00
|
|
|
addStubRead(Context* c, Value* v, unsigned size, StubReadPair** reads)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
|
|
|
if (v) {
|
|
|
|
StubRead* r;
|
|
|
|
if (v->visited) {
|
2008-09-22 14:28:18 +00:00
|
|
|
r = static_cast<StubRead*>(v->lastRead);
|
2008-09-22 00:58:54 +00:00
|
|
|
} else {
|
|
|
|
v->visited = true;
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
r = stubRead(c, size);
|
2008-09-22 00:58:54 +00:00
|
|
|
addRead(c, 0, v, r);
|
|
|
|
}
|
|
|
|
|
2008-09-22 14:28:18 +00:00
|
|
|
StubReadPair* p = (*reads)++;
|
2008-09-22 00:58:54 +00:00
|
|
|
p->value = v;
|
|
|
|
p->read = r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
populateJunctionReads(Context* c, Event* e)
|
|
|
|
{
|
|
|
|
StubReadPair* reads = static_cast<StubReadPair*>
|
|
|
|
(c->zone->allocate(sizeof(StubReadPair) * frameFootprint(c, c->stack)));
|
2008-09-22 14:28:18 +00:00
|
|
|
|
|
|
|
e->junctionReads = reads;
|
2008-09-22 00:58:54 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-24 00:01:42 +00:00
|
|
|
Local* local = c->locals + i;
|
|
|
|
addStubRead(c, local->value, local->size, &reads);
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Stack* s = c->stack; s; s = s->next) {
|
2008-09-24 00:01:42 +00:00
|
|
|
addStubRead(c, s->value, s->size * BytesPerWord, &reads);
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
2008-09-22 14:28:18 +00:00
|
|
|
|
|
|
|
for (StubReadPair* r = e->junctionReads; r < reads; ++r) {
|
|
|
|
r->value->visited = false;
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-22 14:28:18 +00:00
|
|
|
updateStubRead(Context*, StubReadPair* p, Read* r)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
|
|
|
if (p->read->read == 0) p->read->read = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updateJunctionReads(Context* c, Event* e, Event* successor)
|
|
|
|
{
|
|
|
|
StubReadPair* reads = e->junctionReads;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-24 00:01:42 +00:00
|
|
|
if (successor->locals[i].value) {
|
|
|
|
updateStubRead(c, reads++, successor->locals[i].value->reads);
|
2008-09-23 21:18:41 +00:00
|
|
|
}
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Stack* s = successor->stack; s; s = s->next) {
|
|
|
|
updateStubRead(c, reads++, s->value->reads);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
LogicalInstruction*
|
|
|
|
next(Context* c, LogicalInstruction* i)
|
|
|
|
{
|
|
|
|
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
|
|
|
|
i = c->logicalCode[n];
|
2008-09-13 21:09:26 +00:00
|
|
|
if (i) return i;
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
class Block {
|
|
|
|
public:
|
|
|
|
Block(Event* head):
|
2008-09-07 20:12:11 +00:00
|
|
|
head(head), nextInstruction(0), assemblerBlock(0), start(0)
|
2008-08-16 17:45:36 +00:00
|
|
|
{ }
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
Event* head;
|
|
|
|
LogicalInstruction* nextInstruction;
|
2008-09-07 20:12:11 +00:00
|
|
|
Assembler::Block* assemblerBlock;
|
2008-08-16 17:45:36 +00:00
|
|
|
unsigned start;
|
|
|
|
};
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
Block*
|
|
|
|
block(Context* c, Event* head)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Block))) Block(head);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
compile(Context* c)
|
|
|
|
{
|
|
|
|
Assembler* a = c->assembler;
|
|
|
|
|
|
|
|
c->pass = CompilePass;
|
|
|
|
|
|
|
|
Block* firstBlock = block(c, c->firstEvent);
|
|
|
|
Block* block = firstBlock;
|
|
|
|
|
2008-08-30 20:12:27 +00:00
|
|
|
a->allocateFrame(alignedFrameSize(c));
|
2008-08-16 17:45:36 +00:00
|
|
|
|
|
|
|
for (Event* e = c->firstEvent; e; e = e->next) {
|
|
|
|
e->block = block;
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
if (DebugCompile) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"compile %s at %d with %d preds, %d succs, %d stack\n",
|
|
|
|
e->name(), e->logicalInstruction->index,
|
|
|
|
count(e->predecessors), count(e->successors),
|
|
|
|
e->stack ? e->stack->index + e->stack->size : 0);
|
|
|
|
}
|
|
|
|
|
2008-09-07 01:37:12 +00:00
|
|
|
if (e->logicalInstruction->machineOffset == 0) {
|
|
|
|
e->logicalInstruction->machineOffset = a->offset();
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
MyState* state = e->state;
|
|
|
|
if (state) {
|
2008-09-20 23:42:46 +00:00
|
|
|
for (unsigned i = 0; i < state->readCount; ++i) {
|
2008-09-22 14:28:18 +00:00
|
|
|
MultiReadPair* p = state->reads + i;
|
2008-09-20 23:42:46 +00:00
|
|
|
p->value->reads = p->read->nextTarget();
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
if (e->predecessors) {
|
|
|
|
Event* predecessor = static_cast<Event*>(e->predecessors->value);
|
|
|
|
if (e->predecessors->next) {
|
2008-09-22 14:28:18 +00:00
|
|
|
for (Cell* cell = e->predecessors; cell->next; cell = cell->next) {
|
2008-09-22 00:58:54 +00:00
|
|
|
updateJunctionReads(c, static_cast<Event*>(cell->value), e);
|
|
|
|
}
|
2008-09-07 20:12:11 +00:00
|
|
|
setSites(c, e, predecessor->junctionSites);
|
|
|
|
} else if (predecessor->successors->next) {
|
|
|
|
setSites(c, e, predecessor->savedSites);
|
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
populateSources(c, e);
|
|
|
|
|
|
|
|
e->compile(c);
|
|
|
|
|
|
|
|
if (e->successors) {
|
|
|
|
populateSiteTables(c, e);
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
e->compilePostsync(c);
|
2008-08-16 17:45:36 +00:00
|
|
|
|
2008-07-23 23:58:29 +00:00
|
|
|
for (CodePromise* p = e->promises; p; p = p->next) {
|
|
|
|
p->offset = a->offset();
|
2008-04-17 02:55:38 +00:00
|
|
|
}
|
2008-09-20 23:42:46 +00:00
|
|
|
|
2008-09-22 00:58:54 +00:00
|
|
|
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
|
|
|
|
if (e->next == 0
|
|
|
|
or (e->next->logicalInstruction != e->logicalInstruction
|
|
|
|
and (e->logicalInstruction->lastEvent == e
|
|
|
|
or e->next->logicalInstruction != nextInstruction)))
|
|
|
|
{
|
2008-09-20 23:42:46 +00:00
|
|
|
block->nextInstruction = nextInstruction;
|
|
|
|
block->assemblerBlock = a->endBlock(e->next != 0);
|
|
|
|
if (e->next) {
|
|
|
|
block = ::block(c, e->next);
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
}
|
2008-04-17 02:55:38 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
|
|
|
|
block = firstBlock;
|
|
|
|
while (block->nextInstruction) {
|
|
|
|
Block* next = block->nextInstruction->firstEvent->block;
|
2008-09-07 20:12:11 +00:00
|
|
|
next->start = block->assemblerBlock->resolve
|
|
|
|
(block->start, next->assemblerBlock);
|
2008-08-16 17:45:36 +00:00
|
|
|
block = next;
|
|
|
|
}
|
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
return block->assemblerBlock->resolve(block->start, 0);
|
2007-12-12 00:27:04 +00:00
|
|
|
}
|
|
|
|
|
2008-03-15 20:24:04 +00:00
|
|
|
unsigned
|
|
|
|
count(Stack* s)
|
|
|
|
{
|
|
|
|
unsigned c = 0;
|
|
|
|
while (s) {
|
|
|
|
++ c;
|
|
|
|
s = s->next;
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
void
|
2008-09-20 23:42:46 +00:00
|
|
|
allocateTargets(Context* c, MyState* state)
|
2008-09-15 02:28:42 +00:00
|
|
|
{
|
2008-09-20 23:42:46 +00:00
|
|
|
for (unsigned i = 0; i < state->readCount; ++i) {
|
2008-09-22 14:28:18 +00:00
|
|
|
MultiReadPair* p = state->reads + i;
|
2008-09-20 23:42:46 +00:00
|
|
|
p->value->lastRead = p->read;
|
|
|
|
p->read->allocateTarget(c);
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-22 00:58:54 +00:00
|
|
|
void
|
2008-09-24 00:01:42 +00:00
|
|
|
addMultiRead(Context* c, Value* v, unsigned size, MyState* state,
|
|
|
|
unsigned* count)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
|
|
|
if (v and not v->visited) {
|
|
|
|
v->visited = true;
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
MultiRead* r = multiRead(c, size);
|
2008-09-22 00:58:54 +00:00
|
|
|
addRead(c, 0, v, r);
|
|
|
|
|
|
|
|
MultiReadPair* p = state->reads + ((*count)++);
|
|
|
|
p->value = v;
|
|
|
|
p->read = r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
MyState*
|
|
|
|
saveState(Context* c)
|
2007-12-14 18:27:56 +00:00
|
|
|
{
|
2008-09-20 23:42:46 +00:00
|
|
|
MyState* state = new
|
2008-09-22 14:28:18 +00:00
|
|
|
(c->zone->allocate
|
|
|
|
(sizeof(MyState) + (sizeof(MultiReadPair) * frameFootprint(c, c->stack))))
|
2008-09-20 23:42:46 +00:00
|
|
|
MyState(c->stack, c->locals, c->predecessor, c->logicalIp);
|
2007-12-14 18:27:56 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
if (c->predecessor) {
|
2008-09-15 02:28:42 +00:00
|
|
|
c->state = state;
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
unsigned count = 0;
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
for (unsigned i = 0; i < c->localFootprint; ++i) {
|
2008-09-24 00:01:42 +00:00
|
|
|
if (c->locals[i].value) {
|
|
|
|
Local* local = c->locals + i;
|
|
|
|
addMultiRead(c, local->value, local->size, state, &count);
|
|
|
|
}
|
2008-04-28 15:53:48 +00:00
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
|
|
|
|
for (Stack* s = c->stack; s; s = s->next) {
|
2008-09-24 00:01:42 +00:00
|
|
|
addMultiRead(c, s->value, s->size * BytesPerWord, state, &count);
|
2008-09-20 23:42:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
2008-09-22 14:28:18 +00:00
|
|
|
state->reads[i].value->visited = false;
|
2008-09-13 21:09:26 +00:00
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
state->readCount = count;
|
|
|
|
|
|
|
|
allocateTargets(c, state);
|
2008-04-20 19:35:36 +00:00
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
return state;
|
2008-04-20 19:35:36 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-09-13 21:09:26 +00:00
|
|
|
restoreState(Context* c, MyState* s)
|
2007-12-11 23:52:28 +00:00
|
|
|
{
|
2008-09-15 02:28:42 +00:00
|
|
|
if (c->logicalIp >= 0 and c->logicalCode[c->logicalIp]->lastEvent == 0) {
|
|
|
|
appendDummy(c);
|
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
c->stack = s->stack;
|
|
|
|
c->locals = s->locals;
|
2008-09-20 23:42:46 +00:00
|
|
|
c->predecessor = s->predecessor;
|
2008-09-22 14:28:18 +00:00
|
|
|
c->logicalIp = s->logicalIp;
|
2008-09-13 21:09:26 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
if (c->predecessor) {
|
2008-09-15 02:28:42 +00:00
|
|
|
c->state = s;
|
2008-09-20 23:42:46 +00:00
|
|
|
allocateTargets(c, s);
|
2008-09-07 20:12:11 +00:00
|
|
|
}
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
2008-03-13 23:43:11 +00:00
|
|
|
class Client: public Assembler::Client {
|
|
|
|
public:
|
|
|
|
Client(Context* c): c(c) { }
|
|
|
|
|
2008-05-06 21:13:02 +00:00
|
|
|
virtual int acquireTemporary(uint32_t mask) {
|
2008-05-12 13:54:47 +00:00
|
|
|
int r = pickRegister(c, mask)->number;
|
2008-04-30 15:44:17 +00:00
|
|
|
save(r);
|
2008-04-20 00:43:12 +00:00
|
|
|
increment(c, r);
|
2008-03-13 23:43:11 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void releaseTemporary(int r) {
|
2008-05-12 13:54:47 +00:00
|
|
|
decrement(c, c->registers[r]);
|
2008-04-30 15:44:17 +00:00
|
|
|
restore(r);
|
2008-03-13 23:43:11 +00:00
|
|
|
}
|
|
|
|
|
2008-04-27 20:15:18 +00:00
|
|
|
virtual void save(int r) {
|
2008-09-05 15:00:38 +00:00
|
|
|
// todo
|
|
|
|
expect(c, c->registers[r]->refCount == 0);
|
|
|
|
expect(c, c->registers[r]->value == 0);
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
2008-09-05 15:00:38 +00:00
|
|
|
virtual void restore(int) {
|
|
|
|
// todo
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
2008-03-13 23:43:11 +00:00
|
|
|
Context* c;
|
|
|
|
};
|
|
|
|
|
2007-12-08 23:22:13 +00:00
|
|
|
class MyCompiler: public Compiler {
|
|
|
|
public:
|
2008-05-31 22:14:27 +00:00
|
|
|
MyCompiler(System* s, Assembler* assembler, Zone* zone,
|
|
|
|
Compiler::Client* compilerClient):
|
|
|
|
c(s, assembler, zone, compilerClient), client(&c)
|
2008-03-13 23:43:11 +00:00
|
|
|
{
|
|
|
|
assembler->setClient(&client);
|
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
virtual State* saveState() {
|
|
|
|
return ::saveState(&c);
|
2008-04-28 15:53:48 +00:00
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
virtual void restoreState(State* state) {
|
|
|
|
::restoreState(&c, static_cast<MyState*>(state));
|
2008-04-28 15:53:48 +00:00
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
|
2008-08-23 18:04:36 +00:00
|
|
|
unsigned localFootprint, unsigned maxStackFootprint)
|
2008-05-19 04:31:52 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
c.logicalCodeLength = logicalCodeLength;
|
2008-05-19 04:31:52 +00:00
|
|
|
c.parameterFootprint = parameterFootprint;
|
|
|
|
c.localFootprint = localFootprint;
|
2008-08-23 18:04:36 +00:00
|
|
|
c.maxStackFootprint = maxStackFootprint;
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
c.logicalCode = static_cast<LogicalInstruction**>
|
|
|
|
(c.zone->allocate(sizeof(LogicalInstruction*) * logicalCodeLength));
|
|
|
|
memset(c.logicalCode, 0, sizeof(LogicalInstruction*) * logicalCodeLength);
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
c.locals = static_cast<Local*>
|
|
|
|
(c.zone->allocate(sizeof(Local) * localFootprint));
|
2008-09-09 00:31:19 +00:00
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
memset(c.locals, 0, sizeof(Local) * localFootprint);
|
2007-12-17 20:55:31 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void visitLogicalIp(unsigned logicalIp) {
|
2008-09-15 02:28:42 +00:00
|
|
|
assert(&c, logicalIp < c.logicalCodeLength);
|
|
|
|
|
|
|
|
Event* e = c.logicalCode[logicalIp]->firstEvent;
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
if (c.predecessor) {
|
|
|
|
c.predecessor->successors = cons(&c, e, c.predecessor->successors);
|
|
|
|
populateJunctionReads(&c, c.predecessor);
|
|
|
|
e->predecessors = cons(&c, c.predecessor, e->predecessors);
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void startLogicalIp(unsigned logicalIp) {
|
2008-09-15 02:28:42 +00:00
|
|
|
assert(&c, logicalIp < c.logicalCodeLength);
|
|
|
|
assert(&c, c.logicalCode[logicalIp] == 0);
|
|
|
|
|
2008-04-19 21:52:45 +00:00
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, " -- ip: %d\n", logicalIp);
|
|
|
|
}
|
2008-04-20 19:35:36 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
if (c.logicalIp >= 0 and c.logicalCode[c.logicalIp]->lastEvent == 0) {
|
|
|
|
appendDummy(&c);
|
|
|
|
}
|
2008-04-20 19:35:36 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
c.logicalCode[logicalIp] = new
|
|
|
|
(c.zone->allocate(sizeof(LogicalInstruction)))
|
|
|
|
LogicalInstruction(logicalIp, c.stack, c.locals);
|
2008-04-20 19:35:36 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c.logicalIp = logicalIp;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Promise* machineIp(unsigned logicalIp) {
|
|
|
|
return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp);
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Promise* poolAppend(intptr_t value) {
|
2008-03-13 20:50:56 +00:00
|
|
|
return poolAppendPromise(resolved(&c, value));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Promise* poolAppendPromise(Promise* value) {
|
|
|
|
Promise* p = new (c.zone->allocate(sizeof(PoolPromise)))
|
|
|
|
PoolPromise(&c, c.constantCount);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
ConstantPoolNode* constant
|
|
|
|
= new (c.zone->allocate(sizeof(ConstantPoolNode)))
|
|
|
|
ConstantPoolNode(value);
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (c.firstConstant) {
|
|
|
|
c.lastConstant->next = constant;
|
|
|
|
} else {
|
|
|
|
c.firstConstant = constant;
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
2008-02-11 17:21:41 +00:00
|
|
|
c.lastConstant = constant;
|
|
|
|
++ c.constantCount;
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
return p;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* constant(int64_t value) {
|
2008-03-13 20:50:56 +00:00
|
|
|
return promiseConstant(resolved(&c, value));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* promiseConstant(Promise* value) {
|
2008-04-20 19:35:36 +00:00
|
|
|
return ::value(&c, ::constantSite(&c, value));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* address(Promise* address) {
|
2008-04-20 19:35:36 +00:00
|
|
|
return value(&c, ::addressSite(&c, address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* memory(Operand* base,
|
|
|
|
int displacement = 0,
|
|
|
|
Operand* index = 0,
|
2008-04-13 19:48:20 +00:00
|
|
|
unsigned scale = 1)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-04-17 22:07:32 +00:00
|
|
|
Value* result = value(&c);
|
2008-03-15 23:54:20 +00:00
|
|
|
|
2008-04-17 20:48:26 +00:00
|
|
|
appendMemory(&c, static_cast<Value*>(base), displacement,
|
|
|
|
static_cast<Value*>(index), scale, result);
|
2008-03-15 23:54:20 +00:00
|
|
|
|
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* stack() {
|
2008-09-05 15:00:38 +00:00
|
|
|
Site* s = registerSite(&c, c.arch->stack());
|
2008-04-26 20:56:03 +00:00
|
|
|
return value(&c, s, s);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-09-05 15:00:38 +00:00
|
|
|
virtual Operand* thread() {
|
|
|
|
Site* s = registerSite(&c, c.arch->thread());
|
2008-04-26 20:56:03 +00:00
|
|
|
return value(&c, s, s);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-09-05 15:00:38 +00:00
|
|
|
virtual Operand* stackTop() {
|
2008-09-13 21:09:26 +00:00
|
|
|
Site* s = frameSite(&c, c.stack->index);
|
2008-04-26 20:56:03 +00:00
|
|
|
return value(&c, s, s);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
Promise* machineIp() {
|
2008-08-16 17:45:36 +00:00
|
|
|
return codePromise(&c, c.logicalCode[c.logicalIp]->lastEvent);
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
|
2008-04-26 20:56:03 +00:00
|
|
|
virtual void push(unsigned size) {
|
2008-04-27 20:15:18 +00:00
|
|
|
assert(&c, ceiling(size, BytesPerWord));
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
c.stack = ::stack(&c, value(&c), ceiling(size, BytesPerWord), c.stack);
|
2008-04-26 20:56:03 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void push(unsigned size, Operand* value) {
|
2008-04-17 20:48:26 +00:00
|
|
|
::push(&c, size, static_cast<Value*>(value));
|
2007-12-22 00:26:55 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* pop(unsigned size) {
|
|
|
|
return ::pop(&c, size);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
virtual void pushed() {
|
|
|
|
Value* v = value(&c);
|
2008-09-25 00:48:32 +00:00
|
|
|
appendFrameSite
|
|
|
|
(&c, v, BytesPerWord, (c.stack ? c.stack->index + c.stack->size : 0));
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
c.stack = ::stack(&c, v, 1, c.stack);
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
virtual void popped() {
|
2008-09-13 21:09:26 +00:00
|
|
|
c.stack = c.stack->next;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual StackElement* top() {
|
2008-09-13 21:09:26 +00:00
|
|
|
return c.stack;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual unsigned size(StackElement* e) {
|
2008-08-28 22:43:35 +00:00
|
|
|
return static_cast<Stack*>(e)->size;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual unsigned padding(StackElement* e) {
|
2008-08-28 22:43:35 +00:00
|
|
|
return static_cast<Stack*>(e)->padding;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-03-09 21:27:51 +00:00
|
|
|
virtual Operand* peek(unsigned size UNUSED, unsigned index) {
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* s = c.stack;
|
2008-02-17 20:57:40 +00:00
|
|
|
for (unsigned i = index; i > 0;) {
|
2008-08-28 22:43:35 +00:00
|
|
|
i -= s->size;
|
2008-04-29 16:55:56 +00:00
|
|
|
s = s->next;
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
2008-08-28 22:43:35 +00:00
|
|
|
assert(&c, s->size == ceiling(size, BytesPerWord));
|
2008-04-17 20:48:26 +00:00
|
|
|
return s->value;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* call(Operand* address,
|
|
|
|
unsigned flags,
|
|
|
|
TraceHandler* traceHandler,
|
2008-04-18 04:16:20 +00:00
|
|
|
unsigned resultSize,
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned argumentCount,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list a; va_start(a, argumentCount);
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned footprint = 0;
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned size = BytesPerWord;
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* arguments[argumentCount];
|
|
|
|
unsigned argumentSizes[argumentCount];
|
2008-09-05 15:00:38 +00:00
|
|
|
int index = 0;
|
2008-02-11 17:21:41 +00:00
|
|
|
for (unsigned i = 0; i < argumentCount; ++i) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* o = va_arg(a, Value*);
|
2008-02-12 02:06:12 +00:00
|
|
|
if (o) {
|
2008-04-17 20:48:26 +00:00
|
|
|
arguments[index] = o;
|
|
|
|
argumentSizes[index] = size;
|
2008-02-12 02:06:12 +00:00
|
|
|
size = BytesPerWord;
|
2008-04-17 20:48:26 +00:00
|
|
|
++ index;
|
2008-02-12 02:06:12 +00:00
|
|
|
} else {
|
|
|
|
size = 8;
|
|
|
|
}
|
|
|
|
++ footprint;
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
va_end(a);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* oldStack = c.stack;
|
2008-07-05 20:21:13 +00:00
|
|
|
Stack* bottomArgument = 0;
|
2008-04-18 03:47:42 +00:00
|
|
|
|
2008-04-29 16:40:44 +00:00
|
|
|
for (int i = index - 1; i >= 0; --i) {
|
2008-04-18 03:47:42 +00:00
|
|
|
::push(&c, argumentSizes[i], arguments[i]);
|
2008-07-05 20:21:13 +00:00
|
|
|
if (i == index - 1) {
|
2008-09-13 21:09:26 +00:00
|
|
|
bottomArgument = c.stack;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
2008-04-18 03:47:42 +00:00
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* argumentStack = c.stack;
|
|
|
|
c.stack = oldStack;
|
2008-04-18 03:47:42 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
|
2008-08-23 18:04:36 +00:00
|
|
|
resultSize, argumentStack, index, 0);
|
2008-07-05 20:21:13 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual Operand* stackCall(Operand* address,
|
|
|
|
unsigned flags,
|
|
|
|
TraceHandler* traceHandler,
|
|
|
|
unsigned resultSize,
|
|
|
|
unsigned argumentFootprint)
|
|
|
|
{
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
2008-07-05 20:21:13 +00:00
|
|
|
appendCall(&c, static_cast<Value*>(address), flags, traceHandler, result,
|
2008-09-13 21:09:26 +00:00
|
|
|
resultSize, c.stack, 0, argumentFootprint);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void return_(unsigned size, Operand* value) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendReturn(&c, size, static_cast<Value*>(value));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
virtual void initLocal(unsigned size, unsigned index) {
|
|
|
|
assert(&c, index < c.localFootprint);
|
2008-09-24 00:01:42 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
Value* v = value(&c);
|
2008-09-25 00:48:32 +00:00
|
|
|
// fprintf(stderr, "init local %p of size %d at %d\n", v, size, index);
|
|
|
|
appendFrameSite(&c, v, size, index);
|
2008-09-24 00:01:42 +00:00
|
|
|
|
|
|
|
Local* local = c.locals + index;
|
|
|
|
local->value = v;
|
|
|
|
local->size = size;
|
2008-09-09 00:31:19 +00:00
|
|
|
}
|
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
virtual void initLocalsFromLogicalIp(unsigned logicalIp) {
|
|
|
|
assert(&c, logicalIp < c.logicalCodeLength);
|
|
|
|
|
|
|
|
unsigned footprint = sizeof(Local) * c.localFootprint;
|
|
|
|
Local* newLocals = static_cast<Local*>(c.zone->allocate(footprint));
|
|
|
|
memset(newLocals, 0, footprint);
|
|
|
|
c.locals = newLocals;
|
2008-09-24 00:01:42 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
Event* e = c.logicalCode[logicalIp]->firstEvent;
|
|
|
|
for (unsigned i = 0; i < c.localFootprint; ++i) {
|
|
|
|
Local* local = e->locals + i;
|
|
|
|
if (local->value) {
|
|
|
|
initLocal(local->size, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void storeLocal(unsigned size, Operand* src, unsigned index) {
|
2008-05-19 04:31:52 +00:00
|
|
|
assert(&c, index < c.localFootprint);
|
2008-05-20 19:11:42 +00:00
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
unsigned footprint = sizeof(Local) * c.localFootprint;
|
|
|
|
Local* newLocals = static_cast<Local*>(c.zone->allocate(footprint));
|
|
|
|
memcpy(newLocals, c.locals, footprint);
|
2008-09-13 21:09:26 +00:00
|
|
|
c.locals = newLocals;
|
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
// fprintf(stderr, "store local %p of size %d at %d\n", src, size, index);
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
Local* local = c.locals + index;
|
|
|
|
local->value = static_cast<Value*>(src);
|
|
|
|
local->size = size;
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
virtual Operand* loadLocal(unsigned size UNUSED, unsigned index) {
|
2008-05-19 04:31:52 +00:00
|
|
|
assert(&c, index < c.localFootprint);
|
2008-09-24 00:01:42 +00:00
|
|
|
assert(&c, c.locals[index].value);
|
|
|
|
assert(&c, pad(c.locals[index].size) == pad(size));
|
2008-05-20 19:11:42 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
// fprintf(stderr, "load local %p of size %d at %d\n",
|
|
|
|
// c.locals[index].value, size, index);
|
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
return c.locals[index].value;
|
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)
|
|
|
|
{
|
|
|
|
appendBoundsCheck(&c, static_cast<Value*>(object),
|
|
|
|
lengthOffset, static_cast<Value*>(index), handler);
|
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void store(unsigned size, Operand* src, Operand* dst) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendMove(&c, Move, size, static_cast<Value*>(src),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(dst));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* load(unsigned size, Operand* src) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* dst = value(&c);
|
2008-09-05 15:00:38 +00:00
|
|
|
appendMove(&c, Move, size, static_cast<Value*>(src), size, dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
return dst;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* loadz(unsigned size, Operand* src) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* dst = value(&c);
|
2008-09-05 15:00:38 +00:00
|
|
|
appendMove(&c, MoveZ, size, static_cast<Value*>(src), size, dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
return dst;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual Operand* load4To8(Operand* src) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* dst = value(&c);
|
2008-09-05 15:00:38 +00:00
|
|
|
appendMove(&c, Move, 4, static_cast<Value*>(src), 8, dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
return dst;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-06-12 16:56:48 +00:00
|
|
|
virtual Operand* lcmp(Operand* a, Operand* b) {
|
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, LongCompare, 8, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
8, static_cast<Value*>(b), 8, result);
|
2008-06-12 16:56:48 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual void cmp(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendCompare(&c, size, static_cast<Value*>(a),
|
|
|
|
static_cast<Value*>(b));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jl(Operand* address) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendBranch(&c, JumpIfLess, static_cast<Value*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jg(Operand* address) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendBranch(&c, JumpIfGreater, static_cast<Value*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jle(Operand* address) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendBranch(&c, JumpIfLessOrEqual, static_cast<Value*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jge(Operand* address) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendBranch(&c, JumpIfGreaterOrEqual, static_cast<Value*>(address));
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void je(Operand* address) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendBranch(&c, JumpIfEqual, static_cast<Value*>(address));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jne(Operand* address) {
|
2008-04-17 20:48:26 +00:00
|
|
|
appendBranch(&c, JumpIfNotEqual, static_cast<Value*>(address));
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void jmp(Operand* address) {
|
2008-04-17 22:07:32 +00:00
|
|
|
appendBranch(&c, Jump, static_cast<Value*>(address));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* add(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, Add, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* sub(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, Subtract, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-23 00:00:35 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* mul(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, Multiply, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* div(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, Divide, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-22 00:26:55 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* rem(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, Remainder, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* shl(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
2008-09-05 15:00:38 +00:00
|
|
|
appendCombine(&c, ShiftLeft, BytesPerWord, static_cast<Value*>(a),
|
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* shr(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
2008-09-05 15:00:38 +00:00
|
|
|
appendCombine(&c, ShiftRight, BytesPerWord, static_cast<Value*>(a),
|
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* ushr(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
2008-09-05 15:00:38 +00:00
|
|
|
appendCombine(&c, UnsignedShiftRight, BytesPerWord, static_cast<Value*>(a),
|
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* and_(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, And, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* or_(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, Or, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-12 18:59:45 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* xor_(unsigned size, Operand* a, Operand* b) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendCombine(&c, Xor, size, static_cast<Value*>(a),
|
2008-09-05 15:00:38 +00:00
|
|
|
size, static_cast<Value*>(b), size, result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
virtual Operand* neg(unsigned size, Operand* a) {
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* result = value(&c);
|
|
|
|
appendTranslate(&c, Negate, size, static_cast<Value*>(a), result);
|
2008-02-11 17:21:41 +00:00
|
|
|
return result;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual unsigned compile() {
|
2008-09-23 21:18:41 +00:00
|
|
|
return c.machineCodeSize = ::compile(&c);
|
2007-12-11 23:52:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual unsigned poolSize() {
|
2008-03-11 16:40:28 +00:00
|
|
|
return c.constantCount * BytesPerWord;
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
virtual void writeTo(uint8_t* dst) {
|
|
|
|
c.machineCode = dst;
|
2008-09-05 15:00:38 +00:00
|
|
|
c.assembler->writeTo(dst);
|
2007-12-11 23:52:28 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
int i = 0;
|
|
|
|
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
|
2008-09-23 21:18:41 +00:00
|
|
|
*reinterpret_cast<intptr_t*>(dst + pad(c.machineCodeSize) + i)
|
2008-02-11 17:21:41 +00:00
|
|
|
= n->promise->value();
|
2008-04-20 19:35:36 +00:00
|
|
|
i += BytesPerWord;
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dispose() {
|
2008-02-11 17:21:41 +00:00
|
|
|
// ignore
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 20:03:21 +00:00
|
|
|
Context c;
|
2008-05-31 22:14:27 +00:00
|
|
|
::Client client;
|
2007-12-08 23:22:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
|
|
|
Compiler*
|
2008-05-06 21:13:02 +00:00
|
|
|
makeCompiler(System* system, Assembler* assembler, Zone* zone,
|
2008-05-31 22:14:27 +00:00
|
|
|
Compiler::Client* client)
|
2007-12-08 23:22:13 +00:00
|
|
|
{
|
2007-12-31 22:40:56 +00:00
|
|
|
return new (zone->allocate(sizeof(MyCompiler)))
|
2008-05-31 22:14:27 +00:00
|
|
|
MyCompiler(system, assembler, zone, client);
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
} // namespace vm
|