1 bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
3 Function *fun = CI->getCalledFunction();
4 StringRef funName = fun->getName();
5 std::vector<Value *> parameters;
7 User::op_iterator begin = CI->arg_begin();
8 User::op_iterator end = CI->arg_end();
9 for (User::op_iterator it = begin; it != end; ++it) {
11 parameters.push_back(param);
14 // obtain source line number of the CallInst
15 Value *position = getPosition(CI, IRB);
17 // the pointer to the address is always the first argument
18 Value *OrigPtr = parameters[0];
19 int Idx = getMemoryAccessFuncIndex(OrigPtr, DL);
23 const unsigned ByteSize = 1U << Idx;
24 const unsigned BitSize = ByteSize * 8;
25 Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
26 Type *PtrTy = Ty->getPointerTo();
28 // atomic_init; args = {obj, order}
29 if (funName.contains("atomic_init")) {
30 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
31 Value *val = IRB.CreateBitOrPointerCast(parameters[1], Ty);
32 Value *args[] = {ptr, val, position};
34 Instruction* funcInst=CallInst::Create(CDSAtomicInit[Idx], args);
35 ReplaceInstWithInst(CI, funcInst);
40 // atomic_load; args = {obj, order}
41 if (funName.contains("atomic_load")) {
42 bool isExplicit = funName.contains("atomic_load_explicit");
44 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
47 order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
49 order = ConstantInt::get(OrdTy,
50 (int) AtomicOrderingCABI::seq_cst);
51 Value *args[] = {ptr, order, position};
53 Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
54 ReplaceInstWithInst(CI, funcInst);
59 // atomic_store; args = {obj, val, order}
60 if (funName.contains("atomic_store")) {
61 bool isExplicit = funName.contains("atomic_store_explicit");
62 Value *OrigVal = parameters[1];
64 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
65 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
68 order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
70 order = ConstantInt::get(OrdTy,
71 (int) AtomicOrderingCABI::seq_cst);
72 Value *args[] = {ptr, val, order, position};
74 Instruction* funcInst=CallInst::Create(CDSAtomicStore[Idx], args);
75 ReplaceInstWithInst(CI, funcInst);
80 // atomic_fetch_*; args = {obj, val, order}
81 if (funName.contains("atomic_fetch_") ||
82 funName.contains("atomic_exchange") ) {
83 bool isExplicit = funName.contains("_explicit");
84 Value *OrigVal = parameters[1];
87 if ( funName.contains("_fetch_add") )
88 op = AtomicRMWInst::Add;
89 else if ( funName.contains("_fetch_sub") )
90 op = AtomicRMWInst::Sub;
91 else if ( funName.contains("_fetch_and") )
92 op = AtomicRMWInst::And;
93 else if ( funName.contains("_fetch_or") )
94 op = AtomicRMWInst::Or;
95 else if ( funName.contains("_fetch_xor") )
96 op = AtomicRMWInst::Xor;
97 else if ( funName.contains("atomic_exchange") )
98 op = AtomicRMWInst::Xchg;
100 errs() << "Unknown atomic read modify write operation\n";
104 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
105 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
108 order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
110 order = ConstantInt::get(OrdTy,
111 (int) AtomicOrderingCABI::seq_cst);
112 Value *args[] = {ptr, val, order, position};
114 Instruction* funcInst=CallInst::Create(CDSAtomicRMW[op][Idx], args);
115 ReplaceInstWithInst(CI, funcInst);
120 /* atomic_compare_exchange_*;
121 args = {obj, expected, new value, order1, order2}
123 if ( funName.contains("atomic_compare_exchange_") ) {
124 bool isExplicit = funName.contains("_explicit");
126 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
127 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
128 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
130 Value *order_succ, *order_fail;
132 order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
133 order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
135 order_succ = ConstantInt::get(OrdTy,
136 (int) AtomicOrderingCABI::seq_cst);
137 order_fail = ConstantInt::get(OrdTy,
138 (int) AtomicOrderingCABI::seq_cst);
141 Value *args[] = {Addr, CmpOperand, NewOperand,
142 order_succ, order_fail, position};
144 Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args);
145 ReplaceInstWithInst(CI, funcInst);