From 17449eaf1bdf53e6b48385b245ed2a60a6766ae0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 28 Jan 2011 17:16:08 -0700 Subject: [PATCH] progress towards fixing the ARM build --- src/arm.cpp | 219 ++++++++++++++++++++++++++++++---------------- src/arm.h | 1 + src/compile-arm.S | 2 +- 3 files changed, 145 insertions(+), 77 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 768e1af9a7..990c08f89a 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -164,13 +164,12 @@ inline int carry16(intptr_t v) { return static_cast(v) < 0 ? 1 : 0; } inline bool isOfWidth(long long i, int size) { return static_cast(i) >> size == 0; } inline bool isOfWidth(int i, int size) { return static_cast(i) >> size == 0; } -const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1); +const unsigned FrameHeaderSize = 1; const unsigned StackAlignmentInBytes = 8; const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord; const int ThreadRegister = 8; -const int FrameRegister = 12; const int StackRegister = 13; const int LinkRegister = 14; const int ProgramCounter = 15; @@ -865,6 +864,51 @@ void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Regist } } +void +addC(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b, Assembler::Register* dst) +{ + assert(c, size == BytesPerWord); + + int32_t v = a->value->value(); + if (v) { + if (v > 0 and v < 1024 and v % 4 == 0) { + emit(c, addi(dst->low, b->low, v >> 2, 15)); + } else { + emit(c, addi(dst->low, b->low, lo8(v))); + if (not isOfWidth(v, 8)) { + emit(c, addi(dst->low, b->low, hi8(v), 12)); + if (not isOfWidth(v, 16)) { + emit(c, addi(dst->low, b->low, lo8(hi16(v)), 8)); + if (not isOfWidth(v, 24)) { + emit(c, addi(dst->low, b->low, hi8(hi16(v)), 4)); + } + } + } + } + } else { + moveRR(c, size, b, size, dst); + } +} + +void +subC(Context* c, unsigned size, Assembler::Constant* a, + Assembler::Register* b, Assembler::Register* dst) +{ + assert(c, size == BytesPerWord); + + int32_t v = a->value->value(); + if (v > 0 and v < 256) { + emit(c, subi(dst->low, b->low, v)); + } else if (v > 0 and v < 1024 and v % 4 == 0) { + emit(c, subi(dst->low, b->low, v >> 2, 15)); + } else { + ResolvedPromise promise(- v); + Assembler::Constant constant(&promise); + addC(c, size, &constant, b, dst); + } +} + void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { bool useTemporaries = b->low == t->low; @@ -1569,6 +1613,55 @@ memoryBarrier(Context*) {} // END OPERATION COMPILERS +void +nextFrame(ArchitectureContext* c UNUSED, uint32_t* start, unsigned size UNUSED, + unsigned footprint, int32_t*, void* link, void* stackLimit, + unsigned targetParameterFootprint UNUSED, void** ip, void** stack) +{ + assert(c, *ip >= start); + assert(c, *ip <= start + (size / BytesPerWord)); + + uint32_t* instruction = static_cast(*ip); + + if ((*start >> 20) == 0xe59) { + // skip stack overflow check + start += 3; + } + + if (instruction <= start) { + *ip = link; + return; + } + + unsigned offset = footprint + FrameHeaderSize + - (stackLimit == *stack ? 1 : 0); + + if (instruction <= start + 2) { + *ip = link; + *stack = reinterpret_cast(*stack) + offset; + } + + if (*instruction == 0xe12fff1e) { // return + *ip = link; + return; + } + + if (TailCalls) { + if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { + offset += argumentFootprint(targetParameterFootprint) + - StackAlignmentInWords; + } + + // todo: check for post-non-tail-call stack adjustment of the form + // "add sp, sp, #offset" + + // todo: use frameTable to check for and handle tail calls + } + + *ip = reinterpret_cast(*stack)[offset]; + *stack = reinterpret_cast(*stack) + offset; +} + void populateTables(ArchitectureContext* c) { @@ -1701,9 +1794,6 @@ class MyArchitecture: public Assembler::Architecture { virtual bool reserved(int register_) { switch (register_) { - case FrameRegister: - return UseFramePointer; - case LinkRegister: case StackRegister: case ThreadRegister: @@ -1788,6 +1878,15 @@ class MyArchitecture: public Assembler::Architecture { - FrameHeaderSize; } + virtual void nextFrame(void* start, unsigned size, unsigned footprint, + int32_t* frameTable, void* link, void* stackLimit, + unsigned targetParameterFootprint, void** ip, + void** stack) + { + ::nextFrame(&c, static_cast(start), size, footprint, frameTable, + link, stackLimit, targetParameterFootprint, ip, stack); + } + virtual void* frameIp(void* stack) { return stack ? static_cast(stack)[returnAddressOffset()] : 0; } @@ -1809,7 +1908,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual int framePointerOffset() { - return -2; + return 0; } virtual void nextFrame(void** stack, void**) { @@ -2010,14 +2109,6 @@ class MyAssembler: public Assembler { } virtual void saveFrame(unsigned stackOffset) { - appendFrameSizeEvent(&c, FrameSizePoison); - - // ??? - Register returnAddress(LinkRegister); - Memory returnAddressDst(StackRegister, - BytesPerWord); - moveAndUpdateRM(&c, BytesPerWord, &returnAddress, BytesPerWord, - &returnAddressDst); - Register stack(StackRegister); Memory stackDst(ThreadRegister, stackOffset); moveRM(&c, BytesPerWord, &stack, BytesPerWord, &stackDst); @@ -2053,7 +2144,7 @@ class MyAssembler: public Assembler { offset += ceiling(arguments[i].size, BytesPerWord); } else { - Memory dst(ThreadRegister, (offset + FrameFooterSize) * BytesPerWord); + Memory dst(StackRegister, offset * BytesPerWord); apply(Move, arguments[i].size, arguments[i].type, arguments[i].operand, @@ -2065,79 +2156,62 @@ class MyAssembler: public Assembler { } virtual void allocateFrame(unsigned footprint) { - Register stack(StackRegister); - Constant footprintConstant(resolved(&c, footprint * BytesPerWord)); - subCR(&c, BytesPerWord, &footprintConstant, BytesPerWord, &stack, - BytesPerWord, &stack); + footprint += FrameHeaderSize; - appendFrameSizeEvent(&c, footprint); + // larger frames may require multiple subtract/add instructions + // to allocate/deallocate, and nextFrame will need to be taught + // how to handle them: + assert(&c, footprint < 256); + + Register stack(StackRegister); + ResolvedPromise footprintPromise(footprint * BytesPerWord); + Constant footprintConstant(&footprintPromise); + subC(&c, BytesPerWord, &footprintConstant, &stack, &stack); Register returnAddress(LinkRegister); Memory returnAddressDst(StackRegister, (footprint - 1) * BytesPerWord); moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst); - - if (UseFramePointer) { - Register frame(FrameRegister); - Memory frameDst(StackRegister, (footprint - 2) * BytesPerWord); - moveRM(&c, BytesPerWord, &frame, BytesPerWord, &frameDst); - } } virtual void adjustFrame(unsigned difference) { - appendFrameSizeEvent(&c, - difference); - Register stack(StackRegister); - Constant differenceConstant(resolved(&c, difference * BytesPerWord)); - subCR(&c, BytesPerWord, &differenceConstant, BytesPerWord, &stack, - BytesPerWord, &stack); - - appendFrameSizeEvent(&c, difference); + ResolvedPromise differencePromise(difference * BytesPerWord); + Constant differenceConstant(&differencePromise); + subC(&c, BytesPerWord, &differenceConstant, &stack, &stack); } - virtual void popFrame(unsigned frameFootprint) { - if (UseFramePointer) { - Register frame(FrameRegister); - Memory frameSrc(StackRegister, (frameFootprint - 1) * BytesPerWord); - moveMR(&c, BytesPerWord, &frameSrc, BytesPerWord, &frame); - } + virtual void popFrame(unsigned footprint) { + footprint += FrameHeaderSize; Register returnAddress(LinkRegister); - Memory returnAddressSrc - (StackRegister, (frameFootprint - 1) * BytesPerWord); + Memory returnAddressSrc(StackRegister, (footprint - 1) * BytesPerWord); moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &returnAddress); Register stack(StackRegister); - Constant differenceConstant(resolved(&c, frameFootprint * BytesPerWord)); - addCR(&c, BytesPerWord, &differenceConstant, BytesPerWord, &stack, - BytesPerWord, &stack); - - appendFrameSizeEvent(&c, - frameFootprint); + ResolvedPromise footprintPromise(footprint * BytesPerWord); + Constant footprintConstant(&footprintPromise); + addC(&c, BytesPerWord, &footprintConstant, &stack, &stack); } virtual void popFrameForTailCall(unsigned footprint, int offset, int returnAddressSurrogate, - int framePointerSurrogate) + int framePointerSurrogate UNUSED) { + assert(&c, framePointerSurrogate == NoRegister); + if (TailCalls) { if (offset) { - if (UseFramePointer) { - Register frame(FrameRegister); - Memory frameSrc(StackRegister, (footprint - 1) * BytesPerWord); - moveMR(&c, BytesPerWord, &frameSrc, BytesPerWord, &frame); - } - Register link(LinkRegister); Memory returnAddressSrc (StackRegister, (footprint - 1) * BytesPerWord); moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &link); Register stack(StackRegister); - Constant footprintConstant - (resolved(&c, (footprint - offset + 1) * BytesPerWord)); - addCR(&c, BytesPerWord, &footprintConstant, BytesPerWord, &stack); - - appendFrameSizeEvent(&c, - (frameFootprint - offset + 1)); + ResolvedPromise footprintPromise + ((footprint - offset + 1) * BytesPerWord); + Constant footprintConstant(&footprintPromise); + addC(&c, BytesPerWord, &footprintConstant, &stack, &stack); if (returnAddressSurrogate != NoRegister) { assert(&c, offset > 0); @@ -2146,14 +2220,6 @@ class MyAssembler: public Assembler { Memory dst(StackRegister, (offset - 1) * BytesPerWord); moveRM(&c, BytesPerWord, &ras, BytesPerWord, &dst); } - - if (framePointerSurrogate != NoRegister) { - assert(&c, offset > 0); - - Register las(framePointerSurrogate); - Memory dst(StackRegister, (offset - 2) * BytesPerWord); - moveRM(&c, BytesPerWord, &las, BytesPerWord, &dst); - } } else { popFrame(footprint); } @@ -2175,26 +2241,19 @@ class MyAssembler: public Assembler { offset = argumentFootprint - StackAlignmentInWords; Register stack(StackRegister); - Constant adjustment(resolved(&c, offset * BytesPerWord)); - addCR(&c, BytesPerWord, &adjustment, BytesPerWord, &stack); - - appendFrameSizeEvent(&c, - offset); + ResolvedPromise adjustmentPromise(offset * BytesPerWord); + Constant adjustment(&adjustmentPromise); + addC(&c, BytesPerWord, &adjustment, &stack, &stack); } else { offset = 0; } return_(&c); - - // todo: this is not necessary if there are no instructions to - // follow: - appendFrameSizeEvent(&c, frameFootprint + offset); } virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, unsigned stackOffsetFromThread) { - appendFrameSizeEvent(&c, FrameSizePoison); - popFrame(frameFootprint); Register stack(StackRegister); @@ -2372,6 +2431,14 @@ class MyAssembler: public Assembler { return c.code.length(); } + virtual unsigned frameEventCount() { + return 0; + } + + virtual FrameEvent* firstFrameEvent() { + return 0; + } + virtual void dispose() { c.code.dispose(); } diff --git a/src/arm.h b/src/arm.h index 198a76945f..e5b47b2d0a 100644 --- a/src/arm.h +++ b/src/arm.h @@ -19,6 +19,7 @@ #define IP_REGISTER(context) (context->uc_mcontext.arm_pc) #define STACK_REGISTER(context) (context->uc_mcontext.arm_sp) #define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip) +#define LINK_REGISTER(context) (context->uc_mcontext.arm_lr) extern "C" uint64_t vmNativeCall(void* function, unsigned stackTotal, void* memoryTable, diff --git a/src/compile-arm.S b/src/compile-arm.S index ed66b222a1..102db1a541 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -22,7 +22,7 @@ # define GLOBAL(x) x #endif -#define THREAD_STACK 2152 +#define THREAD_STACK 2148 #define THREAD_CONTINUATION 2156 #define THREAD_EXCEPTION 44 #define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160