diff --git a/src/app/test/testx86.cpp b/src/app/test/testx86.cpp index cf944cb..7ba6737 100644 --- a/src/app/test/testx86.cpp +++ b/src/app/test/testx86.cpp @@ -851,7 +851,7 @@ struct X86Test_AllocGpLo : public X86Test { // ============================================================================ struct X86Test_AllocRepMovsb : public X86Test { - X86Test_AllocRepMovsb() : X86Test("[Special] Rep Movsb") {} + X86Test_AllocRepMovsb() : X86Test("[Alloc] Rep Movsb") {} static void add(PodVector& tests) { tests.append(new X86Test_AllocSetz()); @@ -887,6 +887,117 @@ struct X86Test_AllocRepMovsb : public X86Test { } }; +// ============================================================================ +// [X86Test_AllocIfElse1] +// ============================================================================ + +struct X86Test_AllocIfElse1 : public X86Test { + X86Test_AllocIfElse1() : X86Test("[Alloc] If-Else #1") {} + + static void add(PodVector& tests) { + tests.append(new X86Test_AllocIfElse1()); + } + + virtual void compile(Compiler& c) { + c.addFunc(kFuncConvHost, FuncBuilder2()); + + GpVar v1(c, kVarTypeInt32); + GpVar v2(c, kVarTypeInt32); + + Label L_1(c); + Label L_2(c); + + c.setArg(0, v1); + c.setArg(1, v2); + + c.cmp(v1, v2); + c.jg(L_1); + + c.mov(v1, 1); + c.jmp(L_2); + + c.bind(L_1); + c.mov(v1, 2); + + c.bind(L_2); + c.ret(v1); + c.endFunc(); + } + + virtual bool run(void* _func, StringBuilder& result, StringBuilder& expect) { + typedef int (*Func)(int, int); + Func func = asmjit_cast(_func); + + int a = func(1, 0); + int b = func(0, 1); + + result.appendFormat("ret={%d, %d}", a, b); + result.appendFormat("ret={%d, %d}", 2, 1); + + return a == 2 && b == 1; + } +}; + +// ============================================================================ +// [X86Test_AllocIfElse2] +// ============================================================================ + +struct X86Test_AllocIfElse2 : public X86Test { + X86Test_AllocIfElse2() : X86Test("[Alloc] If-Else #1") {} + + static void add(PodVector& tests) { + tests.append(new X86Test_AllocIfElse2()); + } + + virtual void compile(Compiler& c) { + c.addFunc(kFuncConvHost, FuncBuilder2()); + + GpVar v1(c, kVarTypeInt32); + GpVar v2(c, kVarTypeInt32); + + Label L_1(c); + Label L_2(c); + Label L_3(c); + Label L_4(c); + + c.setArg(0, v1); + c.setArg(1, v2); + + c.jmp(L_1); + c.bind(L_2); + c.jmp(L_4); + c.bind(L_1); + + c.cmp(v1, v2); + c.jg(L_3); + + c.mov(v1, 1); + c.jmp(L_2); + + c.bind(L_3); + c.mov(v1, 2); + c.jmp(L_2); + + c.bind(L_4); + + c.ret(v1); + c.endFunc(); + } + + virtual bool run(void* _func, StringBuilder& result, StringBuilder& expect) { + typedef int (*Func)(int, int); + Func func = asmjit_cast(_func); + + int a = func(1, 0); + int b = func(0, 1); + + result.appendFormat("ret={%d, %d}", a, b); + result.appendFormat("ret={%d, %d}", 2, 1); + + return a == 2 && b == 1; + } +}; + // ============================================================================ // [X86Test_AllocArgs] // ============================================================================ @@ -1705,6 +1816,8 @@ X86TestSuite::X86TestSuite() : ADD_TEST(X86Test_AllocShlRor); ADD_TEST(X86Test_AllocGpLo); ADD_TEST(X86Test_AllocRepMovsb); + ADD_TEST(X86Test_AllocIfElse1); + ADD_TEST(X86Test_AllocIfElse2); ADD_TEST(X86Test_AllocArgs); ADD_TEST(X86Test_AllocStack); ADD_TEST(X86Test_AllocMemcpy); diff --git a/src/asmjit/base/compiler.cpp b/src/asmjit/base/compiler.cpp index 74e8031..548cc6c 100644 --- a/src/asmjit/base/compiler.cpp +++ b/src/asmjit/base/compiler.cpp @@ -176,6 +176,32 @@ BaseNode* BaseCompiler::addNodeAfter(BaseNode* node, BaseNode* ref) { return node; } +static ASMJIT_INLINE void BaseCompiler_nodeRemoved(BaseCompiler* self, BaseNode* node_) { + if (node_->isJmpOrJcc()) { + JumpNode* node = static_cast(node_); + TargetNode* target = node->getTarget(); + + // Disconnect. + JumpNode** pPrev = &target->_from; + for (;;) { + ASMJIT_ASSERT(*pPrev != NULL); + JumpNode* current = *pPrev; + + if (current == NULL) + break; + + if (current == node) { + *pPrev = node->_jumpNext; + break; + } + + pPrev = ¤t->_jumpNext; + } + + target->subNumRefs(); + } +} + BaseNode* BaseCompiler::removeNode(BaseNode* node) { BaseNode* prev = node->_prev; BaseNode* next = node->_next; @@ -195,6 +221,7 @@ BaseNode* BaseCompiler::removeNode(BaseNode* node) { if (_cursor == node) _cursor = prev; + BaseCompiler_nodeRemoved(this, node); return node; } @@ -228,6 +255,7 @@ void BaseCompiler::removeNodes(BaseNode* first, BaseNode* last) { if (_cursor == node) _cursor = prev; + BaseCompiler_nodeRemoved(this, node); if (node == last) break; diff --git a/src/asmjit/base/compiler.h b/src/asmjit/base/compiler.h index 7896f81..f26964a 100644 --- a/src/asmjit/base/compiler.h +++ b/src/asmjit/base/compiler.h @@ -1063,8 +1063,11 @@ struct TargetNode : public BaseNode { ASMJIT_INLINE uint32_t getNumRefs() const { return _numRefs; } //! @brief Set number of jumps to this target. ASMJIT_INLINE void setNumRefs(uint32_t i) { _numRefs = i; } + //! @brief Add number of jumps to this target. ASMJIT_INLINE void addNumRefs(uint32_t i = 1) { _numRefs += i; } + //! @brief Subtract number of jumps to this target. + ASMJIT_INLINE void subNumRefs(uint32_t i = 1) { _numRefs -= i; } // -------------------------------------------------------------------------- // [Members] diff --git a/src/asmjit/base/globals.cpp b/src/asmjit/base/globals.cpp index 9e13c9f..55e06bf 100644 --- a/src/asmjit/base/globals.cpp +++ b/src/asmjit/base/globals.cpp @@ -13,7 +13,6 @@ // [Api-Begin] #include "../base/apibegin.h" -// helpers namespace asmjit { // ============================================================================ diff --git a/src/asmjit/base/globals.h b/src/asmjit/base/globals.h index 9dd27c3..c6e92bb 100644 --- a/src/asmjit/base/globals.h +++ b/src/asmjit/base/globals.h @@ -40,7 +40,7 @@ ASMJIT_ENUM(kGlobals) { //! @brief Memory grow threshold. //! - //! After the grow threshold is reached the capacity won't be doubled + //! After the grow threshold is reached the capacity won't be doubled //! anymore. kMemAllocGrowMax = 8192 * 1024, diff --git a/src/asmjit/base/podlist.h b/src/asmjit/base/podlist.h index dfda5a5..93f59d6 100644 --- a/src/asmjit/base/podlist.h +++ b/src/asmjit/base/podlist.h @@ -113,4 +113,5 @@ struct PodList { // [Api-End] #include "../base/apiend.h" +// [Guard] #endif // _ASMJIT_BASE_PODLIST_H diff --git a/src/asmjit/base/podvector.h b/src/asmjit/base/podvector.h index 4c4d5aa..2223ceb 100644 --- a/src/asmjit/base/podvector.h +++ b/src/asmjit/base/podvector.h @@ -259,4 +259,5 @@ struct PodVector : PodVectorBase { // [Api-End] #include "../base/apiend.h" +// [Guard] #endif // _ASMJIT_BASE_PODVECTOR_H diff --git a/src/asmjit/base/string.h b/src/asmjit/base/string.h index 90797ad..ef15622 100644 --- a/src/asmjit/base/string.h +++ b/src/asmjit/base/string.h @@ -347,4 +347,5 @@ struct StringBuilderT : public StringBuilder { // [Api-End] #include "../base/apiend.h" +// [Guard] #endif // _ASMJIT_BASE_STRING_H diff --git a/src/asmjit/base/zone.h b/src/asmjit/base/zone.h index 4d11248..699b70a 100644 --- a/src/asmjit/base/zone.h +++ b/src/asmjit/base/zone.h @@ -188,4 +188,5 @@ struct Zone { // [Api-End] #include "../base/apiend.h" +// [Guard] #endif // _ASMJIT_BASE_ZONE_H diff --git a/src/asmjit/x86/x86context.cpp b/src/asmjit/x86/x86context.cpp index c5f7ec2..cdab540 100644 --- a/src/asmjit/x86/x86context.cpp +++ b/src/asmjit/x86/x86context.cpp @@ -1367,6 +1367,8 @@ static ASMJIT_INLINE void X86X64Context_switchStateVars(X86X64Context* self, Var } void X86X64Context::switchState(BaseVarState* src_) { + ASMJIT_ASSERT(src_ != NULL); + VarState* cur = getState(); VarState* src = static_cast(src_); @@ -1476,7 +1478,7 @@ static void X86X64Context_prepareSingleVarInst(uint32_t code, VarAttr* va) { //! @internal //! //! @brief Add unreachable-flow data to the unreachable flow list. -static ASMJIT_INLINE Error X86X64Context_prepareAddUnreachableNode(X86X64Context* self, BaseNode* node) { +static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self, BaseNode* node) { PodList::Link* link = self->_zoneAllocator.allocT::Link>(); if (link == NULL) return self->setError(kErrorNoHeapMemory); @@ -1490,7 +1492,7 @@ static ASMJIT_INLINE Error X86X64Context_prepareAddUnreachableNode(X86X64Context //! @internal //! //! @brief Add jump-flow data to the jcc flow list. -static ASMJIT_INLINE Error X86X64Context_prepareAddJccNode(X86X64Context* self, BaseNode* node) { +static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, BaseNode* node) { PodList::Link* link = self->_zoneAllocator.allocT::Link>(); if (link == NULL) @@ -2059,7 +2061,7 @@ _NextGroup: // natural flow of the function. if (jNode->isJmp()) { if (!jNext->isFetched()) - ASMJIT_PROPAGATE_ERROR(X86X64Context_prepareAddUnreachableNode(this, jNext)); + ASMJIT_PROPAGATE_ERROR(X86X64Context_addUnreachableNode(this, jNext)); node_ = jTarget; goto _Do; @@ -2080,7 +2082,7 @@ _NextGroup: goto _Do; } else { - ASMJIT_PROPAGATE_ERROR(X86X64Context_prepareAddJccNode(this, jNode)); + ASMJIT_PROPAGATE_ERROR(X86X64Context_addJccNode(this, jNode)); node_ = X86X64Context_getJccFlow(jNode); goto _Do; @@ -2409,6 +2411,8 @@ _OnVisit: if (node == func) goto _OnDone; + + ASMJIT_ASSERT(node->getPrev()); node = node->getPrev(); } @@ -4671,22 +4675,26 @@ _NextGroup: goto _Done; } else { - JumpNode* jNode = static_cast(jLink->getValue()); + node_ = jLink->getValue(); jLink = jLink->getNext(); - BaseNode* jFlow = X86X64Context_getOppositeJccFlow(jNode); - loadState(jNode->getState()); + BaseNode* jFlow = X86X64Context_getOppositeJccFlow(static_cast(node_)); + loadState(node_->getState()); - // TODO: - if (jNode->getNext() == jFlow) { + if (jFlow->getState()) { + X86X64Context_translateJump(this, + static_cast(node_), + static_cast(jFlow)); + + node_ = jFlow; + if (node_->isTranslated()) + goto _NextGroup; } else { - X86X64Context_translateJump(this, jNode, static_cast(jFlow)); + node_ = jFlow; } - node_ = jFlow; - if (node_->isTranslated()) - goto _NextGroup; + break; } } diff --git a/tools/autoexp.dat b/tools/autoexp.dat index ac8a12e..4d2de36 100644 --- a/tools/autoexp.dat +++ b/tools/autoexp.dat @@ -62,14 +62,14 @@ @define asmjit::kNodeTypeAlign (0x1) @define asmjit::kNodeTypeEmbed (0x2) @define asmjit::kNodeTypeComment (0x3) -@define asmjit::kNodeTypeMark (0x4) -@define asmjit::kNodeTypeHint (0x5) -@define asmjit::kNodeTypeTarget (0x6) -@define asmjit::kNodeTypeInst (0x7) -@define asmjit::kNodeTypeFunc (0x8) -@define asmjit::kNodeTypeEnd (0x9) -@define asmjit::kNodeTypeRet (0xA) -@define asmjit::kNodeTypeCall (0xB) +@define asmjit::kNodeTypeHint (0x4) +@define asmjit::kNodeTypeTarget (0x5) +@define asmjit::kNodeTypeInst (0x6) +@define asmjit::kNodeTypeFunc (0x7) +@define asmjit::kNodeTypeEnd (0x8) +@define asmjit::kNodeTypeRet (0x9) +@define asmjit::kNodeTypeCall (0xA) +@define asmjit::kNodeTypeSArg (0xB) @ @define asmjit::kNodeFlagIsTranslated (0x0001) @define asmjit::kNodeFlagIsJmp (0x0002) @@ -801,13 +801,12 @@ asmjit::BaseVarInst|asmjit::x86x64::VarInst { ; [asmjit::X86 - Compiler - BaseNode] ; ============================================================================= -asmjit::BaseNode|asmjit::AlignNode|asmjit::EmbedNode|asmjit::CommentNode|asmjit::MarkNode|asmjit::HintNode|asmjit::TargetNode|asmjit::InstNode|asmjit::JumpNode::asmjit::FuncNode|asmjit::EndNode|asmjit::RetNode|asmjit::x86x64::X86X64FuncNode|asmjit::x86x64::X86X64CallNode { +asmjit::BaseNode|asmjit::AlignNode|asmjit::EmbedNode|asmjit::CommentNode|asmjit::HintNode|asmjit::TargetNode|asmjit::InstNode|asmjit::JumpNode::asmjit::FuncNode|asmjit::EndNode|asmjit::RetNode|asmjit::x86x64::X86X64FuncNode|asmjit::x86x64::X86X64CallNode|asmjit::SArgNode { preview( #( #if ($e._type == asmjit::kNodeTypeAlign) ("AlignNode") #elif ($e._type == asmjit::kNodeTypeEmbed) ("EmbedNode") #elif ($e._type == asmjit::kNodeTypeComment) ("CommentNode") - #elif ($e._type == asmjit::kNodeTypeMark) ("MarkNode") #elif ($e._type == asmjit::kNodeTypeHint) ("HintNode") #elif ($e._type == asmjit::kNodeTypeTarget) ("TargetNode") #elif ($e._type == asmjit::kNodeTypeInst) ("InstNode") @@ -815,6 +814,7 @@ asmjit::BaseNode|asmjit::AlignNode|asmjit::EmbedNode|asmjit::CommentNode|asmjit: #elif ($e._type == asmjit::kNodeTypeEnd) ("EndNode") #elif ($e._type == asmjit::kNodeTypeRet) ("RetNode") #elif ($e._type == asmjit::kNodeTypeCall) ("CallNode") + #elif ($e._type == asmjit::kNodeTypeSArg) ("SArgNode") #else ("BaseNode"), "(",