From 6aaf6abb692dbdc0f0400ab5c76c438034957d55 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 13 Jan 2017 16:45:54 +0100 Subject: Include the ARMv7 assembler in the qmldevtools bootstrap build Even when the C++ target is not ARMv7 we want to include it in order to be able to generate QML cache files with code ahead of time. This requires a few changes: * The Jump classes need to move from the AbstractMacroAssembler super-class into the concrete assembler sub-class, in order to use it in specializations. * Some of the template specializations in LinkBuffer for example or for platform dependent operations need to be pre-processor enabled when bootstrapping * The generic loadPtr/addPtr etc. functions need to move to the concrete assemblers to be able to call the correct 32-bit or 64-bit variations. * We need to force what looks like a loss of precision to the compiler in the 32-bit ARMv7 linking code when linking jumps. Finally then we can explicitly instantiate at least QV4::JIT::Assembler for ARMv7 when bootstrapping. Currently only on x86-64 hosts, but that is a temporary limitation. Change-Id: I501db2360e1fded48f17f17d9e87252d47f8537e Reviewed-by: Simon Hausmann --- src/3rdparty/masm/assembler/ARMv7Assembler.h | 81 ++++++++++++++++++++-- .../masm/assembler/AbstractMacroAssembler.h | 20 +++++- src/3rdparty/masm/assembler/LinkBuffer.h | 10 +-- src/3rdparty/masm/assembler/MacroAssembler.h | 15 +++- src/3rdparty/masm/assembler/MacroAssemblerARMv7.h | 79 +++++++++++++++++++-- src/3rdparty/masm/assembler/MacroAssemblerX86.h | 32 +++++++++ src/3rdparty/masm/assembler/MacroAssemblerX86_64.h | 27 ++++++++ src/3rdparty/masm/assembler/X86Assembler.h | 40 +++++++++++ src/3rdparty/masm/stubs/ExecutableAllocator.h | 8 +-- 9 files changed, 285 insertions(+), 27 deletions(-) (limited to 'src/3rdparty') diff --git a/src/3rdparty/masm/assembler/ARMv7Assembler.h b/src/3rdparty/masm/assembler/ARMv7Assembler.h index ba7517a750..6b32fbf487 100644 --- a/src/3rdparty/masm/assembler/ARMv7Assembler.h +++ b/src/3rdparty/masm/assembler/ARMv7Assembler.h @@ -27,10 +27,11 @@ #ifndef ARMAssembler_h #define ARMAssembler_h -#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) +#if ENABLE(ASSEMBLER) && (CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)) #include "AssemblerBuffer.h" #include "MacroAssemblerCodeRef.h" +#include "AbstractMacroAssembler.h" #include #include #include @@ -491,8 +492,8 @@ public: private: union { struct RealTypes { - intptr_t m_from : 31; - intptr_t m_to : 31; + int32_t m_from : 31; + int32_t m_to : 31; JumpType m_type : 8; JumpLinkType m_linkType : 8; Condition m_condition : 16; @@ -510,6 +511,56 @@ public: { } + + // Jump: + // + // A jump object is a reference to a jump instruction that has been planted + // into the code buffer - it is typically used to link the jump, setting the + // relative offset such that when executed it will jump to the desired + // destination. + template + class Jump { + template friend class AbstractMacroAssembler; + friend class Call; + template class> friend class LinkBufferBase;; + public: + Jump() + { + } + + // Fixme: this information should be stored in the instruction stream, not in the Jump object. + Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid) + : m_label(jmp) + , m_type(type) + , m_condition(condition) + { + } + + LabelType label() const + { + LabelType result; + result.m_label = m_label; + return result; + } + + void link(AbstractMacroAssembler* masm) const + { + masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); + } + + void linkTo(LabelType label, AbstractMacroAssembler* masm) const + { + masm->m_assembler.linkJump(m_label, label.label(), m_type, m_condition); + } + + bool isSet() const { return m_label.isSet(); } + + private: + AssemblerLabel m_label; + ARMv7Assembler::JumpType m_type; + ARMv7Assembler::Condition m_condition; + }; + private: // ARMv7, Appx-A.6.3 @@ -2115,6 +2166,7 @@ public: linkJumpAbsolute(location, to); } +#if !defined(V4_BOOTSTRAP) static void linkCall(void* code, AssemblerLabel from, void* to) { ASSERT(!(reinterpret_cast(code) & 1)); @@ -2123,12 +2175,14 @@ public: setPointer(reinterpret_cast(reinterpret_cast(code) + from.m_offset) - 1, to, false); } +#endif static void linkPointer(void* code, AssemblerLabel where, void* value) { setPointer(reinterpret_cast(code) + where.m_offset, value, false); } +#if !defined(V4_BOOTSTRAP) static void relinkJump(void* from, void* to) { ASSERT(!(reinterpret_cast(from) & 1)); @@ -2146,11 +2200,12 @@ public: setPointer(reinterpret_cast(from) - 1, to, true); } - + static void* readCallTarget(void* from) { return readPointer(reinterpret_cast(from) - 1); } +#endif static void repatchInt32(void* where, int32_t value) { @@ -2179,6 +2234,7 @@ public: cacheFlush(location, sizeof(uint16_t) * 2); } +#if !defined(V4_BOOTSTRAP) static void repatchPointer(void* where, void* value) { ASSERT(!(reinterpret_cast(where) & 1)); @@ -2190,7 +2246,8 @@ public: { return reinterpret_cast(readInt32(where)); } - +#endif + static void replaceWithJump(void* instructionStart, void* to) { ASSERT(!(bitwise_cast(instructionStart) & 1)); @@ -2433,7 +2490,9 @@ private: static void setPointer(void* code, void* value, bool flush) { - setInt32(code, reinterpret_cast(value), flush); + // ### Deliberate "loss" of precision here. On 64-bit hosts void* is wider + // than uint32_t, but the target is 32-bit ARM anyway. + setInt32(code, static_cast(reinterpret_cast(value)), flush); } static bool isB(void* address) @@ -2597,6 +2656,11 @@ private: static void linkBX(uint16_t* instruction, void* target) { +#if defined(V4_BOOTSTRAP) + UNUSED_PARAM(instruction); + UNUSED_PARAM(target); + RELEASE_ASSERT_NOT_REACHED(); +#else // FIMXE: this should be up in the MacroAssembler layer. :-( ASSERT(!(reinterpret_cast(instruction) & 1)); ASSERT(!(reinterpret_cast(target) & 1)); @@ -2609,6 +2673,7 @@ private: instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); +#endif } void linkConditionalBX(Condition cond, uint16_t* instruction, void* target) @@ -2641,6 +2706,9 @@ private: instruction[-3] = OP_NOP_T2b; linkJumpT4(instruction, target); } else { +#if defined(V4_BOOTSTRAP) + RELEASE_ASSERT_NOT_REACHED(); +#else const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast(reinterpret_cast(target) + 1)); ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast(reinterpret_cast(target) >> 16)); @@ -2649,6 +2717,7 @@ private: instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); +#endif } } diff --git a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h index a9035efed7..4f27e85c98 100644 --- a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h +++ b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h @@ -66,7 +66,9 @@ public: typedef MacroAssemblerCodePtr CodePtr; typedef MacroAssemblerCodeRef CodeRef; +#if !CPU(ARM_THUMB2) && !defined(V4_BOOTSTRAP) class Jump; +#endif typedef typename AssemblerType::RegisterID RegisterID; typedef typename AssemblerType::FPRegisterID FPRegisterID; @@ -342,6 +344,8 @@ public: } bool isSet() const { return m_label.isSet(); } + + const AssemblerLabel &label() const { return m_label; } private: AssemblerLabel m_label; }; @@ -451,6 +455,11 @@ public: AssemblerLabel m_label; }; +#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP) + using Jump = typename AssemblerType::template Jump