Browse Source

Support for AtomicCmpXChg

Brian Fiete 1 year ago
parent
commit
f67eaa6d8a
2 changed files with 60 additions and 26 deletions
  1. 59 26
      IDEHelper/Compiler/CeMachine.cpp
  2. 1 0
      IDEHelper/Compiler/CeMachine.h

+ 59 - 26
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);

+ 1 - 0
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);