1 // todo: come up with better rules for function name checking
3 bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
5 Function *fun = CI->getCalledFunction();
6 StringRef funName = fun->getName();
7 std::vector<Value *> parameters;
9 User::op_iterator begin = CI->arg_begin();
10 User::op_iterator end = CI->arg_end();
11 for (User::op_iterator it = begin; it != end; ++it) {
13 parameters.push_back(param);
16 // obtain source line number of the CallInst
17 Value *position = getPosition(CI, IRB);
19 // the pointer to the address is always the first argument
20 Value *OrigPtr = parameters[0];
21 int Idx = getMemoryAccessFuncIndex(OrigPtr, DL);
25 const unsigned ByteSize = 1U << Idx;
26 const unsigned BitSize = ByteSize * 8;
27 Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
28 Type *PtrTy = Ty->getPointerTo();
30 // atomic_init; args = {obj, order}
31 if (funName.contains("atomic_init")) {
32 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
33 Value *val = IRB.CreateBitOrPointerCast(parameters[1], Ty);
34 Value *args[] = {ptr, val, position};
36 Instruction* funcInst=CallInst::Create(CDSAtomicInit[Idx], args);
37 ReplaceInstWithInst(CI, funcInst);
42 // atomic_load; args = {obj, order}
43 if (funName.contains("atomic_load")) {
44 bool isExplicit = funName.contains("atomic_load_explicit");
46 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
49 order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
51 order = ConstantInt::get(OrdTy,
52 (int) AtomicOrderingCABI::seq_cst);
53 Value *args[] = {ptr, order, position};
55 Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
56 ReplaceInstWithInst(CI, funcInst);
59 } else if (funName.contains("atomic") &&
60 funName.contains("load")) {
61 // does this version of call always have an atomic order as an argument?
62 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
63 Value *order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
64 Value *args[] = {ptr, order, position};
66 //Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
67 CallInst *funcInst = IRB.CreateCall(CDSAtomicLoad[Idx], args);
68 Value *RetVal = IRB.CreateIntToPtr(funcInst, CI->getType());
70 CI->replaceAllUsesWith(RetVal);
71 CI->eraseFromParent();
76 // atomic_store; args = {obj, val, order}
77 if (funName.contains("atomic_store")) {
78 bool isExplicit = funName.contains("atomic_store_explicit");
79 Value *OrigVal = parameters[1];
81 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
82 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
85 order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
87 order = ConstantInt::get(OrdTy,
88 (int) AtomicOrderingCABI::seq_cst);
89 Value *args[] = {ptr, val, order, position};
91 Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
92 ReplaceInstWithInst(CI, funcInst);
95 } else if (funName.contains("atomic") &&
96 funName.contains("EEEE5store")) {
97 // does this version of call always have an atomic order as an argument?
98 Value *OrigVal = parameters[1];
100 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
101 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
102 Value *order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
103 Value *args[] = {ptr, val, order, position};
105 Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
106 ReplaceInstWithInst(CI, funcInst);
111 // atomic_fetch_*; args = {obj, val, order}
112 if (funName.contains("atomic_fetch_") ||
113 funName.contains("atomic_exchange") ) {
114 bool isExplicit = funName.contains("_explicit");
115 Value *OrigVal = parameters[1];
118 if ( funName.contains("_fetch_add") )
119 op = AtomicRMWInst::Add;
120 else if ( funName.contains("_fetch_sub") )
121 op = AtomicRMWInst::Sub;
122 else if ( funName.contains("_fetch_and") )
123 op = AtomicRMWInst::And;
124 else if ( funName.contains("_fetch_or") )
125 op = AtomicRMWInst::Or;
126 else if ( funName.contains("_fetch_xor") )
127 op = AtomicRMWInst::Xor;
128 else if ( funName.contains("atomic_exchange") )
129 op = AtomicRMWInst::Xchg;
131 errs() << "Unknown atomic read modify write operation\n";
135 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
136 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
139 order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
141 order = ConstantInt::get(OrdTy,
142 (int) AtomicOrderingCABI::seq_cst);
143 Value *args[] = {ptr, val, order, position};
145 Instruction* funcInst=CallInst::Create(CDSAtomicRMW[op][Idx], args);
146 ReplaceInstWithInst(CI, funcInst);
149 } else if (funName.contains("fetch")) {
150 errs() << "atomic exchange captured. Not implemented yet. ";
151 errs() << "See source file :";
152 getPositionPrint(CI, IRB);
153 } else if (funName.contains("exchange") &&
154 !funName.contains("compare_exchange") ) {
155 errs() << "atomic exchange captured. Not implemented yet. ";
156 errs() << "See source file :";
157 getPositionPrint(CI, IRB);
160 /* atomic_compare_exchange_*;
161 args = {obj, expected, new value, order1, order2}
163 if ( funName.contains("atomic_compare_exchange_") ) {
164 bool isExplicit = funName.contains("_explicit");
166 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
167 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
168 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
170 Value *order_succ, *order_fail;
172 order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
173 order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
175 order_succ = ConstantInt::get(OrdTy,
176 (int) AtomicOrderingCABI::seq_cst);
177 order_fail = ConstantInt::get(OrdTy,
178 (int) AtomicOrderingCABI::seq_cst);
181 Value *args[] = {Addr, CmpOperand, NewOperand,
182 order_succ, order_fail, position};
184 Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args);
185 ReplaceInstWithInst(CI, funcInst);
188 } else if ( funName.contains("compare_exchange_strong") ||
189 funName.contains("compare_exchange_wesk") ) {
190 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
191 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
192 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
194 Value *order_succ, *order_fail;
195 order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
196 order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
198 Value *args[] = {Addr, CmpOperand, NewOperand,
199 order_succ, order_fail, position};
200 Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args);
201 ReplaceInstWithInst(CI, funcInst);