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:
Kyungwoo Lee 2015-04-23 14:37:18 -07:00
Родитель ef5ebebd32
Коммит ca0807ce35
3 изменённых файлов: 54 добавлений и 7 удалений

Просмотреть файл

@ -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.