diff --git a/makefile b/makefile index 8a3b4a7e81..b83d2d45a7 100755 --- a/makefile +++ b/makefile @@ -962,6 +962,7 @@ ifeq ($(process),compile) $(src)/codegen/compiler/event.cpp \ $(src)/codegen/compiler/promise.cpp \ $(src)/codegen/compiler/frame.cpp \ + $(src)/codegen/compiler/ir.cpp \ $(src)/codegen/registers.cpp \ $(src)/codegen/targets.cpp diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index 5f1f9ab431..23c62a8b5e 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -25,6 +25,7 @@ #include "codegen/compiler/event.h" #include "codegen/compiler/promise.h" #include "codegen/compiler/frame.h" +#include "codegen/compiler/ir.h" using namespace vm; @@ -45,14 +46,6 @@ const unsigned StealRegisterReserveCount = 2; // compare instruction: const unsigned ResolveRegisterReserveCount = (TargetBytesPerWord == 8 ? 2 : 4); -class Stack; -class PushEvent; -class Read; -class MultiRead; -class StubRead; -class Block; -class Snapshot; - void apply(Context* c, lir::UnaryOperation op, unsigned s1Size, Site* s1Low, Site* s1High); @@ -68,57 +61,6 @@ apply(Context* c, lir::TernaryOperation op, unsigned s2Size, Site* s2Low, Site* s2High, unsigned s3Size, Site* s3Low, Site* s3High); -class ForkElement { - public: - Value* value; - MultiRead* read; - bool local; -}; - -class ForkState: public Compiler::State { - public: - ForkState(Stack* stack, Local* locals, Cell* saved, Event* predecessor, - unsigned logicalIp): - stack(stack), - locals(locals), - saved(saved), - predecessor(predecessor), - logicalIp(logicalIp), - readCount(0) - { } - - Stack* stack; - Local* locals; - Cell* saved; - Event* predecessor; - unsigned logicalIp; - unsigned readCount; - ForkElement elements[0]; -}; - -class MySubroutine: public Compiler::Subroutine { - public: - MySubroutine(): forkState(0) { } - - ForkState* forkState; -}; - -class LogicalInstruction { - public: - LogicalInstruction(int index, Stack* stack, Local* locals): - firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack), - locals(locals), machineOffset(0), subroutine(0), index(index) - { } - - Event* firstEvent; - Event* lastEvent; - LogicalInstruction* immediatePredecessor; - Stack* stack; - Local* locals; - Promise* machineOffset; - MySubroutine* subroutine; - int index; -}; class ConstantPoolNode { public: @@ -128,106 +70,6 @@ class ConstantPoolNode { ConstantPoolNode* next; }; -class PoolPromise: public Promise { - public: - PoolPromise(Context* c, int key): c(c), key(key) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast - (c->machineCode + pad(c->machineCodeSize, TargetBytesPerWord) - + (key * TargetBytesPerWord)); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0; - } - - Context* c; - int key; -}; - -unsigned -machineOffset(Context* c, int logicalIp) -{ - return c->logicalCode[logicalIp]->machineOffset->value(); -} - -class IpPromise: public Promise { - public: - IpPromise(Context* c, int logicalIp): - c(c), - logicalIp(logicalIp) - { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast - (c->machineCode + machineOffset(c, logicalIp)); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0 - and c->logicalCode[logicalIp]->machineOffset->resolved(); - } - - Context* c; - int logicalIp; -}; - -template -Cell* reverseDestroy(Cell* cell) { - Cell* previous = 0; - while (cell) { - Cell* next = cell->next; - cell->next = previous; - previous = cell; - cell = next; - } - return previous; -} - -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; -} - -void -clearSites(Context* c, Value* v) -{ - if (DebugSites) { - fprintf(stderr, "clear sites for %p\n", v); - } - for (SiteIterator it(c, v); it.hasMore();) { - it.next(); - it.remove(c); - } -} - Read* live(Context* c UNUSED, Value* v) { @@ -321,7 +163,7 @@ popRead(Context* c, Event* e UNUSED, Value* v) if (r) { deadBuddy(c, v, r); } else { - clearSites(c, v); + v->clearSites(c); } } } @@ -1140,11 +982,11 @@ removeBuddy(Context* c, Value* v) assert(c, p->buddy); if (not live(c, next)) { - clearSites(c, next); + next->clearSites(c); } if (not live(c, v)) { - clearSites(c, v); + v->clearSites(c); } } } @@ -1437,7 +1279,7 @@ visit(Context* c, Link* link) v->reads = p->read->nextTarget(); // fprintf(stderr, "next read %p for %p from %p\n", v->reads, v, p->read); if (not live(c, v)) { - clearSites(c, v); + v->clearSites(c); } } } @@ -1492,67 +1334,6 @@ appendBuddy(Context* c, Value* original, Value* buddy) append(c, new(c->zone) BuddyEvent(c, original, buddy)); } -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) { - popRead(c, this, r->value); - } - } -}; - -void -appendSaveLocals(Context* c) -{ - append(c, new(c->zone) SaveLocalsEvent(c)); -} - -class DummyEvent: public Event { - public: - DummyEvent(Context* c, Local* locals): - Event(c), - locals_(locals) - { } - - virtual const char* name() { - return "DummyEvent"; - } - - virtual void compile(Context*) { } - - virtual Local* locals() { - return locals_; - } - - Local* locals_; -}; - -void -appendDummy(Context* c) -{ - Stack* stack = c->stack; - Local* locals = c->locals; - LogicalInstruction* i = c->logicalCode[c->logicalIp]; - - c->stack = i->stack; - c->locals = i->locals; - - append(c, new(c->zone) DummyEvent(c, locals)); - - c->stack = stack; - c->locals = locals; -} - void append(Context* c, Event* e) { @@ -1898,11 +1679,11 @@ resetFrame(Context* c, Event* e) { for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) { FrameIterator::Element el = it.next(c); - clearSites(c, el.value); + el.value->clearSites(c); } while (c->acquiredResources) { - clearSites(c, c->acquiredResources->value); + c->acquiredResources->value->clearSites(c); } } @@ -2058,35 +1839,6 @@ updateJunctionReads(Context* c, JunctionState* state) } } -LogicalInstruction* -next(Context* c, LogicalInstruction* i) -{ - for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) { - i = c->logicalCode[n]; - if (i) return i; - } - return 0; -} - -class Block { - public: - Block(Event* head): - head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0) - { } - - Event* head; - Block* nextBlock; - LogicalInstruction* nextInstruction; - Assembler::Block* assemblerBlock; - unsigned start; -}; - -Block* -block(Context* c, Event* head) -{ - return new(c->zone) Block(head); -} - void compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) { @@ -2110,8 +1862,8 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) fprintf(stderr, " -- compile %s at %d with %d preds %d succs %d stack\n", e->name(), e->logicalInstruction->index, - countPredecessors(e->predecessors), - countSuccessors(e->successors), + e->predecessors->countPredecessors(), + e->successors->countSuccessors(), e->stackBefore ? e->stackBefore->index + 1 : 0); } @@ -2125,7 +1877,7 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) } if (e->predecessors) { - visit(c, lastPredecessor(e->predecessors)); + visit(c, e->predecessors->lastPredecessor()); Event* first = e->predecessors->predecessor; if (e->predecessors->nextPredecessor) { @@ -2191,7 +1943,7 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) a->endEvent(); - LogicalInstruction* nextInstruction = next(c, e->logicalInstruction); + LogicalInstruction* nextInstruction = e->logicalInstruction->next(c); if (e->next == 0 or (e->next->logicalInstruction != e->logicalInstruction and (e->next->logicalInstruction != nextInstruction @@ -2433,9 +2185,7 @@ class MyCompiler: public Compiler { memset(c.locals, 0, sizeof(Local) * localFootprint); - c.logicalCode[-1] = new - (c.zone->allocate(sizeof(LogicalInstruction))) - LogicalInstruction(-1, c.stack, c.locals); + c.logicalCode[-1] = new(c.zone) LogicalInstruction(-1, c.stack, c.locals); } virtual void visitLogicalIp(unsigned logicalIp) { @@ -2494,9 +2244,7 @@ class MyCompiler: public Compiler { p->localsAfter = c.locals; } - c.logicalCode[logicalIp] = new - (c.zone->allocate(sizeof(LogicalInstruction))) - LogicalInstruction(logicalIp, c.stack, c.locals); + c.logicalCode[logicalIp] = new(c.zone) LogicalInstruction(logicalIp, c.stack, c.locals); bool startSubroutine = c.subroutine != 0; if (startSubroutine) { @@ -2525,7 +2273,7 @@ class MyCompiler: public Compiler { } virtual Promise* machineIp(unsigned logicalIp) { - return new(c.zone) IpPromise(&c, logicalIp); + return ipPromise(&c, logicalIp); } virtual Promise* poolAppend(intptr_t value) { @@ -2533,7 +2281,7 @@ class MyCompiler: public Compiler { } virtual Promise* poolAppendPromise(Promise* value) { - Promise* p = new(c.zone) PoolPromise(&c, c.constantCount); + Promise* p = poolPromise(&c, c.constantCount); ConstantPoolNode* constant = new (c.zone) ConstantPoolNode(value); diff --git a/src/codegen/compiler/context.h b/src/codegen/compiler/context.h index 8508086978..974de8e17a 100644 --- a/src/codegen/compiler/context.h +++ b/src/codegen/compiler/context.h @@ -54,6 +54,18 @@ unsigned count(Cell* c) { return count; } +template +Cell* reverseDestroy(Cell* cell) { + Cell* previous = 0; + while (cell) { + Cell* next = cell->next; + cell->next = previous; + previous = cell; + cell = next; + } + return previous; +} + class Context { public: Context(vm::System* system, Assembler* assembler, vm::Zone* zone, diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index 68d3bccfd6..ba8c0c222a 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -18,6 +18,7 @@ #include "codegen/compiler/value.h" #include "codegen/compiler/promise.h" #include "codegen/compiler/frame.h" +#include "codegen/compiler/ir.h" namespace avian { namespace codegen { @@ -148,6 +149,32 @@ bool Event::isUnreachable() { return this->predecessors != 0; } +unsigned Link::countPredecessors() { + Link* link = this; + unsigned c = 0; + for (; link; link = link->nextPredecessor) { + ++ c; + } + return c; +} + +Link* Link::lastPredecessor() { + Link* link = this; + while (link->nextPredecessor) { + link = link->nextPredecessor; + } + return link; +} + +unsigned Link::countSuccessors() { + Link* link = this; + unsigned c = 0; + for (; link; link = link->nextSuccessor) { + ++ c; + } + return c; +} + Link* link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, Link* nextSuccessor, ForkState* forkState) { @@ -1605,6 +1632,67 @@ appendFrameSite(Context* c, Value* value, int index) append(c, new(c->zone) FrameSiteEvent(c, value, index)); } +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) { + popRead(c, this, r->value); + } + } +}; + +void +appendSaveLocals(Context* c) +{ + append(c, new(c->zone) SaveLocalsEvent(c)); +} + +class DummyEvent: public Event { + public: + DummyEvent(Context* c, Local* locals): + Event(c), + locals_(locals) + { } + + virtual const char* name() { + return "DummyEvent"; + } + + virtual void compile(Context*) { } + + virtual Local* locals() { + return locals_; + } + + Local* locals_; +}; + +void +appendDummy(Context* c) +{ + Stack* stack = c->stack; + Local* locals = c->locals; + LogicalInstruction* i = c->logicalCode[c->logicalIp]; + + c->stack = i->stack; + c->locals = i->locals; + + append(c, new(c->zone) DummyEvent(c, locals)); + + c->stack = stack; + c->locals = locals; +} + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index c28fa6230b..504da33bae 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -97,6 +97,10 @@ class Link { junctionState(0) { } + unsigned countPredecessors(); + Link* lastPredecessor(); + unsigned countSuccessors(); + Event* predecessor; Link* nextPredecessor; Event* successor; @@ -154,6 +158,12 @@ appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, void appendFrameSite(Context* c, Value* value, int index); +void +appendSaveLocals(Context* c); + +void +appendDummy(Context* c); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/ir.cpp b/src/codegen/compiler/ir.cpp new file mode 100644 index 0000000000..671fd86df8 --- /dev/null +++ b/src/codegen/compiler/ir.cpp @@ -0,0 +1,48 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "codegen/compiler/context.h" +#include "codegen/compiler/ir.h" + +namespace avian { +namespace codegen { +namespace compiler { + +LogicalInstruction::LogicalInstruction(int index, Stack* stack, Local* locals): + firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack), + locals(locals), machineOffset(0), subroutine(0), index(index) +{ } + +LogicalInstruction* LogicalInstruction::next(Context* c) { + LogicalInstruction* i = this; + for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) { + i = c->logicalCode[n]; + if (i) return i; + } + return 0; +} + +unsigned +machineOffset(Context* c, int logicalIp) +{ + return c->logicalCode[logicalIp]->machineOffset->value(); +} + +Block::Block(Event* head): + head(head), nextBlock(0), nextInstruction(0), assemblerBlock(0), start(0) +{ } + +Block* block(Context* c, Event* head) { + return new(c->zone) Block(head); +} + +} // namespace compiler +} // namespace codegen +} // namespace avian diff --git a/src/codegen/compiler/ir.h b/src/codegen/compiler/ir.h new file mode 100644 index 0000000000..56a0283367 --- /dev/null +++ b/src/codegen/compiler/ir.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2008-2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_CODEGEN_COMPILER_IR_H +#define AVIAN_CODEGEN_COMPILER_IR_H + +namespace avian { +namespace codegen { +namespace compiler { + +class MultiRead; + +class ForkElement { + public: + Value* value; + MultiRead* read; + bool local; +}; + +class ForkState: public Compiler::State { + public: + ForkState(Stack* stack, Local* locals, Cell* saved, Event* predecessor, + unsigned logicalIp): + stack(stack), + locals(locals), + saved(saved), + predecessor(predecessor), + logicalIp(logicalIp), + readCount(0) + { } + + Stack* stack; + Local* locals; + Cell* saved; + Event* predecessor; + unsigned logicalIp; + unsigned readCount; + ForkElement elements[0]; +}; + +class LogicalInstruction { + public: + LogicalInstruction(int index, Stack* stack, Local* locals); + + LogicalInstruction* next(Context* c); + + Event* firstEvent; + Event* lastEvent; + LogicalInstruction* immediatePredecessor; + Stack* stack; + Local* locals; + Promise* machineOffset; + MySubroutine* subroutine; + int index; +}; + +class MySubroutine: public Compiler::Subroutine { + public: + MySubroutine(): forkState(0) { } + + ForkState* forkState; +}; + +class Block { + public: + Block(Event* head); + + Event* head; + Block* nextBlock; + LogicalInstruction* nextInstruction; + Assembler::Block* assemblerBlock; + unsigned start; +}; + +Block* block(Context* c, Event* head); + +unsigned machineOffset(Context* c, int logicalIp); + +} // namespace compiler +} // namespace codegen +} // namespace avian + +#endif // AVIAN_CODEGEN_COMPILER_IR_H diff --git a/src/codegen/compiler/promise.cpp b/src/codegen/compiler/promise.cpp index e4e55edbc9..fc5a69da63 100644 --- a/src/codegen/compiler/promise.cpp +++ b/src/codegen/compiler/promise.cpp @@ -8,8 +8,11 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include "target.h" + #include "codegen/compiler/context.h" #include "codegen/compiler/promise.h" +#include "codegen/compiler/ir.h" namespace avian { namespace codegen { @@ -51,6 +54,63 @@ Promise* resolvedPromise(Context* c, int64_t value) { return new (c->zone) ResolvedPromise(value); } +class IpPromise: public Promise { + public: + IpPromise(Context* c, int logicalIp): + c(c), + logicalIp(logicalIp) + { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast + (c->machineCode + machineOffset(c, logicalIp)); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0 + and c->logicalCode[logicalIp]->machineOffset->resolved(); + } + + Context* c; + int logicalIp; +}; + +Promise* ipPromise(Context* c, int logicalIp) { + return new (c->zone) IpPromise(c, logicalIp); +} + + +class PoolPromise: public Promise { + public: + PoolPromise(Context* c, int key): c(c), key(key) { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast + (c->machineCode + vm::pad(c->machineCodeSize, vm::TargetBytesPerWord) + + (key * vm::TargetBytesPerWord)); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0; + } + + Context* c; + int key; +}; + +Promise* poolPromise(Context* c, int key) { + return new(c->zone) PoolPromise(c, key); +} + + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/promise.h b/src/codegen/compiler/promise.h index d7262b3724..516782e0cd 100644 --- a/src/codegen/compiler/promise.h +++ b/src/codegen/compiler/promise.h @@ -39,6 +39,10 @@ Promise* combinedPromise(Context* c, Promise* low, Promise* high); Promise* resolvedPromise(Context* c, int64_t value); +Promise* ipPromise(Context* c, int logicalIp); + +Promise* poolPromise(Context* c, int key); + } // namespace compiler } // namespace codegen } // namespace avian diff --git a/src/codegen/compiler/value.cpp b/src/codegen/compiler/value.cpp index cc3ac08092..58c3f341ae 100644 --- a/src/codegen/compiler/value.cpp +++ b/src/codegen/compiler/value.cpp @@ -123,6 +123,16 @@ bool Value::uniqueSite(Context* c, Site* s) { } } +void Value::clearSites(Context* c) { + if (DebugSites) { + fprintf(stderr, "clear sites for %p\n", this); + } + for (SiteIterator it(c, this); it.hasMore();) { + it.next(); + it.remove(c); + } +} + #ifndef NDEBUG bool Value::hasBuddy(Context* c, Value* b) { diff --git a/src/codegen/compiler/value.h b/src/codegen/compiler/value.h index f567c86cd5..9cdac0bba3 100644 --- a/src/codegen/compiler/value.h +++ b/src/codegen/compiler/value.h @@ -60,6 +60,7 @@ class Value: public Compiler::Operand { bool uniqueSite(Context* c, Site* s); + void clearSites(Context* c); #ifndef NDEBUG bool hasBuddy(Context* c, Value* b);