clang: lib/CodeGen/ConstantInitBuilder.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

17

18using namespace clang;

20

22 assert(Data && "dereferencing null future");

23 if (const auto *C = dyn_cast<llvm::Constant *>(Data)) {

24 return C->getType();

25 } else {

27 }

28}

29

31 assert(Data && "abandoning null future");

32 if (auto *builder = dyn_cast<ConstantInitBuilderBase *>(Data)) {

33 builder->abandon(0);

34 }

35 Data = nullptr;

36}

37

39 assert(Data && "installing null future");

40 if (auto *C = dyn_cast<llvm::Constant *>(Data)) {

41 GV->setInitializer(C);

42 } else {

44 assert(builder.Buffer.size() == 1);

45 builder.setGlobalInitializer(GV, builder.Buffer[0]);

46 builder.Buffer.clear();

47 Data = nullptr;

48 }

49}

50

52ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {

53 assert(Buffer.empty() && "buffer not current empty");

54 Buffer.push_back(initializer);

56}

57

58

60 : Data(builder) {

61 assert(!builder->Frozen);

62 assert(builder->Buffer.size() == 1);

63 assert(builder->Buffer[0] != nullptr);

64}

65

66llvm::GlobalVariable *

67ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer,

68 const llvm::Twine &name,

70 bool constant,

71 llvm::GlobalValue::LinkageTypes linkage,

72 unsigned addressSpace) {

73 auto GV = new llvm::GlobalVariable(CGM.getModule(),

74 initializer->getType(),

75 constant,

76 linkage,

77 initializer,

78 name,

79 nullptr,

80 llvm::GlobalValue::NotThreadLocal,

81 addressSpace);

82 GV->setAlignment(alignment.getAsAlign());

83 resolveSelfReferences(GV);

84 return GV;

85}

86

87void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV,

88 llvm::Constant *initializer){

89 GV->setInitializer(initializer);

90

91 if (!SelfReferences.empty())

92 resolveSelfReferences(GV);

93}

94

95void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable *GV) {

96 for (auto &entry : SelfReferences) {

97 llvm::Constant *resolvedReference =

98 llvm::ConstantExpr::getInBoundsGetElementPtr(

99 GV->getValueType(), GV, entry.Indices);

100 auto dummy = entry.Dummy;

101 dummy->replaceAllUsesWith(resolvedReference);

102 dummy->eraseFromParent();

103 }

104 SelfReferences.clear();

105}

106

107void ConstantInitBuilderBase::abandon(size_t newEnd) {

108

109 Buffer.erase(Buffer.begin() + newEnd, Buffer.end());

110

111

112

113

114 if (newEnd == 0) {

115 for (auto &entry : SelfReferences) {

116 auto dummy = entry.Dummy;

117 dummy->replaceAllUsesWith(llvm::PoisonValue::get(dummy->getType()));

118 dummy->eraseFromParent();

119 }

120 SelfReferences.clear();

121 }

122}

123

127

128llvm::Constant *

129ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,

130 llvm::Constant *target) {

131 return getRelativeOffsetToPosition(offsetType, target,

132 Builder.Buffer.size() - Begin);

133}

134

135llvm::Constant *ConstantAggregateBuilderBase::getRelativeOffsetToPosition(

136 llvm::IntegerType *offsetType, llvm::Constant *target, size_t position) {

137

139

140

141 base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy);

142 target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy);

143 llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base);

144

145

146 if (Builder.CGM.IntPtrTy != offsetType) {

147 offset = llvm::ConstantExpr::getTrunc(offset, offsetType);

148 }

149

150 return offset;

151}

152

153llvm::Constant *

155 size_t position) {

156

157

158 auto dummy = new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,

159 llvm::GlobalVariable::PrivateLinkage,

160 nullptr, "");

161 Builder.SelfReferences.emplace_back(dummy);

162 auto &entry = Builder.SelfReferences.back();

163 getGEPIndicesTo(entry.Indices, position + Begin);

164 return dummy;

165}

166

167llvm::Constant *

169

170

171 auto dummy =

172 new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,

173 llvm::GlobalVariable::PrivateLinkage,

174 nullptr, "");

175 Builder.SelfReferences.emplace_back(dummy);

176 auto &entry = Builder.SelfReferences.back();

178 return dummy;

179}

180

181void ConstantAggregateBuilderBase::getGEPIndicesTo(

183 size_t position) const {

184

187

188

189 } else {

190 assert(indices.empty());

191 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));

192 }

193

194 assert(position >= Begin);

195

196

197 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty,

198 position - Begin));

199}

200

203

205

206

208

209

210 auto &layout = Builder.CGM.getDataLayout();

214

217

218 return position;

219}

220

221CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{

223 assert(cacheEnd <= end);

224

225

226 if (cacheEnd == end) {

228 }

229

230

231

233 if (cacheEnd < Begin) {

234 assert(cacheEnd == 0);

235 assert(Parent && "Begin != 0 for root builder");

236 cacheEnd = Begin;

237 offset = Parent->getOffsetFromGlobalTo(Begin);

238 } else {

240 }

241

242

243 if (cacheEnd != end) {

244 auto &layout = Builder.CGM.getDataLayout();

245 do {

246 llvm::Constant *element = Builder.Buffer[cacheEnd];

247 assert(element != nullptr &&

248 "cannot compute offset when a placeholder is present");

249 llvm::Type *elementType = element->getType();

254 } while (++cacheEnd != end);

255 }

256

257

260 return offset;

261}

262

265

267 assert((Begin < buffer.size() ||

268 (Begin == buffer.size() && eltTy))

269 && "didn't add any array elements without element type");

271 if (!eltTy) eltTy = elts[0]->getType();

272 auto type = llvm::ArrayType::get(eltTy, elts.size());

273 auto constant = llvm::ConstantArray::get(type, elts);

274 buffer.erase(buffer.begin() + Begin, buffer.end());

275 return constant;

276}

277

278llvm::Constant *

281

284

285 if (ty == nullptr && elts.empty())

286 ty = llvm::StructType::get(Builder.CGM.getLLVMContext(), {}, Packed);

287

288 llvm::Constant *constant;

289 if (ty) {

290 assert(ty->isPacked() == Packed);

291 constant = llvm::ConstantStruct::get(ty, elts);

292 } else {

293 constant = llvm::ConstantStruct::getAnon(elts, Packed);

294 }

295

296 buffer.erase(buffer.begin() + Begin, buffer.end());

297 return constant;

298}

299

300

301

305 if (!Schema || Builder.CGM.shouldSignPointer(Schema))

307

308 llvm::Constant *StorageAddress = nullptr;

311 }

312

313 llvm::Constant *SignedPointer = Builder.CGM.getConstantSignedPointer(

314 Pointer, Schema, StorageAddress, CalleeDecl, CalleeType);

315 add(SignedPointer);

316}

CharUnits - This is an opaque type for sizes expressed in character units.

llvm::Align getAsAlign() const

getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...

static CharUnits fromQuantity(QuantityType Quantity)

fromQuantity - Construct a CharUnits quantity from a raw integer type.

CharUnits alignTo(const CharUnits &Align) const

alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...

llvm::Module & getModule() const

An opaque class to hold the abstract position of a placeholder.

llvm::Constant * getAddrOfPosition(llvm::Type *type, size_t position)

Produce an address which points to a position in the aggregate being constructed.

Definition ConstantInitBuilder.cpp:154

CharUnits CachedOffsetFromGlobal

PlaceholderPosition addPlaceholder()

Add a placeholder value to the structure.

llvm::SmallVectorImpl< llvm::Constant * > & getBuffer()

void add(llvm::Constant *value)

Add a new value to this initializer.

llvm::Constant * finishArray(llvm::Type *eltTy)

Definition ConstantInitBuilder.cpp:263

PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType)

Add a placeholder, giving the expected type that will be filled in.

Definition ConstantInitBuilder.cpp:202

void addSize(CharUnits size)

Add an integer value of type size_t.

Definition ConstantInitBuilder.cpp:124

llvm::Constant * finishStruct(llvm::StructType *structTy)

Definition ConstantInitBuilder.cpp:279

llvm::Constant * getAddrOfCurrentPosition(llvm::Type *type)

Produce an address which will eventually point to the next position to be filled.

Definition ConstantInitBuilder.cpp:168

CharUnits getNextOffsetFromGlobal() const

Return the offset from the start of the initializer to the next position, assuming no padding is requ...

llvm::ArrayRef< llvm::Constant * > getGEPIndicesToCurrentPosition(llvm::SmallVectorImpl< llvm::Constant * > &indices)

size_t size() const

Return the number of elements that have been added to this struct or array.

void addSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, GlobalDecl CalleeDecl, QualType CalleeType)

Add a signed pointer using the given pointer authentication schema.

Definition ConstantInitBuilder.cpp:302

ConstantInitBuilderBase & Builder

ConstantAggregateBuilderBase * Parent

A convenience builder class for complex constant initializers, especially for anonymous global struct...

friend class ConstantInitFuture

A "future" for a completed constant initializer, which can be passed around independently of any sub-...

llvm::Type * getType() const

Return the type of the initializer.

Definition ConstantInitBuilder.cpp:21

void abandon()

Abandon this initializer.

Definition ConstantInitBuilder.cpp:30

void installInGlobal(llvm::GlobalVariable *global)

Install the initializer into a global variable.

Definition ConstantInitBuilder.cpp:38

GlobalDecl - represents a global declaration.

bool isAddressDiscriminated() const

A (possibly-)qualified type.

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

The JSON file list parser is used to communicate input to InstallAPI.

U cast(CodeGen::Address addr)