function that returns source line number
[c11llvm.git] / instrumentAtomicCall.hpp
1 bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
2         IRBuilder<> IRB(CI);
3         Function *fun = CI->getCalledFunction();
4         StringRef funName = fun->getName();
5         std::vector<Value *> parameters;
6
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) {
10                 Value *param = *it;
11                 parameters.push_back(param);
12         }
13
14         // obtain source line number of the CallInst
15         Value *position = getPosition(CI, IRB);
16
17         // the pointer to the address is always the first argument
18         Value *OrigPtr = parameters[0];
19         int Idx = getMemoryAccessFuncIndex(OrigPtr, DL);
20         if (Idx < 0)
21                 return false;
22
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();
27
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};
33
34                 Instruction* funcInst=CallInst::Create(CDSAtomicInit[Idx], args);
35                 ReplaceInstWithInst(CI, funcInst);
36
37                 return true;
38         }
39
40         // atomic_load; args = {obj, order}
41         if (funName.contains("atomic_load")) {
42                 bool isExplicit = funName.contains("atomic_load_explicit");
43
44                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
45                 Value *order;
46                 if (isExplicit)
47                         order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
48                 else 
49                         order = ConstantInt::get(OrdTy, 
50                                                         (int) AtomicOrderingCABI::seq_cst);
51                 Value *args[] = {ptr, order, position};
52                 
53                 Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args);
54                 ReplaceInstWithInst(CI, funcInst);
55
56                 return true;
57         }
58
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];
63
64                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
65                 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
66                 Value *order;
67                 if (isExplicit)
68                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
69                 else 
70                         order = ConstantInt::get(OrdTy, 
71                                                         (int) AtomicOrderingCABI::seq_cst);
72                 Value *args[] = {ptr, val, order, position};
73                 
74                 Instruction* funcInst=CallInst::Create(CDSAtomicStore[Idx], args);
75                 ReplaceInstWithInst(CI, funcInst);
76
77                 return true;
78         }
79
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];
85
86                 int op;
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;
99                 else {
100                         errs() << "Unknown atomic read modify write operation\n";
101                         return false;
102                 }
103
104                 Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
105                 Value *val = IRB.CreatePointerCast(OrigVal, Ty);
106                 Value *order;
107                 if (isExplicit)
108                         order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
109                 else 
110                         order = ConstantInt::get(OrdTy, 
111                                                         (int) AtomicOrderingCABI::seq_cst);
112                 Value *args[] = {ptr, val, order, position};
113                 
114                 Instruction* funcInst=CallInst::Create(CDSAtomicRMW[op][Idx], args);
115                 ReplaceInstWithInst(CI, funcInst);
116
117                 return true;
118         }
119
120         /* atomic_compare_exchange_*; 
121            args = {obj, expected, new value, order1, order2}
122         */
123         if ( funName.contains("atomic_compare_exchange_") ) {
124                 bool isExplicit = funName.contains("_explicit");
125
126                 Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
127                 Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
128                 Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
129
130                 Value *order_succ, *order_fail;
131                 if (isExplicit) {
132                         order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
133                         order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
134                 } else  {
135                         order_succ = ConstantInt::get(OrdTy, 
136                                                         (int) AtomicOrderingCABI::seq_cst);
137                         order_fail = ConstantInt::get(OrdTy, 
138                                                         (int) AtomicOrderingCABI::seq_cst);
139                 }
140
141                 Value *args[] = {Addr, CmpOperand, NewOperand, 
142                                                         order_succ, order_fail, position};
143                 
144                 Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args);
145                 ReplaceInstWithInst(CI, funcInst);
146
147                 return true;
148         }
149
150         return false;
151 }