diff options
author | kobalicek <kobalicek.petr@gmail.com> | 2022-09-18 11:02:39 +0300 |
---|---|---|
committer | Petr Kobalicek <kobalicek.petr@gmail.com> | 2022-09-18 11:26:53 +0300 |
commit | 052b4430e93f021709d27d2b5d42694ce0c49ce6 (patch) | |
tree | ef85d7bbb9a5888f8c152f71e56846bf3a11a70e | |
parent | 5c469e3f7c307da939d38d72e09f08db7ca076ef (diff) |
Fixed indirect jumps to a single label (Compiler) (fixes #380)
-rw-r--r-- | src/asmjit/core/rapass.cpp | 11 | ||||
-rw-r--r-- | test/asmjit_test_compiler_x86.cpp | 124 |
2 files changed, 131 insertions, 4 deletions
diff --git a/src/asmjit/core/rapass.cpp b/src/asmjit/core/rapass.cpp index 0e87ab6..a1a4490 100644 --- a/src/asmjit/core/rapass.cpp +++ b/src/asmjit/core/rapass.cpp @@ -328,9 +328,14 @@ Error BaseRAPass::initSharedAssignments(const ZoneVector<uint32_t>& sharedAssign RABlock* firstSuccessor = successors[0]; // NOTE: Shared assignments connect all possible successors so we only need the first to propagate exit scratch // GP registers. - ASMJIT_ASSERT(firstSuccessor->hasSharedAssignmentId()); - RASharedAssignment& sa = _sharedAssignments[firstSuccessor->sharedAssignmentId()]; - sa.addEntryScratchGpRegs(block->exitScratchGpRegs()); + if (firstSuccessor->hasSharedAssignmentId()) { + RASharedAssignment& sa = _sharedAssignments[firstSuccessor->sharedAssignmentId()]; + sa.addEntryScratchGpRegs(block->exitScratchGpRegs()); + } + else { + // This is only allowed if there is a single successor - in that case shared assignment is not necessary. + ASMJIT_ASSERT(successors.size() == 1u); + } } } if (block->hasSharedAssignmentId()) { diff --git a/test/asmjit_test_compiler_x86.cpp b/test/asmjit_test_compiler_x86.cpp index a3a067d..bc867eb 100644 --- a/test/asmjit_test_compiler_x86.cpp +++ b/test/asmjit_test_compiler_x86.cpp @@ -277,7 +277,7 @@ public: } virtual void compile(x86::Compiler& cc) { - Label L0 = cc.newLabel(); + Label L0 = cc.newLabel(); Label L1 = cc.newLabel(); Label L2 = cc.newLabel(); Label LEnd = cc.newLabel(); @@ -715,6 +715,126 @@ public: } }; +// x86::Compiler - X86Test_JumpTable3 +// ================================== + +class X86Test_JumpTable3 : public X86TestCase { +public: + X86Test_JumpTable3() + : X86TestCase("JumpTable {Jumping to a single label}") {} + + static void add(TestApp& app) { + app.add(new X86Test_JumpTable3()); + } + + virtual void compile(x86::Compiler& cc) { + cc.addFunc(FuncSignatureT<int>(CallConvId::kHost)); + + Label L_Target = cc.newLabel(); + x86::Gp target = cc.newUIntPtr("target"); + x86::Gp result = cc.newUInt32("result"); + + JumpAnnotation* annotation = cc.newJumpAnnotation(); + annotation->addLabel(L_Target); + + cc.lea(target, x86::ptr(L_Target)); + cc.jmp(target, annotation); + + cc.bind(L_Target); + cc.mov(result, 1234); + cc.ret(result); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef int (*Func)(void); + Func func = ptr_as_func<Func>(_func); + + int out = func(); + int expected = 1234; + + result.assignFormat("ret=%d", out); + expect.assignFormat("ret=%d", expected); + + return result == expect; + } +}; + +// x86::Compiler - X86Test_JumpTable4 +// ================================== + +class X86Test_JumpTable4 : public X86TestCase { +public: + X86Test_JumpTable4() + : X86TestCase("JumpTable {Jumping to a single label and multiple labels}") {} + + static void add(TestApp& app) { + app.add(new X86Test_JumpTable4()); + } + + virtual void compile(x86::Compiler& cc) { + x86::Gp result = cc.newUInt32("result"); + x86::Gp condition = cc.newUInt32("condition"); + + FuncNode* func = cc.addFunc(FuncSignatureT<int, int>(CallConvId::kHost)); + func->setArg(0, condition); + + Label L_NonZero = cc.newLabel(); + cc.test(condition, condition); + cc.jnz(L_NonZero); + + { + JumpAnnotation* annotation = cc.newJumpAnnotation(); + Label L_Target = cc.newLabel(); + annotation->addLabel(L_Target); + + x86::Gp target = cc.newUIntPtr("target"); + cc.lea(target, x86::ptr(L_Target)); + cc.jmp(target, annotation); + cc.bind(L_Target); + cc.mov(result, 1234); + cc.ret(result); + } + + { + JumpAnnotation* annotation = cc.newJumpAnnotation(); + Label L_Target1 = cc.newLabel(); + Label L_Target2 = cc.newLabel(); + annotation->addLabel(L_Target1); + annotation->addLabel(L_Target2); + + cc.bind(L_NonZero); + x86::Gp target = cc.newUIntPtr("target"); + cc.lea(target, x86::ptr(L_Target1)); + cc.jmp(target, annotation); + + cc.bind(L_Target1); + cc.mov(result, 4321); + cc.ret(result); + + // Never executed. + cc.bind(L_Target2); + cc.mov(result, 0); + cc.ret(result); + } + + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef int (*Func)(int); + Func func = ptr_as_func<Func>(_func); + + int results[2] = { func(0), func(1) }; + int expected[2] = { 1234, 4321 }; + + result.assignFormat("ret={%d, %d}", results[0], results[1]); + expect.assignFormat("ret={%d, %d}", expected[0], expected[1]); + + return result == expect; + } +}; + // x86::Compiler - X86Test_AllocBase // ================================= @@ -4246,6 +4366,8 @@ void compiler_add_x86_tests(TestApp& app) { app.addT<X86Test_JumpUnreachable2>(); app.addT<X86Test_JumpTable1>(); app.addT<X86Test_JumpTable2>(); + app.addT<X86Test_JumpTable3>(); + app.addT<X86Test_JumpTable4>(); // Alloc tests. app.addT<X86Test_AllocBase>(); |