1 // AsmJit - Machine code generation for C++
2 //
3 // * Official AsmJit Home Page: https://asmjit.com
4 // * Official Github Repository: https://github.com/asmjit/asmjit
5 //
6 // Copyright (c) 2008-2020 The AsmJit Authors
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not be
21 // misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source distribution.
23
24 #include "../core/api-build_p.h"
25 #ifndef ASMJIT_NO_JIT
26
27 #include "../core/cpuinfo.h"
28 #include "../core/jitruntime.h"
29
30 ASMJIT_BEGIN_NAMESPACE
31
32 // ============================================================================
33 // [asmjit::JitRuntime - Utilities]
34 // ============================================================================
35
36 // Only useful on non-x86 architectures.
JitRuntime_flushInstructionCache(const void * p,size_t size)37 static inline void JitRuntime_flushInstructionCache(const void* p, size_t size) noexcept {
38 #if ASMJIT_ARCH_X86
39 DebugUtils::unused(p, size);
40 #else
41 # if defined(_WIN32)
42 // Windows has a built-in support in `kernel32.dll`.
43 ::FlushInstructionCache(::GetCurrentProcess(), p, size);
44 # elif defined(__GNUC__)
45 char* start = static_cast<char*>(const_cast<void*>(p));
46 char* end = start + size;
47 __builtin___clear_cache(start, end);
48 # else
49 DebugUtils::unused(p, size);
50 # endif
51 #endif
52 }
53
54 // ============================================================================
55 // [asmjit::JitRuntime - Construction / Destruction]
56 // ============================================================================
57
JitRuntime(const JitAllocator::CreateParams * params)58 JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept
59 : _allocator(params) {
60 _environment = hostEnvironment();
61 _environment.setFormat(Environment::kFormatJIT);
62 }
63
~JitRuntime()64 JitRuntime::~JitRuntime() noexcept {}
65
66 // ============================================================================
67 // [asmjit::JitRuntime - Interface]
68 // ============================================================================
69
_add(void ** dst,CodeHolder * code)70 Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept {
71 *dst = nullptr;
72
73 ASMJIT_PROPAGATE(code->flatten());
74 ASMJIT_PROPAGATE(code->resolveUnresolvedLinks());
75
76 size_t estimatedCodeSize = code->codeSize();
77 if (ASMJIT_UNLIKELY(estimatedCodeSize == 0))
78 return DebugUtils::errored(kErrorNoCodeGenerated);
79
80 uint8_t* ro;
81 uint8_t* rw;
82 ASMJIT_PROPAGATE(_allocator.alloc((void**)&ro, (void**)&rw, estimatedCodeSize));
83
84 // Relocate the code.
85 Error err = code->relocateToBase(uintptr_t((void*)ro));
86 if (ASMJIT_UNLIKELY(err)) {
87 _allocator.release(ro);
88 return err;
89 }
90
91 // Recalculate the final code size and shrink the memory we allocated for it
92 // in case that some relocations didn't require records in an address table.
93 size_t codeSize = code->codeSize();
94
95 for (Section* section : code->_sections) {
96 size_t offset = size_t(section->offset());
97 size_t bufferSize = size_t(section->bufferSize());
98 size_t virtualSize = size_t(section->virtualSize());
99
100 ASMJIT_ASSERT(offset + bufferSize <= codeSize);
101 memcpy(rw + offset, section->data(), bufferSize);
102
103 if (virtualSize > bufferSize) {
104 ASMJIT_ASSERT(offset + virtualSize <= codeSize);
105 memset(rw + offset + bufferSize, 0, virtualSize - bufferSize);
106 }
107 }
108
109 if (codeSize < estimatedCodeSize)
110 _allocator.shrink(ro, codeSize);
111
112 flush(ro, codeSize);
113 *dst = ro;
114
115 return kErrorOk;
116 }
117
_release(void * p)118 Error JitRuntime::_release(void* p) noexcept {
119 return _allocator.release(p);
120 }
121
flush(const void * p,size_t size)122 void JitRuntime::flush(const void* p, size_t size) noexcept {
123 JitRuntime_flushInstructionCache(p, size);
124 }
125
126 ASMJIT_END_NAMESPACE
127
128 #endif
129