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-11-09 23:56:37 +00:00
|
|
|
const bool DebugAppend = false;
|
2009-01-11 23:46:36 +00:00
|
|
|
const bool DebugCompile = false;
|
|
|
|
const bool DebugResources = false;
|
2009-01-04 01:17:51 +00:00
|
|
|
const bool DebugFrame = false;
|
2009-01-11 23:46:36 +00:00
|
|
|
const bool DebugControl = false;
|
2009-01-04 01:17:51 +00:00
|
|
|
const bool DebugReads = false;
|
2008-12-12 01:09:36 +00:00
|
|
|
const bool DebugSites = false;
|
2009-01-04 22:58:05 +00:00
|
|
|
const bool DebugMoves = false;
|
2009-01-11 22:53:51 +00:00
|
|
|
const bool DebugBuddies = false;
|
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-10-12 00:23:08 +00:00
|
|
|
class ConstantSite;
|
|
|
|
class AddressSite;
|
2008-05-15 23:19:23 +00:00
|
|
|
class RegisterSite;
|
2008-09-28 21:56:12 +00:00
|
|
|
class MemorySite;
|
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;
|
2008-11-01 22:16:18 +00:00
|
|
|
class Snapshot;
|
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;
|
2008-11-02 22:25:51 +00:00
|
|
|
unsigned footprint;
|
2008-09-24 00:01:42 +00:00
|
|
|
};
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class Site {
|
|
|
|
public:
|
|
|
|
Site(): next(0) { }
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
virtual Site* readTarget(Context*, Read*) { return this; }
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context*, char*, unsigned) = 0;
|
2008-10-04 17:26:35 +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-12-21 21:41:56 +00:00
|
|
|
virtual void freeze(Context*, Value*, unsigned) { }
|
2008-05-12 13:54:47 +00:00
|
|
|
|
2008-12-21 21:41:56 +00:00
|
|
|
virtual void thaw(Context*, Value*, unsigned) { }
|
2008-05-12 13:54:47 +00:00
|
|
|
|
2009-01-04 20:35:09 +00:00
|
|
|
virtual bool frozen(Context*, unsigned) { return false; }
|
|
|
|
|
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
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
virtual Site* copy(Context*) = 0;
|
2008-10-04 17:26:35 +00:00
|
|
|
|
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-11-02 22:25:51 +00:00
|
|
|
Stack(unsigned index, unsigned footprint, Value* value, Stack* next):
|
2008-11-09 23:56:37 +00:00
|
|
|
index(index), footprint(footprint), value(value), next(next)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
unsigned index;
|
2008-11-02 22:25:51 +00:00
|
|
|
unsigned footprint;
|
2008-07-05 20:21:13 +00:00
|
|
|
Value* value;
|
2008-04-17 22:07:32 +00:00
|
|
|
Stack* next;
|
|
|
|
};
|
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
class SavedValue {
|
|
|
|
public:
|
|
|
|
SavedValue(unsigned footprint, Value* value, SavedValue* next):
|
|
|
|
footprint(footprint), value(value), next(next)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
unsigned footprint;
|
|
|
|
Value* value;
|
|
|
|
SavedValue* next;
|
|
|
|
};
|
|
|
|
|
2008-11-02 20:35:35 +00:00
|
|
|
class ForkElement {
|
2008-09-22 14:28:18 +00:00
|
|
|
public:
|
|
|
|
Value* value;
|
|
|
|
MultiRead* read;
|
2008-11-02 20:35:35 +00:00
|
|
|
bool local;
|
2008-09-22 14:28:18 +00:00
|
|
|
};
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
class ForkState: public Compiler::State {
|
2008-04-17 22:07:32 +00:00
|
|
|
public:
|
2008-11-07 00:39:38 +00:00
|
|
|
ForkState(Stack* stack, Local* locals, SavedValue* saved, Event* predecessor,
|
2008-10-14 00:18:18 +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-11-07 00:39:38 +00:00
|
|
|
saved(saved),
|
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-11-07 00:39:38 +00:00
|
|
|
SavedValue* saved;
|
2008-09-20 23:42:46 +00:00
|
|
|
Event* predecessor;
|
|
|
|
unsigned logicalIp;
|
|
|
|
unsigned readCount;
|
2008-11-02 20:35:35 +00:00
|
|
|
ForkElement elements[0];
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
2008-11-14 00:59:21 +00:00
|
|
|
class MySubroutine: public Compiler::Subroutine {
|
|
|
|
public:
|
|
|
|
MySubroutine(): forkState(0) { }
|
|
|
|
|
|
|
|
ForkState* forkState;
|
|
|
|
};
|
|
|
|
|
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),
|
2008-11-14 00:59:21 +00:00
|
|
|
locals(locals), machineOffset(0), subroutine(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-11-14 00:59:21 +00:00
|
|
|
MySubroutine* subroutine;
|
2008-08-30 20:12:27 +00:00
|
|
|
int index;
|
2008-04-17 22:07:32 +00:00
|
|
|
};
|
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
class Resource {
|
2008-04-17 22:07:32 +00:00
|
|
|
public:
|
2009-01-03 21:34:45 +00:00
|
|
|
Resource(bool reserved = false):
|
|
|
|
value(0), site(0), size(0), freezeCount(0), referenceCount(0),
|
|
|
|
reserved(reserved)
|
2009-01-03 00:44:47 +00:00
|
|
|
{ }
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
virtual void freeze(Context*, Value*) = 0;
|
|
|
|
|
|
|
|
virtual void thaw(Context*, Value*) = 0;
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context*, char*, unsigned) = 0;
|
2009-01-03 00:44:47 +00:00
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
Value* value;
|
2008-12-24 20:35:43 +00:00
|
|
|
Site* site;
|
2009-01-03 21:34:45 +00:00
|
|
|
uint8_t size;
|
|
|
|
uint8_t freezeCount;
|
|
|
|
uint8_t referenceCount;
|
|
|
|
bool reserved;
|
2008-09-28 21:56:12 +00:00
|
|
|
};
|
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
class RegisterResource: public Resource {
|
2008-09-28 21:56:12 +00:00
|
|
|
public:
|
2009-01-03 00:44:47 +00:00
|
|
|
RegisterResource(bool reserved):
|
2009-01-03 21:34:45 +00:00
|
|
|
Resource(reserved)
|
2009-01-03 00:44:47 +00:00
|
|
|
{ }
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
virtual void freeze(Context*, Value*);
|
|
|
|
|
|
|
|
virtual void thaw(Context*, Value*);
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context*, char*, unsigned);
|
2009-01-03 00:44:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class FrameResource: public Resource {
|
2009-01-11 18:48:02 +00:00
|
|
|
public:
|
|
|
|
virtual void freeze(Context*, Value*);
|
|
|
|
|
|
|
|
virtual void thaw(Context*, Value*);
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context*, char*, unsigned);
|
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-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-11-01 19:14:13 +00:00
|
|
|
reads(0), lastRead(0), sites(site), source(0), target(target), buddy(this),
|
2009-01-03 00:44:47 +00:00
|
|
|
home(NoFrameIndex)
|
2008-04-17 22:07:32 +00:00
|
|
|
{ }
|
2008-09-13 21:09:26 +00:00
|
|
|
|
|
|
|
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-11-01 19:14:13 +00:00
|
|
|
Value* buddy;
|
2009-01-03 00:44:47 +00:00
|
|
|
int8_t home;
|
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-11-07 00:39:38 +00:00
|
|
|
saved(0),
|
2008-09-20 23:42:46 +00:00
|
|
|
predecessor(0),
|
2008-04-17 22:07:32 +00:00
|
|
|
logicalCode(0),
|
2009-01-03 00:44:47 +00:00
|
|
|
registerResources
|
|
|
|
(static_cast<RegisterResource*>
|
|
|
|
(zone->allocate(sizeof(RegisterResource) * arch->registerCount()))),
|
2008-09-28 21:56:12 +00:00
|
|
|
frameResources(0),
|
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-10-14 00:18:18 +00:00
|
|
|
forkState(0),
|
2008-11-14 00:59:21 +00:00
|
|
|
subroutine(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),
|
2008-09-23 21:18:41 +00:00
|
|
|
machineCodeSize(0),
|
2008-09-28 19:00:52 +00:00
|
|
|
alignedFrameSize(0),
|
2009-01-11 18:48:02 +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) {
|
2009-01-03 00:44:47 +00:00
|
|
|
new (registerResources + i) RegisterResource(arch->reserved(i));
|
2009-01-11 18:48:02 +00:00
|
|
|
if (registerResources[i].reserved) {
|
|
|
|
-- 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-11-07 00:39:38 +00:00
|
|
|
SavedValue* saved;
|
2008-09-20 23:42:46 +00:00
|
|
|
Event* predecessor;
|
2008-08-16 17:45:36 +00:00
|
|
|
LogicalInstruction** logicalCode;
|
2009-01-03 00:44:47 +00:00
|
|
|
RegisterResource* registerResources;
|
2008-09-28 21:56:12 +00:00
|
|
|
FrameResource* frameResources;
|
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-10-14 00:18:18 +00:00
|
|
|
ForkState* forkState;
|
2008-11-14 00:59:21 +00:00
|
|
|
MySubroutine* subroutine;
|
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;
|
2008-09-23 21:18:41 +00:00
|
|
|
unsigned machineCodeSize;
|
2008-09-28 19:00:52 +00:00
|
|
|
unsigned alignedFrameSize;
|
2009-01-11 18:48:02 +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
|
|
|
};
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
unsigned
|
2009-01-03 21:34:45 +00:00
|
|
|
RegisterResource::toString(Context* c, char* buffer, unsigned bufferSize)
|
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf
|
|
|
|
(buffer, bufferSize, "register %"LD, this - c->registerResources);
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
unsigned
|
2009-01-03 21:34:45 +00:00
|
|
|
FrameResource::toString(Context* c, char* buffer, unsigned bufferSize)
|
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf(buffer, bufferSize, "frame %"LD, this - c->frameResources);
|
2009-01-03 21:34:45 +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-10-15 00:45:31 +00:00
|
|
|
Cell*
|
|
|
|
reverseDestroy(Cell* cell)
|
|
|
|
{
|
|
|
|
Cell* previous = 0;
|
|
|
|
while (cell) {
|
|
|
|
Cell* next = cell->next;
|
|
|
|
cell->next = previous;
|
|
|
|
previous = cell;
|
|
|
|
cell = next;
|
|
|
|
}
|
|
|
|
return previous;
|
|
|
|
}
|
|
|
|
|
2008-09-22 14:28:18 +00:00
|
|
|
class StubReadPair {
|
|
|
|
public:
|
|
|
|
Value* value;
|
|
|
|
StubRead* read;
|
|
|
|
};
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
class JunctionState {
|
2008-04-18 17:00:55 +00:00
|
|
|
public:
|
2008-12-15 14:35:19 +00:00
|
|
|
JunctionState(unsigned frameFootprint): frameFootprint(frameFootprint) { }
|
2008-04-18 17:00:55 +00:00
|
|
|
|
2008-12-15 14:35:19 +00:00
|
|
|
unsigned frameFootprint;
|
2008-10-14 00:18:18 +00:00
|
|
|
StubReadPair reads[0];
|
|
|
|
};
|
2008-09-07 01:37:12 +00:00
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
class Link {
|
|
|
|
public:
|
|
|
|
Link(Event* predecessor, Link* nextPredecessor, Event* successor,
|
|
|
|
Link* nextSuccessor, ForkState* forkState):
|
|
|
|
predecessor(predecessor), nextPredecessor(nextPredecessor),
|
|
|
|
successor(successor), nextSuccessor(nextSuccessor), forkState(forkState),
|
|
|
|
junctionState(0)
|
|
|
|
{ }
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
Event* predecessor;
|
|
|
|
Link* nextPredecessor;
|
|
|
|
Event* successor;
|
|
|
|
Link* nextSuccessor;
|
|
|
|
ForkState* forkState;
|
|
|
|
JunctionState* junctionState;
|
|
|
|
};
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
Link*
|
|
|
|
link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor,
|
|
|
|
Link* nextSuccessor, ForkState* forkState)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Link))) Link
|
|
|
|
(predecessor, nextPredecessor, successor, nextSuccessor, forkState);
|
|
|
|
}
|
2008-04-18 17:00:55 +00:00
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
unsigned
|
|
|
|
countPredecessors(Link* link)
|
|
|
|
{
|
|
|
|
unsigned c = 0;
|
|
|
|
for (; link; link = link->nextPredecessor) ++ c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
Link*
|
|
|
|
lastPredecessor(Link* link)
|
|
|
|
{
|
|
|
|
while (link->nextPredecessor) link = link->nextPredecessor;
|
|
|
|
return link;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
countSuccessors(Link* link)
|
|
|
|
{
|
|
|
|
unsigned c = 0;
|
|
|
|
for (; link; link = link->nextSuccessor) ++ c;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
class Event {
|
|
|
|
public:
|
|
|
|
Event(Context* c):
|
|
|
|
next(0), stackBefore(c->stack), localsBefore(c->locals),
|
|
|
|
stackAfter(0), localsAfter(0), promises(0), reads(0),
|
2008-11-01 22:16:18 +00:00
|
|
|
junctionSites(0), snapshots(0), predecessors(0), successors(0),
|
2008-10-15 00:45:31 +00:00
|
|
|
visitLinks(0), block(0), logicalInstruction(c->logicalCode[c->logicalIp]),
|
2008-10-14 00:18:18 +00:00
|
|
|
readCount(0)
|
|
|
|
{ }
|
2008-04-18 17:00:55 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
virtual const char* name() = 0;
|
2008-04-18 17:00:55 +00:00
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
virtual void compile(Context* c) = 0;
|
2008-08-30 20:12:27 +00:00
|
|
|
|
2008-10-08 00:08:13 +00:00
|
|
|
virtual bool isBranch() { return false; }
|
|
|
|
|
2008-04-18 17:00:55 +00:00
|
|
|
Event* next;
|
2008-10-04 17:26:35 +00:00
|
|
|
Stack* stackBefore;
|
|
|
|
Local* localsBefore;
|
|
|
|
Stack* stackAfter;
|
|
|
|
Local* localsAfter;
|
2008-04-18 17:00:55 +00:00
|
|
|
CodePromise* promises;
|
|
|
|
Read* reads;
|
2008-08-30 20:12:27 +00:00
|
|
|
Site** junctionSites;
|
2008-11-01 22:16:18 +00:00
|
|
|
Snapshot* snapshots;
|
2008-10-14 00:18:18 +00:00
|
|
|
Link* predecessors;
|
|
|
|
Link* successors;
|
2008-10-15 00:45:31 +00:00
|
|
|
Cell* visitLinks;
|
2008-08-30 20:12:27 +00:00
|
|
|
Block* block;
|
|
|
|
LogicalInstruction* logicalInstruction;
|
2008-05-15 14:29:19 +00:00
|
|
|
unsigned readCount;
|
2008-04-18 17:00:55 +00:00
|
|
|
};
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
int
|
2008-11-02 22:25:51 +00:00
|
|
|
frameIndex(Context* c, int index, unsigned footprint)
|
2008-05-19 04:31:52 +00:00
|
|
|
{
|
2009-01-03 21:34:45 +00:00
|
|
|
assert(c, static_cast<int>
|
|
|
|
(c->alignedFrameSize + c->parameterFootprint - index - footprint)
|
|
|
|
>= 0);
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
return c->alignedFrameSize + c->parameterFootprint - index - footprint;
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-10-25 02:12:02 +00:00
|
|
|
unsigned
|
|
|
|
frameIndexToOffset(Context* c, unsigned frameIndex)
|
2008-09-28 21:56:12 +00:00
|
|
|
{
|
2008-10-25 02:12:02 +00:00
|
|
|
return ((frameIndex >= c->alignedFrameSize) ?
|
|
|
|
(frameIndex
|
|
|
|
+ (c->arch->frameFooterSize() * 2)
|
|
|
|
+ c->arch->frameHeaderSize()) :
|
|
|
|
(frameIndex
|
|
|
|
+ c->arch->frameFooterSize())) * BytesPerWord;
|
|
|
|
}
|
2008-09-28 21:56:12 +00:00
|
|
|
|
2008-10-25 02:12:02 +00:00
|
|
|
unsigned
|
|
|
|
offsetToFrameIndex(Context* c, unsigned offset)
|
|
|
|
{
|
|
|
|
unsigned normalizedOffset = offset / BytesPerWord;
|
2008-09-28 21:56:12 +00:00
|
|
|
|
2008-10-25 02:12:02 +00:00
|
|
|
return ((normalizedOffset
|
|
|
|
>= c->alignedFrameSize
|
|
|
|
+ c->arch->frameFooterSize()) ?
|
|
|
|
(normalizedOffset
|
|
|
|
- (c->arch->frameFooterSize() * 2)
|
|
|
|
- c->arch->frameHeaderSize()) :
|
|
|
|
(normalizedOffset
|
|
|
|
- c->arch->frameFooterSize()));
|
2008-09-28 21:56:12 +00:00
|
|
|
}
|
|
|
|
|
2008-11-01 19:14:13 +00:00
|
|
|
class FrameIterator {
|
|
|
|
public:
|
|
|
|
class Element {
|
|
|
|
public:
|
2008-11-02 22:25:51 +00:00
|
|
|
Element(Value* value, unsigned localIndex, unsigned footprint):
|
|
|
|
value(value), localIndex(localIndex), footprint(footprint)
|
2008-11-01 19:14:13 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
Value* const value;
|
|
|
|
const unsigned localIndex;
|
2008-11-02 22:25:51 +00:00
|
|
|
const unsigned footprint;
|
2008-11-01 19:14:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
FrameIterator(Context* c, Stack* stack, Local* locals):
|
|
|
|
stack(stack), locals(locals), localIndex(c->localFootprint - 1)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
bool hasMore() {
|
|
|
|
while (localIndex >= 0 and locals[localIndex].value == 0) -- localIndex;
|
|
|
|
|
|
|
|
return stack != 0 or localIndex >= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Element next(Context* c) {
|
|
|
|
Value* v;
|
|
|
|
unsigned li;
|
2008-11-02 22:25:51 +00:00
|
|
|
unsigned footprint;
|
2008-11-01 19:14:13 +00:00
|
|
|
if (stack) {
|
|
|
|
Stack* s = stack;
|
|
|
|
v = s->value;
|
|
|
|
li = s->index + c->localFootprint;
|
2008-11-02 22:25:51 +00:00
|
|
|
footprint = s->footprint;
|
2008-11-01 19:14:13 +00:00
|
|
|
stack = stack->next;
|
|
|
|
} else {
|
|
|
|
Local* l = locals + localIndex;
|
|
|
|
v = l->value;
|
|
|
|
li = localIndex;
|
2008-11-02 22:25:51 +00:00
|
|
|
footprint = l->footprint;
|
2008-11-01 19:14:13 +00:00
|
|
|
-- localIndex;
|
|
|
|
}
|
2008-11-02 22:25:51 +00:00
|
|
|
return Element(v, li, footprint);
|
2008-11-01 19:14:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Stack* stack;
|
|
|
|
Local* locals;
|
|
|
|
int localIndex;
|
|
|
|
};
|
|
|
|
|
|
|
|
int
|
|
|
|
frameIndex(Context* c, FrameIterator::Element* element)
|
|
|
|
{
|
2008-11-02 22:25:51 +00:00
|
|
|
return frameIndex(c, element->localIndex, element->footprint);
|
2008-11-01 19:14:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class SiteIterator {
|
|
|
|
public:
|
2008-11-02 20:35:35 +00:00
|
|
|
SiteIterator(Value* v, bool includeBuddies = true):
|
2008-11-01 19:14:13 +00:00
|
|
|
originalValue(v),
|
|
|
|
currentValue(v),
|
2008-11-02 20:35:35 +00:00
|
|
|
includeBuddies(includeBuddies),
|
2008-11-01 19:14:13 +00:00
|
|
|
next_(findNext(&(v->sites))),
|
|
|
|
previous(0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Site** findNext(Site** p) {
|
|
|
|
if (*p) {
|
|
|
|
return p;
|
|
|
|
} else {
|
2008-11-02 20:35:35 +00:00
|
|
|
if (includeBuddies) {
|
|
|
|
for (Value* v = currentValue->buddy;
|
|
|
|
v != originalValue;
|
|
|
|
v = v->buddy)
|
|
|
|
{
|
|
|
|
if (v->sites) {
|
|
|
|
currentValue = v;
|
|
|
|
return &(v->sites);
|
|
|
|
}
|
2008-11-01 19:14:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasMore() {
|
|
|
|
if (previous) {
|
|
|
|
next_ = findNext(&((*previous)->next));
|
|
|
|
previous = 0;
|
|
|
|
}
|
|
|
|
return next_ != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Site* next() {
|
|
|
|
previous = next_;
|
|
|
|
return *previous;
|
|
|
|
}
|
|
|
|
|
|
|
|
void remove(Context* c) {
|
|
|
|
(*previous)->release(c);
|
|
|
|
*previous = (*previous)->next;
|
|
|
|
next_ = findNext(previous);
|
|
|
|
previous = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value* originalValue;
|
|
|
|
Value* currentValue;
|
2008-11-02 20:35:35 +00:00
|
|
|
bool includeBuddies;
|
2008-11-01 19:14:13 +00:00
|
|
|
Site** next_;
|
|
|
|
Site** previous;
|
|
|
|
};
|
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
bool
|
|
|
|
hasMoreThanOneSite(Value* v)
|
|
|
|
{
|
|
|
|
SiteIterator it(v);
|
|
|
|
if (it.hasMore()) {
|
|
|
|
it.next();
|
|
|
|
return it.hasMore();
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
hasSite(Value* v)
|
|
|
|
{
|
|
|
|
SiteIterator it(v);
|
|
|
|
return it.hasMore();
|
|
|
|
}
|
|
|
|
|
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-12-12 01:09:36 +00:00
|
|
|
if (DebugSites) {
|
|
|
|
char buffer[256]; s->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "add site %s to %p\n", buffer, 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
|
|
|
{
|
2008-11-01 19:14:13 +00:00
|
|
|
for (SiteIterator it(v); it.hasMore();) {
|
|
|
|
if (s == it.next()) {
|
2008-12-12 01:09:36 +00:00
|
|
|
if (DebugSites) {
|
|
|
|
char buffer[256]; s->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "remove site %s from %p\n", buffer, v);
|
|
|
|
}
|
2008-11-01 19:14:13 +00:00
|
|
|
it.remove(c);
|
2008-04-30 15:44:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-12-12 01:09:36 +00:00
|
|
|
if (DebugSites) {
|
|
|
|
fprintf(stderr, "%p has more: %d\n", v, hasSite(v));
|
|
|
|
}
|
|
|
|
assert(c, not findSite(c, v, s));
|
2008-04-30 15:44:17 +00:00
|
|
|
}
|
|
|
|
|
2008-04-19 07:03:59 +00:00
|
|
|
void
|
|
|
|
clearSites(Context* c, Value* v)
|
|
|
|
{
|
2008-12-12 01:09:36 +00:00
|
|
|
if (DebugSites) {
|
|
|
|
fprintf(stderr, "clear sites for %p\n", v);
|
|
|
|
}
|
2008-11-01 22:16:18 +00:00
|
|
|
for (SiteIterator it(v); it.hasMore();) {
|
|
|
|
it.next();
|
|
|
|
it.remove(c);
|
2008-04-19 07:03:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
bool
|
|
|
|
valid(Read* r)
|
|
|
|
{
|
|
|
|
return r and r->valid();
|
|
|
|
}
|
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
Read*
|
2008-07-05 20:21:13 +00:00
|
|
|
live(Value* v)
|
|
|
|
{
|
2009-01-11 22:53:51 +00:00
|
|
|
Value* p = v;
|
|
|
|
do {
|
|
|
|
if (valid(p->reads)) {
|
|
|
|
return p->reads;
|
|
|
|
}
|
|
|
|
p = p->buddy;
|
|
|
|
} while (p != v);
|
2008-11-01 19:14:13 +00:00
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
return 0;
|
2008-11-01 19:14:13 +00:00
|
|
|
}
|
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
Read*
|
2008-11-01 19:14:13 +00:00
|
|
|
liveNext(Context* c, Value* v)
|
|
|
|
{
|
2008-11-01 22:16:18 +00:00
|
|
|
Read* r = v->reads->next(c);
|
|
|
|
if (valid(r)) return r;
|
2008-11-01 19:14:13 +00:00
|
|
|
|
|
|
|
for (Value* p = v->buddy; p != v; p = p->buddy) {
|
2008-11-01 22:16:18 +00:00
|
|
|
if (valid(p->reads)) return p->reads;
|
2008-11-01 19:14:13 +00:00
|
|
|
}
|
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
return 0;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
void
|
|
|
|
deadBuddy(Context* c, Value* v, Read* r)
|
|
|
|
{
|
|
|
|
assert(c, v->buddy != v);
|
|
|
|
assert(c, r);
|
|
|
|
|
|
|
|
if (DebugBuddies) {
|
2009-01-11 23:24:25 +00:00
|
|
|
fprintf(stderr, "remove dead buddy %p from", v);
|
2009-01-11 22:53:51 +00:00
|
|
|
for (Value* p = v->buddy; p != v; p = p->buddy) {
|
|
|
|
fprintf(stderr, " %p", p);
|
|
|
|
}
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
Value* next = v->buddy;
|
|
|
|
v->buddy = v;
|
|
|
|
Value* p = next;
|
|
|
|
while (p->buddy != v) p = p->buddy;
|
|
|
|
p->buddy = next;
|
|
|
|
|
|
|
|
for (SiteIterator it(v); it.hasMore();) {
|
|
|
|
Site* s = it.next();
|
|
|
|
it.remove(c);
|
|
|
|
|
|
|
|
addSite(c, 0, 0, r->size, next, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-19 00:19:45 +00:00
|
|
|
void
|
2008-11-12 01:09:45 +00:00
|
|
|
nextRead(Context* c, Event* e UNUSED, Value* v)
|
2008-04-19 00:19:45 +00:00
|
|
|
{
|
2008-09-25 00:48:32 +00:00
|
|
|
assert(c, e == v->reads->event);
|
|
|
|
|
2008-12-12 01:09:36 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "pop read %p from %p next %p event %p (%s)\n",
|
|
|
|
v->reads, v, v->reads->next(c), e, (e ? e->name() : 0));
|
|
|
|
}
|
2008-04-19 07:03:59 +00:00
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
v->reads = v->reads->next(c);
|
2009-01-11 22:53:51 +00:00
|
|
|
|
|
|
|
if (not valid(v->reads)) {
|
|
|
|
Read* r = live(v);
|
|
|
|
if (r) {
|
|
|
|
deadBuddy(c, v, r);
|
|
|
|
} else {
|
|
|
|
clearSites(c, v);
|
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
bool
|
|
|
|
buddies(Value* a, Value* b)
|
|
|
|
{
|
|
|
|
if (a == b) return true;
|
|
|
|
for (Value* p = a->buddy; p != a; p = p->buddy) {
|
|
|
|
if (p == b) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
increment(Context* c, Resource* r)
|
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
if (not r->reserved) {
|
|
|
|
if (DebugResources) {
|
|
|
|
char buffer[256]; r->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "increment %s to %d\n", buffer, r->referenceCount + 1);
|
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
++ r->referenceCount;
|
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
decrement(Context* c, Resource* r)
|
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
if (not r->reserved) {
|
|
|
|
if (DebugResources) {
|
|
|
|
char buffer[256]; r->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "decrement %s to %d\n", buffer, r->referenceCount - 1);
|
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
assert(c, r->referenceCount > 0);
|
2009-01-03 21:34:45 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
-- r->referenceCount;
|
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-01-11 18:48:02 +00:00
|
|
|
freezeResource(Context* c, Resource* r, Value* v)
|
2009-01-03 21:34:45 +00:00
|
|
|
{
|
2009-01-11 18:48:02 +00:00
|
|
|
if (DebugResources) {
|
|
|
|
char buffer[256]; r->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "%p freeze %s to %d\n", v, buffer, r->freezeCount + 1);
|
|
|
|
}
|
2009-01-04 01:17:51 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
assert(c, r->value == 0 or buddies(r->value, v));
|
2009-01-04 01:17:51 +00:00
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
++ r->freezeCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RegisterResource::freeze(Context* c, Value* v)
|
|
|
|
{
|
|
|
|
if (not reserved) {
|
|
|
|
freezeResource(c, this, v);
|
|
|
|
|
|
|
|
if (freezeCount == 1) {
|
|
|
|
assert(c, c->availableRegisterCount);
|
|
|
|
-- c->availableRegisterCount;
|
2009-01-11 22:53:51 +00:00
|
|
|
|
|
|
|
if (DebugResources) {
|
|
|
|
fprintf(stderr, "%d registers available\n", c->availableRegisterCount);
|
|
|
|
}
|
2009-01-11 18:48:02 +00:00
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-01-11 18:48:02 +00:00
|
|
|
FrameResource::freeze(Context* c, Value* v)
|
|
|
|
{
|
|
|
|
freezeResource(c, this, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
thawResource(Context* c, Resource* r, Value* v)
|
2009-01-03 21:34:45 +00:00
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
if (not r->reserved) {
|
|
|
|
if (DebugResources) {
|
|
|
|
char buffer[256]; r->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "%p thaw %s to %d\n", v, buffer, r->freezeCount - 1);
|
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
assert(c, r->freezeCount);
|
2009-01-11 22:53:51 +00:00
|
|
|
assert(c, r->value == 0 or buddies(r->value, v));
|
2009-01-03 21:34:45 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
-- r->freezeCount;
|
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
void
|
|
|
|
RegisterResource::thaw(Context* c, Value* v)
|
|
|
|
{
|
|
|
|
if (not reserved) {
|
|
|
|
thawResource(c, this, v);
|
|
|
|
|
|
|
|
if (freezeCount == 0) {
|
|
|
|
++ c->availableRegisterCount;
|
2009-01-11 22:53:51 +00:00
|
|
|
|
|
|
|
if (DebugResources) {
|
|
|
|
fprintf(stderr, "%d registers available\n", c->availableRegisterCount);
|
|
|
|
}
|
2009-01-11 18:48:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FrameResource::thaw(Context* c, Value* v)
|
|
|
|
{
|
|
|
|
thawResource(c, this, v);
|
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
class Target {
|
|
|
|
public:
|
|
|
|
static const int FrameIndex = -2;
|
2009-01-11 23:42:41 +00:00
|
|
|
static const unsigned Impossible = 5;
|
2009-01-03 21:34:45 +00:00
|
|
|
|
|
|
|
Target(): cost(Impossible) { }
|
|
|
|
|
|
|
|
Target(int low, int high, unsigned cost):
|
|
|
|
low(low), high(high), cost(cost)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
int16_t low;
|
|
|
|
int8_t high;
|
|
|
|
uint8_t cost;
|
|
|
|
};
|
|
|
|
|
|
|
|
Target
|
2009-01-11 18:48:02 +00:00
|
|
|
pickTarget(Context* c, Read* r, bool intersectRead, bool acceptLastRegister);
|
2009-01-03 21:34:45 +00:00
|
|
|
|
|
|
|
unsigned
|
|
|
|
resourceCost(Context* c, Value* v, Resource* r)
|
|
|
|
{
|
|
|
|
if (r->reserved or r->freezeCount or r->referenceCount) {
|
|
|
|
return Target::Impossible;
|
2009-01-04 22:58:05 +00:00
|
|
|
} else if (r->value) {
|
2009-01-03 21:34:45 +00:00
|
|
|
assert(c, findSite(c, r->value, r->site));
|
|
|
|
|
2009-01-04 19:34:38 +00:00
|
|
|
if (v and buddies(r->value, v)) {
|
2009-01-03 21:34:45 +00:00
|
|
|
return 0;
|
2009-01-04 19:34:38 +00:00
|
|
|
} else if (hasMoreThanOneSite(r->value)) {
|
2009-01-03 21:34:45 +00:00
|
|
|
return 1;
|
2009-01-04 19:34:38 +00:00
|
|
|
} else {
|
|
|
|
return 2;
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
pickRegisterTarget(Context* c, Value* v, uint32_t mask, unsigned* cost)
|
|
|
|
{
|
|
|
|
int target = NoRegister;
|
|
|
|
unsigned bestCost = Target::Impossible;
|
|
|
|
for (int i = c->arch->registerCount() - 1; i >= 0; --i) {
|
|
|
|
if ((1 << i) & mask) {
|
|
|
|
RegisterResource* r = c->registerResources + i;
|
|
|
|
unsigned myCost = resourceCost(c, v, r);
|
|
|
|
if ((static_cast<uint32_t>(1) << i) == mask) {
|
|
|
|
*cost = myCost;
|
|
|
|
return i;
|
|
|
|
} else if (myCost < bestCost) {
|
|
|
|
bestCost = myCost;
|
|
|
|
target = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*cost = bestCost;
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
Target
|
|
|
|
pickRegisterTarget(Context* c, Value* v, uint64_t mask, unsigned size)
|
|
|
|
{
|
|
|
|
unsigned lowCost;
|
|
|
|
int low = pickRegisterTarget(c, v, mask, &lowCost);
|
|
|
|
if (lowCost >= Target::Impossible) {
|
|
|
|
return Target();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned highCost;
|
|
|
|
int high;
|
|
|
|
if (size > BytesPerWord) {
|
|
|
|
increment(c, c->registerResources + low);
|
|
|
|
|
2009-01-11 23:42:41 +00:00
|
|
|
high = pickRegisterTarget(c, v, mask >> 32, &highCost);
|
2009-01-03 21:34:45 +00:00
|
|
|
|
|
|
|
decrement(c, c->registerResources + low);
|
|
|
|
|
|
|
|
if (highCost >= Target::Impossible) {
|
|
|
|
return Target();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
highCost = 0;
|
|
|
|
high = NoRegister;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Target(low, high, lowCost + highCost);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
frameCost(Context* c, Value* v, int frameIndex, unsigned size)
|
|
|
|
{
|
|
|
|
unsigned lowCost = resourceCost(c, v, c->frameResources + frameIndex);
|
|
|
|
if (lowCost >= Target::Impossible) {
|
|
|
|
return Target::Impossible;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned highCost;
|
|
|
|
if (size > BytesPerWord) {
|
|
|
|
increment(c, c->frameResources + frameIndex);
|
|
|
|
|
|
|
|
highCost = resourceCost(c, v, c->frameResources + frameIndex + 1);
|
|
|
|
|
|
|
|
decrement(c, c->frameResources + frameIndex);
|
|
|
|
|
|
|
|
if (highCost >= Target::Impossible) {
|
|
|
|
return Target::Impossible;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
highCost = 0;
|
|
|
|
}
|
|
|
|
|
2009-01-04 20:35:09 +00:00
|
|
|
return lowCost + highCost + 1;
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Target
|
|
|
|
pickFrameTarget(Context* c, Value* v, unsigned size)
|
|
|
|
{
|
|
|
|
Target best;
|
|
|
|
|
|
|
|
Value* p = v;
|
|
|
|
do {
|
|
|
|
if (p->home >= 0) {
|
|
|
|
Target mine(p->home, Target::FrameIndex, frameCost(c, v, p->home, size));
|
|
|
|
if (mine.cost == 0) {
|
|
|
|
return mine;
|
|
|
|
} else if (mine.cost < best.cost) {
|
|
|
|
best = mine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p = p->buddy;
|
|
|
|
} while (p != v);
|
|
|
|
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
|
|
|
Target
|
2009-01-11 18:48:02 +00:00
|
|
|
pickTarget(Context* c, Read* read, bool intersectRead, bool acceptLastRegister)
|
2009-01-03 21:34:45 +00:00
|
|
|
{
|
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0);
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
read->intersect(&typeMask, ®isterMask, &frameIndex);
|
2009-01-11 18:48:02 +00:00
|
|
|
|
|
|
|
bool tryRegister = acceptLastRegister
|
|
|
|
or (c->availableRegisterCount > ceiling(read->size, BytesPerWord));
|
2009-01-03 21:34:45 +00:00
|
|
|
|
|
|
|
Target best;
|
2009-01-11 18:48:02 +00:00
|
|
|
if (tryRegister and (typeMask & (1 << RegisterOperand))) {
|
2009-01-03 21:34:45 +00:00
|
|
|
Target mine = pickRegisterTarget(c, read->value, registerMask, read->size);
|
|
|
|
if (mine.cost == 0) {
|
|
|
|
return mine;
|
|
|
|
} else if (mine.cost < best.cost) {
|
|
|
|
best = mine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((typeMask & (1 << MemoryOperand)) && frameIndex >= 0) {
|
|
|
|
Target mine(frameIndex, Target::FrameIndex,
|
|
|
|
frameCost(c, read->value, frameIndex, read->size));
|
|
|
|
if (mine.cost == 0) {
|
|
|
|
return mine;
|
|
|
|
} else if (mine.cost < best.cost) {
|
|
|
|
best = mine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
if (intersectRead) {
|
2009-01-03 21:34:45 +00:00
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
if (tryRegister) {
|
|
|
|
Target mine = pickRegisterTarget
|
2009-01-03 21:34:45 +00:00
|
|
|
(c, read->value, ~static_cast<uint64_t>(0), read->size);
|
|
|
|
if (mine.cost == 0) {
|
|
|
|
return mine;
|
|
|
|
} else if (mine.cost < best.cost) {
|
|
|
|
best = mine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{ Target mine = pickFrameTarget(c, read->value, read->size);
|
|
|
|
if (mine.cost == 0) {
|
|
|
|
return mine;
|
|
|
|
} else if (mine.cost < best.cost) {
|
|
|
|
best = mine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
acquire(Context* c, Resource* r, unsigned newSize, Value* newValue,
|
|
|
|
Site* newSite, Stack* stack, Local* locals);
|
|
|
|
|
|
|
|
void
|
|
|
|
release(Context* c, Resource* r);
|
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
ConstantSite*
|
|
|
|
constantSite(Context* c, Promise* value);
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class ConstantSite: public Site {
|
|
|
|
public:
|
|
|
|
ConstantSite(Promise* value): value(value) { }
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
|
2008-10-04 17:26:35 +00:00
|
|
|
if (value.value->resolved()) {
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf
|
|
|
|
(buffer, bufferSize, "constant %"LLD, value.value->value());
|
2008-10-04 17:26:35 +00:00
|
|
|
} else {
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf(buffer, bufferSize, "constant unresolved");
|
2008-10-04 17:26:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-18 18:36:57 +00:00
|
|
|
virtual unsigned copyCost(Context*, Site* s) {
|
2009-01-04 01:17:51 +00:00
|
|
|
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 << 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;
|
|
|
|
}
|
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
virtual Site* copy(Context* c) {
|
|
|
|
return constantSite(c, value.value);
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
AddressSite*
|
|
|
|
addressSite(Context* c, Promise* address);
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class AddressSite: public Site {
|
|
|
|
public:
|
|
|
|
AddressSite(Promise* address): address(address) { }
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) {
|
2008-10-04 17:26:35 +00:00
|
|
|
if (address.address->resolved()) {
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf
|
|
|
|
(buffer, bufferSize, "address %"LLD, address.address->value());
|
2008-10-04 17:26:35 +00:00
|
|
|
} else {
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf(buffer, bufferSize, "address unresolved");
|
2008-10-04 17:26:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-18 18:36:57 +00:00
|
|
|
virtual unsigned copyCost(Context*, Site* s) {
|
2009-01-04 01:17:51 +00:00
|
|
|
return (s == this ? 0 : 2);
|
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;
|
|
|
|
}
|
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
virtual Site* copy(Context* c) {
|
|
|
|
return addressSite(c, address.address);
|
|
|
|
}
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
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
|
2009-01-03 00:44:47 +00:00
|
|
|
acquire(Context* c, Resource* r, unsigned newSize, Value* newValue,
|
|
|
|
Site* newSite, Stack* stack, Local* locals);
|
2008-05-15 00:04:25 +00:00
|
|
|
|
|
|
|
void
|
2009-01-03 00:44:47 +00:00
|
|
|
release(Context* c, Resource* r);
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
RegisterSite*
|
|
|
|
freeRegisterSite(Context* c, uint64_t mask = ~static_cast<uint64_t>(0));
|
|
|
|
|
2008-04-16 20:58:21 +00:00
|
|
|
class RegisterSite: public Site {
|
|
|
|
public:
|
2009-01-03 00:44:47 +00:00
|
|
|
RegisterSite(uint64_t mask, RegisterResource* low = 0,
|
|
|
|
RegisterResource* high = 0):
|
2008-05-13 17:27:57 +00:00
|
|
|
mask(mask), low(low), high(high), register_(NoRegister, NoRegister)
|
2008-05-12 13:54:47 +00:00
|
|
|
{ }
|
|
|
|
|
2008-12-24 20:35:43 +00:00
|
|
|
void sync(Context* c) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
register_.low = low - c->registerResources;
|
|
|
|
register_.high = (high? high - c->registerResources : NoRegister);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize) {
|
2008-10-04 17:26:35 +00:00
|
|
|
if (low) {
|
|
|
|
sync(c);
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf(buffer, bufferSize, "%p register %d %d",
|
|
|
|
this, register_.low, register_.high);
|
2008-10-04 17:26:35 +00:00
|
|
|
} else {
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf(buffer, bufferSize, "%p register unacquired", this);
|
2008-10-04 17:26:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 {
|
2009-01-04 01:17:51 +00:00
|
|
|
return 1;
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2009-01-03 21:34:45 +00:00
|
|
|
Target target;
|
|
|
|
if (low) {
|
|
|
|
target = Target(low - c->registerResources,
|
|
|
|
high ? high - c->registerResources : NoRegister,
|
|
|
|
0);
|
|
|
|
} else {
|
|
|
|
target = pickRegisterTarget(c, v, mask, size);
|
|
|
|
expect(c, target.cost < Target::Impossible);
|
|
|
|
}
|
2009-01-03 00:44:47 +00:00
|
|
|
|
|
|
|
low = c->registerResources + target.low;
|
|
|
|
::acquire(c, low, size, v, this, stack, locals);
|
2008-05-20 22:47:53 +00:00
|
|
|
if (size > BytesPerWord) {
|
2009-01-11 18:48:02 +00:00
|
|
|
low->freeze(c, v);
|
2009-01-03 00:44:47 +00:00
|
|
|
|
|
|
|
high = c->registerResources + target.high;
|
|
|
|
::acquire(c, high, size, v, this, stack, locals);
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
low->thaw(c, v);
|
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-12-21 21:41:56 +00:00
|
|
|
virtual void freeze(Context* c, Value* v, unsigned size) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
low->freeze(c, v);
|
2008-12-21 21:41:56 +00:00
|
|
|
if (size > BytesPerWord) {
|
2009-01-11 18:48:02 +00:00
|
|
|
high->freeze(c, v);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-21 21:41:56 +00:00
|
|
|
virtual void thaw(Context* c, Value* v, unsigned size) {
|
2008-05-12 13:54:47 +00:00
|
|
|
assert(c, low);
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
low->thaw(c, v);
|
2008-12-21 21:41:56 +00:00
|
|
|
if (size > BytesPerWord) {
|
2009-01-11 18:48:02 +00:00
|
|
|
high->thaw(c, v);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2009-01-04 20:35:09 +00:00
|
|
|
virtual bool frozen(Context* c UNUSED, unsigned size) {
|
|
|
|
assert(c, low);
|
|
|
|
|
|
|
|
return low->freezeCount or (size > BytesPerWord and high->freezeCount);
|
|
|
|
}
|
|
|
|
|
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-10-12 00:23:08 +00:00
|
|
|
virtual Site* copy(Context* c) {
|
|
|
|
uint64_t mask;
|
|
|
|
|
|
|
|
if (low) {
|
|
|
|
sync(c);
|
|
|
|
mask = static_cast<uint64_t>(1) << register_.low;
|
|
|
|
if (register_.high != NoRegister) {
|
2008-11-11 02:12:36 +00:00
|
|
|
mask |= static_cast<uint64_t>(1) << (register_.high + 32);
|
2008-10-12 00:23:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mask = this->mask;
|
2008-10-04 17:26:35 +00:00
|
|
|
}
|
2008-10-12 00:23:08 +00:00
|
|
|
|
|
|
|
return freeRegisterSite(c, mask);
|
2008-10-04 17:26:35 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 13:54:47 +00:00
|
|
|
uint64_t mask;
|
2009-01-03 00:44:47 +00:00
|
|
|
RegisterResource* low;
|
|
|
|
RegisterResource* 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
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
uint64_t mask;
|
2009-01-03 00:44:47 +00:00
|
|
|
RegisterResource* hr;
|
2008-05-12 13:54:47 +00:00
|
|
|
if (high == NoRegister) {
|
2008-05-13 17:27:57 +00:00
|
|
|
hr = 0;
|
2009-01-04 01:17:51 +00:00
|
|
|
mask = ((~static_cast<uint64_t>(1)) << 32) | (1 << low);
|
2008-05-12 13:54:47 +00:00
|
|
|
} else {
|
2009-01-03 00:44:47 +00:00
|
|
|
hr = c->registerResources + high;
|
2009-01-04 01:17:51 +00:00
|
|
|
mask = (1 << (high + 32)) | (1 << low);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-16 20:58:21 +00:00
|
|
|
return new (c->zone->allocate(sizeof(RegisterSite)))
|
2009-01-04 01:17:51 +00:00
|
|
|
RegisterSite(mask, c->registerResources + low, hr);
|
2008-04-16 20:58:21 +00:00
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
RegisterSite*
|
2008-10-12 00:23:08 +00:00
|
|
|
freeRegisterSite(Context* c, uint64_t mask)
|
2008-05-12 13:54:47 +00:00
|
|
|
{
|
2009-01-03 00:44:47 +00:00
|
|
|
return new (c->zone->allocate(sizeof(RegisterSite))) RegisterSite(mask);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
2008-04-17 22:07:32 +00:00
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
MemorySite*
|
|
|
|
memorySite(Context* c, int base, int offset = 0, int index = NoRegister,
|
|
|
|
unsigned scale = 1);
|
|
|
|
|
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);
|
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
value.base = base - c->registerResources;
|
|
|
|
value.index = (index? index - c->registerResources : NoRegister);
|
2008-05-12 13:54:47 +00:00
|
|
|
}
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
virtual unsigned toString(Context* c, char* buffer, unsigned bufferSize) {
|
2008-10-04 17:26:35 +00:00
|
|
|
if (base) {
|
|
|
|
sync(c);
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf(buffer, bufferSize, "memory %d 0x%x %d %d",
|
|
|
|
value.base, value.offset, value.index, value.scale);
|
2008-10-04 17:26:35 +00:00
|
|
|
} else {
|
2009-01-04 01:17:51 +00:00
|
|
|
return snprintf(buffer, bufferSize, "memory unacquired");
|
2008-10-04 17:26:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
2008-10-25 02:12:02 +00:00
|
|
|
&& static_cast<int>(frameIndexToOffset(c, frameIndex))
|
|
|
|
== value.offset);
|
2008-08-23 18:04:36 +00:00
|
|
|
} else {
|
2008-10-19 00:15:57 +00:00
|
|
|
return true;
|
2008-08-23 18:04:36 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-28 21:56:12 +00:00
|
|
|
virtual void acquire(Context* c, Stack* stack, Local* locals, unsigned size,
|
|
|
|
Value* v)
|
|
|
|
{
|
2009-01-03 00:44:47 +00:00
|
|
|
base = c->registerResources + value.base;
|
2008-12-24 20:35:43 +00:00
|
|
|
increment(c, base);
|
2008-04-19 00:19:45 +00:00
|
|
|
if (value.index != NoRegister) {
|
2009-01-03 00:44:47 +00:00
|
|
|
index = c->registerResources + value.index;
|
2008-12-24 20:35:43 +00:00
|
|
|
increment(c, index);
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
2008-09-28 21:56:12 +00:00
|
|
|
|
|
|
|
if (value.base == c->arch->stack()) {
|
|
|
|
assert(c, value.index == NoRegister);
|
2009-01-03 00:44:47 +00:00
|
|
|
|
|
|
|
FrameResource* low = c->frameResources
|
|
|
|
+ offsetToFrameIndex(c, value.offset);
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
::acquire(c, low, size, v, this, stack, locals);
|
2009-01-03 00:44:47 +00:00
|
|
|
|
|
|
|
if (size > BytesPerWord) {
|
|
|
|
assert(c, (low - c->frameResources) < static_cast<int>
|
|
|
|
(c->alignedFrameSize + c->parameterFootprint));
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
low->freeze(c, v);
|
2009-01-03 00:44:47 +00:00
|
|
|
|
|
|
|
::acquire(c, low + 1, size, v, this, stack, locals);
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
low->thaw(c, v);
|
2009-01-03 00:44:47 +00:00
|
|
|
}
|
2008-09-28 21:56:12 +00:00
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void release(Context* c) {
|
2008-09-28 21:56:12 +00:00
|
|
|
if (value.base == c->arch->stack()) {
|
|
|
|
assert(c, value.index == NoRegister);
|
2009-01-03 21:34:45 +00:00
|
|
|
|
|
|
|
FrameResource* low = c->frameResources
|
|
|
|
+ offsetToFrameIndex(c, value.offset);
|
|
|
|
|
|
|
|
if (low->size > BytesPerWord) {
|
|
|
|
::release(c, low + 1);
|
|
|
|
}
|
2009-01-11 23:24:25 +00:00
|
|
|
::release(c, low);
|
2008-09-28 21:56:12 +00:00
|
|
|
}
|
|
|
|
|
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-12-21 21:41:56 +00:00
|
|
|
virtual void freeze(Context* c, Value* v, unsigned size) {
|
2008-11-17 15:20:48 +00:00
|
|
|
if (value.base == c->arch->stack()) {
|
2009-01-03 21:34:45 +00:00
|
|
|
FrameResource* low = c->frameResources
|
|
|
|
+ offsetToFrameIndex(c, value.offset);
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
low->freeze(c, v);
|
2009-01-03 21:34:45 +00:00
|
|
|
if (size > BytesPerWord) {
|
2009-01-11 18:48:02 +00:00
|
|
|
low[1].freeze(c, v);
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-21 21:41:56 +00:00
|
|
|
virtual void thaw(Context* c, Value* v, unsigned size) {
|
2008-11-17 15:20:48 +00:00
|
|
|
if (value.base == c->arch->stack()) {
|
2009-01-03 21:34:45 +00:00
|
|
|
FrameResource* low = c->frameResources
|
|
|
|
+ offsetToFrameIndex(c, value.offset);
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
low->thaw(c, v);
|
2009-01-03 21:34:45 +00:00
|
|
|
if (size > BytesPerWord) {
|
2009-01-11 18:48:02 +00:00
|
|
|
low[1].thaw(c, v);
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
2008-11-17 15:20:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-04 20:35:09 +00:00
|
|
|
virtual bool frozen(Context* c, unsigned size) {
|
|
|
|
if (value.base == c->arch->stack()) {
|
|
|
|
FrameResource* low = c->frameResources
|
|
|
|
+ offsetToFrameIndex(c, value.offset);
|
|
|
|
|
|
|
|
return low->freezeCount or (size > BytesPerWord and low[1].freezeCount);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-10-12 00:23:08 +00:00
|
|
|
virtual Site* copy(Context* c) {
|
|
|
|
return memorySite(c, value.base, value.offset, value.index, value.scale);
|
|
|
|
}
|
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
RegisterResource* base;
|
|
|
|
RegisterResource* index;
|
2008-04-16 20:58:21 +00:00
|
|
|
Assembler::Memory value;
|
|
|
|
};
|
|
|
|
|
|
|
|
MemorySite*
|
2008-10-12 00:23:08 +00:00
|
|
|
memorySite(Context* c, int base, int offset, int index, unsigned scale)
|
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);
|
2008-10-19 00:15:57 +00:00
|
|
|
return memorySite
|
2008-10-25 02:12:02 +00:00
|
|
|
(c, c->arch->stack(), frameIndexToOffset(c, frameIndex));
|
2008-08-23 18:04:36 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
void
|
|
|
|
move(Context* c, Stack* stack, Local* locals, unsigned size, Value* value,
|
|
|
|
Site* src, Site* dst)
|
|
|
|
{
|
|
|
|
src->freeze(c, value, size);
|
|
|
|
|
|
|
|
addSite(c, stack, locals, size, value, dst);
|
|
|
|
|
|
|
|
src->thaw(c, value, size);
|
|
|
|
|
|
|
|
if (dst->type(c) == MemoryOperand
|
|
|
|
and (src->type(c) == MemoryOperand
|
|
|
|
or src->type(c) == AddressOperand))
|
|
|
|
{
|
|
|
|
src->freeze(c, value, size);
|
|
|
|
|
|
|
|
Site* tmp = freeRegisterSite(c);
|
|
|
|
addSite(c, stack, locals, size, value, tmp);
|
|
|
|
|
|
|
|
src->thaw(c, value, size);
|
|
|
|
|
|
|
|
if (DebugMoves) {
|
|
|
|
char srcb[256]; src->toString(c, srcb, 256);
|
|
|
|
char tmpb[256]; tmp->toString(c, tmpb, 256);
|
|
|
|
fprintf(stderr, "move %s to %s for %p\n", srcb, tmpb, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
apply(c, Move, size, src, size, tmp);
|
|
|
|
|
|
|
|
src = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DebugMoves) {
|
|
|
|
char srcb[256]; src->toString(c, srcb, 256);
|
|
|
|
char dstb[256]; dst->toString(c, dstb, 256);
|
|
|
|
fprintf(stderr, "move %s to %s for %p\n", srcb, dstb, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
apply(c, Move, size, src, size, dst);
|
|
|
|
}
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
unsigned
|
|
|
|
sitesToString(Context* c, Site* sites, char* buffer, unsigned size)
|
|
|
|
{
|
|
|
|
unsigned total = 0;
|
|
|
|
for (Site* s = sites; s; s = s->next) {
|
|
|
|
total += s->toString(c, buffer + total, size - total);
|
|
|
|
|
|
|
|
if (s->next) {
|
|
|
|
assert(c, size > total + 2);
|
|
|
|
memcpy(buffer + total, ", ", 2);
|
|
|
|
total += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(c, size > total);
|
|
|
|
buffer[total] = 0;
|
|
|
|
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
sitesToString(Context* c, Value* v, char* buffer, unsigned size)
|
|
|
|
{
|
|
|
|
unsigned total = 0;
|
|
|
|
Value* p = v;
|
|
|
|
do {
|
|
|
|
if (total) {
|
|
|
|
assert(c, size > total + 2);
|
|
|
|
memcpy(buffer + total, "; ", 2);
|
|
|
|
total += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->sites) {
|
|
|
|
total += snprintf(buffer + total, size - total, "%p has ", p);
|
|
|
|
total += sitesToString(c, p->sites, buffer + total, size - total);
|
|
|
|
} else {
|
|
|
|
total += snprintf(buffer + total, size - total, "%p has nothing", p);
|
|
|
|
}
|
|
|
|
|
|
|
|
p = p->buddy;
|
|
|
|
} while (p != v);
|
|
|
|
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
Site*
|
2009-01-11 18:48:02 +00:00
|
|
|
pickTargetSite(Context* c, Read* read, bool intersectRead = false,
|
|
|
|
bool acceptLastRegister = true)
|
2009-01-03 21:34:45 +00:00
|
|
|
{
|
2009-01-11 18:48:02 +00:00
|
|
|
Target target(pickTarget(c, read, intersectRead, acceptLastRegister));
|
2009-01-03 21:34:45 +00:00
|
|
|
expect(c, target.cost < Target::Impossible);
|
|
|
|
if (target.high == Target::FrameIndex) {
|
|
|
|
return frameSite(c, target.low);
|
|
|
|
} else {
|
|
|
|
return registerSite(c, target.low, target.high);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
steal(Context* c, Resource* r, Value* thief, Stack* stack, Local* locals)
|
|
|
|
{
|
|
|
|
if (DebugResources) {
|
2009-01-04 01:17:51 +00:00
|
|
|
char resourceBuffer[256]; r->toString(c, resourceBuffer, 256);
|
2009-01-04 19:38:31 +00:00
|
|
|
char siteBuffer[1024]; sitesToString(c, r->value, siteBuffer, 1024);
|
2009-01-04 01:17:51 +00:00
|
|
|
fprintf(stderr, "%p steal %s from %p (%s)\n",
|
|
|
|
thief, resourceBuffer, r->value, siteBuffer);
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
if (not ((thief and buddies(thief, r->value))
|
|
|
|
or hasMoreThanOneSite(r->value)))
|
|
|
|
{
|
|
|
|
r->freeze(c, r->value);
|
2009-01-03 21:34:45 +00:00
|
|
|
|
|
|
|
move(c, stack, locals, r->size, r->value, r->site,
|
|
|
|
pickTargetSite(c, live(r->value)));
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
r->thaw(c, r->value);
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
removeSite(c, r->value, r->site);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
acquire(Context* c, Resource* r, unsigned newSize, Value* newValue,
|
|
|
|
Site* newSite, Stack* stack, Local* locals)
|
|
|
|
{
|
|
|
|
assert(c, newValue);
|
|
|
|
assert(c, newSite);
|
|
|
|
assert(c, newSize);
|
|
|
|
|
|
|
|
if (not r->reserved) {
|
|
|
|
if (DebugResources) {
|
|
|
|
char buffer[256]; r->toString(c, buffer, 256);
|
2009-01-11 23:24:25 +00:00
|
|
|
fprintf(stderr, "%p acquire %s size %d\n", newValue, buffer, newSize);
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (r->value) {
|
|
|
|
assert(c, findSite(c, r->value, r->site));
|
|
|
|
steal(c, r, newValue, stack, locals);
|
|
|
|
}
|
|
|
|
|
|
|
|
r->size = newSize;
|
|
|
|
r->value = newValue;
|
|
|
|
r->site = newSite;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
release(Context* c, Resource* r)
|
|
|
|
{
|
|
|
|
if (not r->reserved) {
|
|
|
|
if (DebugResources) {
|
|
|
|
char buffer[256]; r->toString(c, buffer, 256);
|
2009-01-11 23:24:25 +00:00
|
|
|
fprintf(stderr, "%p release %s size %d\n", r->value, buffer, r->size);
|
2009-01-03 21:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(c, r->value);
|
|
|
|
assert(c, r->site);
|
|
|
|
assert(c, r->size);
|
|
|
|
|
|
|
|
r->size = 0;
|
|
|
|
r->value = 0;
|
|
|
|
r->site = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{ }
|
|
|
|
|
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-11-12 01:09:45 +00:00
|
|
|
virtual void append(Context* c UNUSED, Read* r) {
|
2008-09-13 21:09:26 +00:00
|
|
|
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)
|
|
|
|
{
|
2008-09-28 21:56:12 +00:00
|
|
|
assert(c, (typeMask != 1 << MemoryOperand) or frameIndex >= 0);
|
2008-08-28 22:43:35 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
class MultiRead: public Read {
|
|
|
|
public:
|
|
|
|
MultiRead(unsigned size):
|
|
|
|
Read(size), reads(0), lastRead(0), firstTarget(0), lastTarget(0),
|
|
|
|
visited(false)
|
|
|
|
{ }
|
2009-01-03 00:44:47 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
virtual bool intersect(uint8_t* typeMask, uint64_t* registerMask,
|
|
|
|
int* frameIndex)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
if (not visited) {
|
|
|
|
visited = true;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
visited = false;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2008-12-24 20:35:43 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
virtual bool valid() {
|
|
|
|
bool result = false;
|
|
|
|
if (not visited) {
|
|
|
|
visited = true;
|
|
|
|
for (Cell** cell = &reads; *cell;) {
|
|
|
|
Read* r = static_cast<Read*>((*cell)->value);
|
|
|
|
if (r->valid()) {
|
|
|
|
result = true;
|
|
|
|
cell = &((*cell)->next);
|
|
|
|
} else {
|
|
|
|
*cell = (*cell)->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
visited = false;
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
return result;
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
virtual void append(Context* c, Read* r) {
|
|
|
|
Cell* cell = cons(c, r, 0);
|
|
|
|
if (lastRead == 0) {
|
|
|
|
reads = cell;
|
|
|
|
} else {
|
|
|
|
lastRead->next = cell;
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
lastRead = cell;
|
|
|
|
|
|
|
|
lastTarget->value = r;
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
virtual Read* next(Context* c) {
|
|
|
|
abort(c);
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
void allocateTarget(Context* c) {
|
|
|
|
Cell* cell = cons(c, 0, 0);
|
|
|
|
if (lastTarget) {
|
|
|
|
lastTarget->next = cell;
|
|
|
|
} else {
|
|
|
|
firstTarget = cell;
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
2009-01-03 21:34:45 +00:00
|
|
|
lastTarget = cell;
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
Read* nextTarget() {
|
|
|
|
Read* r = static_cast<Read*>(firstTarget->value);
|
|
|
|
firstTarget = firstTarget->next;
|
|
|
|
return r;
|
2008-12-24 20:35:43 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
Cell* reads;
|
|
|
|
Cell* lastRead;
|
|
|
|
Cell* firstTarget;
|
|
|
|
Cell* lastTarget;
|
|
|
|
bool visited;
|
|
|
|
};
|
2008-12-24 20:35:43 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
MultiRead*
|
|
|
|
multiRead(Context* c, unsigned size)
|
2009-01-03 00:44:47 +00:00
|
|
|
{
|
2009-01-03 21:34:45 +00:00
|
|
|
return new (c->zone->allocate(sizeof(MultiRead))) MultiRead(size);
|
2009-01-03 00:44:47 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
class StubRead: public Read {
|
|
|
|
public:
|
|
|
|
StubRead(unsigned size):
|
|
|
|
Read(size), next_(0), read(0), visited(false), valid_(true)
|
|
|
|
{ }
|
2008-11-17 15:20:48 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
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 valid_;
|
2009-01-03 00:44:47 +00:00
|
|
|
}
|
2008-12-23 00:55:29 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
virtual bool valid() {
|
|
|
|
return valid_;
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
virtual void append(Context* c UNUSED, Read* r) {
|
|
|
|
assert(c, next_ == 0);
|
|
|
|
next_ = r;
|
|
|
|
}
|
2009-01-03 00:44:47 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
virtual Read* next(Context*) {
|
|
|
|
return next_;
|
2008-11-17 15:20:48 +00:00
|
|
|
}
|
2008-04-27 20:15:18 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
Read* next_;
|
|
|
|
Read* read;
|
|
|
|
bool visited;
|
|
|
|
bool valid_;
|
|
|
|
};
|
2009-01-03 00:44:47 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
StubRead*
|
|
|
|
stubRead(Context* c, unsigned size)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(StubRead))) StubRead(size);
|
2008-04-27 20:15:18 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
bool
|
|
|
|
find(Value* needle, Value* haystack)
|
2009-01-03 00:44:47 +00:00
|
|
|
{
|
2009-01-03 21:34:45 +00:00
|
|
|
if (haystack) {
|
|
|
|
if (needle == haystack) return true;
|
|
|
|
|
|
|
|
for (Value* p = haystack->buddy; p != haystack; p = p->buddy) {
|
|
|
|
if (needle == p) return true;
|
|
|
|
}
|
|
|
|
}
|
2009-01-03 00:44:47 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
return false;
|
2008-10-17 00:10:35 +00:00
|
|
|
}
|
|
|
|
|
2008-11-11 04:25:36 +00:00
|
|
|
unsigned
|
|
|
|
footprintSizeInBytes(unsigned footprint)
|
|
|
|
{
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
return 8;
|
|
|
|
} else {
|
|
|
|
return footprint * 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-11-08 20:47:26 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "add read %p to %p last %p event %p (%s)\n", r, v, v->lastRead, e, (e ? e->name() : 0));
|
|
|
|
}
|
2008-09-25 00:48:32 +00:00
|
|
|
|
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-12-12 01:09:36 +00:00
|
|
|
// if (DebugReads) {
|
|
|
|
// fprintf(stderr, "append %p to %p for %p\n", r, v->lastRead, v);
|
|
|
|
// }
|
2008-11-08 20:47:26 +00:00
|
|
|
|
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-10-06 00:50:59 +00:00
|
|
|
clean(Context* c, Value* v, unsigned popIndex)
|
2008-07-05 20:21:13 +00:00
|
|
|
{
|
2008-11-01 22:16:18 +00:00
|
|
|
for (SiteIterator it(v); it.hasMore();) {
|
|
|
|
Site* s = it.next();
|
|
|
|
if (not (s->match(c, 1 << MemoryOperand, 0, AnyFrameIndex)
|
|
|
|
and offsetToFrameIndex
|
|
|
|
(c, static_cast<MemorySite*>(s)->value.offset)
|
|
|
|
>= popIndex))
|
2008-10-06 00:50:59 +00:00
|
|
|
{
|
2009-01-04 22:58:05 +00:00
|
|
|
if (false) {
|
|
|
|
char buffer[256]; s->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "remove %s from %p at %d pop index %d\n",
|
|
|
|
buffer, v, offsetToFrameIndex
|
|
|
|
(c, static_cast<MemorySite*>(s)->value.offset), popIndex);
|
|
|
|
}
|
2008-11-01 22:16:18 +00:00
|
|
|
it.remove(c);
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
void
|
2008-10-06 00:50:59 +00:00
|
|
|
clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads,
|
|
|
|
unsigned popIndex)
|
2008-05-19 04:31:52 +00:00
|
|
|
{
|
2008-11-01 19:14:13 +00:00
|
|
|
for (FrameIterator it(c, stack, locals); it.hasMore();) {
|
|
|
|
FrameIterator::Element e = it.next(c);
|
|
|
|
clean(c, e.value, popIndex);
|
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-11-25 17:34:48 +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-10-14 00:18:18 +00:00
|
|
|
void
|
|
|
|
append(Context* c, Event* e);
|
|
|
|
|
2008-11-25 17:34:48 +00:00
|
|
|
void
|
|
|
|
saveLocals(Context* c, Event* e)
|
|
|
|
{
|
|
|
|
for (unsigned li = 0; li < c->localFootprint; ++li) {
|
|
|
|
Local* local = e->localsBefore + li;
|
|
|
|
if (local->value) {
|
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "local save read %p of footprint %d at %d of %d\n",
|
|
|
|
local->value, local->footprint,
|
|
|
|
::frameIndex(c, li, local->footprint),
|
|
|
|
c->alignedFrameSize + c->parameterFootprint);
|
|
|
|
}
|
|
|
|
|
|
|
|
addRead(c, e, local->value, read
|
|
|
|
(c, footprintSizeInBytes(local->footprint), 1 << MemoryOperand,
|
|
|
|
0, ::frameIndex(c, li, local->footprint)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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),
|
2008-10-25 02:12:02 +00:00
|
|
|
popIndex(0),
|
2008-11-09 23:56:37 +00:00
|
|
|
padIndex(0),
|
|
|
|
padding(0),
|
2008-04-17 20:48:26 +00:00
|
|
|
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-10-25 02:12:02 +00:00
|
|
|
unsigned frameIndex = 0;
|
2008-11-08 22:36:38 +00:00
|
|
|
|
|
|
|
if (argumentCount) {
|
|
|
|
unsigned ai = 0;
|
|
|
|
while (true) {
|
|
|
|
Read* target;
|
|
|
|
if (index < c->arch->argumentRegisterCount()) {
|
|
|
|
int r = c->arch->argumentRegister(index);
|
2008-11-08 20:47:26 +00:00
|
|
|
|
2008-11-08 22:36:38 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "reg %d arg read %p\n", r, s->value);
|
|
|
|
}
|
2008-11-08 20:47:26 +00:00
|
|
|
|
2008-11-08 22:36:38 +00:00
|
|
|
target = fixedRegisterRead(c, footprintSizeInBytes(s->footprint), r);
|
|
|
|
mask &= ~(1 << r);
|
|
|
|
} else {
|
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "stack %d arg read %p\n", frameIndex, s->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
target = read(c, footprintSizeInBytes(s->footprint),
|
|
|
|
1 << MemoryOperand, 0, frameIndex);
|
|
|
|
frameIndex += s->footprint;
|
2008-11-08 20:47:26 +00:00
|
|
|
}
|
2008-11-08 22:36:38 +00:00
|
|
|
addRead(c, this, s->value, target);
|
|
|
|
index += s->footprint;
|
2008-11-08 20:47:26 +00:00
|
|
|
|
2008-11-08 22:36:38 +00:00
|
|
|
if ((++ ai) < argumentCount) {
|
|
|
|
s = s->next;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2008-04-19 00:19:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-08 20:47:26 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "address read %p\n", address);
|
|
|
|
}
|
|
|
|
|
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-10-04 17:26:35 +00:00
|
|
|
for (Stack* s = stackBefore; s; s = s->next) {
|
2008-09-23 21:18:41 +00:00
|
|
|
if (footprint > 0) {
|
2008-11-08 20:47:26 +00:00
|
|
|
if (DebugReads) {
|
2008-11-08 22:36:38 +00:00
|
|
|
fprintf(stderr, "stack arg read %p of footprint %d at %d of %d\n",
|
|
|
|
s->value, s->footprint, frameIndex,
|
|
|
|
c->alignedFrameSize + c->parameterFootprint);
|
2008-11-08 20:47:26 +00:00
|
|
|
}
|
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
addRead(c, this, s->value, read
|
2008-11-02 22:25:51 +00:00
|
|
|
(c, footprintSizeInBytes(s->footprint),
|
2008-09-25 00:48:32 +00:00
|
|
|
1 << MemoryOperand, 0, frameIndex));
|
2008-11-08 22:36:38 +00:00
|
|
|
} else {
|
2008-11-25 23:00:40 +00:00
|
|
|
unsigned logicalIndex = ::frameIndex
|
2008-11-08 22:36:38 +00:00
|
|
|
(c, s->index + c->localFootprint, s->footprint);
|
|
|
|
|
2008-11-08 20:47:26 +00:00
|
|
|
if (DebugReads) {
|
2008-11-08 22:36:38 +00:00
|
|
|
fprintf(stderr, "stack save read %p of footprint %d at %d of %d\n",
|
2008-11-25 23:00:40 +00:00
|
|
|
s->value, s->footprint, logicalIndex,
|
2008-11-08 22:36:38 +00:00
|
|
|
c->alignedFrameSize + c->parameterFootprint);
|
2008-11-08 20:47:26 +00:00
|
|
|
}
|
|
|
|
|
2008-09-23 21:18:41 +00:00
|
|
|
addRead(c, this, s->value, read
|
2008-11-08 22:36:38 +00:00
|
|
|
(c, footprintSizeInBytes(s->footprint), 1 << MemoryOperand,
|
2008-11-25 23:00:40 +00:00
|
|
|
0, logicalIndex));
|
2008-08-23 18:04:36 +00:00
|
|
|
}
|
2008-11-08 22:36:38 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
footprint -= s->footprint;
|
2008-11-08 22:36:38 +00:00
|
|
|
|
|
|
|
if (footprint == 0) {
|
2008-11-09 23:56:37 +00:00
|
|
|
unsigned logicalIndex = ::frameIndex
|
|
|
|
(c, s->index + c->localFootprint, s->footprint);
|
|
|
|
|
|
|
|
assert(c, logicalIndex >= frameIndex);
|
|
|
|
|
|
|
|
padding = logicalIndex - frameIndex;
|
|
|
|
padIndex = s->index + c->localFootprint;
|
2008-11-08 22:36:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
frameIndex += s->footprint;
|
2008-05-15 20:00:57 +00:00
|
|
|
}
|
2008-09-25 00:48:32 +00:00
|
|
|
|
2008-11-25 23:00:40 +00:00
|
|
|
popIndex = ::frameIndex
|
|
|
|
(c, (stackBefore
|
|
|
|
? stackBefore->index
|
|
|
|
+ stackBefore->footprint
|
|
|
|
- stackArgumentFootprint
|
|
|
|
: 0)
|
|
|
|
+ c->localFootprint, 0);
|
|
|
|
|
2008-11-25 17:34:48 +00:00
|
|
|
saveLocals(c, this);
|
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-11-09 23:56:37 +00:00
|
|
|
traceHandler->handleTrace(codePromise(c, c->assembler->offset()),
|
|
|
|
padIndex, padding);
|
2008-05-15 23:19:23 +00:00
|
|
|
}
|
|
|
|
|
2008-10-06 00:50:59 +00:00
|
|
|
clean(c, this, stackBefore, localsBefore, reads, popIndex);
|
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-10-06 00:50:59 +00:00
|
|
|
unsigned popIndex;
|
2008-11-09 23:56:37 +00:00
|
|
|
unsigned padIndex;
|
|
|
|
unsigned padding;
|
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-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(CallEvent)))
|
|
|
|
CallEvent(c, address, flags, traceHandler, result,
|
|
|
|
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-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(ReturnEvent)))
|
|
|
|
ReturnEvent(c, size, value));
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
|
|
|
|
2008-10-25 02:12:02 +00:00
|
|
|
void
|
|
|
|
preserve(Context* c, Stack* stack, Local* locals, unsigned size, Value* v,
|
2009-01-03 00:44:47 +00:00
|
|
|
Site* s, Read* r)
|
2008-10-25 02:12:02 +00:00
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
s->freeze(c, v, size);
|
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
move(c, stack, locals, size, v, s, pickTargetSite(c, r));
|
2009-01-04 01:17:51 +00:00
|
|
|
|
|
|
|
s->thaw(c, v, size);
|
2008-10-25 02:12:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
maybePreserve(Context* c, Stack* stack, Local* locals, unsigned size,
|
|
|
|
Value* v, Site* s)
|
|
|
|
{
|
2008-11-01 22:16:18 +00:00
|
|
|
Read* r = liveNext(c, v);
|
|
|
|
if (r and not hasMoreThanOneSite(v)) {
|
|
|
|
preserve(c, stack, locals, size, v, s, r);
|
2008-10-25 02:12:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-12 00:39:26 +00:00
|
|
|
void
|
|
|
|
addBuddy(Value* original, Value* buddy)
|
|
|
|
{
|
|
|
|
buddy->buddy = original;
|
|
|
|
Value* p = original;
|
|
|
|
while (p->buddy != original) p = p->buddy;
|
|
|
|
p->buddy = buddy;
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
if (DebugBuddies) {
|
|
|
|
fprintf(stderr, "add buddy %p to", buddy);
|
|
|
|
for (Value* p = buddy->buddy; p != buddy; p = p->buddy) {
|
|
|
|
fprintf(stderr, " %p", p);
|
|
|
|
}
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
2008-11-12 00:39:26 +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) {
|
2009-01-03 00:44:47 +00:00
|
|
|
Read* read = live(dst);
|
|
|
|
bool isStore = read == 0;
|
2008-05-19 13:44:39 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
Site* target;
|
|
|
|
if (dst->target) {
|
|
|
|
target = dst->target;
|
2009-01-11 18:48:02 +00:00
|
|
|
} else if (isStore) {
|
|
|
|
return;
|
2009-01-03 21:34:45 +00:00
|
|
|
} else {
|
|
|
|
target = pickTargetSite(c, read);
|
|
|
|
}
|
2008-07-05 20:21:13 +00:00
|
|
|
unsigned cost = src->source->copyCost(c, target);
|
2008-11-12 00:39:26 +00:00
|
|
|
|
|
|
|
if (srcSize != dstSize) cost = 1;
|
|
|
|
|
2008-12-21 21:41:56 +00:00
|
|
|
if (cost) {
|
|
|
|
addSite(c, stackBefore, localsBefore, dstSize, dst, target);
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
uint8_t typeMask = ~static_cast<uint8_t>(0);
|
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
|
|
|
dstRead->intersect(&typeMask, ®isterMask, &frameIndex);
|
|
|
|
|
2008-11-08 20:47:26 +00:00
|
|
|
bool useTemporary = ((target->type(c) == MemoryOperand
|
|
|
|
and src->source->type(c) == MemoryOperand)
|
|
|
|
or (srcSize != dstSize
|
|
|
|
and target->type(c) != RegisterOperand));
|
2008-10-04 17:26:35 +00:00
|
|
|
|
|
|
|
if (target->match(c, typeMask, registerMask, frameIndex)
|
2008-11-08 20:47:26 +00:00
|
|
|
and not useTemporary)
|
2008-10-04 17:26:35 +00:00
|
|
|
{
|
2008-11-11 02:12:36 +00:00
|
|
|
if (DebugMoves) {
|
|
|
|
char srcb[256]; src->source->toString(c, srcb, 256);
|
|
|
|
char dstb[256]; target->toString(c, dstb, 256);
|
|
|
|
fprintf(stderr, "move %s to %s for %p to %p\n",
|
|
|
|
srcb, dstb, src, dst);
|
|
|
|
}
|
2008-10-19 00:15:57 +00:00
|
|
|
|
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-10-04 17:26:35 +00:00
|
|
|
addSite(c, stackBefore, localsBefore, dstSize, dst, tmpTarget);
|
2008-05-16 16:01:24 +00:00
|
|
|
|
2008-11-11 02:12:36 +00:00
|
|
|
if (DebugMoves) {
|
|
|
|
char srcb[256]; src->source->toString(c, srcb, 256);
|
|
|
|
char dstb[256]; tmpTarget->toString(c, dstb, 256);
|
|
|
|
fprintf(stderr, "move %s to %s for %p to %p\n",
|
|
|
|
srcb, dstb, src, dst);
|
|
|
|
}
|
2008-10-19 00:15:57 +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-11-08 20:47:26 +00:00
|
|
|
if (useTemporary or isStore) {
|
2008-11-11 02:12:36 +00:00
|
|
|
if (DebugMoves) {
|
|
|
|
char srcb[256]; tmpTarget->toString(c, srcb, 256);
|
|
|
|
char dstb[256]; target->toString(c, dstb, 256);
|
|
|
|
fprintf(stderr, "move %s to %s for %p to %p\n",
|
|
|
|
srcb, dstb, src, dst);
|
|
|
|
}
|
2008-10-19 00:15:57 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
apply(c, Move, dstSize, tmpTarget, dstSize, target);
|
2008-12-20 21:55:45 +00:00
|
|
|
|
|
|
|
if (isStore) {
|
|
|
|
removeSite(c, dst, tmpTarget);
|
|
|
|
}
|
2008-05-18 01:26:36 +00:00
|
|
|
} else {
|
|
|
|
removeSite(c, dst, target);
|
|
|
|
}
|
2008-05-16 16:01:24 +00:00
|
|
|
}
|
2008-12-21 21:41:56 +00:00
|
|
|
} else {
|
|
|
|
target = src->source;
|
|
|
|
|
|
|
|
addBuddy(src, dst);
|
|
|
|
|
|
|
|
if (DebugMoves) {
|
|
|
|
char dstb[256]; target->toString(c, dstb, 256);
|
|
|
|
fprintf(stderr, "null move in %s for %p to %p\n", dstb, src, dst);
|
|
|
|
}
|
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-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(MoveEvent)))
|
|
|
|
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)
|
|
|
|
{
|
2008-11-01 22:16:18 +00:00
|
|
|
for (SiteIterator it(v); it.hasMore();) {
|
|
|
|
Site* s = it.next();
|
2008-06-11 00:17:44 +00:00
|
|
|
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-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(CompareEvent)))
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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-12-21 21:41:56 +00:00
|
|
|
first->source->freeze(c, first, firstSize);
|
2008-12-20 23:05:01 +00:00
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
Site* target;
|
|
|
|
if (c->arch->condensedAddressing()) {
|
2008-10-04 17:26:35 +00:00
|
|
|
maybePreserve(c, stackBefore, localsBefore, secondSize, second,
|
|
|
|
second->source);
|
2009-01-11 18:48:02 +00:00
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
target = second->source;
|
2009-01-11 18:48:02 +00:00
|
|
|
|
|
|
|
removeSite(c, second, target);
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
target->freeze(c, second, secondSize);
|
2008-09-07 20:12:11 +00:00
|
|
|
} else {
|
2009-01-03 00:44:47 +00:00
|
|
|
target = pickTargetSite(c, resultRead);
|
2008-10-04 17:26:35 +00:00
|
|
|
addSite(c, stackBefore, localsBefore, resultSize, result, target);
|
2008-09-07 20:12:11 +00:00
|
|
|
}
|
2008-04-29 16:25:20 +00:00
|
|
|
|
2008-10-04 17:26:35 +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
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
first->source->thaw(c, first, firstSize);
|
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
nextRead(c, this, first);
|
|
|
|
nextRead(c, this, second);
|
2008-09-23 21:18:41 +00:00
|
|
|
|
2008-11-11 00:07:44 +00:00
|
|
|
if (c->arch->condensedAddressing()) {
|
2009-01-11 22:53:51 +00:00
|
|
|
target->thaw(c, second, secondSize);
|
2009-01-11 18:48:02 +00:00
|
|
|
|
2008-11-11 00:07:44 +00:00
|
|
|
if (live(result)) {
|
|
|
|
addSite(c, 0, 0, resultSize, result, target);
|
|
|
|
}
|
2008-09-23 21:18:41 +00:00
|
|
|
}
|
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-11-01 19:14:13 +00:00
|
|
|
void
|
2008-11-01 22:16:18 +00:00
|
|
|
removeBuddy(Context* c, Value* v)
|
2008-11-01 19:14:13 +00:00
|
|
|
{
|
|
|
|
if (v->buddy != v) {
|
2009-01-11 22:53:51 +00:00
|
|
|
if (DebugBuddies) {
|
|
|
|
fprintf(stderr, "remove buddy %p from", v);
|
|
|
|
for (Value* p = v->buddy; p != v; p = p->buddy) {
|
|
|
|
fprintf(stderr, " %p", p);
|
|
|
|
}
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
2008-11-01 19:14:13 +00:00
|
|
|
|
|
|
|
Value* next = v->buddy;
|
|
|
|
v->buddy = v;
|
|
|
|
Value* p = next;
|
|
|
|
while (p->buddy != v) p = p->buddy;
|
|
|
|
p->buddy = next;
|
2008-11-01 22:16:18 +00:00
|
|
|
|
|
|
|
if (not live(next)) {
|
|
|
|
clearSites(c, next);
|
|
|
|
}
|
2008-12-16 01:21:01 +00:00
|
|
|
|
|
|
|
if (not live(v)) {
|
|
|
|
clearSites(c, v);
|
|
|
|
}
|
2008-11-01 19:14:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
Site*
|
|
|
|
copy(Context* c, Site* s)
|
|
|
|
{
|
|
|
|
Site* start = 0;
|
|
|
|
Site* end = 0;
|
|
|
|
for (; s; s = s->next) {
|
|
|
|
Site* n = s->copy(c);
|
|
|
|
if (end) {
|
|
|
|
end->next = n;
|
|
|
|
} else {
|
|
|
|
start = n;
|
|
|
|
}
|
|
|
|
end = n;
|
|
|
|
}
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
|
|
|
|
class Snapshot {
|
|
|
|
public:
|
|
|
|
Snapshot(Context* c, Value* value, Snapshot* next):
|
|
|
|
value(value), buddy(value->buddy), sites(copy(c, value->sites)), next(next)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Value* value;
|
|
|
|
Value* buddy;
|
|
|
|
Site* sites;
|
|
|
|
Snapshot* next;
|
|
|
|
};
|
|
|
|
|
|
|
|
Snapshot*
|
|
|
|
snapshot(Context* c, Value* value, Snapshot* next)
|
|
|
|
{
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugControl) {
|
2009-01-04 01:17:51 +00:00
|
|
|
char buffer[256]; sitesToString(c, value->sites, buffer, 256);
|
2008-11-02 22:25:51 +00:00
|
|
|
fprintf(stderr, "snapshot %p buddy %p sites %s\n",
|
|
|
|
value, value->buddy, buffer);
|
|
|
|
}
|
2008-11-01 22:16:18 +00:00
|
|
|
|
|
|
|
return new (c->zone->allocate(sizeof(Snapshot))) Snapshot(c, value, next);
|
|
|
|
}
|
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
Snapshot*
|
|
|
|
makeSnapshots(Context* c, Value* value, Snapshot* next)
|
|
|
|
{
|
|
|
|
next = snapshot(c, value, next);
|
|
|
|
for (Value* p = value->buddy; p != value; p = p->buddy) {
|
|
|
|
next = snapshot(c, p, next);
|
|
|
|
}
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
Stack*
|
2008-11-07 00:39:38 +00:00
|
|
|
stack(Context* c, Value* value, unsigned footprint, unsigned index,
|
|
|
|
Stack* next)
|
2008-08-28 22:43:35 +00:00
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(Stack)))
|
2008-11-07 00:39:38 +00:00
|
|
|
Stack(index, footprint, value, next);
|
2008-08-28 22:43:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Stack*
|
2008-11-07 00:39:38 +00:00
|
|
|
stack(Context* c, Value* value, unsigned footprint, Stack* next)
|
2008-08-28 22:43:35 +00:00
|
|
|
{
|
|
|
|
return stack
|
2008-11-07 00:39:38 +00:00
|
|
|
(c, value, footprint, (next ? next->index + next->footprint : 0), next);
|
|
|
|
}
|
|
|
|
|
|
|
|
SavedValue*
|
|
|
|
savedValue(Context* c, Value* value, unsigned footprint, SavedValue* next)
|
|
|
|
{
|
|
|
|
return new (c->zone->allocate(sizeof(SavedValue)))
|
|
|
|
SavedValue(footprint, value, next);
|
2008-08-28 22:43:35 +00:00
|
|
|
}
|
|
|
|
|
2008-11-02 20:35:35 +00:00
|
|
|
Value*
|
|
|
|
maybeBuddy(Context* c, Value* v, unsigned sizeInBytes);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void
|
2008-11-02 22:25:51 +00:00
|
|
|
push(Context* c, unsigned footprint, Value* v)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-11-02 22:25:51 +00:00
|
|
|
assert(c, footprint);
|
2008-04-28 22:08:31 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
v = maybeBuddy(c, v, footprintSizeInBytes(footprint));
|
2008-11-02 20:35:35 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugFrame) {
|
|
|
|
fprintf(stderr, "push %p of footprint %d\n", v, footprint);
|
|
|
|
}
|
2008-11-02 20:35:35 +00:00
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
Stack* s = stack(c, v, footprint, c->stack);
|
|
|
|
v->home = frameIndex(c, s->index + c->localFootprint, s->footprint);
|
|
|
|
c->stack = s;
|
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*
|
2008-11-02 22:25:51 +00:00
|
|
|
pop(Context* c, unsigned footprint UNUSED)
|
2008-08-28 22:43:35 +00:00
|
|
|
{
|
2008-09-13 21:09:26 +00:00
|
|
|
Stack* s = c->stack;
|
2008-11-02 22:25:51 +00:00
|
|
|
assert(c, footprint == s->footprint);
|
2009-01-03 00:44:47 +00:00
|
|
|
assert(c, s->value->home >= 0);
|
2008-11-02 20:35:35 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugFrame) {
|
|
|
|
fprintf(stderr, "pop %p of size %d\n", s->value, footprint);
|
|
|
|
}
|
2008-08-28 22:43:35 +00:00
|
|
|
|
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-11-02 22:25:51 +00:00
|
|
|
::push(c, ceiling(secondSize, BytesPerWord), second);
|
|
|
|
::push(c, ceiling(firstSize, BytesPerWord), 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-10-14 00:18:18 +00:00
|
|
|
append
|
|
|
|
(c, new (c->zone->allocate(sizeof(CombineEvent)))
|
|
|
|
CombineEvent
|
|
|
|
(c, type,
|
|
|
|
firstSize, first,
|
|
|
|
secondSize, second,
|
|
|
|
resultSize, result,
|
|
|
|
read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex),
|
|
|
|
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,
|
2008-10-15 00:45:31 +00:00
|
|
|
Value* result, Read* valueRead, Read* resultRead):
|
|
|
|
Event(c), type(type), size(size), value(value), result(result),
|
|
|
|
resultRead(resultRead)
|
2008-02-17 20:57:40 +00:00
|
|
|
{
|
2008-10-15 00:45:31 +00:00
|
|
|
addRead(c, this, value, valueRead);
|
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-10-15 00:45:31 +00:00
|
|
|
Site* target;
|
|
|
|
if (c->arch->condensedAddressing()) {
|
|
|
|
maybePreserve(c, stackBefore, localsBefore, size, value, value->source);
|
2009-01-11 18:48:02 +00:00
|
|
|
|
2008-10-15 00:45:31 +00:00
|
|
|
target = value->source;
|
2009-01-11 18:48:02 +00:00
|
|
|
|
|
|
|
removeSite(c, value, target);
|
|
|
|
|
|
|
|
target->freeze(c, 0, size);
|
2008-10-15 00:45:31 +00:00
|
|
|
} else {
|
2009-01-11 18:48:02 +00:00
|
|
|
value->source->freeze(c, value, size);
|
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
target = pickTargetSite(c, resultRead);
|
2008-10-15 00:45:31 +00:00
|
|
|
addSite(c, stackBefore, localsBefore, size, result, target);
|
|
|
|
}
|
2008-04-29 16:25:20 +00:00
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
apply(c, type, size, value->source, size, target);
|
2009-01-11 18:48:02 +00:00
|
|
|
|
|
|
|
if (not c->arch->condensedAddressing()) {
|
|
|
|
value->source->thaw(c, value, size);
|
|
|
|
}
|
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-11-11 00:07:44 +00:00
|
|
|
if (c->arch->condensedAddressing()) {
|
2009-01-11 18:48:02 +00:00
|
|
|
target->thaw(c, 0, size);
|
|
|
|
|
2008-11-11 00:07:44 +00:00
|
|
|
if (live(result)) {
|
|
|
|
addSite(c, 0, 0, size, result, target);
|
|
|
|
}
|
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-10-15 00:45:31 +00:00
|
|
|
Read* resultRead;
|
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-10-15 00:45:31 +00:00
|
|
|
Read* resultRead = read
|
|
|
|
(c, size, resultTypeMask, resultRegisterMask, AnyFrameIndex);
|
|
|
|
Read* firstRead;
|
|
|
|
if (c->arch->condensedAddressing()) {
|
|
|
|
firstRead = resultRead;
|
|
|
|
} else {
|
|
|
|
firstRead = read
|
|
|
|
(c, size, firstTypeMask, firstRegisterMask, AnyFrameIndex);
|
|
|
|
}
|
2008-08-28 22:43:35 +00:00
|
|
|
// todo: respect resultTypeMask and resultRegisterMask
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(TranslateEvent)))
|
|
|
|
TranslateEvent
|
2008-10-15 00:45:31 +00:00
|
|
|
(c, type, size, value, result, firstRead, resultRead));
|
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));
|
2009-01-04 22:58:05 +00:00
|
|
|
if (index) {
|
|
|
|
addRead(c, this, index, registerOrConstantRead(c, BytesPerWord));
|
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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-12-24 20:35:43 +00:00
|
|
|
addSite(c, c->stack, c->locals, 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
|
|
|
{
|
2008-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(MemoryEvent)))
|
|
|
|
MemoryEvent(c, base, displacement, index, scale, result));
|
2008-04-17 20:48:26 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-10-08 00:08:13 +00:00
|
|
|
virtual bool isBranch() { return true; }
|
|
|
|
|
2008-04-20 05:23:08 +00:00
|
|
|
UnaryOperation type;
|
|
|
|
Value* address;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendBranch(Context* c, UnaryOperation type, Value* address)
|
|
|
|
{
|
2008-10-14 00:18:18 +00:00
|
|
|
append(c, 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;
|
|
|
|
|
2008-12-24 20:35:43 +00:00
|
|
|
MemorySite length(base, lengthOffset, NoRegister, 1);
|
2009-01-03 00:44:47 +00:00
|
|
|
length.base = c->registerResources + base;
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-24 20:35:43 +00:00
|
|
|
apply(c, Compare, 4, index->source, 4, &length);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2008-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(BoundsCheckEvent)))
|
|
|
|
BoundsCheckEvent(c, object, lengthOffset, index, handler));
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
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-11-14 00:59:21 +00:00
|
|
|
if (live(value)) {
|
|
|
|
addSite(c, stackBefore, localsBefore, size, value, frameSite(c, index));
|
|
|
|
}
|
2008-09-09 00:31:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(FrameSiteEvent)))
|
|
|
|
FrameSiteEvent(c, value, size, index));
|
2008-09-09 00:31:19 +00:00
|
|
|
}
|
|
|
|
|
2008-10-05 00:14:43 +00:00
|
|
|
unsigned
|
|
|
|
frameFootprint(Context* c, Stack* s)
|
|
|
|
{
|
2008-11-02 22:25:51 +00:00
|
|
|
return c->localFootprint + (s ? (s->index + s->footprint) : 0);
|
2008-10-14 00:18:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-10-15 00:45:31 +00:00
|
|
|
visit(Context* c, Link* link)
|
2008-10-14 00:18:18 +00:00
|
|
|
{
|
2008-12-12 01:09:36 +00:00
|
|
|
// fprintf(stderr, "visit link from %d to %d fork %p junction %p\n",
|
2008-10-17 00:10:35 +00:00
|
|
|
// link->predecessor->logicalInstruction->index,
|
2008-12-12 01:09:36 +00:00
|
|
|
// link->successor->logicalInstruction->index,
|
|
|
|
// link->forkState,
|
|
|
|
// link->junctionState);
|
2008-10-14 00:18:18 +00:00
|
|
|
|
|
|
|
ForkState* forkState = link->forkState;
|
|
|
|
if (forkState) {
|
|
|
|
for (unsigned i = 0; i < forkState->readCount; ++i) {
|
2008-11-02 20:35:35 +00:00
|
|
|
ForkElement* p = forkState->elements + i;
|
2008-10-14 00:18:18 +00:00
|
|
|
Value* v = p->value;
|
|
|
|
v->reads = p->read->nextTarget();
|
2008-10-17 00:10:35 +00:00
|
|
|
// fprintf(stderr, "next read %p for %p\n", v->reads, v);
|
2008-10-14 00:18:18 +00:00
|
|
|
if (not live(v)) {
|
|
|
|
clearSites(c, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JunctionState* junctionState = link->junctionState;
|
|
|
|
if (junctionState) {
|
2008-12-15 14:35:19 +00:00
|
|
|
for (unsigned i = 0; i < junctionState->frameFootprint; ++i) {
|
|
|
|
StubReadPair* p = junctionState->reads + i;
|
|
|
|
|
2008-12-23 01:25:00 +00:00
|
|
|
if (p->value and p->value->reads) {
|
2008-12-15 14:35:19 +00:00
|
|
|
assert(c, p->value->reads == p->read);
|
|
|
|
nextRead(c, 0, p->value);
|
|
|
|
}
|
2008-10-14 00:18:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-01 19:14:13 +00:00
|
|
|
class BuddyEvent: public Event {
|
|
|
|
public:
|
|
|
|
BuddyEvent(Context* c, Value* original, Value* buddy, unsigned size):
|
|
|
|
Event(c), original(original), buddy(buddy)
|
|
|
|
{
|
|
|
|
addRead(c, this, original,
|
|
|
|
read(c, size, ~0, ~static_cast<uint64_t>(0), AnyFrameIndex));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const char* name() {
|
|
|
|
return "BuddyEvent";
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void compile(Context* c) {
|
2008-12-12 01:09:36 +00:00
|
|
|
// fprintf(stderr, "original %p buddy %p\n", original, buddy);
|
|
|
|
assert(c, hasSite(original));
|
|
|
|
|
2008-11-12 00:39:26 +00:00
|
|
|
addBuddy(original, buddy);
|
2008-11-01 19:14:13 +00:00
|
|
|
|
|
|
|
nextRead(c, this, original);
|
|
|
|
}
|
|
|
|
|
|
|
|
Value* original;
|
|
|
|
Value* buddy;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendBuddy(Context* c, Value* original, Value* buddy, unsigned size)
|
|
|
|
{
|
|
|
|
append(c, new (c->zone->allocate(sizeof(BuddyEvent)))
|
|
|
|
BuddyEvent(c, original, buddy, size));
|
|
|
|
}
|
|
|
|
|
2008-11-25 17:34:48 +00:00
|
|
|
class SaveLocalsEvent: public Event {
|
|
|
|
public:
|
|
|
|
SaveLocalsEvent(Context* c):
|
|
|
|
Event(c)
|
|
|
|
{
|
|
|
|
saveLocals(c, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual const char* name() {
|
|
|
|
return "SaveLocalsEvent";
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void compile(Context* c) {
|
|
|
|
for (Read* r = reads; r; r = r->eventNext) {
|
|
|
|
nextRead(c, this, r->value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendSaveLocals(Context* c)
|
|
|
|
{
|
|
|
|
append(c, new (c->zone->allocate(sizeof(SaveLocalsEvent)))
|
|
|
|
SaveLocalsEvent(c));
|
|
|
|
}
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
class DummyEvent: public Event {
|
|
|
|
public:
|
|
|
|
DummyEvent(Context* c):
|
|
|
|
Event(c)
|
2008-10-05 00:14:43 +00:00
|
|
|
{ }
|
2008-09-15 02:28:42 +00:00
|
|
|
|
|
|
|
virtual const char* name() {
|
|
|
|
return "DummyEvent";
|
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
|
|
|
|
virtual void compile(Context*) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
appendDummy(Context* c)
|
|
|
|
{
|
2008-10-05 00:14:43 +00:00
|
|
|
Stack* stack = c->stack;
|
|
|
|
Local* locals = c->locals;
|
|
|
|
LogicalInstruction* i = c->logicalCode[c->logicalIp];
|
|
|
|
|
|
|
|
c->stack = i->stack;
|
|
|
|
c->locals = i->locals;
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
append(c, new (c->zone->allocate(sizeof(DummyEvent))) DummyEvent(c));
|
2008-10-05 00:14:43 +00:00
|
|
|
|
|
|
|
c->stack = stack;
|
|
|
|
c->locals = locals;
|
2008-09-13 21:09:26 +00:00
|
|
|
}
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
void
|
|
|
|
append(Context* c, Event* e)
|
|
|
|
{
|
2008-10-25 02:12:02 +00:00
|
|
|
LogicalInstruction* i = c->logicalCode[c->logicalIp];
|
|
|
|
if (c->stack != i->stack or c->locals != i->locals) {
|
|
|
|
appendDummy(c);
|
2008-10-14 00:18:18 +00:00
|
|
|
}
|
|
|
|
|
2008-10-25 02:12:02 +00:00
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, " -- append %s at %d with %d stack before\n",
|
|
|
|
e->name(), e->logicalInstruction->index, c->stack ?
|
2008-11-02 22:25:51 +00:00
|
|
|
c->stack->index + c->stack->footprint : 0);
|
2008-10-25 02:12:02 +00:00
|
|
|
}
|
2008-10-14 00:18:18 +00:00
|
|
|
|
|
|
|
if (c->lastEvent) {
|
|
|
|
c->lastEvent->next = e;
|
|
|
|
} else {
|
|
|
|
c->firstEvent = e;
|
|
|
|
}
|
|
|
|
c->lastEvent = e;
|
|
|
|
|
|
|
|
Event* p = c->predecessor;
|
|
|
|
if (p) {
|
|
|
|
Link* link = ::link(c, p, e->predecessors, e, p->successors, c->forkState);
|
|
|
|
e->predecessors = link;
|
|
|
|
p->successors = link;
|
|
|
|
}
|
|
|
|
c->forkState = 0;
|
|
|
|
|
|
|
|
c->predecessor = e;
|
|
|
|
|
|
|
|
if (e->logicalInstruction->firstEvent == 0) {
|
|
|
|
e->logicalInstruction->firstEvent = e;
|
|
|
|
}
|
|
|
|
e->logicalInstruction->lastEvent = e;
|
|
|
|
}
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
bool
|
|
|
|
acceptMatch(Context* c, Site* s, Read*, uint8_t typeMask,
|
|
|
|
uint64_t registerMask, int frameIndex)
|
|
|
|
{
|
|
|
|
return s->match(c, typeMask, registerMask, frameIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
isHome(Value* v, int frameIndex)
|
|
|
|
{
|
|
|
|
Value* p = v;
|
|
|
|
do {
|
|
|
|
if (p->home == frameIndex) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
p = p->buddy;
|
|
|
|
} while (p != v);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
acceptForResolve(Context* c, Site* s, Read* read, uint8_t typeMask,
|
|
|
|
uint64_t registerMask, int frameIndex)
|
|
|
|
{
|
|
|
|
if (acceptMatch(c, s, read, typeMask, registerMask, frameIndex)
|
|
|
|
and (not s->frozen(c, read->size)))
|
|
|
|
{
|
|
|
|
if (s->type(c) == RegisterOperand) {
|
|
|
|
return c->availableRegisterCount > ceiling(read->size, BytesPerWord);
|
|
|
|
} else {
|
|
|
|
assert(c, s->match(c, 1 << MemoryOperand, 0, AnyFrameIndex));
|
|
|
|
return isHome(read->value, offsetToFrameIndex
|
|
|
|
(c, static_cast<MemorySite*>(s)->value.offset));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-18 03:47:42 +00:00
|
|
|
Site*
|
2009-01-04 20:35:09 +00:00
|
|
|
pickSourceSite(Context* c, Read* read, Site* target = 0,
|
|
|
|
unsigned* cost = 0, uint8_t typeMask = ~0,
|
2009-01-11 18:48:02 +00:00
|
|
|
bool intersectRead = true, bool includeBuddies = true,
|
2009-01-11 22:53:51 +00:00
|
|
|
bool (*accept)(Context*, Site*, Read*, uint8_t, uint64_t, int)
|
|
|
|
= acceptMatch)
|
2008-04-18 03:47:42 +00:00
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
uint64_t registerMask = ~static_cast<uint64_t>(0);
|
|
|
|
int frameIndex = AnyFrameIndex;
|
2008-11-02 20:35:35 +00:00
|
|
|
|
2009-01-04 20:35:09 +00:00
|
|
|
if (intersectRead) {
|
2009-01-04 01:17:51 +00:00
|
|
|
read->intersect(&typeMask, ®isterMask, &frameIndex);
|
|
|
|
}
|
2009-01-11 18:48:02 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
Site* site = 0;
|
|
|
|
unsigned copyCost = 0xFFFFFFFF;
|
2009-01-04 20:35:09 +00:00
|
|
|
for (SiteIterator it(read->value, includeBuddies); it.hasMore();) {
|
2009-01-04 01:17:51 +00:00
|
|
|
Site* s = it.next();
|
2009-01-11 22:53:51 +00:00
|
|
|
if (accept(c, s, read, typeMask, registerMask, frameIndex)) {
|
2009-01-04 01:17:51 +00:00
|
|
|
unsigned v = s->copyCost(c, target);
|
|
|
|
if (v < copyCost) {
|
|
|
|
site = s;
|
|
|
|
copyCost = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DebugMoves and site and target) {
|
|
|
|
char srcb[256]; site->toString(c, srcb, 256);
|
|
|
|
char dstb[256]; target->toString(c, dstb, 256);
|
|
|
|
fprintf(stderr, "pick source %s to %s for %p cost %d\n",
|
2009-01-04 20:35:09 +00:00
|
|
|
srcb, dstb, read->value, copyCost);
|
2009-01-04 01:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cost) *cost = copyCost;
|
|
|
|
return site;
|
|
|
|
}
|
|
|
|
|
|
|
|
Site*
|
|
|
|
readSource(Context* c, Stack* stack, Local* locals, Read* r)
|
|
|
|
{
|
2008-12-20 21:55:45 +00:00
|
|
|
if (DebugReads) {
|
2009-01-04 19:38:31 +00:00
|
|
|
char buffer[1024]; sitesToString(c, r->value, buffer, 1024);
|
2008-12-20 21:55:45 +00:00
|
|
|
fprintf(stderr, "read source for %p from %s\n", r->value, buffer);
|
|
|
|
}
|
2008-05-15 20:00:57 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
if (not hasSite(r->value)) return 0;
|
|
|
|
|
|
|
|
Site* site = pickSourceSite(c, r);
|
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 {
|
2009-01-03 00:44:47 +00:00
|
|
|
Site* target = pickTargetSite(c, r, true);
|
2008-08-30 20:12:27 +00:00
|
|
|
unsigned copyCost;
|
2009-01-11 18:48:02 +00:00
|
|
|
site = pickSourceSite(c, r, target, ©Cost, ~0, false);
|
2008-08-30 20:12:27 +00:00
|
|
|
assert(c, copyCost);
|
2008-10-04 17:26:35 +00:00
|
|
|
move(c, stack, locals, r->size, r->value, site, 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
|
|
|
}
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
void
|
|
|
|
propagateJunctionSites(Context* c, Event* e, Site** sites)
|
2008-07-23 23:58:29 +00:00
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
for (Link* pl = e->predecessors; pl; pl = pl->nextPredecessor) {
|
|
|
|
Event* p = pl->predecessor;
|
|
|
|
if (p->junctionSites == 0) {
|
|
|
|
p->junctionSites = sites;
|
|
|
|
for (Link* sl = p->successors; sl; sl = sl->nextSuccessor) {
|
|
|
|
Event* s = sl->successor;
|
|
|
|
propagateJunctionSites(c, s, sites);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
void
|
|
|
|
propagateJunctionSites(Context* c, Event* e)
|
|
|
|
{
|
|
|
|
for (Link* sl = e->successors; sl; sl = sl->nextSuccessor) {
|
|
|
|
Event* s = sl->successor;
|
|
|
|
if (s->predecessors->nextPredecessor) {
|
|
|
|
unsigned size = sizeof(Site*) * frameFootprint(c, e->stackAfter);
|
|
|
|
Site** junctionSites = static_cast<Site**>
|
|
|
|
(c->zone->allocate(size));
|
|
|
|
memset(junctionSites, 0, size);
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
propagateJunctionSites(c, s, junctionSites);
|
|
|
|
break;
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
2009-01-04 01:17:51 +00:00
|
|
|
}
|
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
class SiteRecord {
|
|
|
|
public:
|
|
|
|
SiteRecord(Site* site, Value* value, unsigned size):
|
|
|
|
site(site), value(value), size(size)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
SiteRecord() { }
|
|
|
|
|
|
|
|
Site* site;
|
|
|
|
Value* value;
|
|
|
|
unsigned size;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SiteRecordList {
|
|
|
|
public:
|
|
|
|
SiteRecordList(SiteRecord* records, unsigned capacity):
|
|
|
|
records(records), index(0), capacity(capacity)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
SiteRecord* records;
|
|
|
|
unsigned index;
|
|
|
|
unsigned capacity;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
freeze(Context* c, SiteRecordList* frozen, Site* s, Value* v, unsigned size)
|
|
|
|
{
|
|
|
|
assert(c, frozen->index < frozen->capacity);
|
|
|
|
|
|
|
|
s->freeze(c, v, size);
|
|
|
|
new (frozen->records + (frozen->index ++)) SiteRecord(s, v, size);
|
|
|
|
}
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
void
|
2009-01-11 22:53:51 +00:00
|
|
|
thaw(Context* c, SiteRecordList* frozen)
|
|
|
|
{
|
|
|
|
while (frozen->index) {
|
|
|
|
SiteRecord* sr = frozen->records + (-- frozen->index);
|
|
|
|
sr->site->thaw(c, sr->value, sr->size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Site*
|
|
|
|
acquireSite(Context* c, Event* e, SiteRecordList* frozen, Site* target,
|
|
|
|
Value* v, Read* r, bool pickSource)
|
2009-01-04 01:17:51 +00:00
|
|
|
{
|
|
|
|
assert(c, hasSite(v));
|
2008-11-01 22:16:18 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
unsigned copyCost;
|
2009-01-11 22:53:51 +00:00
|
|
|
Site* source;
|
|
|
|
if (pickSource) {
|
|
|
|
source = pickSourceSite(c, r, target, ©Cost, ~0, false);
|
|
|
|
} else {
|
|
|
|
copyCost = 0;
|
|
|
|
source = target;
|
|
|
|
}
|
2009-01-04 01:17:51 +00:00
|
|
|
|
|
|
|
if (copyCost) {
|
|
|
|
target = target->copy(c);
|
2009-01-11 22:53:51 +00:00
|
|
|
move(c, e->stackAfter, e->localsAfter, r->size, v, source, target);
|
2009-01-04 01:17:51 +00:00
|
|
|
} else {
|
2009-01-11 22:53:51 +00:00
|
|
|
target = source;
|
2009-01-04 01:17:51 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
freeze(c, frozen, target, v, r->size);
|
|
|
|
|
|
|
|
return target;
|
2009-01-04 01:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2009-01-11 22:53:51 +00:00
|
|
|
resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen,
|
|
|
|
Site** sites)
|
2009-01-04 01:17:51 +00:00
|
|
|
{
|
|
|
|
bool complete = true;
|
|
|
|
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
|
|
|
FrameIterator::Element el = it.next(c);
|
2009-01-11 22:53:51 +00:00
|
|
|
Value* v = el.value;
|
|
|
|
Read* r = live(v);
|
|
|
|
|
|
|
|
if (r) {
|
2009-01-04 21:52:46 +00:00
|
|
|
if (sites[el.localIndex]) {
|
2009-01-04 01:17:51 +00:00
|
|
|
if (DebugControl) {
|
|
|
|
char buffer[256];
|
2009-01-04 21:52:46 +00:00
|
|
|
sites[el.localIndex]->toString(c, buffer, 256);
|
2009-01-04 01:17:51 +00:00
|
|
|
fprintf(stderr, "resolve original %s for %p local %d frame %d\n",
|
|
|
|
buffer, el.value, el.localIndex, frameIndex(c, &el));
|
|
|
|
}
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
acquireSite(c, e, frozen, sites[el.localIndex], v, r, true);
|
2009-01-04 01:17:51 +00:00
|
|
|
} else {
|
|
|
|
complete = false;
|
2008-11-26 02:23:47 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
2009-01-04 01:17:51 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
return complete;
|
|
|
|
}
|
2008-10-12 00:23:08 +00:00
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
bool
|
2009-01-11 22:53:51 +00:00
|
|
|
resolveSourceSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites)
|
2009-01-04 01:17:51 +00:00
|
|
|
{
|
|
|
|
bool complete = true;
|
|
|
|
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
|
|
|
FrameIterator::Element el = it.next(c);
|
|
|
|
Value* v = el.value;
|
|
|
|
Read* r = live(v);
|
|
|
|
|
2009-01-04 21:52:46 +00:00
|
|
|
if (r and sites[el.localIndex] == 0) {
|
2009-01-04 01:17:51 +00:00
|
|
|
const uint32_t mask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
Site* s = pickSourceSite
|
|
|
|
(c, r, 0, 0, mask, true, false, acceptForResolve);
|
2009-01-04 01:17:51 +00:00
|
|
|
if (s == 0) {
|
2009-01-11 22:53:51 +00:00
|
|
|
s = pickSourceSite(c, r, 0, 0, mask, false, false, acceptForResolve);
|
2009-01-04 01:17:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (s) {
|
|
|
|
if (DebugControl) {
|
|
|
|
char buffer[256]; s->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "resolve source %s from %p local %d frame %d\n",
|
|
|
|
buffer, v, el.localIndex, frameIndex(c, &el));
|
|
|
|
}
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
sites[el.localIndex] = acquireSite
|
|
|
|
(c, e, frozen, s, v, r, false)->copy(c);
|
2009-01-04 01:17:51 +00:00
|
|
|
} else {
|
|
|
|
complete = false;
|
|
|
|
}
|
2008-11-02 22:25:51 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
|
2009-01-04 01:17:51 +00:00
|
|
|
return complete;
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-01-11 22:53:51 +00:00
|
|
|
resolveTargetSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites)
|
2008-07-23 23:58:29 +00:00
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
|
|
|
FrameIterator::Element el = it.next(c);
|
2009-01-11 22:53:51 +00:00
|
|
|
Value* v = el.value;
|
|
|
|
Read* r = live(v);
|
2009-01-04 01:17:51 +00:00
|
|
|
|
2009-01-04 21:52:46 +00:00
|
|
|
if (r and sites[el.localIndex] == 0) {
|
|
|
|
const uint32_t mask = (1 << RegisterOperand) | (1 << MemoryOperand);
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
bool useTarget = false;
|
|
|
|
Site* s = pickSourceSite(c, r, 0, 0, mask, true, true, acceptForResolve);
|
2009-01-04 21:52:46 +00:00
|
|
|
if (s == 0) {
|
2009-01-11 22:53:51 +00:00
|
|
|
s = pickSourceSite(c, r, 0, 0, mask, false, true, acceptForResolve);
|
2009-01-04 21:52:46 +00:00
|
|
|
if (s == 0) {
|
2009-01-11 18:48:02 +00:00
|
|
|
s = pickTargetSite(c, r, false, false);
|
2009-01-11 22:53:51 +00:00
|
|
|
useTarget = true;
|
2009-01-04 21:52:46 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-04 01:17:51 +00:00
|
|
|
|
|
|
|
if (DebugControl) {
|
|
|
|
char buffer[256]; s->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "resolve target %s for %p local %d frame %d\n",
|
|
|
|
buffer, el.value, el.localIndex, frameIndex(c, &el));
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
2009-01-04 01:17:51 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
Site* acquired = acquireSite(c, e, frozen, s, v, r, useTarget)->copy(c);
|
2009-01-04 01:17:51 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
sites[el.localIndex] = (useTarget ? s : acquired->copy(c));
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
void
|
2009-01-11 22:53:51 +00:00
|
|
|
resolveJunctionSites(Context* c, Event* e, SiteRecordList* frozen)
|
2008-08-16 17:45:36 +00:00
|
|
|
{
|
2009-01-04 01:17:51 +00:00
|
|
|
bool complete;
|
2008-12-12 01:09:36 +00:00
|
|
|
if (e->junctionSites) {
|
2009-01-11 22:53:51 +00:00
|
|
|
complete = resolveOriginalSites(c, e, frozen, e->junctionSites);
|
2008-12-12 01:09:36 +00:00
|
|
|
} else {
|
2009-01-04 01:17:51 +00:00
|
|
|
propagateJunctionSites(c, e);
|
|
|
|
complete = false;
|
2008-12-12 01:09:36 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-12-12 01:09:36 +00:00
|
|
|
if (e->junctionSites) {
|
2009-01-04 21:52:46 +00:00
|
|
|
if (not complete) {
|
2009-01-11 22:53:51 +00:00
|
|
|
complete = resolveSourceSites(c, e, frozen, e->junctionSites);
|
2009-01-04 21:52:46 +00:00
|
|
|
if (not complete) {
|
2009-01-11 22:53:51 +00:00
|
|
|
resolveTargetSites(c, e, frozen, e->junctionSites);
|
2009-01-04 21:52:46 +00:00
|
|
|
}
|
2008-12-12 01:09:36 +00:00
|
|
|
}
|
2008-10-25 02:12:02 +00:00
|
|
|
|
2008-12-12 01:09:36 +00:00
|
|
|
if (DebugControl) {
|
|
|
|
fprintf(stderr, "resolved junction sites %p at %d\n",
|
|
|
|
e->junctionSites, e->logicalInstruction->index);
|
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-12-12 01:09:36 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
void
|
|
|
|
resolveBranchSites(Context* c, Event* e, SiteRecordList* frozen)
|
2008-12-12 01:09:36 +00:00
|
|
|
{
|
2009-01-11 18:48:02 +00:00
|
|
|
if (e->successors->nextSuccessor and e->junctionSites == 0) {
|
2009-01-11 22:53:51 +00:00
|
|
|
unsigned footprint = frameFootprint(c, e->stackAfter);
|
|
|
|
Site* branchSites[footprint];
|
|
|
|
memset(branchSites, 0, sizeof(Site*) * footprint);
|
2009-01-04 21:52:46 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
if (not resolveSourceSites(c, e, frozen, branchSites)) {
|
|
|
|
resolveTargetSites(c, e, frozen, branchSites);
|
2009-01-04 21:52:46 +00:00
|
|
|
}
|
2009-01-11 18:48:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
captureBranchSnapshots(Context* c, Event* e)
|
|
|
|
{
|
|
|
|
if (e->successors->nextSuccessor) {
|
2008-11-01 19:14:13 +00:00
|
|
|
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
|
|
|
FrameIterator::Element el = it.next(c);
|
2008-11-07 00:39:38 +00:00
|
|
|
e->snapshots = makeSnapshots(c, el.value, e->snapshots);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (SavedValue* sv = e->successors->forkState->saved; sv; sv = sv->next) {
|
|
|
|
e->snapshots = makeSnapshots(c, sv->value, e->snapshots);
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugControl) {
|
|
|
|
fprintf(stderr, "captured snapshots %p at %d\n",
|
|
|
|
e->snapshots, e->logicalInstruction->index);
|
|
|
|
}
|
2008-11-01 22:16:18 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-04-17 02:55:38 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
void
|
|
|
|
populateSiteTables(Context* c, Event* e, SiteRecordList* frozen)
|
2008-12-12 01:09:36 +00:00
|
|
|
{
|
2009-01-11 22:53:51 +00:00
|
|
|
resolveJunctionSites(c, e, frozen);
|
2008-12-13 19:59:02 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
resolveBranchSites(c, e, frozen);
|
2009-01-11 18:48:02 +00:00
|
|
|
|
2008-12-13 19:59:02 +00:00
|
|
|
captureBranchSnapshots(c, e);
|
2008-12-12 01:09:36 +00:00
|
|
|
}
|
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
void
|
2008-11-01 22:16:18 +00:00
|
|
|
setSites(Context* c, Event* e, Value* v, Site* s, unsigned size)
|
2008-10-12 00:23:08 +00:00
|
|
|
{
|
2008-12-16 01:21:01 +00:00
|
|
|
assert(c, live(v));
|
|
|
|
|
2008-10-12 00:23:08 +00:00
|
|
|
for (; s; s = s->next) {
|
2008-11-01 22:16:18 +00:00
|
|
|
addSite(c, e->stackBefore, e->localsBefore, size, v, s->copy(c));
|
2008-10-12 00:23:08 +00:00
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugControl) {
|
2009-01-04 01:17:51 +00:00
|
|
|
char buffer[256]; sitesToString(c, v->sites, buffer, 256);
|
2008-11-02 22:25:51 +00:00
|
|
|
fprintf(stderr, "set sites %s for %p\n", buffer, v);
|
|
|
|
}
|
2008-10-12 00:23:08 +00:00
|
|
|
}
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
void
|
2008-11-01 22:16:18 +00:00
|
|
|
resetFrame(Context* c, Event* e)
|
2008-08-16 17:45:36 +00:00
|
|
|
{
|
2008-11-01 19:14:13 +00:00
|
|
|
for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) {
|
|
|
|
FrameIterator::Element el = it.next(c);
|
|
|
|
clearSites(c, el.value);
|
2008-10-12 00:23:08 +00:00
|
|
|
}
|
2008-11-01 22:16:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setSites(Context* c, Event* e, Site** sites)
|
|
|
|
{
|
|
|
|
resetFrame(c, e);
|
2008-10-12 00:23:08 +00:00
|
|
|
|
2008-11-01 19:14:13 +00:00
|
|
|
for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) {
|
|
|
|
FrameIterator::Element el = it.next(c);
|
2008-11-01 22:16:18 +00:00
|
|
|
if (sites[el.localIndex]) {
|
|
|
|
Read* r = live(el.value);
|
|
|
|
if (r) {
|
|
|
|
setSites(c, e, el.value, sites[el.localIndex], r->size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-13 19:59:02 +00:00
|
|
|
void
|
|
|
|
removeBuddies(Context* c)
|
|
|
|
{
|
|
|
|
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
|
|
|
|
FrameIterator::Element el = it.next(c);
|
|
|
|
removeBuddy(c, el.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
void
|
|
|
|
restore(Context* c, Event* e, Snapshot* snapshots)
|
|
|
|
{
|
|
|
|
for (Snapshot* s = snapshots; s; s = s->next) {
|
2008-11-02 22:25:51 +00:00
|
|
|
// char buffer[256]; toString(c, s->sites, buffer, 256);
|
|
|
|
// fprintf(stderr, "restore %p buddy %p sites %s\n",
|
|
|
|
// s->value, s->value->buddy, buffer);
|
2008-11-01 22:16:18 +00:00
|
|
|
|
|
|
|
s->value->buddy = s->buddy;
|
|
|
|
}
|
|
|
|
|
|
|
|
resetFrame(c, e);
|
|
|
|
|
|
|
|
for (Snapshot* s = snapshots; s; s = s->next) {
|
|
|
|
if (live(s->value)) {
|
|
|
|
Read* r = live(s->value);
|
2008-11-02 20:35:35 +00:00
|
|
|
if (r and s->sites and s->value->sites == 0) {
|
2008-11-01 22:16:18 +00:00
|
|
|
setSites(c, e, s->value, s->sites, r->size);
|
|
|
|
}
|
2008-10-12 00:23:08 +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
|
|
|
void
|
|
|
|
populateSources(Context* c, Event* e)
|
|
|
|
{
|
2009-01-11 22:53:51 +00:00
|
|
|
SiteRecord frozenRecords[e->readCount];
|
|
|
|
SiteRecordList frozen(frozenRecords, e->readCount);
|
2009-01-04 21:52:46 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
for (Read* r = e->reads; r; r = r->eventNext) {
|
2008-10-04 17:26:35 +00:00
|
|
|
r->value->source = readSource(c, e->stackBefore, e->localsBefore, r);
|
2008-08-16 17:45:36 +00:00
|
|
|
|
|
|
|
if (r->value->source) {
|
2008-12-20 21:55:45 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
char buffer[256]; r->value->source->toString(c, buffer, 256);
|
|
|
|
fprintf(stderr, "freeze source %s for %p\n",
|
|
|
|
buffer, r->value);
|
|
|
|
}
|
2008-12-12 01:09:36 +00:00
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
freeze(c, &frozen, r->value->source, r->value, r->size);
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
thaw(c, &frozen);
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
2008-07-23 23:58:29 +00:00
|
|
|
|
2008-09-22 00:58:54 +00:00
|
|
|
void
|
2008-12-15 14:35:19 +00:00
|
|
|
setStubRead(Context* c, StubReadPair* p, Value* v, unsigned size)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
2008-11-01 19:14:13 +00:00
|
|
|
if (v) {
|
2008-10-14 00:18:18 +00:00
|
|
|
StubRead* r = stubRead(c, size);
|
2008-12-15 14:35:19 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "add stub read %p to %p\n", r, v);
|
|
|
|
}
|
2008-10-14 00:18:18 +00:00
|
|
|
addRead(c, 0, v, r);
|
2008-09-22 00:58:54 +00:00
|
|
|
|
|
|
|
p->value = v;
|
|
|
|
p->read = r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-10-14 00:18:18 +00:00
|
|
|
populateJunctionReads(Context* c, Link* link)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
2008-10-14 00:18:18 +00:00
|
|
|
JunctionState* state = new
|
|
|
|
(c->zone->allocate
|
|
|
|
(sizeof(JunctionState)
|
|
|
|
+ (sizeof(StubReadPair) * frameFootprint(c, c->stack))))
|
2008-12-15 14:35:19 +00:00
|
|
|
JunctionState(frameFootprint(c, c->stack));
|
2008-09-22 14:28:18 +00:00
|
|
|
|
2008-12-15 14:35:19 +00:00
|
|
|
memset(state->reads, 0, sizeof(StubReadPair) * frameFootprint(c, c->stack));
|
2008-10-14 00:18:18 +00:00
|
|
|
|
2008-12-15 14:35:19 +00:00
|
|
|
link->junctionState = state;
|
2008-11-01 19:14:13 +00:00
|
|
|
|
|
|
|
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
|
|
|
|
FrameIterator::Element e = it.next(c);
|
2008-12-15 14:35:19 +00:00
|
|
|
setStubRead(c, state->reads + e.localIndex, e.value,
|
|
|
|
footprintSizeInBytes(e.footprint));
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-12-15 14:35:19 +00:00
|
|
|
updateJunctionReads(Context* c, JunctionState* state)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
2008-12-15 14:35:19 +00:00
|
|
|
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
|
|
|
|
FrameIterator::Element e = it.next(c);
|
|
|
|
StubReadPair* p = state->reads + e.localIndex;
|
|
|
|
if (p->value and p->read->read == 0) {
|
|
|
|
Read* r = live(e.value);
|
2008-12-12 01:09:36 +00:00
|
|
|
if (r) {
|
2008-12-15 14:35:19 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "stub read %p for %p valid: %p\n",
|
|
|
|
p->read, p->value, r);
|
|
|
|
}
|
2008-12-12 01:09:36 +00:00
|
|
|
p->read->read = r;
|
|
|
|
}
|
|
|
|
}
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
2008-12-15 14:35:19 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < frameFootprint(c, c->stack); ++i) {
|
|
|
|
StubReadPair* p = state->reads + i;
|
|
|
|
if (p->value and p->read->read == 0) {
|
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "stub read %p for %p invalid\n", p->read, p->value);
|
|
|
|
}
|
|
|
|
p->read->valid_ = false;
|
|
|
|
}
|
|
|
|
}
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
|
|
|
|
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-11-07 00:39:38 +00:00
|
|
|
head(head), nextBlock(0), 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;
|
2008-11-07 00:39:38 +00:00
|
|
|
Block* nextBlock;
|
2008-08-16 17:45:36 +00:00
|
|
|
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)
|
|
|
|
{
|
2008-11-08 23:21:30 +00:00
|
|
|
if (c->logicalCode[c->logicalIp]->lastEvent == 0) {
|
2008-10-05 00:14:43 +00:00
|
|
|
appendDummy(c);
|
|
|
|
}
|
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
Assembler* a = c->assembler;
|
|
|
|
|
|
|
|
c->pass = CompilePass;
|
|
|
|
|
|
|
|
Block* firstBlock = block(c, c->firstEvent);
|
|
|
|
Block* block = firstBlock;
|
|
|
|
|
2008-09-28 19:00:52 +00:00
|
|
|
a->allocateFrame(c->alignedFrameSize);
|
2008-08-16 17:45:36 +00:00
|
|
|
|
|
|
|
for (Event* e = c->firstEvent; e; e = e->next) {
|
2008-09-15 02:28:42 +00:00
|
|
|
if (DebugCompile) {
|
|
|
|
fprintf(stderr,
|
2008-11-09 23:56:37 +00:00
|
|
|
" -- compile %s at %d with %d preds %d succs %d stack\n",
|
2008-09-15 02:28:42 +00:00
|
|
|
e->name(), e->logicalInstruction->index,
|
2008-10-14 00:18:18 +00:00
|
|
|
countPredecessors(e->predecessors),
|
|
|
|
countSuccessors(e->successors),
|
2008-10-04 17:26:35 +00:00
|
|
|
e->stackBefore ?
|
2008-11-09 23:56:37 +00:00
|
|
|
e->stackBefore->index + e->stackBefore->footprint : 0);
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
|
|
|
|
2008-10-15 00:45:31 +00:00
|
|
|
e->block = block;
|
|
|
|
|
|
|
|
c->stack = e->stackBefore;
|
|
|
|
c->locals = e->localsBefore;
|
|
|
|
|
2008-09-07 01:37:12 +00:00
|
|
|
if (e->logicalInstruction->machineOffset == 0) {
|
|
|
|
e->logicalInstruction->machineOffset = a->offset();
|
|
|
|
}
|
|
|
|
|
2008-09-07 20:12:11 +00:00
|
|
|
if (e->predecessors) {
|
2008-10-15 00:45:31 +00:00
|
|
|
visit(c, lastPredecessor(e->predecessors));
|
2008-10-14 00:18:18 +00:00
|
|
|
|
|
|
|
Event* first = e->predecessors->predecessor;
|
|
|
|
if (e->predecessors->nextPredecessor) {
|
|
|
|
for (Link* pl = e->predecessors;
|
|
|
|
pl->nextPredecessor;
|
|
|
|
pl = pl->nextPredecessor)
|
|
|
|
{
|
|
|
|
updateJunctionReads(c, pl->junctionState);
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
2008-11-02 22:25:51 +00:00
|
|
|
|
|
|
|
if (DebugControl) {
|
|
|
|
fprintf(stderr, "set sites to junction sites %p at %d\n",
|
|
|
|
first->junctionSites, first->logicalInstruction->index);
|
|
|
|
}
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
setSites(c, e, first->junctionSites);
|
2008-12-13 19:59:02 +00:00
|
|
|
removeBuddies(c);
|
2008-10-14 00:18:18 +00:00
|
|
|
} else if (first->successors->nextSuccessor) {
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugControl) {
|
|
|
|
fprintf(stderr, "restore snapshots %p at %d\n",
|
|
|
|
first->snapshots, first->logicalInstruction->index);
|
|
|
|
}
|
|
|
|
|
2008-11-01 22:16:18 +00:00
|
|
|
restore(c, e, first->snapshots);
|
2008-09-07 20:12:11 +00:00
|
|
|
}
|
2008-08-16 17:45:36 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
unsigned footprint = frameFootprint(c, e->stackAfter);
|
|
|
|
SiteRecord frozenRecords[footprint];
|
|
|
|
SiteRecordList frozen(frozenRecords, footprint);
|
2008-08-16 17:45:36 +00:00
|
|
|
|
2008-10-08 00:08:13 +00:00
|
|
|
bool branch = e->isBranch();
|
|
|
|
if (branch and e->successors) {
|
2009-01-11 22:53:51 +00:00
|
|
|
populateSiteTables(c, e, &frozen);
|
2008-10-08 00:08:13 +00:00
|
|
|
}
|
|
|
|
|
2009-01-11 18:48:02 +00:00
|
|
|
populateSources(c, e);
|
|
|
|
|
2009-01-11 22:53:51 +00:00
|
|
|
thaw(c, &frozen);
|
2009-01-11 18:48:02 +00:00
|
|
|
|
2008-08-16 17:45:36 +00:00
|
|
|
e->compile(c);
|
|
|
|
|
2008-10-08 00:08:13 +00:00
|
|
|
if ((not branch) and e->successors) {
|
2009-01-11 22:53:51 +00:00
|
|
|
populateSiteTables(c, e, &frozen);
|
|
|
|
thaw(c, &frozen);
|
2008-07-23 23:58:29 +00:00
|
|
|
}
|
|
|
|
|
2008-10-15 00:45:31 +00:00
|
|
|
if (e->visitLinks) {
|
|
|
|
for (Cell* cell = reverseDestroy(e->visitLinks); cell; cell = cell->next)
|
|
|
|
{
|
|
|
|
visit(c, static_cast<Link*>(cell->value));
|
|
|
|
}
|
|
|
|
e->visitLinks = 0;
|
2008-10-14 00:18:18 +00:00
|
|
|
}
|
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-11-07 00:39:38 +00:00
|
|
|
Block* b = e->logicalInstruction->firstEvent->block;
|
|
|
|
if (b != block) {
|
|
|
|
while (b->nextBlock) b = b->nextBlock;
|
|
|
|
b->nextBlock = block;
|
|
|
|
}
|
2008-09-20 23:42:46 +00:00
|
|
|
block->nextInstruction = nextInstruction;
|
|
|
|
block->assemblerBlock = a->endBlock(e->next != 0);
|
2008-11-08 20:47:26 +00:00
|
|
|
// fprintf(stderr, "end block %p at %d\n", block->assemblerBlock, e->logicalInstruction->index);
|
2008-11-07 00:39:38 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
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;
|
2008-11-07 00:39:38 +00:00
|
|
|
while (block->nextBlock or block->nextInstruction) {
|
|
|
|
Block* next = block->nextBlock
|
|
|
|
? block->nextBlock
|
|
|
|
: block->nextInstruction->firstEvent->block;
|
2008-09-07 20:12:11 +00:00
|
|
|
next->start = block->assemblerBlock->resolve
|
|
|
|
(block->start, next->assemblerBlock);
|
2008-11-08 20:47:26 +00:00
|
|
|
// fprintf(stderr, "resolve block %p\n", block->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-11-02 20:35:35 +00:00
|
|
|
restore(Context* c, ForkState* 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-11-02 20:35:35 +00:00
|
|
|
ForkElement* p = state->elements + 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-11-07 00:39:38 +00:00
|
|
|
addForkElement(Context* c, Value* v, unsigned size, ForkState* state,
|
|
|
|
unsigned index)
|
2008-09-22 00:58:54 +00:00
|
|
|
{
|
2008-11-02 20:35:35 +00:00
|
|
|
MultiRead* r = multiRead(c, size);
|
2008-12-15 14:35:19 +00:00
|
|
|
if (DebugReads) {
|
|
|
|
fprintf(stderr, "add multi read %p to %p\n", r, v);
|
|
|
|
}
|
2008-11-02 20:35:35 +00:00
|
|
|
addRead(c, 0, v, r);
|
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
ForkElement* p = state->elements + index;
|
2008-11-02 20:35:35 +00:00
|
|
|
p->value = v;
|
|
|
|
p->read = r;
|
2008-09-22 00:58:54 +00:00
|
|
|
}
|
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
unsigned
|
|
|
|
count(SavedValue* sv)
|
|
|
|
{
|
|
|
|
unsigned count = 0;
|
|
|
|
while (sv) {
|
|
|
|
++ count;
|
|
|
|
sv = sv->next;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
ForkState*
|
2008-09-13 21:09:26 +00:00
|
|
|
saveState(Context* c)
|
2007-12-14 18:27:56 +00:00
|
|
|
{
|
2008-11-07 00:39:38 +00:00
|
|
|
unsigned elementCount = frameFootprint(c, c->stack) + count(c->saved);
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
ForkState* state = new
|
2008-09-22 14:28:18 +00:00
|
|
|
(c->zone->allocate
|
2008-11-07 00:39:38 +00:00
|
|
|
(sizeof(ForkState) + (sizeof(ForkElement) * elementCount)))
|
|
|
|
ForkState(c->stack, c->locals, c->saved, c->predecessor, c->logicalIp);
|
2007-12-14 18:27:56 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
if (c->predecessor) {
|
2008-10-14 00:18:18 +00:00
|
|
|
c->forkState = state;
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
unsigned count = 0;
|
2008-09-15 02:28:42 +00:00
|
|
|
|
2008-11-01 19:14:13 +00:00
|
|
|
for (FrameIterator it(c, c->stack, c->locals); it.hasMore();) {
|
|
|
|
FrameIterator::Element e = it.next(c);
|
2008-11-07 00:39:38 +00:00
|
|
|
addForkElement
|
|
|
|
(c, e.value, footprintSizeInBytes(e.footprint), state, count++);
|
|
|
|
}
|
2008-11-02 20:35:35 +00:00
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
for (SavedValue* sv = c->saved; sv; sv = sv->next) {
|
|
|
|
addForkElement
|
|
|
|
(c, sv->value, footprintSizeInBytes(sv->footprint), state, count++);
|
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;
|
|
|
|
|
2008-11-02 20:35:35 +00:00
|
|
|
restore(c, state);
|
2008-04-20 19:35:36 +00:00
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
c->saved = 0;
|
|
|
|
|
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-10-14 00:18:18 +00:00
|
|
|
restoreState(Context* c, ForkState* s)
|
2007-12-11 23:52:28 +00:00
|
|
|
{
|
2008-11-08 23:21:30 +00:00
|
|
|
if (c->logicalCode[c->logicalIp]->lastEvent == 0) {
|
2008-09-15 02:28:42 +00:00
|
|
|
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-10-14 00:18:18 +00:00
|
|
|
c->forkState = s;
|
2008-11-02 20:35:35 +00:00
|
|
|
restore(c, s);
|
2008-09-07 20:12:11 +00:00
|
|
|
}
|
2008-05-04 20:55:34 +00:00
|
|
|
}
|
|
|
|
|
2008-11-01 19:14:13 +00:00
|
|
|
Value*
|
|
|
|
maybeBuddy(Context* c, Value* v, unsigned sizeInBytes)
|
|
|
|
{
|
2009-01-03 00:44:47 +00:00
|
|
|
if (v->home >= 0) {
|
2008-11-01 19:14:13 +00:00
|
|
|
Value* n = value(c);
|
|
|
|
appendBuddy(c, v, n, sizeInBytes);
|
|
|
|
return n;
|
|
|
|
} else {
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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) {
|
2009-01-03 21:34:45 +00:00
|
|
|
unsigned cost;
|
|
|
|
int r = pickRegisterTarget(c, 0, mask, &cost);
|
|
|
|
expect(c, cost < Target::Impossible);
|
2008-04-30 15:44:17 +00:00
|
|
|
save(r);
|
2009-01-03 00:44:47 +00:00
|
|
|
increment(c, c->registerResources + r);
|
2008-03-13 23:43:11 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void releaseTemporary(int r) {
|
2009-01-03 00:44:47 +00:00
|
|
|
decrement(c, c->registerResources + 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) {
|
2009-01-03 00:44:47 +00:00
|
|
|
RegisterResource* reg = c->registerResources + r;
|
2009-01-11 18:48:02 +00:00
|
|
|
|
2008-12-24 20:35:43 +00:00
|
|
|
assert(c, reg->referenceCount == 0);
|
2009-01-11 18:48:02 +00:00
|
|
|
assert(c, reg->freezeCount == 0);
|
|
|
|
assert(c, not reg->reserved);
|
|
|
|
|
|
|
|
if (reg->value) {
|
|
|
|
steal(c, reg, 0, c->stack, c->locals);
|
|
|
|
}
|
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) {
|
2008-10-14 00:18:18 +00:00
|
|
|
::restoreState(&c, static_cast<ForkState*>(state));
|
2008-04-28 15:53:48 +00:00
|
|
|
}
|
|
|
|
|
2008-11-14 00:59:21 +00:00
|
|
|
virtual Subroutine* startSubroutine() {
|
|
|
|
return c.subroutine = new (c.zone->allocate(sizeof(MySubroutine)))
|
|
|
|
MySubroutine;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void endSubroutine(Subroutine* subroutine) {
|
|
|
|
MySubroutine* sr = static_cast<MySubroutine*>(subroutine);
|
|
|
|
if (sr->forkState) {
|
|
|
|
::restoreState(&c, sr->forkState);
|
|
|
|
} else {
|
|
|
|
sr->forkState = ::saveState(&c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-19 04:31:52 +00:00
|
|
|
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
|
2008-09-28 19:00:52 +00:00
|
|
|
unsigned localFootprint, unsigned alignedFrameSize)
|
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-09-28 19:00:52 +00:00
|
|
|
c.alignedFrameSize = alignedFrameSize;
|
2008-05-19 04:31:52 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
unsigned frameResourceCount = alignedFrameSize + parameterFootprint;
|
2008-09-28 21:56:12 +00:00
|
|
|
|
|
|
|
c.frameResources = static_cast<FrameResource*>
|
2009-01-03 21:34:45 +00:00
|
|
|
(c.zone->allocate(sizeof(FrameResource) * frameResourceCount));
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < frameResourceCount; ++i) {
|
|
|
|
new (c.frameResources + i) FrameResource;
|
|
|
|
}
|
2008-09-28 21:56:12 +00:00
|
|
|
|
2008-11-08 23:21:30 +00:00
|
|
|
// leave room for logical instruction -1
|
|
|
|
unsigned codeSize = sizeof(LogicalInstruction*)
|
|
|
|
* (logicalCodeLength + 1);
|
2008-08-16 17:45:36 +00:00
|
|
|
c.logicalCode = static_cast<LogicalInstruction**>
|
2008-11-08 23:21:30 +00:00
|
|
|
(c.zone->allocate(codeSize));
|
|
|
|
memset(c.logicalCode, 0, codeSize);
|
|
|
|
c.logicalCode++;
|
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);
|
2008-11-08 23:21:30 +00:00
|
|
|
|
|
|
|
c.logicalCode[-1] = new
|
|
|
|
(c.zone->allocate(sizeof(LogicalInstruction)))
|
|
|
|
LogicalInstruction(-1, c.stack, c.locals);
|
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);
|
|
|
|
|
2008-11-08 23:21:30 +00:00
|
|
|
if (c.logicalCode[c.logicalIp]->lastEvent == 0) {
|
2008-11-07 00:39:38 +00:00
|
|
|
appendDummy(&c);
|
|
|
|
}
|
|
|
|
|
2008-09-15 02:28:42 +00:00
|
|
|
Event* e = c.logicalCode[logicalIp]->firstEvent;
|
|
|
|
|
2008-10-04 17:26:35 +00:00
|
|
|
Event* p = c.predecessor;
|
|
|
|
if (p) {
|
2008-12-23 01:25:00 +00:00
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, "visit %d pred %d\n", logicalIp,
|
|
|
|
p->logicalInstruction->index);
|
|
|
|
}
|
2008-11-07 00:39:38 +00:00
|
|
|
|
2008-10-04 17:26:35 +00:00
|
|
|
p->stackAfter = c.stack;
|
|
|
|
p->localsAfter = c.locals;
|
|
|
|
|
2008-10-14 00:18:18 +00:00
|
|
|
Link* link = ::link
|
|
|
|
(&c, p, e->predecessors, e, p->successors, c.forkState);
|
|
|
|
e->predecessors = link;
|
|
|
|
p->successors = link;
|
2008-10-15 00:45:31 +00:00
|
|
|
c.lastEvent->visitLinks = cons(&c, link, c.lastEvent->visitLinks);
|
2008-10-14 00:18:18 +00:00
|
|
|
|
2008-12-23 01:25:00 +00:00
|
|
|
if (DebugAppend) {
|
|
|
|
fprintf(stderr, "populate junction reads for %d to %d\n",
|
|
|
|
p->logicalInstruction->index, logicalIp);
|
|
|
|
}
|
|
|
|
|
2008-12-12 01:09:36 +00:00
|
|
|
populateJunctionReads(&c, link);
|
2008-09-15 02:28:42 +00:00
|
|
|
}
|
2008-10-14 00:18:18 +00:00
|
|
|
|
2008-11-14 00:59:21 +00:00
|
|
|
if (c.subroutine) {
|
|
|
|
c.subroutine->forkState
|
|
|
|
= c.logicalCode[logicalIp]->subroutine->forkState;
|
|
|
|
c.subroutine = 0;
|
|
|
|
}
|
|
|
|
|
2008-12-12 01:09:36 +00:00
|
|
|
c.forkState = 0;
|
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-11-08 23:21:30 +00:00
|
|
|
if (c.logicalCode[c.logicalIp]->lastEvent == 0) {
|
2008-09-13 21:09:26 +00:00
|
|
|
appendDummy(&c);
|
|
|
|
}
|
2008-04-20 19:35:36 +00:00
|
|
|
|
2008-10-06 00:50:59 +00:00
|
|
|
Event* p = c.predecessor;
|
|
|
|
if (p) {
|
|
|
|
p->stackAfter = c.stack;
|
|
|
|
p->localsAfter = c.locals;
|
|
|
|
}
|
|
|
|
|
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-11-14 00:59:21 +00:00
|
|
|
if (c.subroutine) {
|
|
|
|
c.logicalCode[logicalIp]->subroutine = c.subroutine;
|
|
|
|
c.subroutine = 0;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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-11-02 22:25:51 +00:00
|
|
|
virtual void push(unsigned footprint) {
|
|
|
|
assert(&c, footprint);
|
2008-04-27 20:15:18 +00:00
|
|
|
|
2008-11-02 20:35:35 +00:00
|
|
|
Value* v = value(&c);
|
2009-01-03 00:44:47 +00:00
|
|
|
Stack* s = ::stack(&c, v, footprint, c.stack);
|
2009-01-03 21:34:45 +00:00
|
|
|
v->home = frameIndex(&c, s->index + c.localFootprint, s->footprint);
|
2009-01-03 00:44:47 +00:00
|
|
|
c.stack = s;
|
2008-04-26 20:56:03 +00:00
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual void push(unsigned footprint, Operand* value) {
|
|
|
|
::push(&c, footprint, static_cast<Value*>(value));
|
2007-12-22 00:26:55 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-11-14 00:59:21 +00:00
|
|
|
virtual void save(unsigned footprint, Operand* value) {
|
|
|
|
c.saved = savedValue(&c, static_cast<Value*>(value), footprint, c.saved);
|
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual Operand* pop(unsigned footprint) {
|
|
|
|
return ::pop(&c, footprint);
|
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
|
2008-10-04 17:26:35 +00:00
|
|
|
(&c, v, BytesPerWord,
|
2008-10-25 02:12:02 +00:00
|
|
|
frameIndex(&c, (c.stack ? c.stack->index : 0) + c.localFootprint, 1));
|
2008-09-25 00:48:32 +00:00
|
|
|
|
2009-01-03 00:44:47 +00:00
|
|
|
Stack* s = ::stack(&c, v, 1, c.stack);
|
2009-01-03 21:34:45 +00:00
|
|
|
v->home = frameIndex(&c, s->index + c.localFootprint, s->footprint);
|
2009-01-03 00:44:47 +00:00
|
|
|
c.stack = s;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
virtual void popped() {
|
2009-01-03 00:44:47 +00:00
|
|
|
assert(&c, c.stack->value->home >= 0);
|
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
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual unsigned footprint(StackElement* e) {
|
|
|
|
return static_cast<Stack*>(e)->footprint;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
|
2008-11-11 00:07:44 +00:00
|
|
|
virtual unsigned index(StackElement* e) {
|
|
|
|
return static_cast<Stack*>(e)->index;
|
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual Operand* peek(unsigned footprint 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-11-02 22:25:51 +00:00
|
|
|
i -= s->footprint;
|
2008-04-29 16:55:56 +00:00
|
|
|
s = s->next;
|
2008-02-17 20:57:40 +00:00
|
|
|
}
|
2008-11-02 22:25:51 +00:00
|
|
|
assert(&c, s->footprint == footprint);
|
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
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
Stack* argumentStack = 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) {
|
2009-01-03 21:34:45 +00:00
|
|
|
argumentStack = ::stack
|
|
|
|
(&c, arguments[i], ceiling(argumentSizes[i], BytesPerWord),
|
|
|
|
argumentStack);
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
if (i == index - 1) {
|
2009-01-03 21:34:45 +00:00
|
|
|
bottomArgument = argumentStack;
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
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-11-02 22:25:51 +00:00
|
|
|
virtual void initLocal(unsigned footprint, unsigned index) {
|
2008-09-25 00:48:32 +00:00
|
|
|
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-11-02 22:25:51 +00:00
|
|
|
|
|
|
|
if (DebugFrame) {
|
|
|
|
fprintf(stderr, "init local %p of footprint %d at %d (%d)\n",
|
|
|
|
v, footprint, index, frameIndex(&c, index, footprint));
|
|
|
|
}
|
|
|
|
|
2008-10-25 02:12:02 +00:00
|
|
|
appendFrameSite
|
2008-11-02 22:25:51 +00:00
|
|
|
(&c, v, footprintSizeInBytes(footprint),
|
|
|
|
frameIndex(&c, index, footprint));
|
2008-09-24 00:01:42 +00:00
|
|
|
|
|
|
|
Local* local = c.locals + index;
|
|
|
|
local->value = v;
|
2009-01-03 21:34:45 +00:00
|
|
|
v->home = frameIndex(&c, index, footprint);
|
2008-11-02 22:25:51 +00:00
|
|
|
local->footprint = footprint;
|
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) {
|
2008-10-04 17:26:35 +00:00
|
|
|
Local* local = e->localsBefore + i;
|
2008-09-25 00:48:32 +00:00
|
|
|
if (local->value) {
|
2008-11-02 22:25:51 +00:00
|
|
|
initLocal(local->footprint, i);
|
2008-09-25 00:48:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual void storeLocal(unsigned footprint, 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-11-01 19:14:13 +00:00
|
|
|
Local* local = c.locals + index;
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
unsigned sizeInBytes = sizeof(Local) * c.localFootprint;
|
|
|
|
Local* newLocals = static_cast<Local*>(c.zone->allocate(sizeInBytes));
|
|
|
|
memcpy(newLocals, c.locals, sizeInBytes);
|
2008-09-13 21:09:26 +00:00
|
|
|
c.locals = newLocals;
|
|
|
|
|
2008-11-01 19:14:13 +00:00
|
|
|
local = c.locals + index;
|
2008-11-02 22:25:51 +00:00
|
|
|
local->value = maybeBuddy
|
|
|
|
(&c, static_cast<Value*>(src), footprintSizeInBytes(footprint));
|
2008-11-02 20:35:35 +00:00
|
|
|
|
2008-11-11 00:07:44 +00:00
|
|
|
if (footprint == 2) {
|
|
|
|
Local* clobber = local + 1;
|
|
|
|
clobber->value = 0;
|
|
|
|
clobber->footprint = 0;
|
|
|
|
}
|
|
|
|
|
2008-12-23 00:55:29 +00:00
|
|
|
if (index > 0 and local[-1].footprint == 2) {
|
|
|
|
Local* clobber = local - 1;
|
|
|
|
clobber->value = 0;
|
|
|
|
clobber->footprint = 0;
|
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugFrame) {
|
|
|
|
fprintf(stderr, "store local %p of footprint %d at %d\n",
|
|
|
|
local->value, footprint, index);
|
|
|
|
}
|
2008-11-02 20:35:35 +00:00
|
|
|
|
2009-01-03 21:34:45 +00:00
|
|
|
local->value->home = frameIndex(&c, index, footprint);
|
2008-11-02 22:25:51 +00:00
|
|
|
local->footprint = footprint;
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
virtual Operand* loadLocal(unsigned footprint 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);
|
2009-01-03 21:34:45 +00:00
|
|
|
assert(&c, c.locals[index].value->home >= 0);
|
2008-11-02 22:25:51 +00:00
|
|
|
assert(&c, c.locals[index].footprint == footprint);
|
2008-05-20 19:11:42 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
if (DebugFrame) {
|
|
|
|
fprintf(stderr, "load local %p of size %d at %d\n",
|
|
|
|
c.locals[index].value, footprint, index);
|
|
|
|
}
|
2008-09-25 00:48:32 +00:00
|
|
|
|
2008-09-24 00:01:42 +00:00
|
|
|
return c.locals[index].value;
|
2008-05-19 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
2008-11-25 17:34:48 +00:00
|
|
|
virtual void saveLocals() {
|
|
|
|
appendSaveLocals(&c);
|
|
|
|
}
|
|
|
|
|
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-12-21 21:41:56 +00:00
|
|
|
virtual Operand* load(unsigned srcSize, unsigned dstSize, Operand* src) {
|
|
|
|
assert(&c, dstSize >= BytesPerWord);
|
2007-12-08 23:22:13 +00:00
|
|
|
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* dst = value(&c);
|
2008-12-21 21:41:56 +00:00
|
|
|
appendMove(&c, Move, srcSize, static_cast<Value*>(src), dstSize, dst);
|
2008-02-11 17:21:41 +00:00
|
|
|
return dst;
|
2007-12-08 23:22:13 +00:00
|
|
|
}
|
|
|
|
|
2008-12-21 21:41:56 +00:00
|
|
|
virtual Operand* loadz(unsigned srcSize, unsigned dstSize, Operand* src) {
|
|
|
|
assert(&c, dstSize >= BytesPerWord);
|
|
|
|
|
2008-04-17 20:48:26 +00:00
|
|
|
Value* dst = value(&c);
|
2008-12-21 21:41:56 +00:00
|
|
|
appendMove(&c, MoveZ, srcSize, static_cast<Value*>(src), dstSize, 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
|