diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 6fd9e073..969c7ecc 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -973,6 +973,37 @@ void CeBuilder::EmitBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, } } +CeOperand CeBuilder::EmitLoad(CeOperand ceTarget, int loadRefCount) +{ + CeOperand result; + if (ceTarget.mKind == CeOperandKind_AllocaAddr) + { + if (loadRefCount <= 1) + { + result = ceTarget; + result.mKind = CeOperandKind_FrameOfs; + } + else + { + ceTarget.mKind = CeOperandKind_FrameOfs; + result = FrameAlloc(ceTarget.mType); + EmitSizedOp(CeOp_Move_8, ceTarget, NULL, true); + Emit((int32)result.mFrameOfs); + } + } + else + { + BF_ASSERT(ceTarget.mType->IsPointer()); + auto pointerType = (BePointerType*)ceTarget.mType; + auto elemType = pointerType->mElementType; + + CeOperand refOperand = ceTarget; + refOperand.mType = elemType; + EmitSizedOp(CeOp_Load_8, refOperand, &result, true); + } + return result; +} + int CeBuilder::GetCodePos() { return (int)mCeFunction->mCode.size(); @@ -2396,32 +2427,7 @@ void CeBuilder::Build() { auto castedInst = (BeLoadInst*)inst; auto ceTarget = GetOperand(castedInst->mTarget, true); - - if (ceTarget.mKind == CeOperandKind_AllocaAddr) - { - if (inst->mRefCount <= 1) - { - result = ceTarget; - result.mKind = CeOperandKind_FrameOfs; - } - else - { - ceTarget.mKind = CeOperandKind_FrameOfs; - result = FrameAlloc(ceTarget.mType); - EmitSizedOp(CeOp_Move_8, ceTarget, NULL, true); - Emit((int32)result.mFrameOfs); - } - } - else - { - BF_ASSERT(ceTarget.mType->IsPointer()); - auto pointerType = (BePointerType*)ceTarget.mType; - auto elemType = pointerType->mElementType; - - CeOperand refOperand = ceTarget; - refOperand.mType = elemType; - EmitSizedOp(CeOp_Load_8, refOperand, &result, true); - } + result = EmitLoad(ceTarget, inst->mRefCount); } break; case BeBinaryOpInst::TypeId: @@ -3135,6 +3141,33 @@ void CeBuilder::Build() case BfIRIntrinsic_DebugTrap: Emit(CeOp_DbgBreak); break; + case BfIRIntrinsic_AtomicCmpXChg: + { + auto mcPtr = GetOperand(castedInst->mArgs[0].mValue, true); + auto mcComparand = GetOperand(castedInst->mArgs[1].mValue); + auto mcValue = GetOperand(castedInst->mArgs[2].mValue); + + CeOperand mcPrev = EmitLoad(mcPtr); + + CeOperand cmpResult; + EmitBinaryOp(CeOp_Cmp_EQ_I8, CeOp_InvalidOp, mcPrev, mcComparand, cmpResult); + Emit(CeOp_JmpIfNot); + Emit((int32)14); + EmitFrameOffset(cmpResult); + if (mcPtr.mKind == CeOperandKind_AllocaAddr) + { + EmitSizedOp(CeOp_Move_8, mcValue, NULL, true); + Emit((int32)mcPtr.mFrameOfs); + } + else + { + EmitSizedOp(CeOp_Store_8, mcValue, NULL, true); + EmitFrameOffset(mcPtr); + } + + result = mcPrev; + } + break; default: Emit(CeOp_Error); Emit((int32)CeErrorKind_Intrinsic); diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 6a35737f..79bda5af 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -886,6 +886,7 @@ public: void EmitZeroes(int size); void EmitJump(CeOp op, const CeOperand& block); void EmitBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx); + CeOperand EmitLoad(CeOperand mcPtr, int loadRefCount = 1); CeOperand EmitNumericCast(const CeOperand& ceValue, BeType* toType, bool valSigned, bool toSigned); void EmitFrameOffset(const CeOperand& val);