blob: e736e83a8c66e42ab3d6d7c36afee1eb8b7a6699 [file] [log] [blame]
Daniel Dunbarcb463852008-11-01 01:53:16 +00001//===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Daniel Dunbarcb463852008-11-01 01:53:16 +00006//
7//===----------------------------------------------------------------------===//
8
Benjamin Kramer2f5db8b2014-08-13 16:25:19 +00009#ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
10#define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
Daniel Dunbarcb463852008-11-01 01:53:16 +000011
John McCallf26e73d2016-03-11 04:30:43 +000012#include "llvm/IR/DataLayout.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000013#include "llvm/IR/IRBuilder.h"
John McCall7f416cc2015-09-08 08:05:57 +000014#include "Address.h"
15#include "CodeGenTypeCache.h"
Daniel Dunbarcb463852008-11-01 01:53:16 +000016
17namespace clang {
18namespace CodeGen {
John McCall1180f8e2010-07-03 09:25:20 +000019
Alexander Musman515ad8c2014-05-22 08:54:05 +000020class CodeGenFunction;
21
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000022/// This is an IRBuilder insertion helper that forwards to
Sanjay Patel4a96d7c2014-09-10 16:59:01 +000023/// CodeGenFunction::InsertHelper, which adds necessary metadata to
Alexander Musman515ad8c2014-05-22 08:54:05 +000024/// instructions.
Mehdi Amini557c20a2016-03-13 21:05:23 +000025class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter {
Alexander Musman515ad8c2014-05-22 08:54:05 +000026public:
David Blaikie01f42092015-08-12 23:16:55 +000027 CGBuilderInserter() = default;
Alexander Musman515ad8c2014-05-22 08:54:05 +000028 explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
29
30protected:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000031 /// This forwards to CodeGenFunction::InsertHelper.
Alexander Musman515ad8c2014-05-22 08:54:05 +000032 void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
33 llvm::BasicBlock *BB,
34 llvm::BasicBlock::iterator InsertPt) const;
35private:
David Blaikie01f42092015-08-12 23:16:55 +000036 CodeGenFunction *CGF = nullptr;
Alexander Musman515ad8c2014-05-22 08:54:05 +000037};
38
Mehdi Amini557c20a2016-03-13 21:05:23 +000039typedef CGBuilderInserter CGBuilderInserterTy;
John McCall7f416cc2015-09-08 08:05:57 +000040
Mehdi Amini557c20a2016-03-13 21:05:23 +000041typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
42 CGBuilderBaseTy;
John McCall7f416cc2015-09-08 08:05:57 +000043
44class CGBuilderTy : public CGBuilderBaseTy {
45 /// Storing a reference to the type cache here makes it a lot easier
46 /// to build natural-feeling, target-specific IR.
47 const CodeGenTypeCache &TypeCache;
48public:
49 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
50 : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
51 CGBuilderTy(const CodeGenTypeCache &TypeCache,
52 llvm::LLVMContext &C, const llvm::ConstantFolder &F,
53 const CGBuilderInserterTy &Inserter)
54 : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
55 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
56 : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
57 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
58 : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
59
60 llvm::ConstantInt *getSize(CharUnits N) {
61 return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
62 }
63 llvm::ConstantInt *getSize(uint64_t N) {
64 return llvm::ConstantInt::get(TypeCache.SizeTy, N);
65 }
66
67 // Note that we intentionally hide the CreateLoad APIs that don't
68 // take an alignment.
69 llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
70 return CreateAlignedLoad(Addr.getPointer(),
Guillaume Chatelet07c9d532020-01-27 10:37:01 +010071 Addr.getAlignment().getAsAlign(), Name);
John McCall7f416cc2015-09-08 08:05:57 +000072 }
73 llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
74 // This overload is required to prevent string literals from
75 // ending up in the IsVolatile overload.
76 return CreateAlignedLoad(Addr.getPointer(),
Guillaume Chatelet07c9d532020-01-27 10:37:01 +010077 Addr.getAlignment().getAsAlign(), Name);
John McCall7f416cc2015-09-08 08:05:57 +000078 }
79 llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
80 const llvm::Twine &Name = "") {
Guillaume Chatelet07c9d532020-01-27 10:37:01 +010081 return CreateAlignedLoad(
82 Addr.getPointer(), Addr.getAlignment().getAsAlign(), IsVolatile, Name);
John McCall7f416cc2015-09-08 08:05:57 +000083 }
84
85 using CGBuilderBaseTy::CreateAlignedLoad;
86 llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
87 const llvm::Twine &Name = "") {
Guillaume Chatelet07c9d532020-01-27 10:37:01 +010088 return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
John McCall7f416cc2015-09-08 08:05:57 +000089 }
90 llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
91 const char *Name) {
Guillaume Chatelet07c9d532020-01-27 10:37:01 +010092 return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
John McCall7f416cc2015-09-08 08:05:57 +000093 }
94 llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
95 CharUnits Align,
96 const llvm::Twine &Name = "") {
97 assert(Addr->getType()->getPointerElementType() == Ty);
Guillaume Chatelet07c9d532020-01-27 10:37:01 +010098 return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
John McCall7f416cc2015-09-08 08:05:57 +000099 }
John McCall7f416cc2015-09-08 08:05:57 +0000100
101 // Note that we intentionally hide the CreateStore APIs that don't
102 // take an alignment.
103 llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
104 bool IsVolatile = false) {
105 return CreateAlignedStore(Val, Addr.getPointer(),
Guillaume Chateletdbc5acf2019-12-12 15:32:19 +0100106 Addr.getAlignment().getAsAlign(), IsVolatile);
John McCall7f416cc2015-09-08 08:05:57 +0000107 }
108
109 using CGBuilderBaseTy::CreateAlignedStore;
110 llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
111 CharUnits Align, bool IsVolatile = false) {
Guillaume Chatelet59f95222020-01-23 16:18:34 +0100112 return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
John McCall7f416cc2015-09-08 08:05:57 +0000113 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000114
John McCall7f416cc2015-09-08 08:05:57 +0000115 // FIXME: these "default-aligned" APIs should be removed,
116 // but I don't feel like fixing all the builtin code right now.
John McCall7f416cc2015-09-08 08:05:57 +0000117 llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
118 llvm::Value *Addr,
119 bool IsVolatile = false) {
120 return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
121 }
122
123 /// Emit a load from an i1 flag variable.
124 llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
125 const llvm::Twine &Name = "") {
126 assert(Addr->getType()->getPointerElementType() == getInt1Ty());
127 return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
128 }
129
130 /// Emit a store to an i1 flag variable.
131 llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
132 assert(Addr->getType()->getPointerElementType() == getInt1Ty());
133 return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
134 }
135
136 using CGBuilderBaseTy::CreateBitCast;
137 Address CreateBitCast(Address Addr, llvm::Type *Ty,
138 const llvm::Twine &Name = "") {
139 return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
140 Addr.getAlignment());
141 }
142
Anastasia Stulova0a72ed42017-09-27 14:37:00 +0000143 using CGBuilderBaseTy::CreateAddrSpaceCast;
144 Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
145 const llvm::Twine &Name = "") {
146 return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name),
147 Addr.getAlignment());
148 }
149
John McCall7f416cc2015-09-08 08:05:57 +0000150 /// Cast the element type of the given address to a different type,
151 /// preserving information like the alignment and address space.
152 Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
153 const llvm::Twine &Name = "") {
154 auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
155 return CreateBitCast(Addr, PtrTy, Name);
156 }
157
158 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
159 Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
160 const llvm::Twine &Name = "") {
161 llvm::Value *Ptr =
162 CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
163 return Address(Ptr, Addr.getAlignment());
164 }
165
James Y Knight751fe282019-02-09 22:22:28 +0000166 /// Given
167 /// %addr = {T1, T2...}* ...
168 /// produce
169 /// %name = getelementptr inbounds %addr, i32 0, i32 index
170 ///
171 /// This API assumes that drilling into a struct like this is always an
172 /// inbounds operation.
John McCall7f416cc2015-09-08 08:05:57 +0000173 using CGBuilderBaseTy::CreateStructGEP;
James Y Knight751fe282019-02-09 22:22:28 +0000174 Address CreateStructGEP(Address Addr, unsigned Index,
John McCall7f416cc2015-09-08 08:05:57 +0000175 const llvm::Twine &Name = "") {
James Y Knightf5f1b0e2019-02-08 15:34:12 +0000176 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
177 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
James Y Knight751fe282019-02-09 22:22:28 +0000178 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
179 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
James Y Knightf5f1b0e2019-02-08 15:34:12 +0000180
John McCall7f416cc2015-09-08 08:05:57 +0000181 return Address(CreateStructGEP(Addr.getElementType(),
182 Addr.getPointer(), Index, Name),
183 Addr.getAlignment().alignmentAtOffset(Offset));
184 }
185
186 /// Given
187 /// %addr = [n x T]* ...
188 /// produce
189 /// %name = getelementptr inbounds %addr, i64 0, i64 index
190 /// where i64 is actually the target word size.
191 ///
192 /// This API assumes that drilling into an array like this is always
193 /// an inbounds operation.
James Y Knightf5f1b0e2019-02-08 15:34:12 +0000194 Address CreateConstArrayGEP(Address Addr, uint64_t Index,
195 const llvm::Twine &Name = "") {
196 llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
197 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
198 CharUnits EltSize =
199 CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
200
201 return Address(
202 CreateInBoundsGEP(Addr.getPointer(),
203 {getSize(CharUnits::Zero()), getSize(Index)}, Name),
204 Addr.getAlignment().alignmentAtOffset(Index * EltSize));
205 }
206
John McCall7f416cc2015-09-08 08:05:57 +0000207 /// Given
208 /// %addr = T* ...
209 /// produce
210 /// %name = getelementptr inbounds %addr, i64 index
211 /// where i64 is actually the target word size.
John McCall7f416cc2015-09-08 08:05:57 +0000212 Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
John McCall7f416cc2015-09-08 08:05:57 +0000213 const llvm::Twine &Name = "") {
James Y Knightf5f1b0e2019-02-08 15:34:12 +0000214 llvm::Type *ElTy = Addr.getElementType();
215 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
James Y Knight751fe282019-02-09 22:22:28 +0000216 CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
James Y Knightf5f1b0e2019-02-08 15:34:12 +0000217
John McCall7f416cc2015-09-08 08:05:57 +0000218 return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
John McCallf1044c02015-09-08 08:57:00 +0000219 getSize(Index), Name),
John McCall7f416cc2015-09-08 08:05:57 +0000220 Addr.getAlignment().alignmentAtOffset(Index * EltSize));
221 }
222
223 /// Given
224 /// %addr = T* ...
225 /// produce
226 /// %name = getelementptr inbounds %addr, i64 index
227 /// where i64 is actually the target word size.
James Y Knight751fe282019-02-09 22:22:28 +0000228 Address CreateConstGEP(Address Addr, uint64_t Index,
John McCall7f416cc2015-09-08 08:05:57 +0000229 const llvm::Twine &Name = "") {
James Y Knightf5f1b0e2019-02-08 15:34:12 +0000230 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
James Y Knight751fe282019-02-09 22:22:28 +0000231 CharUnits EltSize =
232 CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
233
John McCall7f416cc2015-09-08 08:05:57 +0000234 return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
John McCallf1044c02015-09-08 08:57:00 +0000235 getSize(Index), Name),
John McCall7f416cc2015-09-08 08:05:57 +0000236 Addr.getAlignment().alignmentAtOffset(Index * EltSize));
237 }
238
239 /// Given a pointer to i8, adjust it by a given constant offset.
240 Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
241 const llvm::Twine &Name = "") {
242 assert(Addr.getElementType() == TypeCache.Int8Ty);
243 return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name),
244 Addr.getAlignment().alignmentAtOffset(Offset));
245 }
246 Address CreateConstByteGEP(Address Addr, CharUnits Offset,
247 const llvm::Twine &Name = "") {
248 assert(Addr.getElementType() == TypeCache.Int8Ty);
249 return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
250 Addr.getAlignment().alignmentAtOffset(Offset));
251 }
252
JF Bastien9aab85a2018-07-13 20:33:23 +0000253 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
James Y Knight751fe282019-02-09 22:22:28 +0000254 Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
255 const llvm::Twine &Name = "") {
256 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
James Y Knightf5f1b0e2019-02-08 15:34:12 +0000257
JF Bastien9aab85a2018-07-13 20:33:23 +0000258 auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
259 Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
260 llvm::APInt Offset(
261 DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
Rui Ueyama49a3ad22019-07-16 04:46:31 +0000262 /*isSigned=*/true);
JF Bastien9aab85a2018-07-13 20:33:23 +0000263 if (!GEP->accumulateConstantOffset(DL, Offset))
264 llvm_unreachable("offset of GEP with constants is always computable");
265 return Address(GEP, Addr.getAlignment().alignmentAtOffset(
266 CharUnits::fromQuantity(Offset.getSExtValue())));
267 }
268
John McCall7f416cc2015-09-08 08:05:57 +0000269 using CGBuilderBaseTy::CreateMemCpy;
270 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
271 bool IsVolatile = false) {
Guillaume Chateletdbc5acf2019-12-12 15:32:19 +0100272 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
273 Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
274 IsVolatile);
John McCall7f416cc2015-09-08 08:05:57 +0000275 }
276 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
277 bool IsVolatile = false) {
Guillaume Chateletdbc5acf2019-12-12 15:32:19 +0100278 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
279 Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
280 IsVolatile);
John McCall7f416cc2015-09-08 08:05:57 +0000281 }
282
283 using CGBuilderBaseTy::CreateMemMove;
284 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
285 bool IsVolatile = false) {
Guillaume Chateletdbc5acf2019-12-12 15:32:19 +0100286 return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
287 Src.getPointer(), Src.getAlignment().getAsAlign(),
Daniel Neilsonc8bdc8d2018-01-28 17:27:45 +0000288 Size, IsVolatile);
John McCall7f416cc2015-09-08 08:05:57 +0000289 }
290
291 using CGBuilderBaseTy::CreateMemSet;
292 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
293 llvm::Value *Size, bool IsVolatile = false) {
294 return CreateMemSet(Dest.getPointer(), Value, Size,
Guillaume Chatelet1b2842b2019-12-09 17:36:50 +0100295 Dest.getAlignment().getAsAlign(), IsVolatile);
John McCall7f416cc2015-09-08 08:05:57 +0000296 }
Yonghong Song048493f2019-07-09 04:21:50 +0000297
298 using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
299 Address CreatePreserveStructAccessIndex(Address Addr,
300 unsigned Index,
301 unsigned FieldIndex,
302 llvm::MDNode *DbgInfo) {
303 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
304 const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
305 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
306 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
307
Craig Topper910718b2019-11-03 09:30:08 -0800308 return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
Yonghong Song048493f2019-07-09 04:21:50 +0000309 Index, FieldIndex, DbgInfo),
310 Addr.getAlignment().alignmentAtOffset(Offset));
311 }
John McCall7f416cc2015-09-08 08:05:57 +0000312};
313
Daniel Dunbarcb463852008-11-01 01:53:16 +0000314} // end namespace CodeGen
315} // end namespace clang
316
317#endif