From 84b9cc1cf068b080db61e377d8cef369f09a4b51 Mon Sep 17 00:00:00 2001
From: weiyu <weiyuluo1232@gmail.com>
Date: Thu, 20 Jun 2019 15:55:54 -0700
Subject: [PATCH] add support for libcds atomic function calls

---
 getPosition.hpp          | 12 ++++++++
 instrumentAtomicCall.hpp | 61 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/getPosition.hpp b/getPosition.hpp
index f26d172..afc00c6 100644
--- a/getPosition.hpp
+++ b/getPosition.hpp
@@ -17,3 +17,15 @@ Value *getPosition( Instruction * I, IRBuilder <> IRB)
 
 	return IRB . CreateGlobalStringPtr (position_string);
 }
+
+Value *getPositionPrint( Instruction * I, IRBuilder <> IRB)
+{
+	const DebugLoc & debug_location = I->getDebugLoc ();
+	std::string position_string;
+	{
+		llvm::raw_string_ostream position_stream (position_string);
+		debug_location . print (position_stream);
+	}
+	errs() << position_string << "\n";
+	return IRB . CreateGlobalStringPtr (position_string);
+}
\ No newline at end of file
diff --git a/instrumentAtomicCall.hpp b/instrumentAtomicCall.hpp
index 9052013..4ee6d8d 100644
--- a/instrumentAtomicCall.hpp
+++ b/instrumentAtomicCall.hpp
@@ -1,3 +1,5 @@
+// todo: come up with better rules for function name checking
+
 bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
 	IRBuilder<> IRB(CI);
 	Function *fun = CI->getCalledFunction();
@@ -53,6 +55,21 @@ bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
 		Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
 		ReplaceInstWithInst(CI, funcInst);
 
+		return true;
+	} else if (funName.contains("atomic") && 
+				funName.contains("load")) {
+		// does this version of call always have an atomic order as an argument?
+		Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+		Value *order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
+		Value *args[] = {ptr, order, position};
+
+		//Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
+		CallInst *funcInst = IRB.CreateCall(CDSAtomicLoad[Idx], args);
+		Value *RetVal = IRB.CreateIntToPtr(funcInst, CI->getType());
+
+		CI->replaceAllUsesWith(RetVal);
+		CI->eraseFromParent();
+		
 		return true;
 	}
 
@@ -71,9 +88,23 @@ bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
 							(int) AtomicOrderingCABI::seq_cst);
 		Value *args[] = {ptr, val, order, position};
 		
-		Instruction* funcInst=CallInst::Create(CDSAtomicStore[Idx], args);
+		Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
 		ReplaceInstWithInst(CI, funcInst);
 
+		return true;
+	} else if (funName.contains("atomic") && 
+					funName.contains("store")) {
+		// does this version of call always have an atomic order as an argument?
+		Value *OrigVal = parameters[1];
+
+		Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+		Value *val = IRB.CreatePointerCast(OrigVal, Ty);
+		Value *order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
+		Value *args[] = {ptr, val, order, position};
+
+		Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
+		ReplaceInstWithInst(CI, funcInst);
+		
 		return true;
 	}
 
@@ -115,7 +146,16 @@ bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
 		ReplaceInstWithInst(CI, funcInst);
 
 		return true;
-	}
+	} else if (funName.contains("fetch")) {
+		errs() << "atomic exchange captured. Not implemented yet. "
+		errs() << "See source file :";
+		getPositionPrint(CI, IRB);
+	} else if (funName.contains("exchange") &&
+				!funName.contains("compare_exchange") ) {
+		errs() << "atomic exchange captured. Not implemented yet. "
+		errs() << "See source file :";
+		getPositionPrint(CI, IRB);
+	} 
 
 	/* atomic_compare_exchange_*; 
 	   args = {obj, expected, new value, order1, order2}
@@ -144,6 +184,23 @@ bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
 		Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args);
 		ReplaceInstWithInst(CI, funcInst);
 
+		return true;
+	} else if ( funName.contains("compare_exchange_strong") || 
+				funName.contains("compare_exchange_wesk") ) {
+
+		Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+		Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
+		Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
+
+		Value *order_succ, *order_fail;
+		order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
+		order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
+
+		Value *args[] = {Addr, CmpOperand, NewOperand, 
+							order_succ, order_fail, position};
+		Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args);
+		ReplaceInstWithInst(CI, funcInst);
+
 		return true;
 	}
 
-- 
2.34.1