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 #ifndef ASMJIT_CORE_GLOBALS_H_INCLUDED
25 #define ASMJIT_CORE_GLOBALS_H_INCLUDED
26
27 #include "../core/api-config.h"
28
29 ASMJIT_BEGIN_NAMESPACE
30
31 // ============================================================================
32 // [asmjit::Support]
33 // ============================================================================
34
35 //! \cond INTERNAL
36 //! \addtogroup asmjit_utilities
37 //! \{
38 namespace Support {
39 //! Cast designed to cast between function and void* pointers.
40 template<typename Dst, typename Src>
ptr_cast_impl(Src p)41 static inline Dst ptr_cast_impl(Src p) noexcept { return (Dst)p; }
42 } // {Support}
43
44 #if defined(ASMJIT_NO_STDCXX)
45 namespace Support {
operatorNew(size_t n)46 ASMJIT_INLINE void* operatorNew(size_t n) noexcept { return malloc(n); }
operatorDelete(void * p)47 ASMJIT_INLINE void operatorDelete(void* p) noexcept { if (p) free(p); }
48 } // {Support}
49
50 #define ASMJIT_BASE_CLASS(TYPE) \
51 ASMJIT_INLINE void* operator new(size_t n) noexcept { \
52 return Support::operatorNew(n); \
53 } \
54 \
55 ASMJIT_INLINE void operator delete(void* p) noexcept { \
56 Support::operatorDelete(p); \
57 } \
58 \
59 ASMJIT_INLINE void* operator new(size_t, void* p) noexcept { return p; } \
60 ASMJIT_INLINE void operator delete(void*, void*) noexcept {}
61 #else
62 #define ASMJIT_BASE_CLASS(TYPE)
63 #endif
64
65 //! \}
66 //! \endcond
67
68 // ============================================================================
69 // [asmjit::Globals]
70 // ============================================================================
71
72 //! \addtogroup asmjit_core
73 //! \{
74
75 //! Contains typedefs, constants, and variables used globally by AsmJit.
76 namespace Globals {
77
78 // ============================================================================
79 // [asmjit::Globals::<global>]
80 // ============================================================================
81
82 //! Host memory allocator overhead.
83 static constexpr uint32_t kAllocOverhead = uint32_t(sizeof(intptr_t) * 4);
84
85 //! Host memory allocator alignment.
86 static constexpr uint32_t kAllocAlignment = 8;
87
88 //! Aggressive growing strategy threshold.
89 static constexpr uint32_t kGrowThreshold = 1024 * 1024 * 16;
90
91 //! Maximum depth of RB-Tree is:
92 //!
93 //! `2 * log2(n + 1)`
94 //!
95 //! Size of RB node is at least two pointers (without data),
96 //! so a theoretical architecture limit would be:
97 //!
98 //! `2 * log2(addressableMemorySize / sizeof(Node) + 1)`
99 //!
100 //! Which yields 30 on 32-bit arch and 61 on 64-bit arch.
101 //! The final value was adjusted by +1 for safety reasons.
102 static constexpr uint32_t kMaxTreeHeight = (ASMJIT_ARCH_BITS == 32 ? 30 : 61) + 1;
103
104 //! Maximum number of operands per a single instruction.
105 static constexpr uint32_t kMaxOpCount = 6;
106
107 //! Maximum arguments of a function supported by the Compiler / Function API.
108 static constexpr uint32_t kMaxFuncArgs = 16;
109
110 //! The number of values that can be assigned to a single function argument or
111 //! return value.
112 static constexpr uint32_t kMaxValuePack = 4;
113
114 //! Maximum number of physical registers AsmJit can use per register group.
115 static constexpr uint32_t kMaxPhysRegs = 32;
116
117 //! Maximum alignment.
118 static constexpr uint32_t kMaxAlignment = 64;
119
120 //! Maximum label or symbol size in bytes.
121 static constexpr uint32_t kMaxLabelNameSize = 2048;
122
123 //! Maximum section name size.
124 static constexpr uint32_t kMaxSectionNameSize = 35;
125
126 //! Maximum size of comment.
127 static constexpr uint32_t kMaxCommentSize = 1024;
128
129 //! Invalid identifier.
130 static constexpr uint32_t kInvalidId = 0xFFFFFFFFu;
131
132 //! Returned by `indexOf()` and similar when working with containers that use 32-bit index/size.
133 static constexpr uint32_t kNotFound = 0xFFFFFFFFu;
134
135 //! Invalid base address.
136 static constexpr uint64_t kNoBaseAddress = ~uint64_t(0);
137
138 // ============================================================================
139 // [asmjit::Globals::ResetPolicy]
140 // ============================================================================
141
142 //! Reset policy used by most `reset()` functions.
143 enum ResetPolicy : uint32_t {
144 //! Soft reset, doesn't deallocate memory (default).
145 kResetSoft = 0,
146 //! Hard reset, releases all memory used, if any.
147 kResetHard = 1
148 };
149
150 // ============================================================================
151 // [asmjit::Globals::Link]
152 // ============================================================================
153
154 enum Link : uint32_t {
155 kLinkLeft = 0,
156 kLinkRight = 1,
157
158 kLinkPrev = 0,
159 kLinkNext = 1,
160
161 kLinkFirst = 0,
162 kLinkLast = 1,
163
164 kLinkCount = 2
165 };
166
167 struct Init_ {};
168 struct NoInit_ {};
169
170 static const constexpr Init_ Init {};
171 static const constexpr NoInit_ NoInit {};
172
173 } // {Globals}
174
175 // ============================================================================
176 // [asmjit::ByteOrder]
177 // ============================================================================
178
179 //! Byte order.
180 namespace ByteOrder {
181 enum : uint32_t {
182 kLE = 0,
183 kBE = 1,
184 kNative = ASMJIT_ARCH_LE ? kLE : kBE,
185 kSwapped = ASMJIT_ARCH_LE ? kBE : kLE
186 };
187 }
188
189 // ============================================================================
190 // [asmjit::ptr_as_func / func_as_ptr]
191 // ============================================================================
192
193 template<typename Func>
ptr_as_func(void * func)194 static inline Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl<Func, void*>(func); }
195
196 template<typename Func>
func_as_ptr(Func func)197 static inline void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl<void*, Func>(func); }
198
199 //! \}
200
201 // ============================================================================
202 // [asmjit::Error]
203 // ============================================================================
204
205 //! \addtogroup asmjit_error_handling
206 //! \{
207
208 //! AsmJit error type (uint32_t).
209 typedef uint32_t Error;
210
211 //! AsmJit error codes.
212 enum ErrorCode : uint32_t {
213 // @EnumValuesBegin{"enum": "ErrorCode"}@
214
215 //! No error (success).
216 kErrorOk = 0,
217
218 //! Out of memory.
219 kErrorOutOfMemory,
220
221 //! Invalid argument.
222 kErrorInvalidArgument,
223
224 //! Invalid state.
225 //!
226 //! If this error is returned it means that either you are doing something
227 //! wrong or AsmJit caught itself by doing something wrong. This error should
228 //! never be ignored.
229 kErrorInvalidState,
230
231 //! Invalid or incompatible architecture.
232 kErrorInvalidArch,
233
234 //! The object is not initialized.
235 kErrorNotInitialized,
236 //! The object is already initialized.
237 kErrorAlreadyInitialized,
238
239 //! Built-in feature was disabled at compile time and it's not available.
240 kErrorFeatureNotEnabled,
241
242 //! Too many handles (Windows) or file descriptors (Unix/Posix).
243 kErrorTooManyHandles,
244 //! Code generated is larger than allowed.
245 kErrorTooLarge,
246
247 //! No code generated.
248 //!
249 //! Returned by runtime if the \ref CodeHolder contains no code.
250 kErrorNoCodeGenerated,
251
252 //! Invalid directive.
253 kErrorInvalidDirective,
254 //! Attempt to use uninitialized label.
255 kErrorInvalidLabel,
256 //! Label index overflow - a single \ref BaseAssembler instance can hold
257 //! almost 2^32 (4 billion) labels. If there is an attempt to create more
258 //! labels then this error is returned.
259 kErrorTooManyLabels,
260 //! Label is already bound.
261 kErrorLabelAlreadyBound,
262 //! Label is already defined (named labels).
263 kErrorLabelAlreadyDefined,
264 //! Label name is too long.
265 kErrorLabelNameTooLong,
266 //! Label must always be local if it's anonymous (without a name).
267 kErrorInvalidLabelName,
268 //! Parent id passed to \ref CodeHolder::newNamedLabelEntry() was invalid.
269 kErrorInvalidParentLabel,
270 //! Parent id specified for a non-local (global) label.
271 kErrorNonLocalLabelCannotHaveParent,
272
273 //! Invalid section.
274 kErrorInvalidSection,
275 //! Too many sections (section index overflow).
276 kErrorTooManySections,
277 //! Invalid section name (most probably too long).
278 kErrorInvalidSectionName,
279
280 //! Relocation index overflow (too many relocations).
281 kErrorTooManyRelocations,
282 //! Invalid relocation entry.
283 kErrorInvalidRelocEntry,
284 //! Reloc entry contains address that is out of range (unencodable).
285 kErrorRelocOffsetOutOfRange,
286
287 //! Invalid assignment to a register, function argument, or function return value.
288 kErrorInvalidAssignment,
289 //! Invalid instruction.
290 kErrorInvalidInstruction,
291 //! Invalid register type.
292 kErrorInvalidRegType,
293 //! Invalid register group.
294 kErrorInvalidRegGroup,
295 //! Invalid physical register id.
296 kErrorInvalidPhysId,
297 //! Invalid virtual register id.
298 kErrorInvalidVirtId,
299 //! Invalid element index (ARM).
300 kErrorInvalidElementIndex,
301 //! Invalid prefix combination (X86|X64).
302 kErrorInvalidPrefixCombination,
303 //! Invalid LOCK prefix (X86|X64).
304 kErrorInvalidLockPrefix,
305 //! Invalid XACQUIRE prefix (X86|X64).
306 kErrorInvalidXAcquirePrefix,
307 //! Invalid XRELEASE prefix (X86|X64).
308 kErrorInvalidXReleasePrefix,
309 //! Invalid REP prefix (X86|X64).
310 kErrorInvalidRepPrefix,
311 //! Invalid REX prefix (X86|X64).
312 kErrorInvalidRexPrefix,
313 //! Invalid {...} register (X86|X64).
314 kErrorInvalidExtraReg,
315 //! Invalid {k} use (not supported by the instruction) (X86|X64).
316 kErrorInvalidKMaskUse,
317 //! Invalid {k}{z} use (not supported by the instruction) (X86|X64).
318 kErrorInvalidKZeroUse,
319 //! Invalid broadcast - Currently only related to invalid use of AVX-512 {1tox} (X86|X64).
320 kErrorInvalidBroadcast,
321 //! Invalid 'embedded-rounding' {er} or 'suppress-all-exceptions' {sae} (AVX-512) (X86|X64).
322 kErrorInvalidEROrSAE,
323 //! Invalid address used (not encodable).
324 kErrorInvalidAddress,
325 //! Invalid index register used in memory address (not encodable).
326 kErrorInvalidAddressIndex,
327 //! Invalid address scale (not encodable).
328 kErrorInvalidAddressScale,
329 //! Invalid use of 64-bit address.
330 kErrorInvalidAddress64Bit,
331 //! Invalid use of 64-bit address that require 32-bit zero-extension (X64).
332 kErrorInvalidAddress64BitZeroExtension,
333 //! Invalid displacement (not encodable).
334 kErrorInvalidDisplacement,
335 //! Invalid segment (X86).
336 kErrorInvalidSegment,
337
338 //! Invalid immediate (out of bounds on X86 and invalid pattern on ARM).
339 kErrorInvalidImmediate,
340
341 //! Invalid operand size.
342 kErrorInvalidOperandSize,
343 //! Ambiguous operand size (memory has zero size while it's required to determine the operation type.
344 kErrorAmbiguousOperandSize,
345 //! Mismatching operand size (size of multiple operands doesn't match the operation size).
346 kErrorOperandSizeMismatch,
347
348 //! Invalid option.
349 kErrorInvalidOption,
350 //! Option already defined.
351 kErrorOptionAlreadyDefined,
352
353 //! Invalid TypeId.
354 kErrorInvalidTypeId,
355 //! Invalid use of a 8-bit GPB-HIGH register.
356 kErrorInvalidUseOfGpbHi,
357 //! Invalid use of a 64-bit GPQ register in 32-bit mode.
358 kErrorInvalidUseOfGpq,
359 //! Invalid use of an 80-bit float (\ref Type::kIdF80).
360 kErrorInvalidUseOfF80,
361 //! Some registers in the instruction muse be consecutive (some ARM and AVX512
362 //! neural-net instructions).
363 kErrorNotConsecutiveRegs,
364
365 //! Illegal virtual register - reported by instruction validation.
366 kErrorIllegalVirtReg,
367 //! AsmJit cannot create more virtual registers.
368 kErrorTooManyVirtRegs,
369
370 //! AsmJit requires a physical register, but no one is available.
371 kErrorNoMorePhysRegs,
372 //! A variable has been assigned more than once to a function argument (BaseCompiler).
373 kErrorOverlappedRegs,
374 //! Invalid register to hold stack arguments offset.
375 kErrorOverlappingStackRegWithRegArg,
376
377 //! Unbound label cannot be evaluated by expression.
378 kErrorExpressionLabelNotBound,
379 //! Arithmetic overflow during expression evaluation.
380 kErrorExpressionOverflow,
381
382 //! Failed to open anonymous memory handle or file descriptor.
383 kErrorFailedToOpenAnonymousMemory,
384
385 // @EnumValuesEnd@
386
387 //! Count of AsmJit error codes.
388 kErrorCount
389 };
390
391 // ============================================================================
392 // [asmjit::DebugUtils]
393 // ============================================================================
394
395 //! Debugging utilities.
396 namespace DebugUtils {
397
398 //! \cond INTERNAL
399 //! Used to silence warnings about unused arguments or variables.
400 template<typename... Args>
unused(Args &&...)401 static ASMJIT_INLINE void unused(Args&&...) noexcept {}
402 //! \endcond
403
404 //! Returns the error `err` passed.
405 //!
406 //! Provided for debugging purposes. Putting a breakpoint inside `errored` can
407 //! help with tracing the origin of any error reported / returned by AsmJit.
errored(Error err)408 static constexpr Error errored(Error err) noexcept { return err; }
409
410 //! Returns a printable version of `asmjit::Error` code.
411 ASMJIT_API const char* errorAsString(Error err) noexcept;
412
413 //! Called to output debugging message(s).
414 ASMJIT_API void debugOutput(const char* str) noexcept;
415
416 //! Called on assertion failure.
417 //!
418 //! \param file Source file name where it happened.
419 //! \param line Line in the source file.
420 //! \param msg Message to display.
421 //!
422 //! If you have problems with assertion failures a breakpoint can be put
423 //! at \ref assertionFailed() function (asmjit/core/globals.cpp). A call stack
424 //! will be available when such assertion failure is triggered. AsmJit always
425 //! returns errors on failures, assertions are a last resort and usually mean
426 //! unrecoverable state due to out of range array access or totally invalid
427 //! arguments like nullptr where a valid pointer should be provided, etc...
428 ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, const char* msg) noexcept;
429
430 } // {DebugUtils}
431
432 //! \def ASMJIT_ASSERT(...)
433 //!
434 //! AsmJit's own assert macro used in AsmJit code-base.
435 #if defined(ASMJIT_BUILD_DEBUG)
436 #define ASMJIT_ASSERT(...) \
437 do { \
438 if (ASMJIT_LIKELY(__VA_ARGS__)) \
439 break; \
440 ::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, #__VA_ARGS__); \
441 } while (0)
442 #else
443 #define ASMJIT_ASSERT(...) ((void)0)
444 #endif
445
446 //! \def ASMJIT_PROPAGATE(...)
447 //!
448 //! Propagates a possible `Error` produced by `...` to the caller by returning
449 //! the error immediately. Used by AsmJit internally, but kept public for users
450 //! that want to use the same technique to propagate errors to the caller.
451 #define ASMJIT_PROPAGATE(...) \
452 do { \
453 ::asmjit::Error _err = __VA_ARGS__; \
454 if (ASMJIT_UNLIKELY(_err)) \
455 return _err; \
456 } while (0)
457
458 //! \}
459
460 ASMJIT_END_NAMESPACE
461
462 #endif // ASMJIT_CORE_GLOBALS_H_INCLUDED
463