Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2008-2017, Petr Kobalicek 3 : 4 : This software is provided 'as-is', without any express or implied 5 : warranty. In no event will the authors be held liable for any damages 6 : arising from the use of this software. 7 : 8 : Permission is granted to anyone to use this software for any purpose, 9 : including commercial applications, and to alter it and redistribute it 10 : freely, subject to the following restrictions: 11 : 12 : 1. The origin of this software must not be misrepresented; you must not 13 : claim that you wrote the original software. If you use this software 14 : in a product, an acknowledgment in the product documentation would be 15 : appreciated but is not required. 16 : 2. Altered source versions must be plainly marked as such, and must not be 17 : misrepresented as being the original software. 18 : 3. This notice may not be removed or altered from any source distribution. 19 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 20 : #ifdef __PLUMED_HAS_ASMJIT 21 : #pragma GCC diagnostic push 22 : #pragma GCC diagnostic ignored "-Wpedantic" 23 : // [AsmJit] 24 : // Complete x86/x64 JIT and Remote Assembler for C++. 25 : // 26 : // [License] 27 : // Zlib - See LICENSE.md file in the package. 28 : 29 : // [Export] 30 : #define ASMJIT_EXPORTS 31 : 32 : // [Dependencies] 33 : #include "./assembler.h" 34 : #include "./cpuinfo.h" 35 : #include "./runtime.h" 36 : 37 : // [Api-Begin] 38 : #include "./asmjit_apibegin.h" 39 : 40 : namespace PLMD { 41 : namespace asmjit { 42 : 43 : static ASMJIT_INLINE void hostFlushInstructionCache(const void* p, size_t size) noexcept { 44 : // Only useful on non-x86 architectures. 45 : #if !ASMJIT_ARCH_X86 && !ASMJIT_ARCH_X64 46 : # if ASMJIT_OS_WINDOWS 47 : // Windows has a built-in support in kernel32.dll. 48 : ::FlushInstructionCache(_memMgr.getProcessHandle(), p, size); 49 : # endif // ASMJIT_OS_WINDOWS 50 : #else 51 : ASMJIT_UNUSED(p); 52 : ASMJIT_UNUSED(size); 53 : #endif // !ASMJIT_ARCH_X86 && !ASMJIT_ARCH_X64 54 : } 55 : 56 : static ASMJIT_INLINE uint32_t hostDetectNaturalStackAlignment() noexcept { 57 : // Alignment is assumed to match the pointer-size by default. 58 : uint32_t alignment = sizeof(intptr_t); 59 : 60 : // X86 & X64 61 : // --------- 62 : // 63 : // - 32-bit X86 requires stack to be aligned to 4 bytes. Modern Linux, Mac 64 : // and UNIX guarantees 16-byte stack alignment even on 32-bit. I'm not 65 : // sure about all other UNIX operating systems, because 16-byte alignment 66 : //! is addition to an older specification. 67 : // - 64-bit X86 requires stack to be aligned to at least 16 bytes. 68 : #if ASMJIT_ARCH_X86 || ASMJIT_ARCH_X64 69 : int kIsModernOS = ASMJIT_OS_LINUX || // Linux & ANDROID. 70 : ASMJIT_OS_MAC || // OSX and iOS. 71 : ASMJIT_OS_BSD ; // BSD variants. 72 : alignment = ASMJIT_ARCH_X64 || kIsModernOS ? 16 : 4; 73 : #endif 74 : 75 : // ARM32 & ARM64 76 : // ------------- 77 : // 78 : // - 32-bit ARM requires stack to be aligned to 8 bytes. 79 : // - 64-bit ARM requires stack to be aligned to 16 bytes. 80 : #if ASMJIT_ARCH_ARM32 || ASMJIT_ARCH_ARM64 81 : alignment = ASMJIT_ARCH_ARM32 ? 8 : 16; 82 : #endif 83 : 84 : return alignment; 85 : } 86 : 87 : 88 : // ============================================================================ 89 : // [asmjit::Runtime - Construction / Destruction] 90 : // ============================================================================ 91 : 92 32141 : Runtime::Runtime() noexcept 93 : : _codeInfo(), 94 32141 : _runtimeType(kRuntimeNone), 95 32141 : _allocType(VMemMgr::kAllocFreeable) {} 96 32141 : Runtime::~Runtime() noexcept {} 97 : 98 : // ============================================================================ 99 : // [asmjit::HostRuntime - Construction / Destruction] 100 : // ============================================================================ 101 : 102 32141 : HostRuntime::HostRuntime() noexcept { 103 32141 : _runtimeType = kRuntimeJit; 104 : 105 : // Setup the CodeInfo of this Runtime. 106 32141 : _codeInfo._archInfo = CpuInfo::getHost().getArchInfo(); 107 32141 : _codeInfo._stackAlignment = static_cast<uint8_t>(hostDetectNaturalStackAlignment()); 108 32141 : _codeInfo._cdeclCallConv = CallConv::kIdHostCDecl; 109 32141 : _codeInfo._stdCallConv = CallConv::kIdHostStdCall; 110 32141 : _codeInfo._fastCallConv = CallConv::kIdHostFastCall; 111 32141 : } 112 32141 : HostRuntime::~HostRuntime() noexcept {} 113 : 114 : // ============================================================================ 115 : // [asmjit::HostRuntime - Interface] 116 : // ============================================================================ 117 : 118 32111 : void HostRuntime::flush(const void* p, size_t size) noexcept { 119 : hostFlushInstructionCache(p, size); 120 32111 : } 121 : 122 : // ============================================================================ 123 : // [asmjit::JitRuntime - Construction / Destruction] 124 : // ============================================================================ 125 : 126 32141 : JitRuntime::JitRuntime() noexcept {} 127 64282 : JitRuntime::~JitRuntime() noexcept {} 128 : 129 : // ============================================================================ 130 : // [asmjit::JitRuntime - Interface] 131 : // ============================================================================ 132 : 133 32111 : Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { 134 32111 : size_t codeSize = code->getCodeSize(); 135 32111 : if (ASMJIT_UNLIKELY(codeSize == 0)) { 136 0 : *dst = nullptr; 137 0 : return DebugUtils::errored(kErrorNoCodeGenerated); 138 : } 139 : 140 32111 : void* p = _memMgr.alloc(codeSize, getAllocType()); 141 32111 : if (ASMJIT_UNLIKELY(!p)) { 142 0 : *dst = nullptr; 143 0 : return DebugUtils::errored(kErrorNoVirtualMemory); 144 : } 145 : 146 : // Relocate the code and release the unused memory back to `VMemMgr`. 147 32111 : size_t relocSize = code->relocate(p); 148 32111 : if (ASMJIT_UNLIKELY(relocSize == 0)) { 149 0 : *dst = nullptr; 150 0 : _memMgr.release(p); 151 0 : return DebugUtils::errored(kErrorInvalidState); 152 : } 153 : 154 32111 : if (relocSize < codeSize) 155 0 : _memMgr.shrink(p, relocSize); 156 : 157 32111 : flush(p, relocSize); 158 32111 : *dst = p; 159 : 160 32111 : return kErrorOk; 161 : } 162 : 163 0 : Error JitRuntime::_release(void* p) noexcept { 164 0 : return _memMgr.release(p); 165 : } 166 : 167 : } // asmjit namespace 168 : } // namespace PLMD 169 : 170 : // [Api-End] 171 : #include "./asmjit_apiend.h" 172 : #pragma GCC diagnostic pop 173 : #endif // __PLUMED_HAS_ASMJIT