refactor codes in CDSPass.cpp and also add support for function-like atomic operation...
[c11llvm.git] / instrumentAtomicCall.hpp
1 bool containsStr() {
2
3 }
4
5 bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
6         IRBuilder<> IRB(CI);
7         Function *fun = CI->getCalledFunction();
8         StringRef funName = fun->getName();
9         std::vector<Value *> parameters;
10
11         User::op_iterator begin = CI->arg_begin();
12         User::op_iterator end = CI->arg_end();
13         for (User::op_iterator it = begin; it != end; ++it) {
14                 Value *param = *it;
15                 parameters.push_back(param);
16         }
17
18         // the pointer to the address is always the first argument
19         Value *OrigPtr = parameters[0];
20         int Idx = getMemoryAccessFuncIndex(OrigPtr, DL);
21         if (Idx < 0)
22                 return false;
23
24         const unsigned ByteSize = 1U << Idx;
25         const unsigned BitSize = ByteSize * 8;
26         Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
27         Type *PtrTy = Ty->getPointerTo();
28
29         // atomic_init; args = {obj, order}
30         if (funName.contains("atomic_init")) {
31                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
32                 Value *val = IRB.CreateBitOrPointerCast(parameters[1], Ty);
33                 Value *args[] = {ptr, val};
34
35                 Instruction* funcInst=CallInst::Create(CDSAtomicInit[Idx], args,"");
36                 ReplaceInstWithInst(CI, funcInst);
37
38                 return true;
39         }
40
41         // atomic_load; args = {obj, order}
42         if (funName.contains("atomic_load")) {
43                 bool isExplicit = funName.contains("atomic_load_explicit");
44
45                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
46                 Value *order;
47                 if (isExplicit)
48                         order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
49                 else 
50                         order = ConstantInt::get(OrdTy, 
51                                                         (int) AtomicOrderingCABI::seq_cst);
52                 Value *args[] = {ptr, order};
53                 
54                 Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args,"");
55                 ReplaceInstWithInst(CI, funcInst);
56
57                 return true;
58         }
59
60         // atomic_store; args = {obj, val, order}
61         if (funName.contains("atomic_store")) {
62                 bool isExplicit = funName.contains("atomic_store_explicit");
63                 Value *OrigVal = parameters[1];
64
65                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
66                 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
67                 Value *order;
68                 if (isExplicit)
69                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
70                 else 
71                         order = ConstantInt::get(OrdTy, 
72                                                         (int) AtomicOrderingCABI::seq_cst);
73                 Value *args[] = {ptr, val, order};
74                 
75                 Instruction* funcInst=CallInst::Create(CDSAtomicStore[Idx], args,"");
76                 ReplaceInstWithInst(CI, funcInst);
77
78                 return true;
79         }
80
81         // atomic_fetch_*; args = {obj, val, order}
82         if (funName.contains("atomic_fetch_") || 
83                         funName.contains("atomic_exchange") ) {
84                 bool isExplicit = funName.contains("_explicit");
85                 Value *OrigVal = parameters[1];
86
87                 int op;
88                 if ( funName.contains("_fetch_add") )
89                         op = AtomicRMWInst::Add;
90                 else if ( funName.contains("_fetch_sub") )
91                         op = AtomicRMWInst::Sub;
92                 else if ( funName.contains("_fetch_and") )
93                         op = AtomicRMWInst::And;
94                 else if ( funName.contains("_fetch_or") )
95                         op = AtomicRMWInst::Or;
96                 else if ( funName.contains("_fetch_xor") )
97                         op = AtomicRMWInst::Xor;
98                 else if ( funName.contains("atomic_exchange") )
99                         op = AtomicRMWInst::Xchg;
100                 else {
101                         errs() << "Unknown atomic read modify write operation\n";
102                         return false;
103                 }
104
105                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
106                 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
107                 Value *order;
108                 if (isExplicit)
109                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
110                 else 
111                         order = ConstantInt::get(OrdTy, 
112                                                         (int) AtomicOrderingCABI::seq_cst);
113                 Value *args[] = {ptr, val, order};
114                 
115                 Instruction* funcInst=CallInst::Create(CDSAtomicRMW[op][Idx], args,"");
116                 ReplaceInstWithInst(CI, funcInst);
117
118                 return true;
119         }
120
121         /* atomic_compare_exchange_*; 
122            args = {obj, expected, new value, order1, order2}
123         */
124         if ( funName.contains("atomic_compare_exchange_") ) {
125                 bool isExplicit = funName.contains("_explicit");
126
127                 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
128                 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
129                 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
130
131                 Value *order_succ, *order_fail;
132                 if (isExplicit) {
133                         order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
134                         order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
135                 } else  {
136                         order_succ = ConstantInt::get(OrdTy, 
137                                                         (int) AtomicOrderingCABI::seq_cst);
138                         order_fail = ConstantInt::get(OrdTy, 
139                                                         (int) AtomicOrderingCABI::seq_cst);
140                 }
141
142                 Value *args[] = {Addr, CmpOperand, NewOperand, 
143                                                                         order_succ, order_fail};
144                 
145                 Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args,"");
146                 ReplaceInstWithInst(CI, funcInst);
147
148                 return true;
149         }
150
151         return false;
152 }