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 : #ifndef __PLUMED_asmjit_globals_h
21 : #define __PLUMED_asmjit_globals_h
22 : #ifdef __PLUMED_HAS_ASMJIT
23 : #pragma GCC diagnostic push
24 : #pragma GCC diagnostic ignored "-Wpedantic"
25 : // [AsmJit]
26 : // Complete x86/x64 JIT and Remote Assembler for C++.
27 : //
28 : // [License]
29 : // Zlib - See LICENSE.md file in the package.
30 :
31 : // [Guard]
32 : #ifndef _ASMJIT_BASE_GLOBALS_H
33 : #define _ASMJIT_BASE_GLOBALS_H
34 :
35 : // [Dependencies]
36 : #include "./asmjit_build.h"
37 :
38 : // [Api-Begin]
39 : #include "./asmjit_apibegin.h"
40 :
41 : namespace PLMD {
42 : namespace asmjit {
43 :
44 : //! \addtogroup asmjit_base
45 : //! \{
46 :
47 : // ============================================================================
48 : // [asmjit::Globals]
49 : // ============================================================================
50 :
51 : enum { kInvalidValue = 0xFFFFFFFFU };
52 :
53 : //! AsmJit globals.
54 : namespace Globals {
55 :
56 : //! Invalid index
57 : //!
58 : //! Invalid index is the last possible index that is never used in practice. In
59 : //! AsmJit it is used exclusively with strings to indicate the the length of the
60 : //! string is not known and has to be determined.
61 : static const size_t kInvalidIndex = ~static_cast<size_t>(0);
62 :
63 : //! Invalid base address.
64 : static const uint64_t kNoBaseAddress = ~static_cast<uint64_t>(0);
65 :
66 : //! Global definitions.
67 : ASMJIT_ENUM(Defs) {
68 : //! Invalid register id.
69 : kInvalidRegId = 0xFF,
70 :
71 : //! Host memory allocator overhead.
72 : kAllocOverhead = static_cast<int>(sizeof(intptr_t) * 4),
73 : //! Aggressive growing strategy threshold.
74 : kAllocThreshold = 8192 * 1024
75 : };
76 :
77 : ASMJIT_ENUM(Limits) {
78 : //! Count of register kinds that are important to Function API and CodeCompiler.
79 : //! The target architecture can define more register kinds for special registers,
80 : //! but these will never map to virtual registers and will never be used to pass
81 : //! and return function arguments and function return values, respectively.
82 : kMaxVRegKinds = 4,
83 :
84 : //! Maximum number of physical registers of all kinds of all supported
85 : //! architectures. This is only important for \ref CodeCompiler and its
86 : //! \ref RAPass (register allocator pass).
87 : //!
88 : //! NOTE: The distribution of these registers is architecture specific.
89 : kMaxPhysRegs = 64,
90 :
91 : //! Maximum alignment.
92 : kMaxAlignment = 64,
93 :
94 : //! Maximum label or symbol length in bytes (take into consideration that a
95 : //! single UTF-8 character can take more than single byte to encode it).
96 : kMaxLabelLength = 2048
97 : };
98 :
99 : } // Globals namespace
100 :
101 : // ============================================================================
102 : // [asmjit::Error]
103 : // ============================================================================
104 :
105 : //! AsmJit error type (uint32_t).
106 : typedef uint32_t Error;
107 :
108 : //! AsmJit error codes.
109 : ASMJIT_ENUM(ErrorCode) {
110 : //! No error (success).
111 : //!
112 : //! This is default state and state you want.
113 : kErrorOk = 0,
114 :
115 : //! Heap memory allocation failed.
116 : kErrorNoHeapMemory,
117 :
118 : //! Virtual memory allocation failed.
119 : kErrorNoVirtualMemory,
120 :
121 : //! Invalid argument.
122 : kErrorInvalidArgument,
123 :
124 : //! Invalid state.
125 : //!
126 : //! If this error is returned it means that either you are doing something
127 : //! wrong or AsmJit caught itself by doing something wrong. This error should
128 : //! not be underestimated.
129 : kErrorInvalidState,
130 :
131 : //! Invalid or incompatible architecture.
132 : kErrorInvalidArch,
133 :
134 : //! The object is not initialized.
135 : kErrorNotInitialized,
136 : //! The object is already initialized.
137 : kErrorAlreadyInitialized,
138 :
139 : //! Built-in feature was disabled at compile time and it's not available.
140 : kErrorFeatureNotEnabled,
141 :
142 : //! CodeHolder can't have attached more than one \ref Assembler at a time.
143 : kErrorSlotOccupied,
144 :
145 : //! No code generated.
146 : //!
147 : //! Returned by runtime if the \ref CodeHolder contains no code.
148 : kErrorNoCodeGenerated,
149 : //! Code generated is larger than allowed.
150 : kErrorCodeTooLarge,
151 :
152 : //! Attempt to use uninitialized label.
153 : kErrorInvalidLabel,
154 : //! Label index overflow - a single `Assembler` instance can hold more than
155 : //! 2 billion labels (2147483391 to be exact). If there is an attempt to
156 : //! create more labels this error is returned.
157 : kErrorLabelIndexOverflow,
158 : //! Label is already bound.
159 : kErrorLabelAlreadyBound,
160 : //! Label is already defined (named labels).
161 : kErrorLabelAlreadyDefined,
162 : //! Label name is too long.
163 : kErrorLabelNameTooLong,
164 : //! Label must always be local if it's anonymous (without a name).
165 : kErrorInvalidLabelName,
166 : //! Parent id passed to `CodeHolder::newNamedLabelId()` was invalid.
167 : kErrorInvalidParentLabel,
168 : //! Parent id specified for a non-local (global) label.
169 : kErrorNonLocalLabelCantHaveParent,
170 :
171 : //! Relocation index overflow.
172 : kErrorRelocIndexOverflow,
173 : //! Invalid relocation entry.
174 : kErrorInvalidRelocEntry,
175 :
176 : //! Invalid instruction.
177 : kErrorInvalidInstruction,
178 : //! Invalid register type.
179 : kErrorInvalidRegType,
180 : //! Invalid register kind.
181 : kErrorInvalidRegKind,
182 : //! Invalid register's physical id.
183 : kErrorInvalidPhysId,
184 : //! Invalid register's virtual id.
185 : kErrorInvalidVirtId,
186 : //! Invalid prefix combination.
187 : kErrorInvalidPrefixCombination,
188 : //! Invalid LOCK prefix.
189 : kErrorInvalidLockPrefix,
190 : //! Invalid XACQUIRE prefix.
191 : kErrorInvalidXAcquirePrefix,
192 : //! Invalid XACQUIRE prefix.
193 : kErrorInvalidXReleasePrefix,
194 : //! Invalid REP prefix.
195 : kErrorInvalidRepPrefix,
196 : //! Invalid REX prefix.
197 : kErrorInvalidRexPrefix,
198 : //! Invalid mask register (not 'k').
199 : kErrorInvalidKMaskReg,
200 : //! Invalid {k} use (not supported by the instruction).
201 : kErrorInvalidKMaskUse,
202 : //! Invalid {k}{z} use (not supported by the instruction).
203 : kErrorInvalidKZeroUse,
204 : //! Invalid broadcast - Currently only related to invalid use of AVX-512 {1tox}.
205 : kErrorInvalidBroadcast,
206 : //! Invalid 'embedded-rounding' {er} or 'suppress-all-exceptions' {sae} (AVX-512).
207 : kErrorInvalidEROrSAE,
208 : //! Invalid address used (not encodable).
209 : kErrorInvalidAddress,
210 : //! Invalid index register used in memory address (not encodable).
211 : kErrorInvalidAddressIndex,
212 : //! Invalid address scale (not encodable).
213 : kErrorInvalidAddressScale,
214 : //! Invalid use of 64-bit address.
215 : kErrorInvalidAddress64Bit,
216 : //! Invalid displacement (not encodable).
217 : kErrorInvalidDisplacement,
218 : //! Invalid segment (X86).
219 : kErrorInvalidSegment,
220 :
221 : //! Invalid immediate (out of bounds on X86 and invalid pattern on ARM).
222 : kErrorInvalidImmediate,
223 :
224 : //! Invalid operand size.
225 : kErrorInvalidOperandSize,
226 : //! Ambiguous operand size (memory has zero size while it's required to determine the operation type.
227 : kErrorAmbiguousOperandSize,
228 : //! Mismatching operand size (size of multiple operands doesn't match the operation size).
229 : kErrorOperandSizeMismatch,
230 :
231 : //! Invalid TypeId.
232 : kErrorInvalidTypeId,
233 : //! Invalid use of a 8-bit GPB-HIGH register.
234 : kErrorInvalidUseOfGpbHi,
235 : //! Invalid use of a 64-bit GPQ register in 32-bit mode.
236 : kErrorInvalidUseOfGpq,
237 : //! Invalid use of an 80-bit float (TypeId::kF80).
238 : kErrorInvalidUseOfF80,
239 : //! Some registers in the instruction muse be consecutive (some ARM and AVX512 neural-net instructions).
240 : kErrorNotConsecutiveRegs,
241 :
242 : //! AsmJit requires a physical register, but no one is available.
243 : kErrorNoMorePhysRegs,
244 : //! A variable has been assigned more than once to a function argument (CodeCompiler).
245 : kErrorOverlappedRegs,
246 : //! Invalid register to hold stack arguments offset.
247 : kErrorOverlappingStackRegWithRegArg,
248 :
249 : //! Count of AsmJit error codes.
250 : kErrorCount
251 : };
252 :
253 : // ============================================================================
254 : // [asmjit::Internal]
255 : // ============================================================================
256 :
257 : namespace Internal {
258 :
259 : #if defined(ASMJIT_CUSTOM_ALLOC) && \
260 : defined(ASMJIT_CUSTOM_REALLOC) && \
261 : defined(ASMJIT_CUSTOM_FREE)
262 : static ASMJIT_INLINE void* allocMemory(size_t size) noexcept { return ASMJIT_CUSTOM_ALLOC(size); }
263 : static ASMJIT_INLINE void* reallocMemory(void* p, size_t size) noexcept { return ASMJIT_CUSTOM_REALLOC(p, size); }
264 : static ASMJIT_INLINE void releaseMemory(void* p) noexcept { ASMJIT_CUSTOM_FREE(p); }
265 : #elif !defined(ASMJIT_CUSTOM_ALLOC) && \
266 : !defined(ASMJIT_CUSTOM_REALLOC) && \
267 : !defined(ASMJIT_CUSTOM_FREE)
268 11676 : static ASMJIT_INLINE void* allocMemory(size_t size) noexcept { return ::malloc(size); }
269 0 : static ASMJIT_INLINE void* reallocMemory(void* p, size_t size) noexcept { return ::realloc(p, size); }
270 11676 : static ASMJIT_INLINE void releaseMemory(void* p) noexcept { ::free(p); }
271 : #else
272 : # error "[asmjit] You must provide either none or all of ASMJIT_CUSTOM_[ALLOC|REALLOC|FREE]"
273 : #endif
274 :
275 : //! Cast designed to cast between function and void* pointers.
276 : template<typename Dst, typename Src>
277 : static ASMJIT_INLINE Dst ptr_cast(Src p) noexcept { return (Dst)p; }
278 :
279 : } // Internal namespace
280 :
281 : template<typename Func>
282 : static ASMJIT_INLINE Func ptr_as_func(void* func) noexcept { return Internal::ptr_cast<Func, void*>(func); }
283 :
284 : template<typename Func>
285 : static ASMJIT_INLINE void* func_as_ptr(Func func) noexcept { return Internal::ptr_cast<void*, Func>(func); }
286 :
287 : // ============================================================================
288 : // [asmjit::DebugUtils]
289 : // ============================================================================
290 :
291 : namespace DebugUtils {
292 :
293 : //! Returns the error `err` passed.
294 : //!
295 : //! Provided for debugging purposes. Putting a breakpoint inside `errored` can
296 : //! help with tracing the origin of any error reported / returned by AsmJit.
297 : static ASMJIT_INLINE Error errored(Error err) noexcept { return err; }
298 :
299 : //! Get a printable version of `asmjit::Error` code.
300 : ASMJIT_API const char* errorAsString(Error err) noexcept;
301 :
302 : //! Called to output debugging message(s).
303 : ASMJIT_API void debugOutput(const char* str) noexcept;
304 :
305 : //! Called on assertion failure.
306 : //!
307 : //! \param file Source file name where it happened.
308 : //! \param line Line in the source file.
309 : //! \param msg Message to display.
310 : //!
311 : //! If you have problems with assertions put a breakpoint at assertionFailed()
312 : //! function (asmjit/base/globals.cpp) and check the call stack to locate the
313 : //! failing code.
314 : ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, const char* msg) noexcept;
315 :
316 : #if defined(ASMJIT_DEBUG)
317 : # define ASMJIT_ASSERT(exp) \
318 : do { \
319 : if (ASMJIT_LIKELY(exp)) \
320 : break; \
321 : ::PLMD::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, #exp); \
322 : } while (0)
323 : # define ASMJIT_NOT_REACHED() \
324 : do { \
325 : ::PLMD::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, \
326 : "ASMJIT_NOT_REACHED has been reached"); \
327 : ASMJIT_ASSUME(0); \
328 : } while (0)
329 : #else
330 : # define ASMJIT_ASSERT(exp) ASMJIT_NOP
331 : # define ASMJIT_NOT_REACHED() ASMJIT_ASSUME(0)
332 : #endif // DEBUG
333 :
334 : //! \internal
335 : //!
336 : //! Used by AsmJit to propagate a possible `Error` produced by `...` to the caller.
337 : #define ASMJIT_PROPAGATE(...) \
338 : do { \
339 : ::PLMD::asmjit::Error _err = __VA_ARGS__; \
340 : if (ASMJIT_UNLIKELY(_err)) \
341 : return _err; \
342 : } while (0)
343 :
344 : } // DebugUtils namespace
345 :
346 : // ============================================================================
347 : // [asmjit::Init / NoInit]
348 : // ============================================================================
349 :
350 : #if !defined(ASMJIT_DOCGEN)
351 : struct _Init {};
352 : static const _Init Init = {};
353 :
354 : struct _NoInit {};
355 : static const _NoInit NoInit = {};
356 : #endif // !ASMJIT_DOCGEN
357 :
358 : //! \}
359 :
360 : } // asmjit namespace
361 : } // namespace PLMD
362 :
363 : // [Api-End]
364 : #include "./asmjit_apiend.h"
365 :
366 : // [Guard]
367 : #endif // _ASMJIT_BASE_GLOBALS_H
368 : #pragma GCC diagnostic pop
369 : #endif // __PLUMED_HAS_ASMJIT
370 : #endif
|