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,323 @@
|
|
|
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/emithelper_p.h"
|
|
9
|
+
#include "../core/formatter.h"
|
|
10
|
+
#include "../core/funcargscontext_p.h"
|
|
11
|
+
#include "../core/radefs_p.h"
|
|
12
|
+
|
|
13
|
+
// Can be used for debugging...
|
|
14
|
+
// #define ASMJIT_DUMP_ARGS_ASSIGNMENT
|
|
15
|
+
|
|
16
|
+
ASMJIT_BEGIN_NAMESPACE
|
|
17
|
+
|
|
18
|
+
// BaseEmitHelper - Formatting
|
|
19
|
+
// ===========================
|
|
20
|
+
|
|
21
|
+
#ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT
|
|
22
|
+
static void dumpFuncValue(String& sb, Arch arch, const FuncValue& value) noexcept {
|
|
23
|
+
Formatter::formatTypeId(sb, value.typeId());
|
|
24
|
+
sb.append('@');
|
|
25
|
+
|
|
26
|
+
if (value.isIndirect())
|
|
27
|
+
sb.append('[');
|
|
28
|
+
|
|
29
|
+
if (value.isReg())
|
|
30
|
+
Formatter::formatRegister(sb, 0, nullptr, arch, value.regType(), value.regId());
|
|
31
|
+
else if (value.isStack())
|
|
32
|
+
sb.appendFormat("[%d]", value.stackOffset());
|
|
33
|
+
else
|
|
34
|
+
sb.append("<none>");
|
|
35
|
+
|
|
36
|
+
if (value.isIndirect())
|
|
37
|
+
sb.append(']');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static void dumpAssignment(String& sb, const FuncArgsContext& ctx) noexcept {
|
|
41
|
+
typedef FuncArgsContext::Var Var;
|
|
42
|
+
|
|
43
|
+
Arch arch = ctx.arch();
|
|
44
|
+
uint32_t varCount = ctx.varCount();
|
|
45
|
+
|
|
46
|
+
for (uint32_t i = 0; i < varCount; i++) {
|
|
47
|
+
const Var& var = ctx.var(i);
|
|
48
|
+
const FuncValue& dst = var.out;
|
|
49
|
+
const FuncValue& cur = var.cur;
|
|
50
|
+
|
|
51
|
+
sb.appendFormat("Var%u: ", i);
|
|
52
|
+
dumpFuncValue(sb, arch, dst);
|
|
53
|
+
sb.append(" <- ");
|
|
54
|
+
dumpFuncValue(sb, arch, cur);
|
|
55
|
+
|
|
56
|
+
if (var.isDone())
|
|
57
|
+
sb.append(" {Done}");
|
|
58
|
+
|
|
59
|
+
sb.append('\n');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
// BaseEmitHelper - EmitArgsAssignment
|
|
65
|
+
// ===================================
|
|
66
|
+
|
|
67
|
+
ASMJIT_FAVOR_SIZE Error BaseEmitHelper::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
|
|
68
|
+
typedef FuncArgsContext::Var Var;
|
|
69
|
+
typedef FuncArgsContext::WorkData WorkData;
|
|
70
|
+
|
|
71
|
+
enum WorkFlags : uint32_t {
|
|
72
|
+
kWorkNone = 0x00,
|
|
73
|
+
kWorkDidSome = 0x01,
|
|
74
|
+
kWorkPending = 0x02,
|
|
75
|
+
kWorkPostponed = 0x04
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
Arch arch = frame.arch();
|
|
79
|
+
const ArchTraits& archTraits = ArchTraits::byArch(arch);
|
|
80
|
+
|
|
81
|
+
RAConstraints constraints;
|
|
82
|
+
FuncArgsContext ctx;
|
|
83
|
+
|
|
84
|
+
ASMJIT_PROPAGATE(constraints.init(arch));
|
|
85
|
+
ASMJIT_PROPAGATE(ctx.initWorkData(frame, args, &constraints));
|
|
86
|
+
|
|
87
|
+
#ifdef ASMJIT_DUMP_ARGS_ASSIGNMENT
|
|
88
|
+
{
|
|
89
|
+
String sb;
|
|
90
|
+
dumpAssignment(sb, ctx);
|
|
91
|
+
printf("%s\n", sb.data());
|
|
92
|
+
}
|
|
93
|
+
#endif
|
|
94
|
+
|
|
95
|
+
auto& workData = ctx._workData;
|
|
96
|
+
uint32_t varCount = ctx._varCount;
|
|
97
|
+
uint32_t saVarId = ctx._saVarId;
|
|
98
|
+
|
|
99
|
+
BaseReg sp = BaseReg(_emitter->_gpSignature, archTraits.spRegId());
|
|
100
|
+
BaseReg sa = sp;
|
|
101
|
+
|
|
102
|
+
if (frame.hasDynamicAlignment()) {
|
|
103
|
+
if (frame.hasPreservedFP())
|
|
104
|
+
sa.setId(archTraits.fpRegId());
|
|
105
|
+
else
|
|
106
|
+
sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Register to stack and stack to stack moves must be first as now we have
|
|
110
|
+
// the biggest chance of having as many as possible unassigned registers.
|
|
111
|
+
|
|
112
|
+
if (ctx._stackDstMask) {
|
|
113
|
+
// Base address of all arguments passed by stack.
|
|
114
|
+
BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id())));
|
|
115
|
+
BaseMem baseStackPtr(sp, 0);
|
|
116
|
+
|
|
117
|
+
for (uint32_t varId = 0; varId < varCount; varId++) {
|
|
118
|
+
Var& var = ctx._vars[varId];
|
|
119
|
+
|
|
120
|
+
if (!var.out.isStack())
|
|
121
|
+
continue;
|
|
122
|
+
|
|
123
|
+
FuncValue& cur = var.cur;
|
|
124
|
+
FuncValue& out = var.out;
|
|
125
|
+
|
|
126
|
+
ASMJIT_ASSERT(cur.isReg() || cur.isStack());
|
|
127
|
+
BaseReg reg;
|
|
128
|
+
|
|
129
|
+
BaseMem dstStackPtr = baseStackPtr.cloneAdjusted(out.stackOffset());
|
|
130
|
+
BaseMem srcStackPtr = baseArgPtr.cloneAdjusted(cur.stackOffset());
|
|
131
|
+
|
|
132
|
+
if (cur.isIndirect()) {
|
|
133
|
+
if (cur.isStack()) {
|
|
134
|
+
// TODO: Indirect stack.
|
|
135
|
+
return DebugUtils::errored(kErrorInvalidAssignment);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
srcStackPtr.setBaseId(cur.regId());
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (cur.isReg() && !cur.isIndirect()) {
|
|
143
|
+
WorkData& wd = workData[archTraits.regTypeToGroup(cur.regType())];
|
|
144
|
+
uint32_t regId = cur.regId();
|
|
145
|
+
|
|
146
|
+
reg.setSignatureAndId(archTraits.regTypeToSignature(cur.regType()), regId);
|
|
147
|
+
wd.unassign(varId, regId);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Stack to reg move - tricky since we move stack to stack we can decide which register to use. In general
|
|
151
|
+
// we follow the rule that IntToInt moves will use GP regs with possibility to signature or zero extend,
|
|
152
|
+
// and all other moves will either use GP or VEC regs depending on the size of the move.
|
|
153
|
+
OperandSignature signature = getSuitableRegForMemToMemMove(arch, out.typeId(), cur.typeId());
|
|
154
|
+
if (ASMJIT_UNLIKELY(!signature.isValid()))
|
|
155
|
+
return DebugUtils::errored(kErrorInvalidState);
|
|
156
|
+
|
|
157
|
+
WorkData& wd = workData[signature.regGroup()];
|
|
158
|
+
RegMask availableRegs = wd.availableRegs();
|
|
159
|
+
if (ASMJIT_UNLIKELY(!availableRegs))
|
|
160
|
+
return DebugUtils::errored(kErrorInvalidState);
|
|
161
|
+
|
|
162
|
+
uint32_t availableId = Support::ctz(availableRegs);
|
|
163
|
+
reg.setSignatureAndId(signature, availableId);
|
|
164
|
+
|
|
165
|
+
ASMJIT_PROPAGATE(emitArgMove(reg, out.typeId(), srcStackPtr, cur.typeId()));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (cur.isIndirect() && cur.isReg())
|
|
169
|
+
workData[RegGroup::kGp].unassign(varId, cur.regId());
|
|
170
|
+
|
|
171
|
+
// Register to stack move.
|
|
172
|
+
ASMJIT_PROPAGATE(emitRegMove(dstStackPtr, reg, cur.typeId()));
|
|
173
|
+
var.markDone();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Shuffle all registers that are currently assigned accordingly to target assignment.
|
|
178
|
+
|
|
179
|
+
uint32_t workFlags = kWorkNone;
|
|
180
|
+
for (;;) {
|
|
181
|
+
for (uint32_t varId = 0; varId < varCount; varId++) {
|
|
182
|
+
Var& var = ctx._vars[varId];
|
|
183
|
+
if (var.isDone() || !var.cur.isReg())
|
|
184
|
+
continue;
|
|
185
|
+
|
|
186
|
+
FuncValue& cur = var.cur;
|
|
187
|
+
FuncValue& out = var.out;
|
|
188
|
+
|
|
189
|
+
RegGroup curGroup = archTraits.regTypeToGroup(cur.regType());
|
|
190
|
+
RegGroup outGroup = archTraits.regTypeToGroup(out.regType());
|
|
191
|
+
|
|
192
|
+
uint32_t curId = cur.regId();
|
|
193
|
+
uint32_t outId = out.regId();
|
|
194
|
+
|
|
195
|
+
if (curGroup != outGroup) {
|
|
196
|
+
// TODO: Conversion is not supported.
|
|
197
|
+
return DebugUtils::errored(kErrorInvalidAssignment);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
WorkData& wd = workData[outGroup];
|
|
201
|
+
if (!wd.isAssigned(outId)) {
|
|
202
|
+
EmitMove:
|
|
203
|
+
ASMJIT_PROPAGATE(
|
|
204
|
+
emitArgMove(
|
|
205
|
+
BaseReg(archTraits.regTypeToSignature(out.regType()), outId), out.typeId(),
|
|
206
|
+
BaseReg(archTraits.regTypeToSignature(cur.regType()), curId), cur.typeId()));
|
|
207
|
+
|
|
208
|
+
wd.reassign(varId, outId, curId);
|
|
209
|
+
cur.initReg(out.regType(), outId, out.typeId());
|
|
210
|
+
|
|
211
|
+
if (outId == out.regId())
|
|
212
|
+
var.markDone();
|
|
213
|
+
workFlags |= kWorkDidSome | kWorkPending;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
uint32_t altId = wd._physToVarId[outId];
|
|
217
|
+
Var& altVar = ctx._vars[altId];
|
|
218
|
+
|
|
219
|
+
if (!altVar.out.isInitialized() || (altVar.out.isReg() && altVar.out.regId() == curId)) {
|
|
220
|
+
// Only few architectures provide swap operations, and only for few register groups.
|
|
221
|
+
if (archTraits.hasInstRegSwap(curGroup)) {
|
|
222
|
+
RegType highestType = Support::max(cur.regType(), altVar.cur.regType());
|
|
223
|
+
if (Support::isBetween(highestType, RegType::kGp8Lo, RegType::kGp16))
|
|
224
|
+
highestType = RegType::kGp32;
|
|
225
|
+
|
|
226
|
+
OperandSignature signature = archTraits.regTypeToSignature(highestType);
|
|
227
|
+
ASMJIT_PROPAGATE(
|
|
228
|
+
emitRegSwap(BaseReg(signature, outId), BaseReg(signature, curId)));
|
|
229
|
+
|
|
230
|
+
wd.swap(varId, curId, altId, outId);
|
|
231
|
+
cur.setRegId(outId);
|
|
232
|
+
var.markDone();
|
|
233
|
+
altVar.cur.setRegId(curId);
|
|
234
|
+
|
|
235
|
+
if (altVar.out.isInitialized())
|
|
236
|
+
altVar.markDone();
|
|
237
|
+
workFlags |= kWorkDidSome;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
// If there is a scratch register it can be used to perform the swap.
|
|
241
|
+
RegMask availableRegs = wd.availableRegs();
|
|
242
|
+
if (availableRegs) {
|
|
243
|
+
RegMask inOutRegs = wd.dstRegs();
|
|
244
|
+
if (availableRegs & ~inOutRegs)
|
|
245
|
+
availableRegs &= ~inOutRegs;
|
|
246
|
+
outId = Support::ctz(availableRegs);
|
|
247
|
+
goto EmitMove;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
workFlags |= kWorkPending;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
workFlags |= kWorkPending;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (!(workFlags & kWorkPending))
|
|
262
|
+
break;
|
|
263
|
+
|
|
264
|
+
// If we did nothing twice it means that something is really broken.
|
|
265
|
+
if ((workFlags & (kWorkDidSome | kWorkPostponed)) == kWorkPostponed)
|
|
266
|
+
return DebugUtils::errored(kErrorInvalidState);
|
|
267
|
+
|
|
268
|
+
workFlags = (workFlags & kWorkDidSome) ? kWorkNone : kWorkPostponed;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Load arguments passed by stack into registers. This is pretty simple and
|
|
272
|
+
// it never requires multiple iterations like the previous phase.
|
|
273
|
+
|
|
274
|
+
if (ctx._hasStackSrc) {
|
|
275
|
+
uint32_t iterCount = 1;
|
|
276
|
+
if (frame.hasDynamicAlignment() && !frame.hasPreservedFP())
|
|
277
|
+
sa.setId(saVarId < varCount ? ctx._vars[saVarId].cur.regId() : frame.saRegId());
|
|
278
|
+
|
|
279
|
+
// Base address of all arguments passed by stack.
|
|
280
|
+
BaseMem baseArgPtr(sa, int32_t(frame.saOffset(sa.id())));
|
|
281
|
+
|
|
282
|
+
for (uint32_t iter = 0; iter < iterCount; iter++) {
|
|
283
|
+
for (uint32_t varId = 0; varId < varCount; varId++) {
|
|
284
|
+
Var& var = ctx._vars[varId];
|
|
285
|
+
if (var.isDone())
|
|
286
|
+
continue;
|
|
287
|
+
|
|
288
|
+
if (var.cur.isStack()) {
|
|
289
|
+
ASMJIT_ASSERT(var.out.isReg());
|
|
290
|
+
|
|
291
|
+
uint32_t outId = var.out.regId();
|
|
292
|
+
RegType outType = var.out.regType();
|
|
293
|
+
|
|
294
|
+
RegGroup group = archTraits.regTypeToGroup(outType);
|
|
295
|
+
WorkData& wd = workData[group];
|
|
296
|
+
|
|
297
|
+
if (outId == sa.id() && group == RegGroup::kGp) {
|
|
298
|
+
// This register will be processed last as we still need `saRegId`.
|
|
299
|
+
if (iterCount == 1) {
|
|
300
|
+
iterCount++;
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
wd.unassign(wd._physToVarId[outId], outId);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
BaseReg dstReg = BaseReg(archTraits.regTypeToSignature(outType), outId);
|
|
307
|
+
BaseMem srcMem = baseArgPtr.cloneAdjusted(var.cur.stackOffset());
|
|
308
|
+
|
|
309
|
+
ASMJIT_PROPAGATE(emitArgMove(
|
|
310
|
+
dstReg, var.out.typeId(),
|
|
311
|
+
srcMem, var.cur.typeId()));
|
|
312
|
+
|
|
313
|
+
wd.assign(varId, outId);
|
|
314
|
+
var.cur.initReg(outType, outId, var.cur.typeId(), FuncValue::kFlagIsDone);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return kErrorOk;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
ASMJIT_END_NAMESPACE
|
|
@@ -0,0 +1,58 @@
|
|
|
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_EMITHELPER_P_H_INCLUDED
|
|
7
|
+
#define ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
|
|
8
|
+
|
|
9
|
+
#include "../core/emitter.h"
|
|
10
|
+
#include "../core/operand.h"
|
|
11
|
+
#include "../core/type.h"
|
|
12
|
+
|
|
13
|
+
ASMJIT_BEGIN_NAMESPACE
|
|
14
|
+
|
|
15
|
+
//! \cond INTERNAL
|
|
16
|
+
//! \addtogroup asmjit_core
|
|
17
|
+
//! \{
|
|
18
|
+
|
|
19
|
+
//! Helper class that provides utilities for each supported architecture.
|
|
20
|
+
class BaseEmitHelper {
|
|
21
|
+
public:
|
|
22
|
+
BaseEmitter* _emitter;
|
|
23
|
+
|
|
24
|
+
inline explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept
|
|
25
|
+
: _emitter(emitter) {}
|
|
26
|
+
|
|
27
|
+
inline BaseEmitter* emitter() const noexcept { return _emitter; }
|
|
28
|
+
inline void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; }
|
|
29
|
+
|
|
30
|
+
//! Emits a pure move operation between two registers or the same type or between a register and its home
|
|
31
|
+
//! slot. This function does not handle register conversion.
|
|
32
|
+
virtual Error emitRegMove(
|
|
33
|
+
const Operand_& dst_,
|
|
34
|
+
const Operand_& src_, TypeId typeId, const char* comment = nullptr) = 0;
|
|
35
|
+
|
|
36
|
+
//! Emits swap between two registers.
|
|
37
|
+
virtual Error emitRegSwap(
|
|
38
|
+
const BaseReg& a,
|
|
39
|
+
const BaseReg& b, const char* comment = nullptr) = 0;
|
|
40
|
+
|
|
41
|
+
//! Emits move from a function argument (either register or stack) to a register.
|
|
42
|
+
//!
|
|
43
|
+
//! This function can handle the necessary conversion from one argument to another, and from one register type
|
|
44
|
+
//! to another, if it's possible. Any attempt of conversion that requires third register of a different group
|
|
45
|
+
//! (for example conversion from K to MMX on X86/X64) will fail.
|
|
46
|
+
virtual Error emitArgMove(
|
|
47
|
+
const BaseReg& dst_, TypeId dstTypeId,
|
|
48
|
+
const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) = 0;
|
|
49
|
+
|
|
50
|
+
Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
//! \}
|
|
54
|
+
//! \endcond
|
|
55
|
+
|
|
56
|
+
ASMJIT_END_NAMESPACE
|
|
57
|
+
|
|
58
|
+
#endif // ASMJIT_CORE_EMITHELPER_P_H_INCLUDED
|
|
@@ -0,0 +1,333 @@
|
|
|
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/emitterutils_p.h"
|
|
8
|
+
#include "../core/errorhandler.h"
|
|
9
|
+
#include "../core/logger.h"
|
|
10
|
+
#include "../core/support.h"
|
|
11
|
+
|
|
12
|
+
ASMJIT_BEGIN_NAMESPACE
|
|
13
|
+
|
|
14
|
+
// BaseEmitter - Construction & Destruction
|
|
15
|
+
// ========================================
|
|
16
|
+
|
|
17
|
+
BaseEmitter::BaseEmitter(EmitterType emitterType) noexcept
|
|
18
|
+
: _emitterType(emitterType) {}
|
|
19
|
+
|
|
20
|
+
BaseEmitter::~BaseEmitter() noexcept {
|
|
21
|
+
if (_code) {
|
|
22
|
+
_addEmitterFlags(EmitterFlags::kDestroyed);
|
|
23
|
+
_code->detach(this);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// BaseEmitter - Finalize
|
|
28
|
+
// ======================
|
|
29
|
+
|
|
30
|
+
Error BaseEmitter::finalize() {
|
|
31
|
+
// Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`.
|
|
32
|
+
return kErrorOk;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// BaseEmitter - Internals
|
|
36
|
+
// =======================
|
|
37
|
+
|
|
38
|
+
static constexpr EmitterFlags kEmitterPreservedFlags = EmitterFlags::kOwnLogger | EmitterFlags::kOwnErrorHandler;
|
|
39
|
+
|
|
40
|
+
static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept {
|
|
41
|
+
bool emitComments = false;
|
|
42
|
+
bool hasDiagnosticOptions = false;
|
|
43
|
+
|
|
44
|
+
if (self->emitterType() == EmitterType::kAssembler) {
|
|
45
|
+
// Assembler: Don't emit comments if logger is not attached.
|
|
46
|
+
emitComments = self->_code != nullptr && self->_logger != nullptr;
|
|
47
|
+
hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateAssembler);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Builder/Compiler: Always emit comments, we cannot assume they won't be used.
|
|
51
|
+
emitComments = self->_code != nullptr;
|
|
52
|
+
hasDiagnosticOptions = self->hasDiagnosticOption(DiagnosticOptions::kValidateIntermediate);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (emitComments)
|
|
56
|
+
self->_addEmitterFlags(EmitterFlags::kLogComments);
|
|
57
|
+
else
|
|
58
|
+
self->_clearEmitterFlags(EmitterFlags::kLogComments);
|
|
59
|
+
|
|
60
|
+
// The reserved option tells emitter (Assembler/Builder/Compiler) that there may be either a border
|
|
61
|
+
// case (CodeHolder not attached, for example) or that logging or validation is required.
|
|
62
|
+
if (self->_code == nullptr || self->_logger || hasDiagnosticOptions)
|
|
63
|
+
self->_forcedInstOptions |= InstOptions::kReserved;
|
|
64
|
+
else
|
|
65
|
+
self->_forcedInstOptions &= ~InstOptions::kReserved;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// BaseEmitter - Diagnostic Options
|
|
69
|
+
// ================================
|
|
70
|
+
|
|
71
|
+
void BaseEmitter::addDiagnosticOptions(DiagnosticOptions options) noexcept {
|
|
72
|
+
_diagnosticOptions |= options;
|
|
73
|
+
BaseEmitter_updateForcedOptions(this);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void BaseEmitter::clearDiagnosticOptions(DiagnosticOptions options) noexcept {
|
|
77
|
+
_diagnosticOptions &= ~options;
|
|
78
|
+
BaseEmitter_updateForcedOptions(this);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// BaseEmitter - Logging
|
|
82
|
+
// =====================
|
|
83
|
+
|
|
84
|
+
void BaseEmitter::setLogger(Logger* logger) noexcept {
|
|
85
|
+
#ifndef ASMJIT_NO_LOGGING
|
|
86
|
+
if (logger) {
|
|
87
|
+
_logger = logger;
|
|
88
|
+
_addEmitterFlags(EmitterFlags::kOwnLogger);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
_logger = nullptr;
|
|
92
|
+
_clearEmitterFlags(EmitterFlags::kOwnLogger);
|
|
93
|
+
if (_code)
|
|
94
|
+
_logger = _code->logger();
|
|
95
|
+
}
|
|
96
|
+
BaseEmitter_updateForcedOptions(this);
|
|
97
|
+
#else
|
|
98
|
+
DebugUtils::unused(logger);
|
|
99
|
+
#endif
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// BaseEmitter - Error Handling
|
|
103
|
+
// ============================
|
|
104
|
+
|
|
105
|
+
void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept {
|
|
106
|
+
if (errorHandler) {
|
|
107
|
+
_errorHandler = errorHandler;
|
|
108
|
+
_addEmitterFlags(EmitterFlags::kOwnErrorHandler);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
_errorHandler = nullptr;
|
|
112
|
+
_clearEmitterFlags(EmitterFlags::kOwnErrorHandler);
|
|
113
|
+
if (_code)
|
|
114
|
+
_errorHandler = _code->errorHandler();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Error BaseEmitter::reportError(Error err, const char* message) {
|
|
119
|
+
ErrorHandler* eh = _errorHandler;
|
|
120
|
+
if (eh) {
|
|
121
|
+
if (!message)
|
|
122
|
+
message = DebugUtils::errorAsString(err);
|
|
123
|
+
eh->handleError(err, message, this);
|
|
124
|
+
}
|
|
125
|
+
return err;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// BaseEmitter - Labels
|
|
129
|
+
// ====================
|
|
130
|
+
|
|
131
|
+
Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept {
|
|
132
|
+
return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : Globals::kInvalidId);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept {
|
|
136
|
+
return _code && labelId < _code->labelCount();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// BaseEmitter - Emit (Low-Level)
|
|
140
|
+
// ==============================
|
|
141
|
+
|
|
142
|
+
using EmitterUtils::noExt;
|
|
143
|
+
|
|
144
|
+
Error BaseEmitter::_emitI(InstId instId) {
|
|
145
|
+
return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
Error BaseEmitter::_emitI(InstId instId, const Operand_& o0) {
|
|
149
|
+
return _emit(instId, o0, noExt[1], noExt[2], noExt);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1) {
|
|
153
|
+
return _emit(instId, o0, o1, noExt[2], noExt);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) {
|
|
157
|
+
return _emit(instId, o0, o1, o2, noExt);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
|
|
161
|
+
Operand_ opExt[3] = { o3 };
|
|
162
|
+
return _emit(instId, o0, o1, o2, opExt);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) {
|
|
166
|
+
Operand_ opExt[3] = { o3, o4 };
|
|
167
|
+
return _emit(instId, o0, o1, o2, opExt);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) {
|
|
171
|
+
Operand_ opExt[3] = { o3, o4, o5 };
|
|
172
|
+
return _emit(instId, o0, o1, o2, opExt);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
|
|
176
|
+
const Operand_* op = operands;
|
|
177
|
+
Operand_ opExt[3];
|
|
178
|
+
|
|
179
|
+
switch (opCount) {
|
|
180
|
+
case 0:
|
|
181
|
+
return _emit(instId, noExt[0], noExt[1], noExt[2], noExt);
|
|
182
|
+
|
|
183
|
+
case 1:
|
|
184
|
+
return _emit(instId, op[0], noExt[1], noExt[2], noExt);
|
|
185
|
+
|
|
186
|
+
case 2:
|
|
187
|
+
return _emit(instId, op[0], op[1], noExt[2], noExt);
|
|
188
|
+
|
|
189
|
+
case 3:
|
|
190
|
+
return _emit(instId, op[0], op[1], op[2], noExt);
|
|
191
|
+
|
|
192
|
+
case 4:
|
|
193
|
+
opExt[0] = op[3];
|
|
194
|
+
opExt[1].reset();
|
|
195
|
+
opExt[2].reset();
|
|
196
|
+
return _emit(instId, op[0], op[1], op[2], opExt);
|
|
197
|
+
|
|
198
|
+
case 5:
|
|
199
|
+
opExt[0] = op[3];
|
|
200
|
+
opExt[1] = op[4];
|
|
201
|
+
opExt[2].reset();
|
|
202
|
+
return _emit(instId, op[0], op[1], op[2], opExt);
|
|
203
|
+
|
|
204
|
+
case 6:
|
|
205
|
+
return _emit(instId, op[0], op[1], op[2], op + 3);
|
|
206
|
+
|
|
207
|
+
default:
|
|
208
|
+
return DebugUtils::errored(kErrorInvalidArgument);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// BaseEmitter - Emit Utilities
|
|
213
|
+
// ============================
|
|
214
|
+
|
|
215
|
+
Error BaseEmitter::emitProlog(const FuncFrame& frame) {
|
|
216
|
+
if (ASMJIT_UNLIKELY(!_code))
|
|
217
|
+
return DebugUtils::errored(kErrorNotInitialized);
|
|
218
|
+
|
|
219
|
+
return _funcs.emitProlog(this, frame);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
Error BaseEmitter::emitEpilog(const FuncFrame& frame) {
|
|
223
|
+
if (ASMJIT_UNLIKELY(!_code))
|
|
224
|
+
return DebugUtils::errored(kErrorNotInitialized);
|
|
225
|
+
|
|
226
|
+
return _funcs.emitEpilog(this, frame);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) {
|
|
230
|
+
if (ASMJIT_UNLIKELY(!_code))
|
|
231
|
+
return DebugUtils::errored(kErrorNotInitialized);
|
|
232
|
+
|
|
233
|
+
return _funcs.emitArgsAssignment(this, frame, args);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// BaseEmitter - Comment
|
|
237
|
+
// =====================
|
|
238
|
+
|
|
239
|
+
Error BaseEmitter::commentf(const char* fmt, ...) {
|
|
240
|
+
if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
|
|
241
|
+
if (!hasEmitterFlag(EmitterFlags::kAttached))
|
|
242
|
+
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
|
243
|
+
return kErrorOk;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#ifndef ASMJIT_NO_LOGGING
|
|
247
|
+
StringTmp<1024> sb;
|
|
248
|
+
|
|
249
|
+
va_list ap;
|
|
250
|
+
va_start(ap, fmt);
|
|
251
|
+
Error err = sb.appendVFormat(fmt, ap);
|
|
252
|
+
va_end(ap);
|
|
253
|
+
|
|
254
|
+
ASMJIT_PROPAGATE(err);
|
|
255
|
+
return comment(sb.data(), sb.size());
|
|
256
|
+
#else
|
|
257
|
+
DebugUtils::unused(fmt);
|
|
258
|
+
return kErrorOk;
|
|
259
|
+
#endif
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
Error BaseEmitter::commentv(const char* fmt, va_list ap) {
|
|
263
|
+
if (!hasEmitterFlag(EmitterFlags::kLogComments)) {
|
|
264
|
+
if (!hasEmitterFlag(EmitterFlags::kAttached))
|
|
265
|
+
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
|
266
|
+
return kErrorOk;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
#ifndef ASMJIT_NO_LOGGING
|
|
270
|
+
StringTmp<1024> sb;
|
|
271
|
+
Error err = sb.appendVFormat(fmt, ap);
|
|
272
|
+
|
|
273
|
+
ASMJIT_PROPAGATE(err);
|
|
274
|
+
return comment(sb.data(), sb.size());
|
|
275
|
+
#else
|
|
276
|
+
DebugUtils::unused(fmt, ap);
|
|
277
|
+
return kErrorOk;
|
|
278
|
+
#endif
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// BaseEmitter - Events
|
|
282
|
+
// ====================
|
|
283
|
+
|
|
284
|
+
Error BaseEmitter::onAttach(CodeHolder* code) noexcept {
|
|
285
|
+
_code = code;
|
|
286
|
+
_environment = code->environment();
|
|
287
|
+
_addEmitterFlags(EmitterFlags::kAttached);
|
|
288
|
+
|
|
289
|
+
const ArchTraits& archTraits = ArchTraits::byArch(code->arch());
|
|
290
|
+
RegType nativeRegType = Environment::is32Bit(code->arch()) ? RegType::kGp32 : RegType::kGp64;
|
|
291
|
+
_gpSignature = archTraits.regTypeToSignature(nativeRegType);
|
|
292
|
+
|
|
293
|
+
onSettingsUpdated();
|
|
294
|
+
return kErrorOk;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
Error BaseEmitter::onDetach(CodeHolder* code) noexcept {
|
|
298
|
+
DebugUtils::unused(code);
|
|
299
|
+
|
|
300
|
+
if (!hasOwnLogger())
|
|
301
|
+
_logger = nullptr;
|
|
302
|
+
|
|
303
|
+
if (!hasOwnErrorHandler())
|
|
304
|
+
_errorHandler = nullptr;
|
|
305
|
+
|
|
306
|
+
_clearEmitterFlags(~kEmitterPreservedFlags);
|
|
307
|
+
_forcedInstOptions = InstOptions::kReserved;
|
|
308
|
+
_privateData = 0;
|
|
309
|
+
|
|
310
|
+
_environment.reset();
|
|
311
|
+
_gpSignature.reset();
|
|
312
|
+
|
|
313
|
+
_instOptions = InstOptions::kNone;
|
|
314
|
+
_extraReg.reset();
|
|
315
|
+
_inlineComment = nullptr;
|
|
316
|
+
|
|
317
|
+
return kErrorOk;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
void BaseEmitter::onSettingsUpdated() noexcept {
|
|
321
|
+
// Only called when attached to CodeHolder by CodeHolder.
|
|
322
|
+
ASMJIT_ASSERT(_code != nullptr);
|
|
323
|
+
|
|
324
|
+
if (!hasOwnLogger())
|
|
325
|
+
_logger = _code->logger();
|
|
326
|
+
|
|
327
|
+
if (!hasOwnErrorHandler())
|
|
328
|
+
_errorHandler = _code->errorHandler();
|
|
329
|
+
|
|
330
|
+
BaseEmitter_updateForcedOptions(this);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
ASMJIT_END_NAMESPACE
|