From 3f45d395826a6d3288dbffc63225c39f1e1b77f0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 16 Apr 2008 20:55:38 -0600 Subject: [PATCH] more compiler work --- src/assembler.h | 9 +- src/compiler.cpp | 1938 +++++++++++----------------------------------- 2 files changed, 477 insertions(+), 1470 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index e3129bd2ee..5b2a3b30d1 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -51,10 +51,11 @@ enum BinaryOperation { const unsigned BinaryOperationCount = Xor + 1; enum OperandType { - Constant, - Address, - Register, - Memory + ConstantOperand, + AddressOperand, + RegisterOperand, + MemoryOperand, + StackOperand }; const unsigned OperandTypeCount = Memory + 1; diff --git a/src/compiler.cpp b/src/compiler.cpp index ed66eed911..f17209ca41 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -20,23 +20,27 @@ class Value; void NO_RETURN abort(Context*); -// scratch - class Site { public: Site(): next(0) { } virtual ~Site() { } + virtual Site* resolve(Context*) { return this; } + virtual unsigned copyCost(Context*, Site*) = 0; - virtual void copyTo(Context*, unsigned, Site*) = 0; + virtual void accept(Context* c, unsigned size, Site* src) { + apply(c, Move, size, src, this); + } - virtual void acquire(Context*, unsigned, Value*, Site*) { } + virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { } - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) = 0; + virtual OperandType type(Context*) { + return Constant; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) = 0; Site* next; }; @@ -49,10 +53,6 @@ class ConstantSite: public Site { return 1; } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - virtual OperandType type(Context*) { return Constant; } @@ -91,10 +91,6 @@ class AddressSite: public Site { return 3; } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - virtual OperandType type(Context*) { return Address; } @@ -112,25 +108,85 @@ addressSite(Context* c, Promise* address) return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); } +Site* +pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) +{ + Site* site = 0; + unsigned copyCost = 0xFFFFFFFF; + for (Site* s = sites; s; s = s->next) { + unsigned c = s->copyCost(c, target); + if (c < copyCost) { + site = s; + copyCost = c; + } + } + + if (cost) *cost = copyCost; + return site; +} + void -acquire(Context* c, int r, unsigned newSize, Value* newValue, Site* newSite) +syncStack(Context* c, Stack* start, unsigned count) +{ + Stack* segment[count]; + unsigned index = count; + for (Stack* s = start; s and index; s = s->next) { + segment[--index] = s; + } + + for (unsigned i = 0; i < count; ++i) { + Stack* s = segment[i]; + + if (s->value) { + apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); + + StackSite* site = stackSite(c, s); + site->next = s->value->sites; + s->value->sites = site; + } else { + Assembler::Register stack(c->assembler->stack()); + Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); + c->assembler->apply + (Subtract, BytesPerWord, Constant, &offset, Register, &stack); + } + + s->pushed = true; + } +} + +void +acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, + Site* newSite) { Value* oldValue = c->registers[r].value; if (oldValue) { + if (old->sites->next == 0 and old->reads) { + assert(c, old->sites == oldValue->sites); + + unsigned count = 0; + Stack* start = 0; + for (Stack* s = stack; s and not s->pushed; s = s->next) { + if (s->value == old) { + start = s; + } + if (start) { + ++ count; + } + } + + assert(c, start); + + syncStack(c, start, count); + } + for (Site** p = &(oldValue->sites); *p;) { if (c->registers[r].site == *p) { - site = *p; *p = (*p)->next; break; } else { p = &((*p)->next); } } - - if (old->sites == 0 and old->reads) { - apply(c, Push, c->registers[r].size, c->registers[r].site); - old->sites = ???; - } } c->registers[r].size = newSize; @@ -157,13 +213,11 @@ class RegisterSite: public Site { } } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - - virtual void acquire(Context* c, unsigned size, Value* v, Site* s) { - ::acquire(c, register_.low, size, v, s); - if (register_.high >= 0) ::acquire(c, register_.high, size, v, s); + virtual void acquire(Context* c, Stack* stack, unsigned size, Value* v, + Site* s) + { + ::acquire(c, register_.low, stack, size, v, s); + if (register_.high >= 0) ::acquire(c, register_.high, stack, size, v, s); } virtual OperandType type(Context*) { @@ -186,7 +240,7 @@ registerSite(Context* c, int low, int high = NoRegister) class MemorySite: public Site { public: - RegisterSite(int base, int offset, int index, unsigned scale): + MemorySite(int base, int offset, int index, unsigned scale): value(base, offset, index, scale) { } @@ -205,10 +259,6 @@ class MemorySite: public Site { } } - virtual void copyTo(Context* c, unsigned size, Site* dst) { - apply(c, Move, size, this, dst); - } - virtual OperandType type(Context*) { return Memory; } @@ -227,41 +277,317 @@ memorySite(Context* c, int base, int offset, int index, unsigned scale) MemorySite(base, offset, index, scale); } +class ValueSite: public Site { + public: + ValueSite(Value* value): value(value) { } + + virtual Site* resolve(Context* c) { + return value->sites; + } + + virtual unsigned copyCost(Context* c, Site*) { + abort(c); + } + + virtual void copyTo(Context* c, unsigned, Site*) { + abort(c); + } + + virtual OperandType type(Context* c) { + abort(c); + } + + virtual Assembler::Operand* asAssemblerOperand(Context* c) { + abort(c); + } + + Value* value; +}; + +ValueSite* +valueSite(Context* c, Value* v) +{ + return new (c->zone->allocate(sizeof(ValueSite))) ValueSite(v); +} + +class StackSite: public Site { + public: + StackSite(Stack* stack): stack(stack) { } + + virtual unsigned copyCost(Context*, Site*) { + return 5; + } + + virtual void accept(Context* c, unsigned size, Site* src) { + apply(c, Push, size, src); + } + + virtual OperandType type(Context*) { + return StackOperand; + } + + virtual Assembler::Operand* asAssemblerOperand(Context*) { + abort(c); + } + + Stack* stack; +}; + +StackSite* +stackSite(Context* c, Stack* s) +{ + return new (c->zone->allocate(sizeof(StackSite))) StackSite(s); +} + +class Stack { + public: + Stack(Value* value, unsigned size, unsigned index, Stack* next): + value(value), size(size), index(index), next(next) + { } + + Value* value; + unsigned size; + unsigned index; + Stack* next; +}; + +class State { + public: + State(State* s): + stack(s ? s->stack : 0), + next(s) + { } + + Stack* stack; + State* next; +}; + +class LogicalInstruction { + public: + unsigned visits; + Event* firstEvent; + Event* lastEvent; + unsigned machineOffset; + int predecessor; +}; + +class Register { + public: + Value* value; + Site* site; + unsigned size; + bool reserved; +}; + +class ConstantPoolNode { + public: + ConstantPoolNode(Promise* promise): promise(promise), next(0) { } + + Promise* promise; + ConstantPoolNode* next; +}; + +class Junction { + public: + Junction(unsigned logicalIp, Junction* next): + logicalIp(logicalIp), + next(next) + { } + + unsigned logicalIp; + Junction* next; +}; + +class Context { + public: + Context(System* system, Assembler* assembler, Zone* zone): + system(system), + assembler(assembler), + zone(zone), + logicalIp(-1), + state(new (zone->allocate(sizeof(State))) State(0)), + event(0), + logicalCode(0), + logicalCodeLength(0), + stackOffset(0), + registers(static_cast + (zone->allocate(sizeof(Register) * assembler->registerCount()))), + firstConstant(0), + lastConstant(0), + constantCount(0), + junctions(0), + machineCode(0) + { + memset(registers, 0, sizeof(Register) * assembler->registerCount()); + + registers[assembler->base()].reserved = true; + registers[assembler->stack()].reserved = true; + registers[assembler->thread()].reserved = true; + } + + System* system; + Assembler* assembler; + Zone* zone; + int logicalIp; + State* state; + Event* event; + LogicalInstruction* logicalCode; + unsigned logicalCodeLength; + unsigned stackOffset; + Register* registers; + ConstantPoolNode* firstConstant; + ConstantPoolNode* lastConstant; + unsigned constantCount; + Junction* junctions; + uint8_t* machineCode; +}; + +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); +} + class Read { public: - Read(unsigned size, Value* value, Site* target): - size(size), value(value), target(target), next(0) + Read(unsigned size, Value* value, Site* target, Read* next, Read* eventNext): + size(size), value(value), target(target), next(next), eventNext(eventNext) { } unsigned size; Value* value; Site* target; Read* next; + Read* eventNext; }; class Write { public: - Write(unsigned size, Value* value): - size(size), value(value), next(0) + Write(unsigned size, Value* value, Write* eventNext): + size(size), value(value), eventNext(eventNext) { } unsigned size; Value* value; - Write* next; + Write* eventNext; }; class Value: public Compiler::Operand { public: Value(Site* site): - reads(0), sites(site), source(0), target(0) + reads(0), lastRead(0), sites(site), source(0), target(0) { } Read* reads; + Read* lastRead; Site* sites; Site* source; Site* target; }; +void +apply(Context* c, UnaryOperation op, unsigned size, Value* a) +{ + OperandType type = a->type(c); + Assembler::Operand* operand = a->asAssemblerOperand(c); + + c->assembler->apply(op, size, type, operand); +} + +void +apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b) +{ + OperandType aType = a->type(c); + Assembler::Operand* aOperand = a->asAssemblerOperand(c); + + OperandType bType = b->type(c); + Assembler::Operand* bOperand = b->asAssemblerOperand(c); + + c->assembler->apply(op, size, aType, aOperand, bType, bOperand); +} + +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->assembler->length()) + (key * BytesPerWord)); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0; + } + + Context* c; + int key; +}; + +class CodePromise: public Promise { + public: + CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { } + + CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { } + + virtual int64_t value() { + if (resolved()) { + return reinterpret_cast(c->machineCode + offset); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0 and offset >= 0; + } + + Context* c; + int offset; + CodePromise* next; +}; + +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 + c->logicalCode[logicalIp].machineOffset); + } + + abort(c); + } + + virtual bool resolved() { + return c->machineCode != 0; + } + + Context* c; + int logicalIp; +}; + class Event { public: Event(Context* c): next(0), stack(c->state->stack), promises(0) { @@ -299,6 +625,28 @@ class Stack { Stack* next; }; +void +addRead(Context* c, Value* v, unsigned size, Site* target) +{ + Read* r = new (c->zone->allocate(sizeof(Read))) + Read(v, size, target, 0, c->event-reads); + c->event->reads = r; + + if (v->lastRead) { + r->lastRead->next = r; + } else { + v->reads = r; + } + v->lastRead = r; +} + +void +addWrite(Context* c, Value* v, unsigned size) +{ + c->event->writes = new (c->zone->allocate(sizeof(Write))) + Write(v, size, c->event->writes); +} + class CallEvent: public Event { public: CallEvent(Context* c, Value* address, void* indirection, unsigned flags, @@ -576,13 +924,26 @@ appendMemory(Context* c, Value* base, Value* index, Value* result) } void -addSite(Context* c, int size, Value* v, Site* s) +addSite(Context* c, Stack* stack, unsigned size, Value* v, Site* s) { - s->acquire(c, size, v, s); + s->acquire(c, stack, size, v, s); s->next = v->sites; v->sites = s; } +Site* +target(Context* c, unsigned size, Value* value) +{ + if (value->reads + and value->reads->target + and not value->reads->target->type(c) == StackOperand) + { + return value->reads->target; + } else { + return freeRegister(c, size); + } +} + void compile(Context* c) { @@ -602,25 +963,36 @@ compile(Context* c) LogicalInstruction* li = c->logicalCode + e->logicalIp; li->machineOffset = a->length(); - for (Read* r = e->reads; r; r = r->next) { - Site* site = 0; - unsigned copyCost = Site::MaxCopyCost; - for (Site* s = r->value->sites; s; s = s->next) { - unsigned c = s->copyCost(c, r->target); - if (c < copyCost) { - site = s; - copyCost = c; + for (Read* r = e->reads; r; r = r->eventNext) { + Site* target = (r->target ? r->target->resolve(c) : 0); + + unsigned copyCost; + Site* site = pick(c, r->value->sites, target, ©Cost); + + if (site->type(c) == StackOperand) { + for (Stack* s = e->stack; s; s = s->next) { + if (s->pushed) { + target = ::target(t, s->size * BytesPerWord, s->value); + + addSite(c, e->stack, s->size * BytesPerWord, s->value, target); + + s->pushed = false; + if (s == static_cast(site)->stack) { + site = pick(c, r->value->sites, target, ©Cost); + break; + } + } } } - if (r->target) { + if (target) { if (copyCost) { - addSite(c, r->size, r->value, r->target); + addSite(c, e->stack, r->size, r->value, target); - site->copyTo(c, r->size, r->target); + target->accept(c, r->size, site); } - r->value->source = r->target; + r->value->source = target; } else { r->value->source = site; } @@ -628,14 +1000,10 @@ compile(Context* c) r->value->reads = r->value->reads->next; } - for (Write* w = e->writes; w; w = w->next) { - if (w->value->reads and w->value->reads->target) { - w->value->target = w->value->reads->target; - } else { - w->value->target = freeRegister(c, w->size); - } + for (Write* w = e->writes; w; w = w->eventNext) { + w->value->target = target(t, w->size, w->value); - addSite(c, w->size, w->value, w->value->target); + addSite(c, e->stack, w->size, w->value, w->value->target); } e->compile(c); @@ -646,1376 +1014,6 @@ compile(Context* c) } } -// end scratch - -class Stack { - public: - Stack(MyOperand* operand, unsigned size, unsigned index, Stack* next): - operand(operand), size(size), index(index), next(next) - { } - - MyOperand* operand; - unsigned size; - unsigned index; - Stack* next; -}; - -class State { - public: - State(State* s): - stack(s ? s->stack : 0), - next(s) - { } - - Stack* stack; - State* next; -}; - -class LogicalInstruction { - public: - unsigned visits; - Event* firstEvent; - Event* lastEvent; - unsigned machineOffset; - int predecessor; -}; - -class RegisterElement { - public: - bool reserved; - MyOperand* operand; -}; - -class ConstantPoolNode { - public: - ConstantPoolNode(Promise* promise): promise(promise), next(0) { } - - Promise* promise; - ConstantPoolNode* next; -}; - -class Junction { - public: - Junction(unsigned logicalIp, Junction* next): - logicalIp(logicalIp), - next(next) - { } - - unsigned logicalIp; - Junction* next; -}; - -class Context { - public: - Context(System* system, Assembler* assembler, Zone* zone): - system(system), - assembler(assembler), - zone(zone), - logicalIp(-1), - state(new (zone->allocate(sizeof(State))) State(0)), - event(0), - logicalCode(0), - logicalCodeLength(0), - stackOffset(0), - registers(static_cast - (zone->allocate - (sizeof(RegisterElement) * assembler->registerCount()))), - firstConstant(0), - lastConstant(0), - constantCount(0), - junctions(0), - machineCode(0) - { - memset(registers, 0, sizeof(RegisterElement) * assembler->registerCount()); - - registers[assembler->base()].reserved = true; - registers[assembler->stack()].reserved = true; - registers[assembler->thread()].reserved = true; - } - - System* system; - Assembler* assembler; - Zone* zone; - int logicalIp; - State* state; - Event* event; - LogicalInstruction* logicalCode; - unsigned logicalCodeLength; - unsigned stackOffset; - RegisterElement* registers; - ConstantPoolNode* firstConstant; - ConstantPoolNode* lastConstant; - unsigned constantCount; - Junction* junctions; - uint8_t* machineCode; -}; - -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); -} - -void -apply(Context* c, UnaryOperation op, unsigned size, Value* a) -{ - OperandType type; - Assembler::Operand* operand; - a->asAssemblerOperand(c, &type, &operand); - - c->assembler->apply(op, size, type, operand); -} - -void -apply(Context* c, BinaryOperation op, unsigned size, Value* a, Value* b) -{ - OperandType aType; - Assembler::Operand* aOperand; - a->asAssemblerOperand(c, &aType, &aOperand); - - OperandType bType; - Assembler::Operand* bOperand; - b->asAssemblerOperand(c, &bType, &bOperand); - - c->assembler->apply(op, size, aType, aOperand, bType, bOperand); -} - -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->assembler->length()) + (key * BytesPerWord)); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0; - } - - Context* c; - int key; -}; - -class CodePromise: public Promise { - public: - CodePromise(Context* c, CodePromise* next): c(c), offset(-1), next(next) { } - - CodePromise(Context* c, int offset): c(c), offset(offset), next(0) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast(c->machineCode + offset); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0 and offset >= 0; - } - - Context* c; - int offset; - CodePromise* next; -}; - -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 + c->logicalCode[logicalIp].machineOffset); - } - - abort(c); - } - - virtual bool resolved() { - return c->machineCode != 0; - } - - Context* c; - int logicalIp; -}; - -RegisterValue* -freeRegister(Context* c, unsigned size, bool allowAcquired); - -class ConstantValue: public Value { - public: - ConstantValue(Promise* value): value(value) { } - - virtual OperandType type(Context*) { return Constant; } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Constant; - *operand = &value; - } - - virtual int64_t constantValue(Context*) { - return value.value->value(); - } - - Assembler::Constant value; -}; - -ConstantValue* -constant(Context* c, Promise* value) -{ - return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value); -} - -ResolvedPromise* -resolved(Context* c, int64_t value) -{ - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); -} - -ConstantValue* -constant(Context* c, int64_t value) -{ - return constant(c, resolved(c, value)); -} - -class AddressValue: public Value { - public: - AddressValue(Promise* address): address(address) { } - - virtual OperandType type(Context*) { return Address; } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Address; - *operand = &address; - } - - Assembler::Address address; -}; - -AddressValue* -address(Context* c, Promise* address) -{ - return new (c->zone->allocate(sizeof(AddressValue))) AddressValue(address); -} - -void preserve(Context*, Stack*, int, MyOperand*); - -class RegisterValue: public Value { - public: - RegisterValue(int low, int high): register_(low, high) { } - - virtual OperandType type(Context*) { return Register; } - - virtual bool equals(Context* c, Value* o) { - return this == o or - (o->type(c) == Register - and static_cast(o)->register_.low == register_.low - and static_cast(o)->register_.high == register_.high); - } - - virtual void preserve(Context* c, Stack* s, MyOperand* a) { - ::preserve(c, s, register_.low, a); - if (register_.high >= 0) ::preserve(c, s, register_.high, a); - } - - virtual void acquire(Context* c, Stack* s, MyOperand* a) { - if (a != c->registers[register_.low].operand) { - fprintf(stderr, "%p acquire %d\n", a, register_.low); - - preserve(c, s, a); - c->registers[register_.low].operand = a; - if (register_.high >= 0) { - c->registers[register_.high].operand = a; - } - } - } - - virtual void release(Context* c, MyOperand* a) { - if (a == c->registers[register_.low].operand) { - fprintf(stderr, "%p release %d\n", a, register_.low); - - c->registers[register_.low].operand = 0; - if (register_.high >= 0) c->registers[register_.high].operand = 0; - } - } - - virtual int registerValue(Context*) { - return register_.low; - } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Register; - *operand = ®ister_; - } - - Assembler::Register register_; -}; - -RegisterValue* -register_(Context* c, int low, int high = NoRegister) -{ - return new (c->zone->allocate(sizeof(RegisterValue))) - RegisterValue(low, high); -} - -class MemoryValue: public Value { - public: - MemoryValue(int base, int offset, int index, unsigned scale): - value(base, offset, index, scale) - { } - - virtual OperandType type(Context*) { return Memory; } - - virtual bool equals(Context* c, Value* o) { - return this == o or - (o->type(c) == Memory - and static_cast(o)->value.base == value.base - and static_cast(o)->value.offset == value.offset - and static_cast(o)->value.index == value.index - and static_cast(o)->value.scale == value.scale); - } - - virtual int base(Context*) { - return value.base; - } - - virtual int index(Context*) { - return value.index; - } - - virtual void asAssemblerOperand(Context* c, - OperandType* type, - Assembler::Operand** operand) - { - value.base = base(c); - value.index = index(c); - *type = Memory; - *operand = &value; - } - - Assembler::Memory value; -}; - -class AbstractMemoryValue: public MemoryValue { - public: - AbstractMemoryValue(MyOperand* base, int offset, MyOperand* index, - unsigned scale): - MemoryValue(NoRegister, offset, NoRegister, scale), - base_(base), index_(index) - { } - - virtual void preserve(Context* c, Stack* s, MyOperand*) { - base_->value->preserve(c, s, base_); - if (index_) { - index_->value->preserve(c, s, index_); - } - } - - virtual void release(Context* c, MyOperand*) { - base_->value->release(c, base_); - if (index_) { - index_->value->release(c, index_); - } - } - - virtual bool ready(Context* c) { - return base_->value->registerValue(c) != NoRegister - and (index_ == 0 or index_->value->registerValue(c) != NoRegister); - } - - virtual int base(Context* c) { - int r = base_->value->registerValue(c); - assert(c, r != NoRegister); - return r; - } - - virtual int index(Context* c) { - if (index_) { - int r = index_->value->registerValue(c); - assert(c, r != NoRegister); - return r; - } else { - return NoRegister; - } - } - - MyOperand* base_; - MyOperand* index_; -}; - -AbstractMemoryValue* -memory(Context* c, MyOperand* base, int offset, MyOperand* index, - unsigned scale) -{ - return new (c->zone->allocate(sizeof(AbstractMemoryValue))) - AbstractMemoryValue(base, offset, index, scale); -} - -class StackValue: public Value { - public: - StackValue(Context* c, Stack* stack): - stack(stack), - value - (c->assembler->base(), - - (c->stackOffset + stack->index + 1) * BytesPerWord, - NoRegister, 0, 0) - { } - - virtual OperandType type(Context*) { return Memory; } - - virtual void asAssemblerOperand(Context*, - OperandType* type, - Assembler::Operand** operand) - { - *type = Memory; - *operand = &value; - } - - Stack* stack; - Assembler::Memory value; -}; - -StackValue* -stackValue(Context* c, Stack* stack) -{ - return new (c->zone->allocate(sizeof(StackValue))) StackValue(c, stack); -} - -class Event { - public: - Event(Context* c): next(0), stack(c->state->stack), promises(0) { - assert(c, c->logicalIp >= 0); - - if (c->event) { - c->event->next = this; - } - - if (c->logicalCode[c->logicalIp].firstEvent == 0) { - c->logicalCode[c->logicalIp].firstEvent = this; - } - - c->event = this; - } - - Event(Event* next): next(next) { } - - virtual ~Event() { } - - virtual Value* target(Context* c, MyOperand* value) = 0; - virtual unsigned operandSize(Context* c) = 0; - virtual void compile(Context* c) = 0; - virtual bool isCritical(Context*) { return false; } - - Event* next; - Stack* stack; - CodePromise* promises; -}; - -class NullEvent: public Event { - public: - NullEvent(Context* c): - Event(c) - { } - - virtual Value* target(Context*, MyOperand*) { - return 0; - } - - virtual unsigned operandSize(Context*) { - return 0; - } - - virtual void compile(Context*) { - // ignore - } -}; - -void -setEvent(Context* c, MyOperand* a, Event* e) -{ - if (a->event) { - a->event = new (c->zone->allocate(sizeof(NullEvent))) NullEvent(c); - } else{ - a->event = e; - } -} - -class ArgumentEvent: public Event { - public: - ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): - Event(c), size(size), a(a), index(index) - { - setEvent(c, a, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == a); - - if (index < c->assembler->argumentRegisterCount()) { - return register_(c, c->assembler->argumentRegister(index)); - } else { - return 0; - } - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "ArgumentEvent.compile\n"); - - if (a->target == 0) a->target = target(c, a); - - if (a->target == 0) { - apply(c, Push, size, a->value); - a->value = 0; - } else { - if (not a->target->equals(c, a->value)) { - a->target->preserve(c, stack, a); - apply(c, Move, size, a->value, a->target); - } - a->value->release(c, a); - } - } - - unsigned size; - MyOperand* a; - unsigned index; -}; - -void -appendArgument(Context* c, unsigned size, MyOperand* value, unsigned index) -{ - new (c->zone->allocate(sizeof(ArgumentEvent))) - ArgumentEvent(c, size, value, index); -} - -class ReturnEvent: public Event { - public: - ReturnEvent(Context* c, unsigned size, MyOperand* a): - Event(c), size(size), a(a) - { - if (a) { - setEvent(c, a, this); - } - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == a); - - return register_(c, c->assembler->returnLow(), c->assembler->returnHigh()); - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "ReturnEvent.compile\n"); - - if (a) { - if (a->target == 0) a->target = target(c, a); - - if (not a->target->equals(c, a->value)) { - apply(c, Move, size, a->value, a->target); - } - a->value->release(c, a); - } - - Assembler::Register base(c->assembler->base()); - Assembler::Register stack(c->assembler->stack()); - - c->assembler->apply(Move, BytesPerWord, Register, &base, Register, &stack); - c->assembler->apply(Pop, BytesPerWord, Register, &base); - c->assembler->apply(Return); - } - - unsigned size; - MyOperand* a; -}; - -void -appendReturn(Context* c, unsigned size, MyOperand* value) -{ - new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); -} - -void -syncStack(Context* c, Stack* start, unsigned count) -{ - Stack* segment[count]; - unsigned index = count; - for (Stack* s = start; s and index; s = s->next) { - segment[--index] = s; - } - - for (unsigned i = 0; i < count; ++i) { - Stack* s = segment[i]; - if (s->operand->value) { - apply(c, Push, s->size * BytesPerWord, s->operand->value); - s->operand->value->release(c, s->operand); - } else { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); - c->assembler->apply - (Subtract, BytesPerWord, Constant, &offset, Register, &stack); - } - s->operand->pushed = true; - s->operand->value = stackValue(c, s); - } -} - -void -syncStack(Context* c, Stack* start) -{ - unsigned count = 0; - for (Stack* s = start; s and (not s->operand->pushed); s = s->next) { - ++ count; - } - - syncStack(c, start, count); -} - -class PushEvent: public Event { - public: - PushEvent(Context* c): - Event(c), active(false) - { - assert(c, stack->operand->push == 0); - stack->operand->push = this; - } - - virtual Value* target(Context*, MyOperand*) { - return 0; - } - - virtual unsigned operandSize(Context*) { - return 0; - } - - virtual void compile(Context* c) { - fprintf(stderr, "PushEvent.compile\n"); - - if (active) { - fprintf(stderr, "PushEvent.compile: active\n"); - syncStack(c, stack); - } - } - - void markStack(Context*) { - active = true; - } - - bool active; -}; - -void -appendPush(Context* c) -{ - new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c); -} - -class CallEvent: public Event { - public: - CallEvent(Context* c, MyOperand* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, MyOperand* result): - Event(c), - address(address), - indirection(indirection), - flags(flags), - traceHandler(traceHandler), - result(result) - { - setEvent(c, address, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == address); - - if (indirection) { - return register_(c, c->assembler->returnLow(), NoRegister); - } else { - return 0; - } - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual void compile(Context* c) { - fprintf(stderr, "CallEvent.compile\n"); - - if (indirection and address->target == 0) { - address->target = target(c, address); - } - - UnaryOperation type = ((flags & Compiler::Aligned) ? AlignedCall : Call); - - if (indirection) { - if (not address->target->equals(c, address->value)) { - apply(c, Move, BytesPerWord, address->value, address->target); - } - apply(c, type, BytesPerWord, - constant(c, reinterpret_cast(indirection))); - } else { - apply(c, type, BytesPerWord, address->value); - } - - address->value->release(c, address); - - if (result->event or (result->push and result->push->active)) { - result->value = register_ - (c, c->assembler->returnLow(), c->assembler->returnHigh()); - result->value->acquire(c, stack, result); - } - - if (traceHandler) { - traceHandler->handleTrace - (new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, c->assembler->length())); - } - } - - MyOperand* address; - void* indirection; - unsigned flags; - TraceHandler* traceHandler; - MyOperand* result; -}; - -void -appendCall(Context* c, MyOperand* address, void* indirection, unsigned flags, - TraceHandler* traceHandler, MyOperand* result) -{ - new (c->zone->allocate(sizeof(CallEvent))) - CallEvent(c, address, indirection, flags, traceHandler, result); -} - -int -freeRegisterExcept(Context* c, int except, bool allowAcquired) -{ - for (int i = c->assembler->registerCount(); i >= 0; --i) { - if (i != except - and (not c->registers[i].reserved) - and c->registers[i].operand == 0) - { - return i; - } - } - - if (allowAcquired) { - for (int i = c->assembler->registerCount(); i >= 0; --i) { - if (i != except - and (not c->registers[i].reserved)) - { - return i; - } - } - } - - abort(c); -} - -inline int -freeRegister(Context* c, bool allowAcquired) -{ - return freeRegisterExcept(c, NoRegister, allowAcquired); -} - -RegisterValue* -freeRegister(Context* c, unsigned size, bool allowAcquired) -{ - if (BytesPerWord == 4 and size == 8) { - int low = freeRegister(c, allowAcquired); - return register_(c, low, freeRegisterExcept(c, low, allowAcquired)); - } else { - return register_(c, freeRegister(c, allowAcquired)); - } -} - -class PopEvent: public Event { - public: - PopEvent(Context* c, unsigned count, bool ignore): - Event(c), count(count), ignore(ignore) - { } - - virtual Value* target(Context* c, MyOperand*) { - abort(c); - } - - virtual unsigned operandSize(Context* c) { - abort(c); - } - - virtual void compile(Context* c) { - fprintf(stderr, "PopEvent.compile\n"); - - Stack* s = stack; - unsigned ignored = 0; - for (unsigned i = count; i;) { - MyOperand* dst = s->operand; - if (dst->pushed) { - if (dst->event and (not ignore)) { - assert(c, ignored == 0); - - Value* target = 0; - - if (dst->event->operandSize(c) == BytesPerWord) { - target = dst->event->target(c, dst); - } - if (target == 0 or (not target->ready(c))) { - target = freeRegister(c, BytesPerWord * s->size, false); - } - - target->acquire(c, 0, dst); - - apply(c, Pop, BytesPerWord * s->size, target); - - dst->value = target; - } else { - ignored += s->size; - } - } - - i -= s->size; - s = s->next; - } - - if (ignored) { - Assembler::Register stack(c->assembler->stack()); - Assembler::Constant offset(resolved(c, ignored * BytesPerWord)); - c->assembler->apply - (Add, BytesPerWord, Constant, &offset, Register, &stack); - } - } - - unsigned count; - bool ignore; -}; - -void -appendPop(Context* c, unsigned count, bool ignore) -{ - new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); -} - -bool -safeToSkipMove(Context* c, MyOperand* a, Event* e) -{ - for (; a->push and a->push != e; e = e->next) { - if (e->isCritical(c)) return false; - } - return true; -} - -class MoveEvent: public Event { - public: - MoveEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* src, - MyOperand* dst): - Event(c), type(type), size(size), src(src), dst(dst) - { - setEvent(c, src, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == src); - - if (dst->value) { - return dst->value; - } else if (dst->event) { - return dst->event->target(c, dst); - } - - return 0; - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "MoveEvent.compile\n"); - - if (src->target == 0) src->target = target(c, src); - - if (src->target == 0) { - if (type == Move - and size == BytesPerWord - and safeToSkipMove(c, dst, next)) - { - dst->value = src->value; - return; - } - } else if (type == Move - and size == BytesPerWord - and src->target->type(c) == Register - and src->target->equals(c, src->value)) - { - dst->value = src->value; - return; - } - - src->value->release(c, src); - - if (src->target == 0 or (not src->target->ready(c))) { - src->target = freeRegister(c, size, false); - } - - src->target->acquire(c, stack, dst); - - apply(c, type, size, src->value, src->target); - - dst->value = src->target; - } - - virtual bool isCritical(Context* c) { - if (src->target == 0) src->target = target(c, src); - - return src->target != 0; - } - - BinaryOperation type; - unsigned size; - MyOperand* src; - MyOperand* dst; -}; - -void -appendMove(Context* c, BinaryOperation type, unsigned size, MyOperand* src, - MyOperand* dst) -{ - new (c->zone->allocate(sizeof(MoveEvent))) - MoveEvent(c, type, size, src, dst); -} - -class DupEvent: public Event { - public: - DupEvent(Context* c, unsigned size, MyOperand* src, MyOperand* dst): - Event(c), size(size), src(src), dst(dst) - { } - - virtual Value* target(Context* c, MyOperand*) { - abort(c); - } - - virtual unsigned operandSize(Context* c) { - abort(c); - } - - virtual void compile(Context* c) { - fprintf(stderr, "DupEvent.compile\n"); - - Value* value = src->value; - assert(c, dst->value == 0); - - Value* target = 0; - - if (safeToSkipMove(c, dst, next)) { - dst->value = src->value; - return; - } - - if (dst->event) { - target = dst->event->target(c, dst); - } - if (target == 0 or (not target->ready(c))) { - target = freeRegister(c, size, true); - } - - target->acquire(c, stack, dst); - - apply(c, Move, size, value, target); - - dst->value = target; - } - - unsigned size; - MyOperand* src; - MyOperand* dst; -}; - -void -appendDup(Context* c, unsigned size, MyOperand* src, MyOperand* dst) -{ - new (c->zone->allocate(sizeof(DupEvent))) DupEvent(c, size, src, dst); -} - -class CompareEvent: public Event { - public: - CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): - Event(c), size(size), a(a), b(b) - { - setEvent(c, a, this); - setEvent(c, b, this); - } - - virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { - assert(c, v == a or v == b); - - return 0; - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "CompareEvent.compile\n"); - - apply(c, Compare, size, a->value, b->value); - - a->value->release(c, a); - b->value->release(c, b); - } - - unsigned size; - MyOperand* a; - MyOperand* b; -}; - -void -appendCompare(Context* c, unsigned size, MyOperand* a, MyOperand* b) -{ - new (c->zone->allocate(sizeof(CompareEvent))) CompareEvent(c, size, a, b); -} - -class BranchEvent: public Event { - public: - BranchEvent(Context* c, UnaryOperation type, MyOperand* address): - Event(c), type(type), address(address) - { - setEvent(c, address, this); - } - - virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { - assert(c, v == address); - - return 0; - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual void compile(Context* c) { - fprintf(stderr, "BranchEvent.compile\n"); - - apply(c, type, BytesPerWord, address->value); - - address->value->release(c, address); - } - - UnaryOperation type; - MyOperand* address; -}; - -void -appendBranch(Context* c, UnaryOperation type, MyOperand* address) -{ - new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); -} - -class JumpEvent: public Event { - public: - JumpEvent(Context* c, MyOperand* address): - Event(c), - address(address) - { - setEvent(c, address, this); - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { - assert(c, v == address); - - return 0; - } - - virtual void compile(Context* c) { - fprintf(stderr, "JumpEvent.compile\n"); - - apply(c, Jump, BytesPerWord, address->value); - - address->value->release(c, address); - } - - MyOperand* address; -}; - -void -appendJump(Context* c, MyOperand* address) -{ - new (c->zone->allocate(sizeof(BranchEvent))) JumpEvent(c, address); -} - -class CombineEvent: public Event { - public: - CombineEvent(Context* c, BinaryOperation type, unsigned size, MyOperand* a, - MyOperand* b, MyOperand* result): - Event(c), type(type), size(size), a(a), b(b), result(result) - { - setEvent(c, a, this); - setEvent(c, b, this); - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual Value* target(Context* c, MyOperand* v) { - Assembler::Register ar(NoRegister); - Assembler::Register br(NoRegister); - c->assembler->getTargets(type, size, &ar, &br); - - if (v == a) { - if (ar.low == NoRegister) { - return 0; - } else { - return register_(c, ar.low, ar.high); - } - } else { - assert(c, v == b); - - if (br.low == NoRegister) { - if (result->event) { - Value* v = result->event->target(c, result); - if (v and v->type(c) == Register) { - return v; - } else { - return 0; - } - } else { - return 0; - } - } else { - return register_(c, br.low, br.high); - } - } - } - - virtual void compile(Context* c) { - fprintf(stderr, "CombineEvent.compile\n"); - - if (a->target == 0) a->target = target(c, a); - if (b->target == 0) b->target = target(c, b); - - if (b->target == 0 or (not b->target->ready(c))) { - b->target = freeRegister(c, BytesPerWord, true); - } - - if (a->target and not a->target->equals(c, a->value)) { - apply(c, Move, size, a->value, a->target); - a->value->release(c, a); - a->value = a->target; - a->value->acquire(c, stack, a); - } - - if (b->target and not b->target->equals(c, b->value)) { - apply(c, Move, size, b->value, b->target); - b->value->release(c, b); - b->value = b->target; - b->value->acquire(c, stack, b); - } - - apply(c, type, size, a->value, b->value); - - a->value->release(c, a); - b->value->release(c, b); - b->value->acquire(c, stack, result); - - result->value = b->value; - } - - BinaryOperation type; - unsigned size; - MyOperand* a; - MyOperand* b; - MyOperand* result; -}; - -void -appendCombine(Context* c, BinaryOperation type, unsigned size, MyOperand* a, - MyOperand* b, MyOperand* result) -{ - new (c->zone->allocate(sizeof(CombineEvent))) - CombineEvent(c, type, size, a, b, result); -} - -class TranslateEvent: public Event { - public: - TranslateEvent(Context* c, UnaryOperation type, unsigned size, MyOperand* a, - MyOperand* result): - Event(c), type(type), size(size), a(a), result(result) - { - setEvent(c, a, this); - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == a); - - Assembler::Register r(NoRegister); - c->assembler->getTargets(type, size, &r); - - if (r.low == NoRegister) { - return result->event->target(c, result); - } else { - return register_(c, r.low, r.high); - } - } - - virtual unsigned operandSize(Context*) { - return size; - } - - virtual void compile(Context* c) { - fprintf(stderr, "TranslateEvent.compile\n"); - - if (a->target == 0) a->target = target(c, a); - - if (not a->target->ready(c)) { - a->target = a->value; - } - - result->value->acquire(c, stack, result); - - if (a->target and not a->target->equals(c, a->value)) { - apply(c, Move, size, a->value, a->target); - } - apply(c, type, size, a->value); - - result->value = a->value; - } - - UnaryOperation type; - unsigned size; - MyOperand* a; - MyOperand* result; -}; - -void -appendTranslate(Context* c, UnaryOperation type, unsigned size, MyOperand* a, - MyOperand* result) -{ - new (c->zone->allocate(sizeof(TranslateEvent))) - TranslateEvent(c, type, size, a, result); -} - -class MemoryEvent: public Event { - public: - MemoryEvent(Context* c, MyOperand* base, MyOperand* index, - MyOperand* result): - Event(c), base(base), index(index), result(result) - { - setEvent(c, base, this); - if (index) setEvent(c, index, this); - } - - virtual unsigned operandSize(Context*) { - return BytesPerWord; - } - - virtual Value* target(Context* c, MyOperand* v UNUSED) { - assert(c, v == base or v == index); - return 0; - } - - virtual void compile(Context* c) { - fprintf(stderr, "MemoryEvent.compile\n"); - - if (base->value->type(c) != Register) { - base->target = freeRegister(c, BytesPerWord, true); - apply(c, Move, BytesPerWord, base->value, base->target); - base->value->release(c, base); - base->value = base->target; - } - - if (index and index->value->type(c) != Register) { - index->target = freeRegister(c, BytesPerWord, true); - apply(c, Move, BytesPerWord, index->value, index->target); - index->value->release(c, index); - index->value = index->target; - } - } - - MyOperand* base; - MyOperand* index; - MyOperand* result; -}; - -void -appendMemory(Context* c, MyOperand* a, MyOperand* b, MyOperand* result) -{ - new (c->zone->allocate(sizeof(MemoryEvent))) MemoryEvent(c, a, b, result); -} - -void -preserve(Context* c, Stack* stack, int reg, MyOperand* a) -{ - MyOperand* b = c->registers[reg].operand; - if (b and a != b) { - fprintf(stderr, "%p preserve %d for %p\n", a, reg, b); - - unsigned count = 0; - Stack* start = 0; - for (Stack* s = stack; s and (not s->operand->pushed); s = s->next) { - if (s->operand == b) { - start = s; - } - if (start) { - ++ count; - } - } - - assert(c, start); - - syncStack(c, start, count); - } -} - -MyOperand* -operand(Context* c, Value* value = 0) -{ - return new (c->zone->allocate(sizeof(MyOperand))) MyOperand(value); -} - unsigned count(Stack* s) { @@ -2042,30 +1040,29 @@ popState(Context* c) } Stack* -stack(Context* c, MyOperand* operand, unsigned size, unsigned index, - Stack* next) +stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) { return new (c->zone->allocate(sizeof(Stack))) - Stack(operand, size, index, next); + Stack(value, size, index, next); } Stack* -stack(Context* c, MyOperand* operand, unsigned size, Stack* next) +stack(Context* c, Value* value, unsigned size, Stack* next) { return stack(c, operand, size, (next ? next->index + size : 0), next); } void -push(Context* c, unsigned size, MyOperand* o) +push(Context* c, unsigned size, Value* v) { assert(c, ceiling(size, BytesPerWord)); - c->state->stack = stack(c, o, ceiling(size, BytesPerWord), c->state->stack); + c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack); appendPush(c); } -MyOperand* +Value* pop(Context* c, unsigned size UNUSED) { Stack* s = c->state->stack; @@ -2074,9 +1071,9 @@ pop(Context* c, unsigned size UNUSED) appendPop(c, s->size, false); c->state->stack = s->next; - return s->operand; + return s->value; } - +// tbc void markStack(Context* c, Stack* stack) { @@ -2107,37 +1104,46 @@ updateJunctions(Context* c) } } -void -compile(Context* c) +int +freeRegisterExcept(Context* c, int except, bool allowAcquired) { - Assembler* a = c->assembler; - - Assembler::Register base(a->base()); - Assembler::Register stack(a->stack()); - a->apply(Push, BytesPerWord, Register, &base); - a->apply(Move, BytesPerWord, Register, &stack, Register, &base); - - if (c->stackOffset) { - Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord)); - a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack); + for (int i = c->assembler->registerCount(); i >= 0; --i) { + if (i != except + and (not c->registers[i].reserved) + and c->registers[i].value == 0) + { + return i; + } } - for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { - LogicalInstruction* li = c->logicalCode + i; - li->machineOffset = a->length(); - - for (Event* e = li->firstEvent; e; e = e->next) { - fprintf(stderr, "compile event at ip %d with stack count %d\n", - i, count(e->stack)); - e->compile(c); - - for (CodePromise* p = e->promises; p; p = p->next) { - p->offset = a->length(); + if (allowAcquired) { + for (int i = c->assembler->registerCount(); i >= 0; --i) { + if (i != except + and (not c->registers[i].reserved)) + { + return i; } - - if (e == li->lastEvent) break; } } + + abort(c); +} + +int +freeRegister(Context* c, bool allowAcquired) +{ + return freeRegisterExcept(c, NoRegister, allowAcquired); +} + +RegisterSite* +freeRegister(Context* c, unsigned size, bool allowAcquired) +{ + if (BytesPerWord == 4 and size == 8) { + int low = freeRegister(c, allowAcquired); + return registerSite(c, low, freeRegisterExcept(c, low, allowAcquired)); + } else { + return registerSite(c, freeRegister(c, allowAcquired)); + } } class Client: public Assembler::Client { @@ -2149,7 +1155,7 @@ class Client: public Assembler::Client { r = freeRegisterExcept(c, NoRegister, false); } else { expect(c, not c->registers[r].reserved); - expect(c, c->registers[r].operand == 0); + expect(c, c->registers[r].value == 0); } c->registers[r].reserved = true; return r;