diff --git a/include/avian/codegen/ir.h b/include/avian/codegen/ir.h index 9c84e0c782..c66998c8c4 100644 --- a/include/avian/codegen/ir.h +++ b/include/avian/codegen/ir.h @@ -115,6 +115,8 @@ class Types { enum SignExtendMode { SignExtend, ZeroExtend }; +enum CallingConvention { NativeCallingConvention, AvianCallingConvention }; + class Value { public: ir::Type type; diff --git a/src/codegen/compiler.cpp b/src/codegen/compiler.cpp index fa98b33d70..5d9537e582 100644 --- a/src/codegen/compiler.cpp +++ b/src/codegen/compiler.cpp @@ -2460,7 +2460,7 @@ class MyCompiler: public Compiler { unsigned footprint = 0; unsigned size = TargetBytesPerWord; - RUNTIME_ARRAY(Value*, arguments, argumentCount); + RUNTIME_ARRAY(ir::Value*, arguments, argumentCount); int index = 0; for (unsigned i = 0; i < argumentCount; ++i) { Value* o = va_arg(a, Value*); @@ -2484,20 +2484,23 @@ class MyCompiler: public Compiler { Stack* argumentStack = c.stack; for (int i = index - 1; i >= 0; --i) { - argumentStack = compiler::stack - (&c, RUNTIME_ARRAY_BODY(arguments)[i], argumentStack); + argumentStack = compiler::stack( + &c, + static_cast(RUNTIME_ARRAY_BODY(arguments)[i]), + argumentStack); } Value* result = value(&c, resultType); appendCall(&c, static_cast(address), + ir::NativeCallingConvention, flags, traceHandler, result, resultType.size(), argumentStack, index, - util::Slice(0, 0)); + util::Slice(RUNTIME_ARRAY_BODY(arguments), index)); return result; } @@ -2511,6 +2514,7 @@ class MyCompiler: public Compiler { Value* result = value(&c, resultType); appendCall(&c, static_cast(address), + ir::AvianCallingConvention, flags, traceHandler, result, diff --git a/src/codegen/compiler/event.cpp b/src/codegen/compiler/event.cpp index e991876652..20759eb548 100644 --- a/src/codegen/compiler/event.cpp +++ b/src/codegen/compiler/event.cpp @@ -184,11 +184,110 @@ Link* link(Context* c, Event* predecessor, Link* nextPredecessor, Event* success (predecessor, nextPredecessor, successor, nextSuccessor, forkState); } +Value* maybeBuddySlice(Context* c, Value* v) +{ + if (v->home >= 0) { + Value* n = value(c, v->type); + appendBuddy(c, v, n); + return n; + } else { + return v; + } +} + +template +struct SliceStack : public Slice { + size_t capacity; + + SliceStack(T* items, size_t capacity) + : Slice(items + capacity, 0), capacity(capacity) + { + } + + void push(const T& item) + { + --Slice::items; + ++Slice::count; + *Slice::items = item; + } +}; + +template +struct FixedSliceStack : public SliceStack { + T itemArray[Capacity]; + + FixedSliceStack() : SliceStack(&itemArray[0], Capacity) + { + } +}; + +Value* pushWordSlice(Context* c, Value* v, SliceStack& slice) +{ + if (v) { + v = maybeBuddySlice(c, v); + } + + Stack* s = stack(c, v, c->stack); + assert(c, index > 0); + slice.push(v); + + // if (DebugFrame) { + // fprintf(stderr, "push %p\n", v); + // } + + if (v) { + v->home = frameIndex(c, s->index + c->localFootprint); + } + c->stack = s; + + return v; +} + +void pushSlice(Context* c, + unsigned footprint, + Value* v, + SliceStack& slice) +{ + assert(c, footprint); + + bool bigEndian = c->arch->bigEndian(); + + Value* low = v; + + if (bigEndian) { + v = pushWordSlice(c, v, slice); + } + + Value* high; + if (footprint > 1) { + assert(c, footprint == 2); + + if (vm::TargetBytesPerWord == 4) { + low->maybeSplit(c); + high = pushWordSlice(c, low->nextWord, slice); + } else { + high = pushWordSlice(c, 0, slice); + } + } else { + high = 0; + } + + if (not bigEndian) { + v = pushWordSlice(c, v, slice); + } + + if (high) { + v->nextWord = high; + high->nextWord = v; + high->wordIndex = 1; + } +} class CallEvent: public Event { public: CallEvent(Context* c, Value* address, + ir::CallingConvention callingConvention UNUSED, unsigned flags, TraceHandler* traceHandler, Value* result, @@ -206,13 +305,19 @@ class CallEvent: public Event { stackArgumentIndex(0), flags(flags), resultSize(resultSize), - stackArgumentFootprint(arguments.count) + stackArgumentFootprint(callingConvention == ir::AvianCallingConvention + ? arguments.count + : 0) { uint32_t registerMask = c->regFile->generalRegisters.mask; + assert(c, + callingConvention == ir::AvianCallingConvention + || argumentCount == arguments.count); + if (argumentCount) { assert(c, (flags & Compiler::TailJump) == 0); - assert(c, arguments.count == 0); + assert(c, stackArgumentFootprint == 0); Stack* s = argumentStack; unsigned index = 0; @@ -501,6 +606,7 @@ class CallEvent: public Event { void appendCall(Context* c, Value* address, + ir::CallingConvention callingConvention, unsigned flags, TraceHandler* traceHandler, Value* result, @@ -512,6 +618,7 @@ void appendCall(Context* c, append(c, new (c->zone) CallEvent(c, address, + callingConvention, flags, traceHandler, result, @@ -929,6 +1036,7 @@ appendCombine(Context* c, lir::TernaryOperation type, &thunk); if (thunk) { + FixedSliceStack slice; Stack* oldStack = c->stack; bool threadParameter; @@ -938,13 +1046,17 @@ appendCombine(Context* c, lir::TernaryOperation type, unsigned stackSize = ceilingDivide(secondSize, vm::TargetBytesPerWord) + ceilingDivide(firstSize, vm::TargetBytesPerWord); - compiler::push(c, ceilingDivide(secondSize, vm::TargetBytesPerWord), secondValue); - compiler::push(c, ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue); + pushSlice(c, + ceilingDivide(secondSize, vm::TargetBytesPerWord), + secondValue, + slice); + pushSlice( + c, ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue, slice); if (threadParameter) { ++ stackSize; - compiler::push(c, 1, threadRegister(c)); + pushSlice(c, 1, threadRegister(c), slice); } Stack* argumentStack = c->stack; @@ -954,13 +1066,14 @@ appendCombine(Context* c, lir::TernaryOperation type, value(c, ir::Type(ir::Type::Address, vm::TargetBytesPerWord), constantSite(c, handler)), + ir::NativeCallingConvention, 0, 0, resultValue, resultSize, argumentStack, stackSize, - util::Slice(0, 0)); + slice); } else { append (c, new(c->zone) @@ -1066,8 +1179,10 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, if (thunk) { Stack* oldStack = c->stack; + FixedSliceStack slice; - compiler::push(c, ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue); + pushSlice( + c, ceilingDivide(firstSize, vm::TargetBytesPerWord), firstValue, slice); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -1077,13 +1192,14 @@ appendTranslate(Context* c, lir::BinaryOperation type, unsigned firstSize, ir::Type(ir::Type::Address, vm::TargetBytesPerWord), constantSite( c, c->client->getThunk(type, firstSize, resultSize))), + ir::NativeCallingConvention, 0, 0, resultValue, resultSize, argumentStack, ceilingDivide(firstSize, vm::TargetBytesPerWord), - util::Slice(0, 0)); + slice); } else { append(c, new(c->zone) TranslateEvent @@ -1422,6 +1538,7 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first vm::TargetBytesPerWord, &thunk); if (thunk) { + FixedSliceStack slice; Stack* oldStack = c->stack; bool threadParameter; @@ -1430,8 +1547,10 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first assert(c, not threadParameter); - compiler::push(c, ceilingDivide(size, vm::TargetBytesPerWord), secondValue); - compiler::push(c, ceilingDivide(size, vm::TargetBytesPerWord), firstValue); + pushSlice( + c, ceilingDivide(size, vm::TargetBytesPerWord), secondValue, slice); + pushSlice( + c, ceilingDivide(size, vm::TargetBytesPerWord), firstValue, slice); Stack* argumentStack = c->stack; c->stack = oldStack; @@ -1442,13 +1561,14 @@ appendBranch(Context* c, lir::TernaryOperation type, unsigned size, Value* first value(c, ir::Type(ir::Type::Address, vm::TargetBytesPerWord), constantSite(c, handler)), + ir::NativeCallingConvention, 0, 0, result, 4, argumentStack, ceilingDivide(size, vm::TargetBytesPerWord) * 2, - util::Slice(0, 0)); + slice); appendBranch(c, thunkBranch(c, type), diff --git a/src/codegen/compiler/event.h b/src/codegen/compiler/event.h index 41a02c5345..31d2483fda 100644 --- a/src/codegen/compiler/event.h +++ b/src/codegen/compiler/event.h @@ -115,6 +115,7 @@ link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, void appendCall(Context* c, Value* address, + ir::CallingConvention callingConvention, unsigned flags, TraceHandler* traceHandler, Value* result, @@ -168,6 +169,8 @@ appendSaveLocals(Context* c); void appendDummy(Context* c); +void appendBuddy(Context* c, Value* original, Value* buddy); + } // namespace compiler } // namespace codegen } // namespace avian