fix up syntax errors
[c11llvm.git] / instrumentAtomicCall.hpp
1 // todo: come up with better rules for function name checking
2
3 bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
4         IRBuilder<> IRB(CI);
5         Function *fun = CI->getCalledFunction();
6         StringRef funName = fun->getName();
7         std::vector<Value *> parameters;
8
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) {
12                 Value *param = *it;
13                 parameters.push_back(param);
14         }
15
16         // obtain source line number of the CallInst
17         Value *position = getPosition(CI, IRB);
18
19         // the pointer to the address is always the first argument
20         Value *OrigPtr = parameters[0];
21         int Idx = getMemoryAccessFuncIndex(OrigPtr, DL);
22         if (Idx < 0)
23                 return false;
24
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();
29
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};
35
36                 Instruction* funcInst=CallInst::Create(CDSAtomicInit[Idx], args);
37                 ReplaceInstWithInst(CI, funcInst);
38
39                 return true;
40         }
41
42         // atomic_load; args = {obj, order}
43         if (funName.contains("atomic_load")) {
44                 bool isExplicit = funName.contains("atomic_load_explicit");
45
46                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
47                 Value *order;
48                 if (isExplicit)
49                         order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
50                 else 
51                         order = ConstantInt::get(OrdTy, 
52                                                         (int) AtomicOrderingCABI::seq_cst);
53                 Value *args[] = {ptr, order, position};
54                 
55                 Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
56                 ReplaceInstWithInst(CI, funcInst);
57
58                 return true;
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};
65
66                 //Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
67                 CallInst *funcInst = IRB.CreateCall(CDSAtomicLoad[Idx], args);
68                 Value *RetVal = IRB.CreateIntToPtr(funcInst, CI->getType());
69
70                 CI->replaceAllUsesWith(RetVal);
71                 CI->eraseFromParent();
72                 
73                 return true;
74         }
75
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];
80
81                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
82                 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
83                 Value *order;
84                 if (isExplicit)
85                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
86                 else 
87                         order = ConstantInt::get(OrdTy, 
88                                                         (int) AtomicOrderingCABI::seq_cst);
89                 Value *args[] = {ptr, val, order, position};
90                 
91                 Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
92                 ReplaceInstWithInst(CI, funcInst);
93
94                 return true;
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];
99
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};
104
105                 Instruction* funcInst = CallInst::Create(CDSAtomicStore[Idx], args);
106                 ReplaceInstWithInst(CI, funcInst);
107
108                 return true;
109         }
110
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];
116
117                 int op;
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;
130                 else {
131                         errs() << "Unknown atomic read modify write operation\n";
132                         return false;
133                 }
134
135                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
136                 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
137                 Value *order;
138                 if (isExplicit)
139                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
140                 else 
141                         order = ConstantInt::get(OrdTy, 
142                                                         (int) AtomicOrderingCABI::seq_cst);
143                 Value *args[] = {ptr, val, order, position};
144                 
145                 Instruction* funcInst=CallInst::Create(CDSAtomicRMW[op][Idx], args);
146                 ReplaceInstWithInst(CI, funcInst);
147
148                 return true;
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);
158         } 
159
160         /* atomic_compare_exchange_*; 
161            args = {obj, expected, new value, order1, order2}
162         */
163         if ( funName.contains("atomic_compare_exchange_") ) {
164                 bool isExplicit = funName.contains("_explicit");
165
166                 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
167                 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
168                 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
169
170                 Value *order_succ, *order_fail;
171                 if (isExplicit) {
172                         order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
173                         order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
174                 } else  {
175                         order_succ = ConstantInt::get(OrdTy, 
176                                                         (int) AtomicOrderingCABI::seq_cst);
177                         order_fail = ConstantInt::get(OrdTy, 
178                                                         (int) AtomicOrderingCABI::seq_cst);
179                 }
180
181                 Value *args[] = {Addr, CmpOperand, NewOperand, 
182                                                         order_succ, order_fail, position};
183                 
184                 Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args);
185                 ReplaceInstWithInst(CI, funcInst);
186
187                 return true;
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);
193
194                 Value *order_succ, *order_fail;
195                 order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
196                 order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
197
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);
202
203                 return true;
204         }
205
206         return false;
207 }