asmjit 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/asmjit.gemspec +1 -1
- data/ext/asmjit/asmjit/.editorconfig +10 -0
- data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
- data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
- data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
- data/ext/asmjit/asmjit/.gitignore +6 -0
- data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
- data/ext/asmjit/asmjit/LICENSE.md +17 -0
- data/ext/asmjit/asmjit/README.md +69 -0
- data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
- data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
- data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
- data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
- data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
- data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
- data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
- data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
- data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
- data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
- data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
- data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
- data/ext/asmjit/asmjit/test/broken.cpp +312 -0
- data/ext/asmjit/asmjit/test/broken.h +148 -0
- data/ext/asmjit/asmjit/test/cmdline.h +61 -0
- data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
- data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
- data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
- data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
- data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
- data/ext/asmjit/asmjit.cc +18 -0
- data/lib/asmjit/version.rb +1 -1
- metadata +197 -2
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// This file is part of AsmJit project <https://asmjit.com>
|
|
2
|
+
//
|
|
3
|
+
// See asmjit.h or LICENSE.md for license and copyright information
|
|
4
|
+
// SPDX-License-Identifier: Zlib
|
|
5
|
+
|
|
6
|
+
#ifndef ASMJIT_CORE_FORMATTER_H_INCLUDED
|
|
7
|
+
#define ASMJIT_CORE_FORMATTER_H_INCLUDED
|
|
8
|
+
|
|
9
|
+
#include "../core/globals.h"
|
|
10
|
+
#include "../core/inst.h"
|
|
11
|
+
#include "../core/string.h"
|
|
12
|
+
#include "../core/support.h"
|
|
13
|
+
|
|
14
|
+
ASMJIT_BEGIN_NAMESPACE
|
|
15
|
+
|
|
16
|
+
//! \addtogroup asmjit_logging
|
|
17
|
+
//! \{
|
|
18
|
+
|
|
19
|
+
class BaseBuilder;
|
|
20
|
+
class BaseEmitter;
|
|
21
|
+
class BaseNode;
|
|
22
|
+
struct Operand_;
|
|
23
|
+
|
|
24
|
+
//! Format flags used by \ref Logger and \ref FormatOptions.
|
|
25
|
+
enum class FormatFlags : uint32_t {
|
|
26
|
+
//! No formatting flags.
|
|
27
|
+
kNone = 0u,
|
|
28
|
+
|
|
29
|
+
//! Show also binary form of each logged instruction (Assembler).
|
|
30
|
+
kMachineCode = 0x00000001u,
|
|
31
|
+
//! Show a text explanation of some immediate values.
|
|
32
|
+
kExplainImms = 0x00000002u,
|
|
33
|
+
//! Use hexadecimal notation of immediate values.
|
|
34
|
+
kHexImms = 0x00000004u,
|
|
35
|
+
//! Use hexadecimal notation of addresses and offsets in addresses.
|
|
36
|
+
kHexOffsets = 0x00000008u,
|
|
37
|
+
//! Show casts between virtual register types (Compiler output).
|
|
38
|
+
kRegCasts = 0x00000010u,
|
|
39
|
+
//! Show positions associated with nodes (Compiler output).
|
|
40
|
+
kPositions = 0x00000020u
|
|
41
|
+
};
|
|
42
|
+
ASMJIT_DEFINE_ENUM_FLAGS(FormatFlags)
|
|
43
|
+
|
|
44
|
+
//! Format indentation group, used by \ref FormatOptions.
|
|
45
|
+
enum class FormatIndentationGroup : uint32_t {
|
|
46
|
+
//! Indentation used for instructions and directives.
|
|
47
|
+
kCode = 0u,
|
|
48
|
+
//! Indentation used for labels and function nodes.
|
|
49
|
+
kLabel = 1u,
|
|
50
|
+
//! Indentation used for comments (not inline comments).
|
|
51
|
+
kComment = 2u,
|
|
52
|
+
|
|
53
|
+
//! \cond INTERNAL
|
|
54
|
+
//! Reserved for future use.
|
|
55
|
+
kReserved = 3u,
|
|
56
|
+
//! \endcond
|
|
57
|
+
|
|
58
|
+
//! Maximum value of `FormatIndentationGroup`.
|
|
59
|
+
kMaxValue = kReserved
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
//! Format padding group, used by \ref FormatOptions.
|
|
63
|
+
enum class FormatPaddingGroup : uint32_t {
|
|
64
|
+
//! Describes padding of a regular line, which can represent instruction, data, or assembler directives.
|
|
65
|
+
kRegularLine = 0,
|
|
66
|
+
//! Describes padding of machine code dump that is visible next to the instruction, if enabled.
|
|
67
|
+
kMachineCode = 1,
|
|
68
|
+
|
|
69
|
+
//! Maximum value of `FormatPaddingGroup`.
|
|
70
|
+
kMaxValue = kMachineCode
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
//! Formatting options used by \ref Logger and \ref Formatter.
|
|
74
|
+
class FormatOptions {
|
|
75
|
+
public:
|
|
76
|
+
//! \name Members
|
|
77
|
+
//! \{
|
|
78
|
+
|
|
79
|
+
//! Format flags.
|
|
80
|
+
FormatFlags _flags = FormatFlags::kNone;
|
|
81
|
+
//! Indentations for each indentation group.
|
|
82
|
+
Support::Array<uint8_t, uint32_t(FormatIndentationGroup::kMaxValue) + 1> _indentation {};
|
|
83
|
+
//! Paddings for each padding group.
|
|
84
|
+
Support::Array<uint16_t, uint32_t(FormatPaddingGroup::kMaxValue) + 1> _padding {};
|
|
85
|
+
|
|
86
|
+
//! \}
|
|
87
|
+
|
|
88
|
+
//! \name Reset
|
|
89
|
+
//! \{
|
|
90
|
+
|
|
91
|
+
//! Resets FormatOptions to its default initialized state.
|
|
92
|
+
inline void reset() noexcept {
|
|
93
|
+
_flags = FormatFlags::kNone;
|
|
94
|
+
_indentation.fill(uint8_t(0));
|
|
95
|
+
_padding.fill(uint16_t(0));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//! \}
|
|
99
|
+
|
|
100
|
+
//! \name Accessors
|
|
101
|
+
//! \{
|
|
102
|
+
|
|
103
|
+
//! Returns format flags.
|
|
104
|
+
inline FormatFlags flags() const noexcept { return _flags; }
|
|
105
|
+
//! Tests whether the given `flag` is set in format flags.
|
|
106
|
+
inline bool hasFlag(FormatFlags flag) const noexcept { return Support::test(_flags, flag); }
|
|
107
|
+
|
|
108
|
+
//! Resets all format flags to `flags`.
|
|
109
|
+
inline void setFlags(FormatFlags flags) noexcept { _flags = flags; }
|
|
110
|
+
//! Adds `flags` to format flags.
|
|
111
|
+
inline void addFlags(FormatFlags flags) noexcept { _flags |= flags; }
|
|
112
|
+
//! Removes `flags` from format flags.
|
|
113
|
+
inline void clearFlags(FormatFlags flags) noexcept { _flags &= ~flags; }
|
|
114
|
+
|
|
115
|
+
//! Returns indentation for the given indentation `group`.
|
|
116
|
+
inline uint8_t indentation(FormatIndentationGroup group) const noexcept { return _indentation[group]; }
|
|
117
|
+
//! Sets indentation for the given indentation `group`.
|
|
118
|
+
inline void setIndentation(FormatIndentationGroup group, uint32_t n) noexcept { _indentation[group] = uint8_t(n); }
|
|
119
|
+
//! Resets indentation for the given indentation `group` to zero.
|
|
120
|
+
inline void resetIndentation(FormatIndentationGroup group) noexcept { _indentation[group] = uint8_t(0); }
|
|
121
|
+
|
|
122
|
+
//! Returns pading for the given padding `group`.
|
|
123
|
+
inline size_t padding(FormatPaddingGroup group) const noexcept { return _padding[group]; }
|
|
124
|
+
//! Sets pading for the given padding `group`.
|
|
125
|
+
inline void setPadding(FormatPaddingGroup group, size_t n) noexcept { _padding[group] = uint16_t(n); }
|
|
126
|
+
//! Resets pading for the given padding `group` to zero, which means that a default padding will be used
|
|
127
|
+
//! based on the target architecture properties.
|
|
128
|
+
inline void resetPadding(FormatPaddingGroup group) noexcept { _padding[group] = uint16_t(0); }
|
|
129
|
+
|
|
130
|
+
//! \}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
//! Provides formatting functionality to format operands, instructions, and nodes.
|
|
134
|
+
namespace Formatter {
|
|
135
|
+
|
|
136
|
+
#ifndef ASMJIT_NO_LOGGING
|
|
137
|
+
|
|
138
|
+
//! Appends a formatted `typeId` to the output string `sb`.
|
|
139
|
+
ASMJIT_API Error formatTypeId(
|
|
140
|
+
String& sb,
|
|
141
|
+
TypeId typeId) noexcept;
|
|
142
|
+
|
|
143
|
+
//! Appends a formatted `featureId` to the output string `sb`.
|
|
144
|
+
//!
|
|
145
|
+
//! See \ref CpuFeatures.
|
|
146
|
+
ASMJIT_API Error formatFeature(
|
|
147
|
+
String& sb,
|
|
148
|
+
Arch arch,
|
|
149
|
+
uint32_t featureId) noexcept;
|
|
150
|
+
|
|
151
|
+
//! Appends a formatted register to the output string `sb`.
|
|
152
|
+
//!
|
|
153
|
+
//! \note Emitter is optional, but it's required to format virtual registers, which won't be formatted properly
|
|
154
|
+
//! if the `emitter` is not provided.
|
|
155
|
+
ASMJIT_API Error formatRegister(
|
|
156
|
+
String& sb,
|
|
157
|
+
FormatFlags formatFlags,
|
|
158
|
+
const BaseEmitter* emitter,
|
|
159
|
+
Arch arch,
|
|
160
|
+
RegType regType,
|
|
161
|
+
uint32_t regId) noexcept;
|
|
162
|
+
|
|
163
|
+
//! Appends a formatted label to the output string `sb`.
|
|
164
|
+
//!
|
|
165
|
+
//! \note Emitter is optional, but it's required to format named labels properly, otherwise the formatted as
|
|
166
|
+
//! it is an anonymous label.
|
|
167
|
+
ASMJIT_API Error formatLabel(
|
|
168
|
+
String& sb,
|
|
169
|
+
FormatFlags formatFlags,
|
|
170
|
+
const BaseEmitter* emitter,
|
|
171
|
+
uint32_t labelId) noexcept;
|
|
172
|
+
|
|
173
|
+
//! Appends a formatted operand to the output string `sb`.
|
|
174
|
+
//!
|
|
175
|
+
//! \note Emitter is optional, but it's required to format named labels and virtual registers. See
|
|
176
|
+
//! \ref formatRegister() and \ref formatLabel() for more details.
|
|
177
|
+
ASMJIT_API Error formatOperand(
|
|
178
|
+
String& sb,
|
|
179
|
+
FormatFlags formatFlags,
|
|
180
|
+
const BaseEmitter* emitter,
|
|
181
|
+
Arch arch,
|
|
182
|
+
const Operand_& op) noexcept;
|
|
183
|
+
|
|
184
|
+
//! Appends a formatted data-type to the output string `sb`.
|
|
185
|
+
ASMJIT_API Error formatDataType(
|
|
186
|
+
String& sb,
|
|
187
|
+
FormatFlags formatFlags,
|
|
188
|
+
Arch arch,
|
|
189
|
+
TypeId typeId) noexcept;
|
|
190
|
+
|
|
191
|
+
//! Appends a formatted data to the output string `sb`.
|
|
192
|
+
ASMJIT_API Error formatData(
|
|
193
|
+
String& sb,
|
|
194
|
+
FormatFlags formatFlags,
|
|
195
|
+
Arch arch,
|
|
196
|
+
TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) noexcept;
|
|
197
|
+
|
|
198
|
+
//! Appends a formatted instruction to the output string `sb`.
|
|
199
|
+
//!
|
|
200
|
+
//! \note Emitter is optional, but it's required to format named labels and virtual registers. See
|
|
201
|
+
//! \ref formatRegister() and \ref formatLabel() for more details.
|
|
202
|
+
ASMJIT_API Error formatInstruction(
|
|
203
|
+
String& sb,
|
|
204
|
+
FormatFlags formatFlags,
|
|
205
|
+
const BaseEmitter* emitter,
|
|
206
|
+
Arch arch,
|
|
207
|
+
const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept;
|
|
208
|
+
|
|
209
|
+
#ifndef ASMJIT_NO_BUILDER
|
|
210
|
+
//! Appends a formatted node to the output string `sb`.
|
|
211
|
+
//!
|
|
212
|
+
//! The `node` must belong to the provided `builder`.
|
|
213
|
+
ASMJIT_API Error formatNode(
|
|
214
|
+
String& sb,
|
|
215
|
+
const FormatOptions& formatOptions,
|
|
216
|
+
const BaseBuilder* builder,
|
|
217
|
+
const BaseNode* node) noexcept;
|
|
218
|
+
|
|
219
|
+
//! Appends formatted nodes to the output string `sb`.
|
|
220
|
+
//!
|
|
221
|
+
//! All nodes that are part of the given `builder` will be appended.
|
|
222
|
+
ASMJIT_API Error formatNodeList(
|
|
223
|
+
String& sb,
|
|
224
|
+
const FormatOptions& formatOptions,
|
|
225
|
+
const BaseBuilder* builder) noexcept;
|
|
226
|
+
|
|
227
|
+
//! Appends formatted nodes to the output string `sb`.
|
|
228
|
+
//!
|
|
229
|
+
//! This function works the same as \ref formatNode(), but appends more nodes to the output string,
|
|
230
|
+
//! separating each node with a newline '\n' character.
|
|
231
|
+
ASMJIT_API Error formatNodeList(
|
|
232
|
+
String& sb,
|
|
233
|
+
const FormatOptions& formatOptions,
|
|
234
|
+
const BaseBuilder* builder,
|
|
235
|
+
const BaseNode* begin,
|
|
236
|
+
const BaseNode* end) noexcept;
|
|
237
|
+
#endif
|
|
238
|
+
|
|
239
|
+
#endif
|
|
240
|
+
|
|
241
|
+
} // {Formatter}
|
|
242
|
+
|
|
243
|
+
//! \}
|
|
244
|
+
|
|
245
|
+
ASMJIT_END_NAMESPACE
|
|
246
|
+
|
|
247
|
+
#endif // ASMJIT_CORE_FORMATTER_H_INCLUDED
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// This file is part of AsmJit project <https://asmjit.com>
|
|
2
|
+
//
|
|
3
|
+
// See asmjit.h or LICENSE.md for license and copyright information
|
|
4
|
+
// SPDX-License-Identifier: Zlib
|
|
5
|
+
|
|
6
|
+
#ifndef ASMJIT_CORE_FORMATTER_P_H_INCLUDED
|
|
7
|
+
#define ASMJIT_CORE_FORMATTER_P_H_INCLUDED
|
|
8
|
+
|
|
9
|
+
#include "../core/formatter.h"
|
|
10
|
+
|
|
11
|
+
ASMJIT_BEGIN_NAMESPACE
|
|
12
|
+
|
|
13
|
+
//! \cond INTERNAL
|
|
14
|
+
//! \addtogroup asmjit_logging
|
|
15
|
+
//! \{
|
|
16
|
+
|
|
17
|
+
namespace Formatter {
|
|
18
|
+
|
|
19
|
+
static ASMJIT_FORCE_INLINE size_t paddingFromOptions(const FormatOptions& formatOptions, FormatPaddingGroup group) noexcept {
|
|
20
|
+
static constexpr uint16_t _defaultPaddingTable[uint32_t(FormatPaddingGroup::kMaxValue) + 1] = { 44, 26 };
|
|
21
|
+
static_assert(uint32_t(FormatPaddingGroup::kMaxValue) + 1 == 2, "If a new group is defined it must be added here");
|
|
22
|
+
|
|
23
|
+
size_t padding = formatOptions.padding(group);
|
|
24
|
+
return padding ? padding : size_t(_defaultPaddingTable[uint32_t(group)]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
} // {Formatter}
|
|
28
|
+
|
|
29
|
+
//! \}
|
|
30
|
+
//! \endcond
|
|
31
|
+
|
|
32
|
+
ASMJIT_END_NAMESPACE
|
|
33
|
+
|
|
34
|
+
#endif // ASMJIT_CORE_FORMATTER_H_P_INCLUDED
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// This file is part of AsmJit project <https://asmjit.com>
|
|
2
|
+
//
|
|
3
|
+
// See asmjit.h or LICENSE.md for license and copyright information
|
|
4
|
+
// SPDX-License-Identifier: Zlib
|
|
5
|
+
|
|
6
|
+
#include "../core/api-build_p.h"
|
|
7
|
+
#include "../core/archtraits.h"
|
|
8
|
+
#include "../core/func.h"
|
|
9
|
+
#include "../core/operand.h"
|
|
10
|
+
#include "../core/type.h"
|
|
11
|
+
#include "../core/funcargscontext_p.h"
|
|
12
|
+
|
|
13
|
+
#if !defined(ASMJIT_NO_X86)
|
|
14
|
+
#include "../x86/x86func_p.h"
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
#if !defined(ASMJIT_NO_AARCH64)
|
|
18
|
+
#include "../arm/a64func_p.h"
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
ASMJIT_BEGIN_NAMESPACE
|
|
22
|
+
|
|
23
|
+
// CallConv - Init & Reset
|
|
24
|
+
// =======================
|
|
25
|
+
|
|
26
|
+
ASMJIT_FAVOR_SIZE Error CallConv::init(CallConvId ccId, const Environment& environment) noexcept {
|
|
27
|
+
reset();
|
|
28
|
+
|
|
29
|
+
#if !defined(ASMJIT_NO_X86)
|
|
30
|
+
if (environment.isFamilyX86())
|
|
31
|
+
return x86::FuncInternal::initCallConv(*this, ccId, environment);
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
#if !defined(ASMJIT_NO_AARCH64)
|
|
35
|
+
if (environment.isFamilyAArch64())
|
|
36
|
+
return a64::FuncInternal::initCallConv(*this, ccId, environment);
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
|
+
return DebugUtils::errored(kErrorInvalidArgument);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// FuncDetail - Init / Reset
|
|
43
|
+
// =========================
|
|
44
|
+
|
|
45
|
+
ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const Environment& environment) noexcept {
|
|
46
|
+
CallConvId ccId = signature.callConvId();
|
|
47
|
+
uint32_t argCount = signature.argCount();
|
|
48
|
+
|
|
49
|
+
if (ASMJIT_UNLIKELY(argCount > Globals::kMaxFuncArgs))
|
|
50
|
+
return DebugUtils::errored(kErrorInvalidArgument);
|
|
51
|
+
|
|
52
|
+
CallConv& cc = _callConv;
|
|
53
|
+
ASMJIT_PROPAGATE(cc.init(ccId, environment));
|
|
54
|
+
|
|
55
|
+
uint32_t registerSize = Environment::registerSizeFromArch(cc.arch());
|
|
56
|
+
uint32_t deabstractDelta = TypeUtils::deabstractDeltaOfSize(registerSize);
|
|
57
|
+
|
|
58
|
+
const TypeId* signatureArgs = signature.args();
|
|
59
|
+
for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) {
|
|
60
|
+
FuncValuePack& argPack = _args[argIndex];
|
|
61
|
+
argPack[0].initTypeId(TypeUtils::deabstract(signatureArgs[argIndex], deabstractDelta));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_argCount = uint8_t(argCount);
|
|
65
|
+
_vaIndex = uint8_t(signature.vaIndex());
|
|
66
|
+
|
|
67
|
+
TypeId ret = signature.ret();
|
|
68
|
+
if (ret != TypeId::kVoid)
|
|
69
|
+
_rets[0].initTypeId(TypeUtils::deabstract(ret, deabstractDelta));
|
|
70
|
+
|
|
71
|
+
#if !defined(ASMJIT_NO_X86)
|
|
72
|
+
if (environment.isFamilyX86())
|
|
73
|
+
return x86::FuncInternal::initFuncDetail(*this, signature, registerSize);
|
|
74
|
+
#endif
|
|
75
|
+
|
|
76
|
+
#if !defined(ASMJIT_NO_AARCH64)
|
|
77
|
+
if (environment.isFamilyAArch64())
|
|
78
|
+
return a64::FuncInternal::initFuncDetail(*this, signature, registerSize);
|
|
79
|
+
#endif
|
|
80
|
+
|
|
81
|
+
// We should never bubble here as if `cc.init()` succeeded then there has to be an implementation for the current
|
|
82
|
+
// architecture. However, stay safe.
|
|
83
|
+
return DebugUtils::errored(kErrorInvalidArgument);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// FuncFrame - Init
|
|
87
|
+
// ================
|
|
88
|
+
|
|
89
|
+
ASMJIT_FAVOR_SIZE Error FuncFrame::init(const FuncDetail& func) noexcept {
|
|
90
|
+
Arch arch = func.callConv().arch();
|
|
91
|
+
if (!Environment::isValidArch(arch))
|
|
92
|
+
return DebugUtils::errored(kErrorInvalidArch);
|
|
93
|
+
|
|
94
|
+
const ArchTraits& archTraits = ArchTraits::byArch(arch);
|
|
95
|
+
|
|
96
|
+
// Initializing FuncFrame means making a copy of some properties of `func`. Properties like `_localStackSize` will
|
|
97
|
+
// be set by the user before the frame is finalized.
|
|
98
|
+
reset();
|
|
99
|
+
|
|
100
|
+
_arch = arch;
|
|
101
|
+
_spRegId = uint8_t(archTraits.spRegId());
|
|
102
|
+
_saRegId = uint8_t(BaseReg::kIdBad);
|
|
103
|
+
|
|
104
|
+
uint32_t naturalStackAlignment = func.callConv().naturalStackAlignment();
|
|
105
|
+
uint32_t minDynamicAlignment = Support::max<uint32_t>(naturalStackAlignment, 16);
|
|
106
|
+
|
|
107
|
+
if (minDynamicAlignment == naturalStackAlignment)
|
|
108
|
+
minDynamicAlignment <<= 1;
|
|
109
|
+
|
|
110
|
+
_naturalStackAlignment = uint8_t(naturalStackAlignment);
|
|
111
|
+
_minDynamicAlignment = uint8_t(minDynamicAlignment);
|
|
112
|
+
_redZoneSize = uint8_t(func.redZoneSize());
|
|
113
|
+
_spillZoneSize = uint8_t(func.spillZoneSize());
|
|
114
|
+
_finalStackAlignment = uint8_t(_naturalStackAlignment);
|
|
115
|
+
|
|
116
|
+
if (func.hasFlag(CallConvFlags::kCalleePopsStack)) {
|
|
117
|
+
_calleeStackCleanup = uint16_t(func.argStackSize());
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Initial masks of dirty and preserved registers.
|
|
121
|
+
for (RegGroup group : RegGroupVirtValues{}) {
|
|
122
|
+
_dirtyRegs[group] = func.usedRegs(group);
|
|
123
|
+
_preservedRegs[group] = func.preservedRegs(group);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Exclude stack pointer - this register is never included in saved GP regs.
|
|
127
|
+
_preservedRegs[RegGroup::kGp] &= ~Support::bitMask(archTraits.spRegId());
|
|
128
|
+
|
|
129
|
+
// The size and alignment of save/restore area of registers for each virtual register group
|
|
130
|
+
_saveRestoreRegSize = func.callConv()._saveRestoreRegSize;
|
|
131
|
+
_saveRestoreAlignment = func.callConv()._saveRestoreAlignment;
|
|
132
|
+
|
|
133
|
+
return kErrorOk;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// FuncFrame - Finalize
|
|
137
|
+
// ====================
|
|
138
|
+
|
|
139
|
+
ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept {
|
|
140
|
+
if (!Environment::isValidArch(arch()))
|
|
141
|
+
return DebugUtils::errored(kErrorInvalidArch);
|
|
142
|
+
|
|
143
|
+
const ArchTraits& archTraits = ArchTraits::byArch(arch());
|
|
144
|
+
|
|
145
|
+
uint32_t registerSize = _saveRestoreRegSize[RegGroup::kGp];
|
|
146
|
+
uint32_t vectorSize = _saveRestoreRegSize[RegGroup::kVec];
|
|
147
|
+
uint32_t returnAddressSize = archTraits.hasLinkReg() ? 0u : registerSize;
|
|
148
|
+
|
|
149
|
+
// The final stack alignment must be updated accordingly to call and local stack alignments.
|
|
150
|
+
uint32_t stackAlignment = _finalStackAlignment;
|
|
151
|
+
ASMJIT_ASSERT(stackAlignment == Support::max(_naturalStackAlignment,
|
|
152
|
+
_callStackAlignment,
|
|
153
|
+
_localStackAlignment));
|
|
154
|
+
|
|
155
|
+
bool hasFP = hasPreservedFP();
|
|
156
|
+
bool hasDA = hasDynamicAlignment();
|
|
157
|
+
|
|
158
|
+
uint32_t kSp = archTraits.spRegId();
|
|
159
|
+
uint32_t kFp = archTraits.fpRegId();
|
|
160
|
+
uint32_t kLr = archTraits.linkRegId();
|
|
161
|
+
|
|
162
|
+
// Make frame pointer dirty if the function uses it.
|
|
163
|
+
if (hasFP) {
|
|
164
|
+
_dirtyRegs[RegGroup::kGp] |= Support::bitMask(kFp);
|
|
165
|
+
|
|
166
|
+
// Currently required by ARM, if this works differently across architectures we would have to generalize most
|
|
167
|
+
// likely in CallConv.
|
|
168
|
+
if (kLr != BaseReg::kIdBad)
|
|
169
|
+
_dirtyRegs[RegGroup::kGp] |= Support::bitMask(kLr);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// These two are identical if the function doesn't align its stack dynamically.
|
|
173
|
+
uint32_t saRegId = _saRegId;
|
|
174
|
+
if (saRegId == BaseReg::kIdBad)
|
|
175
|
+
saRegId = kSp;
|
|
176
|
+
|
|
177
|
+
// Fix stack arguments base-register from SP to FP in case it was not picked before and the function performs
|
|
178
|
+
// dynamic stack alignment.
|
|
179
|
+
if (hasDA && saRegId == kSp)
|
|
180
|
+
saRegId = kFp;
|
|
181
|
+
|
|
182
|
+
// Mark as dirty any register but SP if used as SA pointer.
|
|
183
|
+
if (saRegId != kSp)
|
|
184
|
+
_dirtyRegs[RegGroup::kGp] |= Support::bitMask(saRegId);
|
|
185
|
+
|
|
186
|
+
_spRegId = uint8_t(kSp);
|
|
187
|
+
_saRegId = uint8_t(saRegId);
|
|
188
|
+
|
|
189
|
+
// Setup stack size used to save preserved registers.
|
|
190
|
+
uint32_t saveRestoreSizes[2] {};
|
|
191
|
+
for (RegGroup group : RegGroupVirtValues{})
|
|
192
|
+
saveRestoreSizes[size_t(!archTraits.hasInstPushPop(group))]
|
|
193
|
+
+= Support::alignUp(Support::popcnt(savedRegs(group)) * saveRestoreRegSize(group), saveRestoreAlignment(group));
|
|
194
|
+
|
|
195
|
+
_pushPopSaveSize = uint16_t(saveRestoreSizes[0]);
|
|
196
|
+
_extraRegSaveSize = uint16_t(saveRestoreSizes[1]);
|
|
197
|
+
|
|
198
|
+
uint32_t v = 0; // The beginning of the stack frame relative to SP after prolog.
|
|
199
|
+
v += callStackSize(); // Count 'callStackSize' <- This is used to call functions.
|
|
200
|
+
v = Support::alignUp(v, stackAlignment); // Align to function's stack alignment.
|
|
201
|
+
|
|
202
|
+
_localStackOffset = v; // Store 'localStackOffset' <- Function's local stack starts here.
|
|
203
|
+
v += localStackSize(); // Count 'localStackSize' <- Function's local stack ends here.
|
|
204
|
+
|
|
205
|
+
// If the function's stack must be aligned, calculate the alignment necessary to store vector registers, and set
|
|
206
|
+
// `FuncAttributes::kAlignedVecSR` to inform PEI that it can use instructions that perform aligned stores/loads.
|
|
207
|
+
if (stackAlignment >= vectorSize && _extraRegSaveSize) {
|
|
208
|
+
addAttributes(FuncAttributes::kAlignedVecSR);
|
|
209
|
+
v = Support::alignUp(v, vectorSize); // Align 'extraRegSaveOffset'.
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
_extraRegSaveOffset = v; // Store 'extraRegSaveOffset' <- Non-GP save/restore starts here.
|
|
213
|
+
v += _extraRegSaveSize; // Count 'extraRegSaveSize' <- Non-GP save/restore ends here.
|
|
214
|
+
|
|
215
|
+
// Calculate if dynamic alignment (DA) slot (stored as offset relative to SP) is required and its offset.
|
|
216
|
+
if (hasDA && !hasFP) {
|
|
217
|
+
_daOffset = v; // Store 'daOffset' <- DA pointer would be stored here.
|
|
218
|
+
v += registerSize; // Count 'daOffset'.
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
_daOffset = FuncFrame::kTagInvalidOffset;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Link Register
|
|
225
|
+
// -------------
|
|
226
|
+
//
|
|
227
|
+
// The stack is aligned after the function call as the return address is stored in a link register. Some
|
|
228
|
+
// architectures may require to always have aligned stack after PUSH/POP operation, which is represented
|
|
229
|
+
// by ArchTraits::stackAlignmentConstraint().
|
|
230
|
+
//
|
|
231
|
+
// No Link Register (X86/X64)
|
|
232
|
+
// --------------------------
|
|
233
|
+
//
|
|
234
|
+
// The return address should be stored after GP save/restore regs. It has the same size as `registerSize`
|
|
235
|
+
// (basically the native register/pointer size). We don't adjust it now as `v` now contains the exact size
|
|
236
|
+
// that the function requires to adjust (call frame + stack frame, vec stack size). The stack (if we consider
|
|
237
|
+
// this size) is misaligned now, as it's always aligned before the function call - when `call()` is executed
|
|
238
|
+
// it pushes the current EIP|RIP onto the stack, and misaligns it by 12 or 8 bytes (depending on the
|
|
239
|
+
// architecture). So count number of bytes needed to align it up to the function's CallFrame (the beginning).
|
|
240
|
+
if (v || hasFuncCalls() || !returnAddressSize)
|
|
241
|
+
v += Support::alignUpDiff(v + pushPopSaveSize() + returnAddressSize, stackAlignment);
|
|
242
|
+
|
|
243
|
+
_pushPopSaveOffset = v; // Store 'pushPopSaveOffset' <- Function's push/pop save/restore starts here.
|
|
244
|
+
_stackAdjustment = v; // Store 'stackAdjustment' <- SA used by 'add SP, SA' and 'sub SP, SA'.
|
|
245
|
+
v += _pushPopSaveSize; // Count 'pushPopSaveSize' <- Function's push/pop save/restore ends here.
|
|
246
|
+
_finalStackSize = v; // Store 'finalStackSize' <- Final stack used by the function.
|
|
247
|
+
|
|
248
|
+
if (!archTraits.hasLinkReg())
|
|
249
|
+
v += registerSize; // Count 'ReturnAddress' <- As CALL pushes onto stack.
|
|
250
|
+
|
|
251
|
+
// If the function performs dynamic stack alignment then the stack-adjustment must be aligned.
|
|
252
|
+
if (hasDA)
|
|
253
|
+
_stackAdjustment = Support::alignUp(_stackAdjustment, stackAlignment);
|
|
254
|
+
|
|
255
|
+
// Calculate where the function arguments start relative to SP.
|
|
256
|
+
_saOffsetFromSP = hasDA ? FuncFrame::kTagInvalidOffset : v;
|
|
257
|
+
|
|
258
|
+
// Calculate where the function arguments start relative to FP or user-provided register.
|
|
259
|
+
_saOffsetFromSA = hasFP ? returnAddressSize + registerSize // Return address + frame pointer.
|
|
260
|
+
: returnAddressSize + _pushPopSaveSize; // Return address + all push/pop regs.
|
|
261
|
+
|
|
262
|
+
return kErrorOk;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// FuncArgsAssignment - UpdateFuncFrame
|
|
266
|
+
// ====================================
|
|
267
|
+
|
|
268
|
+
ASMJIT_FAVOR_SIZE Error FuncArgsAssignment::updateFuncFrame(FuncFrame& frame) const noexcept {
|
|
269
|
+
Arch arch = frame.arch();
|
|
270
|
+
const FuncDetail* func = funcDetail();
|
|
271
|
+
|
|
272
|
+
if (!func)
|
|
273
|
+
return DebugUtils::errored(kErrorInvalidState);
|
|
274
|
+
|
|
275
|
+
RAConstraints constraints;
|
|
276
|
+
ASMJIT_PROPAGATE(constraints.init(arch));
|
|
277
|
+
|
|
278
|
+
FuncArgsContext ctx;
|
|
279
|
+
ASMJIT_PROPAGATE(ctx.initWorkData(frame, *this, &constraints));
|
|
280
|
+
ASMJIT_PROPAGATE(ctx.markDstRegsDirty(frame));
|
|
281
|
+
ASMJIT_PROPAGATE(ctx.markScratchRegs(frame));
|
|
282
|
+
ASMJIT_PROPAGATE(ctx.markStackArgsReg(frame));
|
|
283
|
+
return kErrorOk;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
ASMJIT_END_NAMESPACE
|