Added a support for indirect jumps within a function (Compiler) (#286)

This commit is contained in:
kobalicek
2020-05-09 00:14:52 +02:00
parent 80645e66a8
commit e78bba83da
51 changed files with 1590 additions and 661 deletions

View File

@@ -65,7 +65,7 @@ class SimpleErrorHandler : public ErrorHandler {
public:
SimpleErrorHandler() : _err(kErrorOk) {}
virtual void handleError(Error err, const char* message, BaseEmitter* origin) {
ASMJIT_UNUSED(origin);
DebugUtils::unused(origin);
_err = err;
_message.assignString(message);
}
@@ -154,7 +154,7 @@ void X86TestApp::showInfo() {
}
int X86TestApp::run() {
#ifndef ASMJIT_NO_LOGGING
#ifndef ASMJIT_NO_LOGGING
uint32_t kFormatFlags = FormatOptions::kFlagMachineCode |
FormatOptions::kFlagExplainImms |
FormatOptions::kFlagRegCasts |
@@ -167,7 +167,7 @@ int X86TestApp::run() {
StringLogger stringLogger;
stringLogger.addFlags(kFormatFlags);
#endif
#endif
for (X86Test* test : _tests) {
JitRuntime runtime;
@@ -177,7 +177,7 @@ int X86TestApp::run() {
code.init(runtime.codeInfo());
code.setErrorHandler(&errorHandler);
#ifndef ASMJIT_NO_LOGGING
#ifndef ASMJIT_NO_LOGGING
if (_verbose) {
code.setLogger(&fileLogger);
}
@@ -185,13 +185,13 @@ int X86TestApp::run() {
stringLogger.clear();
code.setLogger(&stringLogger);
}
#endif
#endif
printf("[Test] %s", test->name());
#ifndef ASMJIT_NO_LOGGING
#ifndef ASMJIT_NO_LOGGING
if (_verbose) printf("\n");
#endif
#endif
x86::Compiler cc(&code);
test->compile(cc);
@@ -202,7 +202,7 @@ int X86TestApp::run() {
if (!err)
err = cc.finalize();
#ifndef ASMJIT_NO_LOGGING
#ifndef ASMJIT_NO_LOGGING
if (_dumpAsm) {
if (!_verbose) printf("\n");
@@ -210,7 +210,7 @@ int X86TestApp::run() {
cc.dump(sb, kFormatFlags);
printf("%s", sb.data());
}
#endif
#endif
if (err == kErrorOk)
err = runtime.add(&func, &code);
@@ -230,9 +230,9 @@ int X86TestApp::run() {
else {
if (!_verbose) printf(" [FAILED]\n");
#ifndef ASMJIT_NO_LOGGING
#ifndef ASMJIT_NO_LOGGING
if (!_verbose) printf("%s", stringLogger.data());
#endif
#endif
printf("[Status]\n");
printf(" Returned: %s\n", result.data());
@@ -249,9 +249,9 @@ int X86TestApp::run() {
else {
if (!_verbose) printf(" [FAILED]\n");
#ifndef ASMJIT_NO_LOGGING
#ifndef ASMJIT_NO_LOGGING
if (!_verbose) printf("%s", stringLogger.data());
#endif
#endif
printf("[Status]\n");
printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data());
@@ -458,8 +458,7 @@ public:
}
virtual bool run(void* _func, String& result, String& expect) {
ASMJIT_UNUSED(result);
ASMJIT_UNUSED(expect);
DebugUtils::unused(result, expect);
typedef void(*Func)(void);
Func func = ptr_as_func<Func>(_func);
@@ -489,8 +488,7 @@ public:
}
virtual bool run(void* _func, String& result, String& expect) {
ASMJIT_UNUSED(result);
ASMJIT_UNUSED(expect);
DebugUtils::unused(result, expect);
typedef void (*Func)(void);
Func func = ptr_as_func<Func>(_func);
@@ -598,8 +596,7 @@ public:
}
virtual bool run(void* _func, String& result, String& expect) {
ASMJIT_UNUSED(result);
ASMJIT_UNUSED(expect);
DebugUtils::unused(result, expect);
typedef void (*Func)(void);
Func func = ptr_as_func<Func>(_func);
@@ -760,6 +757,125 @@ public:
}
};
// ============================================================================
// [X86Test_JumpTable]
// ============================================================================
class X86Test_JumpTable : public X86Test {
public:
bool _annotated;
X86Test_JumpTable(bool annotated)
: X86Test("X86Test_JumpTable"),
_annotated(annotated) {
_name.assignFormat("JumpTable {%s}", annotated ? "Annotated" : "Unknown Reg/Mem");
}
enum Operator {
kOperatorAdd = 0,
kOperatorSub = 1,
kOperatorMul = 2,
kOperatorDiv = 3
};
static void add(X86TestApp& app) {
app.add(new X86Test_JumpTable(false));
app.add(new X86Test_JumpTable(true));
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignatureT<float, float, float, uint32_t>(CallConv::kIdHost));
x86::Xmm a = cc.newXmmSs("a");
x86::Xmm b = cc.newXmmSs("b");
x86::Gp op = cc.newUInt32("op");
x86::Gp target = cc.newIntPtr("target");
x86::Gp offset = cc.newIntPtr("offset");
Label L_End = cc.newLabel();
Label L_Table = cc.newLabel();
Label L_Add = cc.newLabel();
Label L_Sub = cc.newLabel();
Label L_Mul = cc.newLabel();
Label L_Div = cc.newLabel();
cc.setArg(0, a);
cc.setArg(1, b);
cc.setArg(2, op);
cc.lea(offset, x86::ptr(L_Table));
if (cc.is64Bit())
cc.movsxd(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
else
cc.mov(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
cc.add(target, offset);
// JumpAnnotation allows to annotate all possible jump targets of
// instructions where it cannot be deduced from operands.
if (_annotated) {
JumpAnnotation* annotation = cc.newJumpAnnotation();
annotation->addLabel(L_Add);
annotation->addLabel(L_Sub);
annotation->addLabel(L_Mul);
annotation->addLabel(L_Div);
cc.jmp(target, annotation);
}
else {
cc.jmp(target);
}
cc.bind(L_Add);
cc.addss(a, b);
cc.jmp(L_End);
cc.bind(L_Sub);
cc.subss(a, b);
cc.jmp(L_End);
cc.bind(L_Mul);
cc.mulss(a, b);
cc.jmp(L_End);
cc.bind(L_Div);
cc.divss(a, b);
cc.bind(L_End);
cc.ret(a);
cc.endFunc();
cc.bind(L_Table);
cc.embedLabelDelta(L_Add, L_Table, 4);
cc.embedLabelDelta(L_Sub, L_Table, 4);
cc.embedLabelDelta(L_Mul, L_Table, 4);
cc.embedLabelDelta(L_Div, L_Table, 4);
}
virtual bool run(void* _func, String& result, String& expect) {
typedef float (*Func)(float, float, uint32_t);
Func func = ptr_as_func<Func>(_func);
float results[4];
float expected[4];
results[0] = func(33.0f, 14.0f, kOperatorAdd);
results[1] = func(33.0f, 14.0f, kOperatorSub);
results[2] = func(10.0f, 6.0f, kOperatorMul);
results[3] = func(80.0f, 8.0f, kOperatorDiv);
expected[0] = 47.0f;
expected[1] = 19.0f;
expected[2] = 60.0f;
expected[3] = 10.0f;
result.assignFormat("ret={%f, %f, %f, %f}", results[0], results[1], results[2], results[3]);
expect.assignFormat("ret={%f, %f, %f, %f}", expected[0], expected[1], expected[2], expected[3]);
return result == expect;
}
};
// ============================================================================
// [X86Test_AllocBase]
// ============================================================================
@@ -3984,6 +4100,7 @@ int main(int argc, char* argv[]) {
app.addT<X86Test_JumpMany>();
app.addT<X86Test_JumpUnreachable1>();
app.addT<X86Test_JumpUnreachable2>();
app.addT<X86Test_JumpTable>();
// Alloc tests.
app.addT<X86Test_AllocBase>();