зеркало из https://github.com/dotnet/llilc.git
Support for interlockedCmpXchg
I use llvm intrinsic to implement this. I verified code sequence and ran it with a unit test, which I will add to our test asset later.
This commit is contained in:
Родитель
ef5ebebd32
Коммит
ca0807ce35
|
@ -2891,9 +2891,18 @@ public:
|
|||
virtual bool interlockedIntrinsicBinOp(IRNode *Arg1, IRNode *Arg2,
|
||||
IRNode **RetVal,
|
||||
CorInfoIntrinsics IntrinsicID) = 0;
|
||||
virtual bool interlockedCmpXchg(IRNode *Arg1, IRNode *Arg2, IRNode *Arg3,
|
||||
IRNode **RetVal,
|
||||
|
||||
/// Generate inline code for the \p interlockedCmpXchg operation
|
||||
///
|
||||
/// \param Destination A pointer to the destination
|
||||
/// \param Exchange The exchange value
|
||||
/// \param Comparand The value to compare to the destination
|
||||
/// \param Result [out] The result is the initial destination
|
||||
/// \returns true iff the client expanded the interlockedCmpXchg
|
||||
virtual bool interlockedCmpXchg(IRNode *Destination, IRNode *Exchange,
|
||||
IRNode *Comparand, IRNode **Result,
|
||||
CorInfoIntrinsics IntrinsicID) = 0;
|
||||
|
||||
virtual bool memoryBarrier() = 0;
|
||||
virtual void switchOpcode(IRNode *Opr) = 0;
|
||||
virtual void throwOpcode(IRNode *Arg1) = 0;
|
||||
|
|
|
@ -465,11 +465,11 @@ public:
|
|||
CorInfoIntrinsics IntrinsicID) override {
|
||||
throw NotYetImplementedException("interlockedIntrinsicBinOp");
|
||||
};
|
||||
bool interlockedCmpXchg(IRNode *Arg1, IRNode *Arg2, IRNode *Arg3,
|
||||
IRNode **RetVal,
|
||||
CorInfoIntrinsics IntrinsicID) override {
|
||||
throw NotYetImplementedException("interlockedCmpXchg");
|
||||
};
|
||||
|
||||
bool interlockedCmpXchg(IRNode *Destination, IRNode *Exchange,
|
||||
IRNode *Comparand, IRNode **Result,
|
||||
CorInfoIntrinsics IntrinsicID) override;
|
||||
|
||||
bool memoryBarrier() override;
|
||||
|
||||
void switchOpcode(IRNode *Opr) override;
|
||||
|
|
|
@ -4457,6 +4457,44 @@ void GenIR::dup(IRNode *Opr, IRNode **Result1, IRNode **Result2) {
|
|||
*Result2 = Opr;
|
||||
}
|
||||
|
||||
bool GenIR::interlockedCmpXchg(IRNode *Destination, IRNode *Exchange,
|
||||
IRNode *Comparand, IRNode **Result,
|
||||
CorInfoIntrinsics IntrinsicID) {
|
||||
ASSERT(Exchange->getType() == Comparand->getType());
|
||||
switch (IntrinsicID) {
|
||||
case CORINFO_INTRINSIC_InterlockedCmpXchg32:
|
||||
ASSERT(Exchange->getType() == Type::getInt32Ty(*JitContext->LLVMContext));
|
||||
break;
|
||||
case CORINFO_INTRINSIC_InterlockedCmpXchg64:
|
||||
ASSERT(Exchange->getType() == Type::getInt64Ty(*JitContext->LLVMContext));
|
||||
break;
|
||||
default:
|
||||
throw NotYetImplementedException("interlockedCmpXchg");
|
||||
}
|
||||
|
||||
Type *ComparandTy = Comparand->getType();
|
||||
Type *DestinationTy = Destination->getType();
|
||||
|
||||
if (DestinationTy->isIntegerTy()) {
|
||||
Type *CastTy = getManagedPointerType(ComparandTy);
|
||||
Destination = (IRNode *)LLVMBuilder->CreateIntToPtr(Destination, CastTy);
|
||||
} else {
|
||||
ASSERT(DestinationTy->isPointerTy());
|
||||
Type *CastTy = isManagedPointerType(DestinationTy)
|
||||
? getManagedPointerType(ComparandTy)
|
||||
: getUnmanagedPointerType(ComparandTy);
|
||||
Destination = (IRNode *)LLVMBuilder->CreatePointerCast(Destination, CastTy);
|
||||
}
|
||||
|
||||
Value *Pair = LLVMBuilder->CreateAtomicCmpXchg(
|
||||
Destination, Comparand, Exchange, llvm::SequentiallyConsistent,
|
||||
llvm::SequentiallyConsistent);
|
||||
*Result =
|
||||
(IRNode *)LLVMBuilder->CreateExtractValue(Pair, 0, "cmpxchg_result");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GenIR::memoryBarrier() {
|
||||
// TODO: Here we emit mfence which is stronger than sfence
|
||||
// that CLR needs.
|
||||
|
|
Загрузка…
Ссылка в новой задаче