@@ -520,6 +520,11 @@ bool ThreadSanitizer::instrumentMemIntrinsic(Instruction *I) {
520
520
return false ;
521
521
}
522
522
523
+ static Value *createIntOrPtrToIntCast (Value *V, Type* Ty, IRBuilder<> &IRB) {
524
+ return isa<PointerType>(V->getType ()) ?
525
+ IRB.CreatePtrToInt (V, Ty) : IRB.CreateIntCast (V, Ty, false );
526
+ }
527
+
523
528
// Both llvm and ThreadSanitizer atomic operations are based on C++11/C1x
524
529
// standards. For background see C++11 standard. A slightly older, publicly
525
530
// available draft of the standard (not entirely up-to-date, but close enough
@@ -541,9 +546,16 @@ bool ThreadSanitizer::instrumentAtomic(Instruction *I, const DataLayout &DL) {
541
546
Type *PtrTy = Ty->getPointerTo ();
542
547
Value *Args[] = {IRB.CreatePointerCast (Addr, PtrTy),
543
548
createOrdering (&IRB, LI->getOrdering ())};
544
- CallInst *C = CallInst::Create (TsanAtomicLoad[Idx], Args);
545
- ReplaceInstWithInst (I, C);
546
-
549
+ Type *OrigTy = cast<PointerType>(Addr->getType ())->getElementType ();
550
+ if (Ty == OrigTy) {
551
+ Instruction *C = CallInst::Create (TsanAtomicLoad[Idx], Args);
552
+ ReplaceInstWithInst (I, C);
553
+ } else {
554
+ // We are loading a pointer, so we need to cast the return value.
555
+ Value *C = IRB.CreateCall (TsanAtomicLoad[Idx], Args);
556
+ Instruction *Cast = CastInst::Create (Instruction::IntToPtr, C, OrigTy);
557
+ ReplaceInstWithInst (I, Cast);
558
+ }
547
559
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
548
560
Value *Addr = SI->getPointerOperand ();
549
561
int Idx = getMemoryAccessFuncIndex (Addr, DL);
@@ -554,7 +566,7 @@ bool ThreadSanitizer::instrumentAtomic(Instruction *I, const DataLayout &DL) {
554
566
Type *Ty = Type::getIntNTy (IRB.getContext (), BitSize);
555
567
Type *PtrTy = Ty->getPointerTo ();
556
568
Value *Args[] = {IRB.CreatePointerCast (Addr, PtrTy),
557
- IRB. CreateIntCast (SI->getValueOperand (), Ty, false ),
569
+ createIntOrPtrToIntCast (SI->getValueOperand (), Ty, IRB ),
558
570
createOrdering (&IRB, SI->getOrdering ())};
559
571
CallInst *C = CallInst::Create (TsanAtomicStore[Idx], Args);
560
572
ReplaceInstWithInst (I, C);
@@ -584,15 +596,26 @@ bool ThreadSanitizer::instrumentAtomic(Instruction *I, const DataLayout &DL) {
584
596
const unsigned BitSize = ByteSize * 8 ;
585
597
Type *Ty = Type::getIntNTy (IRB.getContext (), BitSize);
586
598
Type *PtrTy = Ty->getPointerTo ();
599
+ Value *CmpOperand =
600
+ createIntOrPtrToIntCast (CASI->getCompareOperand (), Ty, IRB);
601
+ Value *NewOperand =
602
+ createIntOrPtrToIntCast (CASI->getNewValOperand (), Ty, IRB);
587
603
Value *Args[] = {IRB.CreatePointerCast (Addr, PtrTy),
588
- IRB. CreateIntCast (CASI-> getCompareOperand (), Ty, false ) ,
589
- IRB. CreateIntCast (CASI-> getNewValOperand (), Ty, false ) ,
604
+ CmpOperand ,
605
+ NewOperand ,
590
606
createOrdering (&IRB, CASI->getSuccessOrdering ()),
591
607
createOrdering (&IRB, CASI->getFailureOrdering ())};
592
608
CallInst *C = IRB.CreateCall (TsanAtomicCAS[Idx], Args);
593
- Value *Success = IRB.CreateICmpEQ (C, CASI->getCompareOperand ());
609
+ Value *Success = IRB.CreateICmpEQ (C, CmpOperand);
610
+ Value *OldVal = C;
611
+ Type *OrigOldValTy = CASI->getNewValOperand ()->getType ();
612
+ if (Ty != OrigOldValTy) {
613
+ // The value is a pointer, so we need to cast the return value.
614
+ OldVal = IRB.CreateIntToPtr (C, OrigOldValTy);
615
+ }
594
616
595
- Value *Res = IRB.CreateInsertValue (UndefValue::get (CASI->getType ()), C, 0 );
617
+ Value *Res =
618
+ IRB.CreateInsertValue (UndefValue::get (CASI->getType ()), OldVal, 0 );
596
619
Res = IRB.CreateInsertValue (Res, Success, 1 );
597
620
598
621
I->replaceAllUsesWith (Res);
0 commit comments