[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / lib / CodeGen / CGBuilder.h
blob2fcfea64ede667add1a4bcd52b989838ae472562
1 //===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
10 #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
12 #include "Address.h"
13 #include "CodeGenTypeCache.h"
14 #include "llvm/IR/DataLayout.h"
15 #include "llvm/IR/IRBuilder.h"
16 #include "llvm/IR/Type.h"
18 namespace clang {
19 namespace CodeGen {
21 class CodeGenFunction;
23 /// This is an IRBuilder insertion helper that forwards to
24 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
25 /// instructions.
26 class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
27 public:
28 CGBuilderInserter() = default;
29 explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
31 /// This forwards to CodeGenFunction::InsertHelper.
32 void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
33 llvm::BasicBlock *BB,
34 llvm::BasicBlock::iterator InsertPt) const override;
36 private:
37 CodeGenFunction *CGF = nullptr;
40 typedef CGBuilderInserter CGBuilderInserterTy;
42 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
43 CGBuilderBaseTy;
45 class CGBuilderTy : public CGBuilderBaseTy {
46 /// Storing a reference to the type cache here makes it a lot easier
47 /// to build natural-feeling, target-specific IR.
48 const CodeGenTypeCache &TypeCache;
50 public:
51 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
52 : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
53 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C,
54 const llvm::ConstantFolder &F,
55 const CGBuilderInserterTy &Inserter)
56 : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
57 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
58 : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
59 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
60 : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
62 llvm::ConstantInt *getSize(CharUnits N) {
63 return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
65 llvm::ConstantInt *getSize(uint64_t N) {
66 return llvm::ConstantInt::get(TypeCache.SizeTy, N);
69 // Note that we intentionally hide the CreateLoad APIs that don't
70 // take an alignment.
71 llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
72 return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
73 Addr.getAlignment().getAsAlign(), Name);
75 llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
76 // This overload is required to prevent string literals from
77 // ending up in the IsVolatile overload.
78 return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
79 Addr.getAlignment().getAsAlign(), Name);
81 llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
82 const llvm::Twine &Name = "") {
83 return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
84 Addr.getAlignment().getAsAlign(), IsVolatile,
85 Name);
88 using CGBuilderBaseTy::CreateAlignedLoad;
89 llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
90 CharUnits Align,
91 const llvm::Twine &Name = "") {
92 assert(llvm::cast<llvm::PointerType>(Addr->getType())
93 ->isOpaqueOrPointeeTypeMatches(Ty));
94 return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
97 // Note that we intentionally hide the CreateStore APIs that don't
98 // take an alignment.
99 llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
100 bool IsVolatile = false) {
101 return CreateAlignedStore(Val, Addr.getPointer(),
102 Addr.getAlignment().getAsAlign(), IsVolatile);
105 using CGBuilderBaseTy::CreateAlignedStore;
106 llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
107 CharUnits Align,
108 bool IsVolatile = false) {
109 return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
112 // FIXME: these "default-aligned" APIs should be removed,
113 // but I don't feel like fixing all the builtin code right now.
114 llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
115 llvm::Value *Addr,
116 bool IsVolatile = false) {
117 return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
120 /// Emit a load from an i1 flag variable.
121 llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
122 const llvm::Twine &Name = "") {
123 assert(llvm::cast<llvm::PointerType>(Addr->getType())
124 ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
125 return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
128 /// Emit a store to an i1 flag variable.
129 llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
130 assert(llvm::cast<llvm::PointerType>(Addr->getType())
131 ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
132 return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
135 // Temporarily use old signature; clang will be updated to an Address overload
136 // in a subsequent patch.
137 llvm::AtomicCmpXchgInst *
138 CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New,
139 llvm::AtomicOrdering SuccessOrdering,
140 llvm::AtomicOrdering FailureOrdering,
141 llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
142 return CGBuilderBaseTy::CreateAtomicCmpXchg(
143 Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering,
144 SSID);
147 // Temporarily use old signature; clang will be updated to an Address overload
148 // in a subsequent patch.
149 llvm::AtomicRMWInst *
150 CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr,
151 llvm::Value *Val, llvm::AtomicOrdering Ordering,
152 llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
153 return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(),
154 Ordering, SSID);
157 using CGBuilderBaseTy::CreateAddrSpaceCast;
158 Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
159 const llvm::Twine &Name = "") {
160 assert(cast<llvm::PointerType>(Ty)->isOpaqueOrPointeeTypeMatches(
161 Addr.getElementType()) &&
162 "Should not change the element type");
163 return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name));
166 /// Cast the element type of the given address to a different type,
167 /// preserving information like the alignment and address space.
168 Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
169 const llvm::Twine &Name = "") {
170 auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
171 return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name), Ty,
172 Addr.getAlignment());
175 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
176 Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
177 llvm::Type *ElementTy,
178 const llvm::Twine &Name = "") {
179 llvm::Value *Ptr =
180 CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
181 return Address(Ptr, ElementTy, Addr.getAlignment());
184 /// Given
185 /// %addr = {T1, T2...}* ...
186 /// produce
187 /// %name = getelementptr inbounds %addr, i32 0, i32 index
189 /// This API assumes that drilling into a struct like this is always an
190 /// inbounds operation.
191 using CGBuilderBaseTy::CreateStructGEP;
192 Address CreateStructGEP(Address Addr, unsigned Index,
193 const llvm::Twine &Name = "") {
194 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
195 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
196 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
197 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
199 return Address(
200 CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name),
201 ElTy->getElementType(Index),
202 Addr.getAlignment().alignmentAtOffset(Offset));
205 /// Given
206 /// %addr = [n x T]* ...
207 /// produce
208 /// %name = getelementptr inbounds %addr, i64 0, i64 index
209 /// where i64 is actually the target word size.
211 /// This API assumes that drilling into an array like this is always
212 /// an inbounds operation.
213 Address CreateConstArrayGEP(Address Addr, uint64_t Index,
214 const llvm::Twine &Name = "") {
215 llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
216 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
217 CharUnits EltSize =
218 CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
220 return Address(
221 CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
222 {getSize(CharUnits::Zero()), getSize(Index)}, Name),
223 ElTy->getElementType(),
224 Addr.getAlignment().alignmentAtOffset(Index * EltSize));
227 /// Given
228 /// %addr = T* ...
229 /// produce
230 /// %name = getelementptr inbounds %addr, i64 index
231 /// where i64 is actually the target word size.
232 Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
233 const llvm::Twine &Name = "") {
234 llvm::Type *ElTy = Addr.getElementType();
235 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
236 CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
238 return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
239 getSize(Index), Name),
240 ElTy,
241 Addr.getAlignment().alignmentAtOffset(Index * EltSize));
244 /// Given
245 /// %addr = T* ...
246 /// produce
247 /// %name = getelementptr inbounds %addr, i64 index
248 /// where i64 is actually the target word size.
249 Address CreateConstGEP(Address Addr, uint64_t Index,
250 const llvm::Twine &Name = "") {
251 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
252 CharUnits EltSize =
253 CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
255 return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
256 getSize(Index), Name),
257 Addr.getElementType(),
258 Addr.getAlignment().alignmentAtOffset(Index * EltSize));
261 /// Create GEP with single dynamic index. The address alignment is reduced
262 /// according to the element size.
263 using CGBuilderBaseTy::CreateGEP;
264 Address CreateGEP(Address Addr, llvm::Value *Index,
265 const llvm::Twine &Name = "") {
266 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
267 CharUnits EltSize =
268 CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
270 return Address(
271 CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name),
272 Addr.getElementType(),
273 Addr.getAlignment().alignmentOfArrayElement(EltSize));
276 /// Given a pointer to i8, adjust it by a given constant offset.
277 Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
278 const llvm::Twine &Name = "") {
279 assert(Addr.getElementType() == TypeCache.Int8Ty);
280 return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
281 getSize(Offset), Name),
282 Addr.getElementType(),
283 Addr.getAlignment().alignmentAtOffset(Offset));
285 Address CreateConstByteGEP(Address Addr, CharUnits Offset,
286 const llvm::Twine &Name = "") {
287 assert(Addr.getElementType() == TypeCache.Int8Ty);
288 return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
289 getSize(Offset), Name),
290 Addr.getElementType(),
291 Addr.getAlignment().alignmentAtOffset(Offset));
294 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
295 Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
296 const llvm::Twine &Name = "") {
297 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
299 auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
300 Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
301 llvm::APInt Offset(
302 DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
303 /*isSigned=*/true);
304 if (!GEP->accumulateConstantOffset(DL, Offset))
305 llvm_unreachable("offset of GEP with constants is always computable");
306 return Address(GEP, GEP->getResultElementType(),
307 Addr.getAlignment().alignmentAtOffset(
308 CharUnits::fromQuantity(Offset.getSExtValue())));
311 using CGBuilderBaseTy::CreateMemCpy;
312 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
313 bool IsVolatile = false) {
314 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
315 Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
316 IsVolatile);
318 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
319 bool IsVolatile = false) {
320 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
321 Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
322 IsVolatile);
325 using CGBuilderBaseTy::CreateMemCpyInline;
326 llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
327 return CreateMemCpyInline(
328 Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(),
329 Src.getAlignment().getAsAlign(), getInt64(Size));
332 using CGBuilderBaseTy::CreateMemMove;
333 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
334 bool IsVolatile = false) {
335 return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
336 Src.getPointer(), Src.getAlignment().getAsAlign(),
337 Size, IsVolatile);
340 using CGBuilderBaseTy::CreateMemSet;
341 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
342 llvm::Value *Size, bool IsVolatile = false) {
343 return CreateMemSet(Dest.getPointer(), Value, Size,
344 Dest.getAlignment().getAsAlign(), IsVolatile);
347 using CGBuilderBaseTy::CreateMemSetInline;
348 llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
349 uint64_t Size) {
350 return CreateMemSetInline(Dest.getPointer(),
351 Dest.getAlignment().getAsAlign(), Value,
352 getInt64(Size));
355 using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
356 Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
357 unsigned FieldIndex,
358 llvm::MDNode *DbgInfo) {
359 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
360 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
361 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
362 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
364 return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
365 Index, FieldIndex, DbgInfo),
366 ElTy->getElementType(Index),
367 Addr.getAlignment().alignmentAtOffset(Offset));
370 using CGBuilderBaseTy::CreateLaunderInvariantGroup;
371 Address CreateLaunderInvariantGroup(Address Addr) {
372 return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()));
376 } // end namespace CodeGen
377 } // end namespace clang
379 #endif