12
12
13
13
#include " llvm/ADT/DenseMap.h"
14
14
#include " llvm/IR/DataLayout.h"
15
+ #include " llvm/IR/IRBuilder.h"
15
16
#include " llvm/IR/Instructions.h"
16
17
#include " llvm/IR/Intrinsics.h"
17
18
#include " llvm/IR/Module.h"
18
19
#include " llvm/IR/Operator.h"
19
20
#include " llvm/IR/RuntimeLibcalls.h"
20
21
21
22
namespace llvm {
23
+ class AtomicInfo ;
22
24
23
- template < typename IRBuilderTy> struct AtomicInfo {
24
-
25
- IRBuilderTy *Builder;
25
+ class AtomicInfo {
26
+ protected:
27
+ IRBuilderBase *Builder;
26
28
Type *Ty;
27
29
uint64_t AtomicSizeInBits;
28
30
uint64_t ValueSizeInBits;
29
- llvm:: Align AtomicAlign;
30
- llvm:: Align ValueAlign;
31
+ Align AtomicAlign;
32
+ Align ValueAlign;
31
33
bool UseLibcall;
32
34
33
35
public:
34
- AtomicInfo (IRBuilderTy *Builder, Type *Ty, uint64_t AtomicSizeInBits,
35
- uint64_t ValueSizeInBits, llvm:: Align AtomicAlign,
36
- llvm::Align ValueAlign, bool UseLibcall)
36
+ AtomicInfo (IRBuilderBase *Builder, Type *Ty, uint64_t AtomicSizeInBits,
37
+ uint64_t ValueSizeInBits, Align AtomicAlign, Align ValueAlign ,
38
+ bool UseLibcall)
37
39
: Builder(Builder), Ty(Ty), AtomicSizeInBits(AtomicSizeInBits),
38
40
ValueSizeInBits (ValueSizeInBits), AtomicAlign(AtomicAlign),
39
41
ValueAlign(ValueAlign), UseLibcall(UseLibcall) {}
40
42
41
43
virtual ~AtomicInfo () = default ;
42
44
43
- llvm:: Align getAtomicAlignment () const { return AtomicAlign; }
45
+ Align getAtomicAlignment () const { return AtomicAlign; }
44
46
uint64_t getAtomicSizeInBits () const { return AtomicSizeInBits; }
45
47
uint64_t getValueSizeInBits () const { return ValueSizeInBits; }
46
48
bool shouldUseLibcall () const { return UseLibcall; }
47
- llvm:: Type *getAtomicTy () const { return Ty; }
49
+ Type *getAtomicTy () const { return Ty; }
48
50
49
- virtual llvm:: Value *getAtomicPointer () const = 0;
51
+ virtual Value *getAtomicPointer () const = 0;
50
52
virtual void decorateWithTBAA (Instruction *I) = 0;
51
- virtual llvm::AllocaInst *CreateAlloca (llvm::Type *Ty,
52
- const llvm::Twine &Name) const = 0;
53
+ virtual AllocaInst *CreateAlloca (Type *Ty, const Twine &Name) const = 0;
53
54
54
55
/*
55
56
* Is the atomic size larger than the underlying value type?
@@ -62,90 +63,28 @@ template <typename IRBuilderTy> struct AtomicInfo {
62
63
63
64
LLVMContext &getLLVMContext () const { return Builder->getContext (); }
64
65
65
- static bool shouldCastToInt (llvm::Type *ValTy, bool CmpXchg) {
66
- if (ValTy->isFloatingPointTy ())
67
- return ValTy->isX86_FP80Ty () || CmpXchg;
68
- return !ValTy->isIntegerTy () && !ValTy->isPointerTy ();
69
- }
66
+ bool shouldCastToInt (Type *ValTy, bool CmpXchg);
70
67
71
- llvm::Value *EmitAtomicLoadOp (llvm::AtomicOrdering AO, bool IsVolatile,
72
- bool CmpXchg = false ) {
73
- Value *Ptr = getAtomicPointer ();
74
- Type *AtomicTy = Ty;
75
- if (shouldCastToInt (Ty, CmpXchg))
76
- AtomicTy = llvm::IntegerType::get (getLLVMContext (), AtomicSizeInBits);
77
- LoadInst *Load =
78
- Builder->CreateAlignedLoad (AtomicTy, Ptr, AtomicAlign, " atomic-load" );
79
- Load->setAtomic (AO);
80
- if (IsVolatile)
81
- Load->setVolatile (true );
82
- decorateWithTBAA (Load);
83
- return Load;
84
- }
68
+ Value *EmitAtomicLoadOp (AtomicOrdering AO, bool IsVolatile,
69
+ bool CmpXchg = false );
85
70
86
- static CallInst *EmitAtomicLibcall (IRBuilderTy *Builder, StringRef fnName,
87
- Type *ResultType, ArrayRef<Value *> Args) {
88
- LLVMContext &ctx = Builder->getContext ();
89
- SmallVector<Type *, 6 > ArgTys;
90
- for (Value *Arg : Args)
91
- ArgTys.push_back (Arg->getType ());
92
- FunctionType *FnType = FunctionType::get (ResultType, ArgTys, false );
93
- Module *M = Builder->GetInsertBlock ()->getModule ();
94
-
95
- // TODO: Use llvm::TargetLowering for Libcall ABI
96
- llvm::AttrBuilder fnAttrBuilder (ctx);
97
- fnAttrBuilder.addAttribute (llvm::Attribute::NoUnwind);
98
- fnAttrBuilder.addAttribute (llvm::Attribute::WillReturn);
99
- llvm::AttributeList fnAttrs = llvm::AttributeList::get (
100
- ctx, llvm::AttributeList::FunctionIndex, fnAttrBuilder);
101
- FunctionCallee LibcallFn = M->getOrInsertFunction (fnName, FnType, fnAttrs);
102
- CallInst *Call = Builder->CreateCall (LibcallFn, Args);
103
- return Call;
104
- }
71
+ CallInst *EmitAtomicLibcall (IRBuilderBase *Builder, StringRef fnName,
72
+ Type *ResultType, ArrayRef<Value *> Args);
105
73
106
- llvm:: Value *getAtomicSizeValue () const {
74
+ Value *getAtomicSizeValue () const {
107
75
LLVMContext &ctx = getLLVMContext ();
108
-
109
76
// TODO: Get from llvm::TargetMachine / clang::TargetInfo
110
- // if clang shares this codegen in future
77
+ // if clang shares this codegen in future
111
78
constexpr uint16_t SizeTBits = 64 ;
112
79
constexpr uint16_t BitsPerByte = 8 ;
113
- return llvm:: ConstantInt::get (llvm:: IntegerType::get (ctx, SizeTBits),
114
- AtomicSizeInBits / BitsPerByte);
80
+ return ConstantInt::get (IntegerType::get (ctx, SizeTBits),
81
+ AtomicSizeInBits / BitsPerByte);
115
82
}
116
83
117
- std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeLibcall (
118
- llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
119
- llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure) {
120
- LLVMContext &ctx = getLLVMContext ();
121
-
122
- // __atomic_compare_exchange's expected and desired are passed by pointers
123
- // FIXME: types
124
-
125
- // TODO: Get from llvm::TargetMachine / clang::TargetInfo
126
- // if clang shares this codegen in future
127
- constexpr uint64_t IntBits = 32 ;
128
-
129
- // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
130
- // void *desired, int success, int failure);
131
- llvm::Value *Args[6 ] = {
132
- getAtomicSizeValue (),
133
- getAtomicPointer (),
134
- ExpectedVal,
135
- DesiredVal,
136
- llvm::Constant::getIntegerValue (
137
- llvm::IntegerType::get (ctx, IntBits),
138
- llvm::APInt (IntBits, static_cast <uint64_t >(Success),
139
- /* signed=*/ true )),
140
- llvm::Constant::getIntegerValue (
141
- llvm::IntegerType::get (ctx, IntBits),
142
- llvm::APInt (IntBits, static_cast <uint64_t >(Failure),
143
- /* signed=*/ true )),
144
- };
145
- auto Result = EmitAtomicLibcall (Builder, " __atomic_compare_exchange" ,
146
- llvm::IntegerType::getInt1Ty (ctx), Args);
147
- return std::make_pair (ExpectedVal, Result);
148
- }
84
+ std::pair<Value *, Value *>
85
+ EmitAtomicCompareExchangeLibcall (Value *ExpectedVal, Value *DesiredVal,
86
+ AtomicOrdering Success,
87
+ AtomicOrdering Failure);
149
88
150
89
Value *castToAtomicIntPointer (Value *addr) const {
151
90
return addr; // opaque pointer
@@ -155,77 +94,17 @@ template <typename IRBuilderTy> struct AtomicInfo {
155
94
return castToAtomicIntPointer (getAtomicPointer ());
156
95
}
157
96
158
- std::pair<llvm::Value *, llvm::Value *>
159
- EmitAtomicCompareExchangeOp (llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
160
- llvm::AtomicOrdering Success,
161
- llvm::AtomicOrdering Failure,
162
- bool IsVolatile = false , bool IsWeak = false ) {
163
- // Do the atomic store.
164
- Value *Addr = getAtomicAddressAsAtomicIntPointer ();
165
- auto *Inst = Builder->CreateAtomicCmpXchg (Addr, ExpectedVal, DesiredVal,
166
- getAtomicAlignment (), Success,
167
- Failure, llvm::SyncScope::System);
168
- // Other decoration.
169
- Inst->setVolatile (IsVolatile);
170
- Inst->setWeak (IsWeak);
171
-
172
- auto *PreviousVal = Builder->CreateExtractValue (Inst, /* Idxs=*/ 0 );
173
- auto *SuccessFailureVal = Builder->CreateExtractValue (Inst, /* Idxs=*/ 1 );
174
- return std::make_pair (PreviousVal, SuccessFailureVal);
175
- }
97
+ std::pair<Value *, Value *>
98
+ EmitAtomicCompareExchangeOp (Value *ExpectedVal, Value *DesiredVal,
99
+ AtomicOrdering Success, AtomicOrdering Failure,
100
+ bool IsVolatile = false , bool IsWeak = false );
176
101
177
- std::pair<llvm::Value *, llvm::Value *>
178
- EmitAtomicCompareExchange (llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
179
- llvm::AtomicOrdering Success,
180
- llvm::AtomicOrdering Failure, bool IsVolatile,
181
- bool IsWeak) {
182
- if (shouldUseLibcall ())
183
- return EmitAtomicCompareExchangeLibcall (ExpectedVal, DesiredVal, Success,
184
- Failure);
185
-
186
- auto Res = EmitAtomicCompareExchangeOp (ExpectedVal, DesiredVal, Success,
187
- Failure, IsVolatile, IsWeak);
188
- return Res;
189
- }
102
+ std::pair<Value *, Value *>
103
+ EmitAtomicCompareExchange (Value *ExpectedVal, Value *DesiredVal,
104
+ AtomicOrdering Success, AtomicOrdering Failure,
105
+ bool IsVolatile, bool IsWeak);
190
106
191
- // void __atomic_load(size_t size, void *mem, void *return, int order);
192
- std::pair<llvm::LoadInst *, llvm::AllocaInst *>
193
- EmitAtomicLoadLibcall (llvm::AtomicOrdering AO) {
194
- LLVMContext &Ctx = getLLVMContext ();
195
- Type *SizedIntTy = Type::getIntNTy (Ctx, getAtomicSizeInBits ());
196
- Type *ResultTy;
197
- SmallVector<Value *, 6 > Args;
198
- AttributeList Attr;
199
- Module *M = Builder->GetInsertBlock ()->getModule ();
200
- const DataLayout &DL = M->getDataLayout ();
201
- Args.push_back (ConstantInt::get (DL.getIntPtrType (Ctx),
202
- this ->getAtomicSizeInBits () / 8 ));
203
-
204
- Value *PtrVal = getAtomicPointer ();
205
- PtrVal = Builder->CreateAddrSpaceCast (PtrVal, PointerType::getUnqual (Ctx));
206
- Args.push_back (PtrVal);
207
- AllocaInst *AllocaResult =
208
- CreateAlloca (Ty, getAtomicPointer ()->getName () + " atomic.temp.load" );
209
- const Align AllocaAlignment = DL.getPrefTypeAlign (SizedIntTy);
210
- AllocaResult->setAlignment (AllocaAlignment);
211
- Args.push_back (AllocaResult);
212
- Constant *OrderingVal =
213
- ConstantInt::get (Type::getInt32Ty (Ctx), (int )toCABI (AO));
214
- Args.push_back (OrderingVal);
215
-
216
- ResultTy = Type::getVoidTy (Ctx);
217
- SmallVector<Type *, 6 > ArgTys;
218
- for (Value *Arg : Args)
219
- ArgTys.push_back (Arg->getType ());
220
- FunctionType *FnType = FunctionType::get (ResultTy, ArgTys, false );
221
- FunctionCallee LibcallFn =
222
- M->getOrInsertFunction (" __atomic_load" , FnType, Attr);
223
- CallInst *Call = Builder->CreateCall (LibcallFn, Args);
224
- Call->setAttributes (Attr);
225
- return std::make_pair (
226
- Builder->CreateAlignedLoad (Ty, AllocaResult, AllocaAlignment),
227
- AllocaResult);
228
- }
107
+ std::pair<LoadInst *, AllocaInst *> EmitAtomicLoadLibcall (AtomicOrdering AO);
229
108
};
230
109
} // end namespace llvm
231
110
0 commit comments