clang 22.0.0git
CIRGenExprConstant.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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//===----------------------------------------------------------------------===//
8//
9// This contains code to emit Constant Expr nodes as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Address.h"
14#include "CIRGenCXXABI.h"
16#include "CIRGenModule.h"
17#include "CIRGenRecordLayout.h"
18#include "mlir/IR/Attributes.h"
19#include "mlir/IR/BuiltinAttributeInterfaces.h"
20#include "mlir/IR/BuiltinAttributes.h"
21#include "clang/AST/APValue.h"
23#include "clang/AST/Attr.h"
24#include "clang/AST/CharUnits.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/STLExtras.h"
34#include "llvm/Support/ErrorHandling.h"
35#include <functional>
36#include <iterator>
37
38using namespace clang;
39using namespace clang::CIRGen;
40
41//===----------------------------------------------------------------------===//
42// ConstantAggregateBuilder
43//===----------------------------------------------------------------------===//
44
45namespace {
46class ConstExprEmitter;
47
48static mlir::TypedAttr computePadding(CIRGenModule &cgm, CharUnits size) {
49 mlir::Type eltTy = cgm.uCharTy;
51 CIRGenBuilderTy &bld = cgm.getBuilder();
52 if (size > CharUnits::One()) {
53 SmallVector<mlir::Attribute> elts(arSize, cir::ZeroAttr::get(eltTy));
54 return bld.getConstArray(mlir::ArrayAttr::get(bld.getContext(), elts),
55 cir::ArrayType::get(eltTy, arSize));
56 }
57
58 return cir::ZeroAttr::get(eltTy);
59}
60
61static mlir::Attribute
62emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
63 mlir::Type commonElementType, unsigned arrayBound,
65 mlir::TypedAttr filler);
66
67struct ConstantAggregateBuilderUtils {
68 CIRGenModule &cgm;
69 cir::CIRDataLayout dataLayout;
70
71 ConstantAggregateBuilderUtils(CIRGenModule &cgm)
72 : cgm(cgm), dataLayout{cgm.getModule()} {}
73
74 CharUnits getAlignment(const mlir::TypedAttr c) const {
76 dataLayout.getAlignment(c.getType(), /*useABIAlign=*/true));
77 }
78
79 CharUnits getSize(mlir::Type ty) const {
80 return CharUnits::fromQuantity(dataLayout.getTypeAllocSize(ty));
81 }
82
83 CharUnits getSize(const mlir::TypedAttr c) const {
84 return getSize(c.getType());
85 }
86
87 mlir::TypedAttr getPadding(CharUnits size) const {
88 return computePadding(cgm, size);
89 }
90};
91
92/// Incremental builder for an mlir::TypedAttr holding a record or array
93/// constant.
94class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
95 struct Element {
96 Element(mlir::TypedAttr element, CharUnits offset)
97 : element(element), offset(offset) {}
98
99 mlir::TypedAttr element;
100 /// Describes the offset of `element` within the constant.
101 CharUnits offset;
102 };
103 /// The elements of the constant. The elements are kept in increasing offset
104 /// order, and we ensure that there is no overlap:
105 /// elements.offset[i+1] >= elements.offset[i] + getSize(elements.element[i])
106 ///
107 /// This may contain explicit padding elements (in order to create a
108 /// natural layout), but need not. Gaps between elements are implicitly
109 /// considered to be filled with undef.
110 llvm::SmallVector<Element, 32> elements;
111
112 /// The size of the constant (the maximum end offset of any added element).
113 /// May be larger than the end of elems.back() if we split the last element
114 /// and removed some trailing undefs.
115 CharUnits size = CharUnits::Zero();
116
117 /// This is true only if laying out elems in order as the elements of a
118 /// non-packed LLVM struct will give the correct layout.
119 bool naturalLayout = true;
120
121 bool split(size_t index, CharUnits hint);
122 std::optional<size_t> splitAt(CharUnits pos);
123
124 static mlir::Attribute buildFrom(CIRGenModule &cgm, ArrayRef<Element> elems,
125 CharUnits startOffset, CharUnits size,
126 bool naturalLayout, mlir::Type desiredTy,
127 bool allowOversized);
128
129public:
130 ConstantAggregateBuilder(CIRGenModule &cgm)
131 : ConstantAggregateBuilderUtils(cgm) {}
132
133 /// Update or overwrite the value starting at \p offset with \c c.
134 ///
135 /// \param allowOverwrite If \c true, this constant might overwrite (part of)
136 /// a constant that has already been added. This flag is only used to
137 /// detect bugs.
138 bool add(mlir::TypedAttr typedAttr, CharUnits offset, bool allowOverwrite);
139
140 /// Update or overwrite the bits starting at \p offsetInBits with \p bits.
141 bool addBits(llvm::APInt bits, uint64_t offsetInBits, bool allowOverwrite);
142
143 /// Attempt to condense the value starting at \p offset to a constant of type
144 /// \p desiredTy.
145 void condense(CharUnits offset, mlir::Type desiredTy);
146
147 /// Produce a constant representing the entire accumulated value, ideally of
148 /// the specified type. If \p allowOversized, the constant might be larger
149 /// than implied by \p desiredTy (eg, if there is a flexible array member).
150 /// Otherwise, the constant will be of exactly the same size as \p desiredTy
151 /// even if we can't represent it as that type.
152 mlir::Attribute build(mlir::Type desiredTy, bool allowOversized) const {
153 return buildFrom(cgm, elements, CharUnits::Zero(), size, naturalLayout,
154 desiredTy, allowOversized);
155 }
156};
157
158template <typename Container, typename Range = std::initializer_list<
159 typename Container::value_type>>
160static void replace(Container &c, size_t beginOff, size_t endOff, Range vals) {
161 assert(beginOff <= endOff && "invalid replacement range");
162 llvm::replace(c, c.begin() + beginOff, c.begin() + endOff, vals);
163}
164
165bool ConstantAggregateBuilder::add(mlir::TypedAttr typedAttr, CharUnits offset,
166 bool allowOverwrite) {
167 // Common case: appending to a layout.
168 if (offset >= size) {
169 CharUnits align = getAlignment(typedAttr);
170 CharUnits alignedSize = size.alignTo(align);
171 if (alignedSize > offset || offset.alignTo(align) != offset) {
172 naturalLayout = false;
173 } else if (alignedSize < offset) {
174 elements.emplace_back(getPadding(offset - size), size);
175 }
176 elements.emplace_back(typedAttr, offset);
177 size = offset + getSize(typedAttr);
178 return true;
179 }
180
181 // Uncommon case: constant overlaps what we've already created.
182 std::optional<size_t> firstElemToReplace = splitAt(offset);
183 if (!firstElemToReplace)
184 return false;
185
186 CharUnits cSize = getSize(typedAttr);
187 std::optional<size_t> lastElemToReplace = splitAt(offset + cSize);
188 if (!lastElemToReplace)
189 return false;
190
191 assert((firstElemToReplace == lastElemToReplace || allowOverwrite) &&
192 "unexpectedly overwriting field");
193
194 Element newElt(typedAttr, offset);
195 replace(elements, *firstElemToReplace, *lastElemToReplace, {newElt});
196 size = std::max(size, offset + cSize);
197 naturalLayout = false;
198 return true;
199}
200
201bool ConstantAggregateBuilder::addBits(llvm::APInt bits, uint64_t offsetInBits,
202 bool allowOverwrite) {
203 const ASTContext &astContext = cgm.getASTContext();
204 const uint64_t charWidth = astContext.getCharWidth();
205 mlir::Type charTy = cgm.getBuilder().getUIntNTy(charWidth);
206
207 // Offset of where we want the first bit to go within the bits of the
208 // current char.
209 unsigned offsetWithinChar = offsetInBits % charWidth;
210
211 // We split bit-fields up into individual bytes. Walk over the bytes and
212 // update them.
213 for (CharUnits offsetInChars =
214 astContext.toCharUnitsFromBits(offsetInBits - offsetWithinChar);
215 /**/; ++offsetInChars) {
216 // Number of bits we want to fill in this char.
217 unsigned wantedBits =
218 std::min((uint64_t)bits.getBitWidth(), charWidth - offsetWithinChar);
219
220 // Get a char containing the bits we want in the right places. The other
221 // bits have unspecified values.
222 llvm::APInt bitsThisChar = bits;
223 if (bitsThisChar.getBitWidth() < charWidth)
224 bitsThisChar = bitsThisChar.zext(charWidth);
225 if (cgm.getDataLayout().isBigEndian()) {
226 // Figure out how much to shift by. We may need to left-shift if we have
227 // less than one byte of Bits left.
228 int shift = bits.getBitWidth() - charWidth + offsetWithinChar;
229 if (shift > 0)
230 bitsThisChar.lshrInPlace(shift);
231 else if (shift < 0)
232 bitsThisChar = bitsThisChar.shl(-shift);
233 } else {
234 bitsThisChar = bitsThisChar.shl(offsetWithinChar);
235 }
236 if (bitsThisChar.getBitWidth() > charWidth)
237 bitsThisChar = bitsThisChar.trunc(charWidth);
238
239 if (wantedBits == charWidth) {
240 // Got a full byte: just add it directly.
241 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,
242 allowOverwrite);
243 } else {
244 // Partial byte: update the existing integer if there is one. If we
245 // can't split out a 1-CharUnit range to update, then we can't add
246 // these bits and fail the entire constant emission.
247 std::optional<size_t> firstElemToUpdate = splitAt(offsetInChars);
248 if (!firstElemToUpdate)
249 return false;
250 std::optional<size_t> lastElemToUpdate =
251 splitAt(offsetInChars + CharUnits::One());
252 if (!lastElemToUpdate)
253 return false;
254 assert(*lastElemToUpdate - *firstElemToUpdate < 2 &&
255 "should have at most one element covering one byte");
256
257 // Figure out which bits we want and discard the rest.
258 llvm::APInt updateMask(charWidth, 0);
259 if (cgm.getDataLayout().isBigEndian())
260 updateMask.setBits(charWidth - offsetWithinChar - wantedBits,
261 charWidth - offsetWithinChar);
262 else
263 updateMask.setBits(offsetWithinChar, offsetWithinChar + wantedBits);
264 bitsThisChar &= updateMask;
265 bool isNull = false;
266 if (*firstElemToUpdate < elements.size()) {
267 auto firstEltToUpdate =
268 mlir::dyn_cast<cir::IntAttr>(elements[*firstElemToUpdate].element);
269 isNull = firstEltToUpdate && firstEltToUpdate.isNullValue();
270 }
271
272 if (*firstElemToUpdate == *lastElemToUpdate || isNull) {
273 // All existing bits are either zero or undef.
274 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,
275 /*allowOverwrite*/ true);
276 } else {
277 cir::IntAttr ci =
278 mlir::dyn_cast<cir::IntAttr>(elements[*firstElemToUpdate].element);
279 // In order to perform a partial update, we need the existing bitwise
280 // value, which we can only extract for a constant int.
281 if (!ci)
282 return false;
283 // Because this is a 1-CharUnit range, the constant occupying it must
284 // be exactly one CharUnit wide.
285 assert(ci.getBitWidth() == charWidth && "splitAt failed");
286 assert((!(ci.getValue() & updateMask) || allowOverwrite) &&
287 "unexpectedly overwriting bitfield");
288 bitsThisChar |= (ci.getValue() & ~updateMask);
289 elements[*firstElemToUpdate].element =
290 cir::IntAttr::get(charTy, bitsThisChar);
291 }
292 }
293
294 // Stop if we've added all the bits.
295 if (wantedBits == bits.getBitWidth())
296 break;
297
298 // Remove the consumed bits from Bits.
299 if (!cgm.getDataLayout().isBigEndian())
300 bits.lshrInPlace(wantedBits);
301 bits = bits.trunc(bits.getBitWidth() - wantedBits);
302
303 // The remaining bits go at the start of the following bytes.
304 offsetWithinChar = 0;
305 }
306
307 return true;
308}
309
310/// Returns a position within elements such that all elements
311/// before the returned index end before pos and all elements at or after
312/// the returned index begin at or after pos. Splits elements as necessary
313/// to ensure this. Returns std::nullopt if we find something we can't split.
314std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits pos) {
315 if (pos >= size)
316 return elements.size();
317
318 while (true) {
319 // Find the first element that starts after pos.
320 Element *iter =
321 llvm::upper_bound(elements, pos, [](CharUnits pos, const Element &elt) {
322 return pos < elt.offset;
323 });
324
325 if (iter == elements.begin())
326 return 0;
327
328 size_t index = iter - elements.begin() - 1;
329 const Element &elt = elements[index];
330
331 // If we already have an element starting at pos, we're done.
332 if (elt.offset == pos)
333 return index;
334
335 // Check for overlap with the element that starts before pos.
336 CharUnits eltEnd = elt.offset + getSize(elt.element);
337 if (eltEnd <= pos)
338 return index + 1;
339
340 // Try to decompose it into smaller constants.
341 if (!split(index, pos))
342 return std::nullopt;
343 }
344}
345
346/// Split the constant at index, if possible. Return true if we did.
347/// Hint indicates the location at which we'd like to split, but may be
348/// ignored.
349bool ConstantAggregateBuilder::split(size_t index, CharUnits hint) {
350 cgm.errorNYI("split constant at index");
351 return false;
352}
353
354void ConstantAggregateBuilder::condense(CharUnits offset,
355 mlir::Type desiredTy) {
356 CharUnits desiredSize = getSize(desiredTy);
357
358 std::optional<size_t> firstElemToReplace = splitAt(offset);
359 if (!firstElemToReplace)
360 return;
361 size_t first = *firstElemToReplace;
362
363 std::optional<size_t> lastElemToReplace = splitAt(offset + desiredSize);
364 if (!lastElemToReplace)
365 return;
366 size_t last = *lastElemToReplace;
367
368 size_t length = last - first;
369 if (length == 0)
370 return;
371
372 if (length == 1 && elements[first].offset == offset &&
373 getSize(elements[first].element) == desiredSize) {
374 cgm.errorNYI("re-wrapping single element records");
375 return;
376 }
377
378 // Build a new constant from the elements in the range.
379 SmallVector<Element> subElems(elements.begin() + first,
380 elements.begin() + last);
381 mlir::Attribute replacement =
382 buildFrom(cgm, subElems, offset, desiredSize,
383 /*naturalLayout=*/false, desiredTy, false);
384
385 // Replace the range with the condensed constant.
386 Element newElt(mlir::cast<mlir::TypedAttr>(replacement), offset);
387 replace(elements, first, last, {newElt});
388}
389
390mlir::Attribute
391ConstantAggregateBuilder::buildFrom(CIRGenModule &cgm, ArrayRef<Element> elems,
392 CharUnits startOffset, CharUnits size,
393 bool naturalLayout, mlir::Type desiredTy,
394 bool allowOversized) {
395 ConstantAggregateBuilderUtils utils(cgm);
396
397 if (elems.empty())
398 return cir::UndefAttr::get(desiredTy);
399
400 // If we want an array type, see if all the elements are the same type and
401 // appropriately spaced.
402 if (mlir::isa<cir::ArrayType>(desiredTy)) {
403 cgm.errorNYI("array aggregate constants");
404 return {};
405 }
406
407 // The size of the constant we plan to generate. This is usually just the size
408 // of the initialized type, but in AllowOversized mode (i.e. flexible array
409 // init), it can be larger.
410 CharUnits desiredSize = utils.getSize(desiredTy);
411 if (size > desiredSize) {
412 assert(allowOversized && "elems are oversized");
413 desiredSize = size;
414 }
415
416 // The natural alignment of an unpacked CIR record with the given elements.
417 CharUnits align = CharUnits::One();
418 for (auto [e, offset] : elems)
419 align = std::max(align, utils.getAlignment(e));
420
421 // The natural size of an unpacked LLVM struct with the given elements.
422 CharUnits alignedSize = size.alignTo(align);
423
424 bool packed = false;
425 bool padded = false;
426
427 llvm::SmallVector<mlir::Attribute, 32> unpackedElems;
428 if (desiredSize < alignedSize || desiredSize.alignTo(align) != desiredSize) {
429 naturalLayout = false;
430 packed = true;
431 } else {
432 // The natural layout would be too small. Add padding to fix it. (This
433 // is ignored if we choose a packed layout.)
434 unpackedElems.reserve(elems.size() + 1);
435 llvm::transform(elems, std::back_inserter(unpackedElems),
436 std::mem_fn(&Element::element));
437 if (desiredSize > alignedSize)
438 unpackedElems.push_back(utils.getPadding(desiredSize - size));
439 }
440
441 // If we don't have a natural layout, insert padding as necessary.
442 // As we go, double-check to see if we can actually just emit Elems
443 // as a non-packed record and do so opportunistically if possible.
444 llvm::SmallVector<mlir::Attribute, 32> packedElems;
445 packedElems.reserve(elems.size());
446 if (!naturalLayout) {
447 CharUnits sizeSoFar = CharUnits::Zero();
448 for (auto [element, offset] : elems) {
449 CharUnits align = utils.getAlignment(element);
450 CharUnits naturalOffset = sizeSoFar.alignTo(align);
451 CharUnits desiredOffset = offset - startOffset;
452 assert(desiredOffset >= sizeSoFar && "elements out of order");
453
454 if (desiredOffset != naturalOffset)
455 packed = true;
456 if (desiredOffset != sizeSoFar)
457 packedElems.push_back(utils.getPadding(desiredOffset - sizeSoFar));
458 packedElems.push_back(element);
459 sizeSoFar = desiredOffset + utils.getSize(element);
460 }
461 // If we're using the packed layout, pad it out to the desired size if
462 // necessary.
463 if (packed) {
464 assert(sizeSoFar <= desiredSize &&
465 "requested size is too small for contents");
466
467 if (sizeSoFar < desiredSize)
468 packedElems.push_back(utils.getPadding(desiredSize - sizeSoFar));
469 }
470 }
471
472 CIRGenBuilderTy &builder = cgm.getBuilder();
473 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(),
474 packed ? packedElems : unpackedElems);
475
476 cir::RecordType recordType = builder.getCompleteRecordType(arrAttr, packed);
477 if (auto desired = mlir::dyn_cast<cir::RecordType>(desiredTy))
478 if (desired.isLayoutIdentical(recordType))
479 recordType = desired;
480
481 return builder.getConstRecordOrZeroAttr(arrAttr, packed, padded, recordType);
482}
483
484//===----------------------------------------------------------------------===//
485// ConstRecordBuilder
486//===----------------------------------------------------------------------===//
487
488class ConstRecordBuilder {
489 CIRGenModule &cgm;
490 ConstantEmitter &emitter;
491 ConstantAggregateBuilder &builder;
492 CharUnits startOffset;
493
494public:
495 static mlir::Attribute buildRecord(ConstantEmitter &emitter,
496 InitListExpr *ile, QualType valTy);
497 static mlir::Attribute buildRecord(ConstantEmitter &emitter,
498 const APValue &value, QualType valTy);
499 static bool updateRecord(ConstantEmitter &emitter,
500 ConstantAggregateBuilder &constant, CharUnits offset,
501 InitListExpr *updater);
502
503private:
504 ConstRecordBuilder(ConstantEmitter &emitter,
505 ConstantAggregateBuilder &builder, CharUnits startOffset)
506 : cgm(emitter.cgm), emitter(emitter), builder(builder),
507 startOffset(startOffset) {}
508
509 bool appendField(const FieldDecl *field, uint64_t fieldOffset,
510 mlir::TypedAttr initCst, bool allowOverwrite = false);
511
512 bool appendBytes(CharUnits fieldOffsetInChars, mlir::TypedAttr initCst,
513 bool allowOverwrite = false);
514
515 bool appendBitField(const FieldDecl *field, uint64_t fieldOffset,
516 cir::IntAttr ci, bool allowOverwrite = false);
517
518 /// Applies zero-initialization to padding bytes before and within a field.
519 /// \param layout The record layout containing field offset information.
520 /// \param fieldNo The field index in the record.
521 /// \param field The field declaration.
522 /// \param allowOverwrite Whether to allow overwriting existing values.
523 /// \param sizeSoFar The current size processed, updated by this function.
524 /// \param zeroFieldSize Set to true if the field has zero size.
525 /// \returns true on success, false if padding could not be applied.
526 bool applyZeroInitPadding(const ASTRecordLayout &layout, unsigned fieldNo,
527 const FieldDecl &field, bool allowOverwrite,
528 CharUnits &sizeSoFar, bool &zeroFieldSize);
529
530 /// Applies zero-initialization to trailing padding bytes in a record.
531 /// \param layout The record layout containing size information.
532 /// \param allowOverwrite Whether to allow overwriting existing values.
533 /// \param sizeSoFar The current size processed.
534 /// \returns true on success, false if padding could not be applied.
535 bool applyZeroInitPadding(const ASTRecordLayout &layout, bool allowOverwrite,
536 CharUnits &sizeSoFar);
537
538 bool build(InitListExpr *ile, bool allowOverwrite);
539 bool build(const APValue &val, const RecordDecl *rd, bool isPrimaryBase,
540 const CXXRecordDecl *vTableClass, CharUnits baseOffset);
541
542 mlir::Attribute finalize(QualType ty);
543};
544
545bool ConstRecordBuilder::appendField(const FieldDecl *field,
546 uint64_t fieldOffset,
547 mlir::TypedAttr initCst,
548 bool allowOverwrite) {
549 const ASTContext &astContext = cgm.getASTContext();
550
551 CharUnits fieldOffsetInChars = astContext.toCharUnitsFromBits(fieldOffset);
552
553 return appendBytes(fieldOffsetInChars, initCst, allowOverwrite);
554}
555
556bool ConstRecordBuilder::appendBytes(CharUnits fieldOffsetInChars,
557 mlir::TypedAttr initCst,
558 bool allowOverwrite) {
559 return builder.add(initCst, startOffset + fieldOffsetInChars, allowOverwrite);
560}
561
562bool ConstRecordBuilder::appendBitField(const FieldDecl *field,
563 uint64_t fieldOffset, cir::IntAttr ci,
564 bool allowOverwrite) {
565 const CIRGenRecordLayout &rl =
567 const CIRGenBitFieldInfo &info = rl.getBitFieldInfo(field);
568 llvm::APInt fieldValue = ci.getValue();
569
570 // Promote the size of FieldValue if necessary
571 // FIXME: This should never occur, but currently it can because initializer
572 // constants are cast to bool, and because clang is not enforcing bitfield
573 // width limits.
574 if (info.size > fieldValue.getBitWidth())
575 fieldValue = fieldValue.zext(info.size);
576
577 // Truncate the size of FieldValue to the bit field size.
578 if (info.size < fieldValue.getBitWidth())
579 fieldValue = fieldValue.trunc(info.size);
580
581 return builder.addBits(fieldValue,
582 cgm.getASTContext().toBits(startOffset) + fieldOffset,
583 allowOverwrite);
584}
585
586bool ConstRecordBuilder::applyZeroInitPadding(
587 const ASTRecordLayout &layout, unsigned fieldNo, const FieldDecl &field,
588 bool allowOverwrite, CharUnits &sizeSoFar, bool &zeroFieldSize) {
589 uint64_t startBitOffset = layout.getFieldOffset(fieldNo);
590 CharUnits startOffset =
591 cgm.getASTContext().toCharUnitsFromBits(startBitOffset);
592 if (sizeSoFar < startOffset) {
593 if (!appendBytes(sizeSoFar, computePadding(cgm, startOffset - sizeSoFar),
594 allowOverwrite))
595 return false;
596 }
597
598 if (!field.isBitField()) {
599 CharUnits fieldSize =
601 sizeSoFar = startOffset + fieldSize;
602 zeroFieldSize = fieldSize.isZero();
603 } else {
604 const CIRGenRecordLayout &rl =
606 const CIRGenBitFieldInfo &info = rl.getBitFieldInfo(&field);
607 uint64_t endBitOffset = startBitOffset + info.size;
608 sizeSoFar = cgm.getASTContext().toCharUnitsFromBits(endBitOffset);
609 if (endBitOffset % cgm.getASTContext().getCharWidth() != 0)
610 sizeSoFar++;
611 zeroFieldSize = info.size == 0;
612 }
613 return true;
614}
615
616bool ConstRecordBuilder::applyZeroInitPadding(const ASTRecordLayout &layout,
617 bool allowOverwrite,
618 CharUnits &sizeSoFar) {
619 CharUnits totalSize = layout.getSize();
620 if (sizeSoFar < totalSize) {
621 if (!appendBytes(sizeSoFar, computePadding(cgm, totalSize - sizeSoFar),
622 allowOverwrite))
623 return false;
624 }
625 sizeSoFar = totalSize;
626 return true;
627}
628
629bool ConstRecordBuilder::build(InitListExpr *ile, bool allowOverwrite) {
630 RecordDecl *rd = ile->getType()->castAsRecordDecl();
631 const ASTRecordLayout &layout = cgm.getASTContext().getASTRecordLayout(rd);
632
633 // Bail out if we have base classes. We could support these, but they only
634 // arise in C++1z where we will have already constant folded most interesting
635 // cases. FIXME: There are still a few more cases we can handle this way.
636 if (auto *cxxrd = dyn_cast<CXXRecordDecl>(rd))
637 if (cxxrd->getNumBases())
638 return false;
639
640 const bool zeroInitPadding = cgm.shouldZeroInitPadding();
641 bool zeroFieldSize = false;
642 CharUnits sizeSoFar = CharUnits::Zero();
643
644 unsigned elementNo = 0;
645 for (auto [index, field] : llvm::enumerate(rd->fields())) {
646
647 // If this is a union, skip all the fields that aren't being initialized.
648 if (rd->isUnion() &&
650 continue;
651
652 // Don't emit anonymous bitfields.
653 if (field->isUnnamedBitField())
654 continue;
655
656 // Get the initializer. A record can include fields without initializers,
657 // we just use explicit null values for them.
658 Expr *init = nullptr;
659 if (elementNo < ile->getNumInits())
660 init = ile->getInit(elementNo++);
661 if (isa_and_nonnull<NoInitExpr>(init))
662 continue;
663
664 // Zero-sized fields are not emitted, but their initializers may still
665 // prevent emission of this record as a constant.
666 if (field->isZeroSize(cgm.getASTContext())) {
667 if (init->HasSideEffects(cgm.getASTContext()))
668 return false;
669 continue;
670 }
671
672 if (zeroInitPadding &&
673 !applyZeroInitPadding(layout, index, *field, allowOverwrite, sizeSoFar,
674 zeroFieldSize))
675 return false;
676
677 // When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
678 // represents additional overwriting of our current constant value, and not
679 // a new constant to emit independently.
680 if (allowOverwrite &&
681 (field->getType()->isArrayType() || field->getType()->isRecordType())) {
682 cgm.errorNYI(field->getSourceRange(), "designated init lists");
683 return false;
684 }
685
686 mlir::Attribute eltInitAttr =
687 init ? emitter.tryEmitPrivateForMemory(init, field->getType())
688 : emitter.emitNullForMemory(cgm.getLoc(ile->getSourceRange()),
689 field->getType());
690 if (!eltInitAttr)
691 return false;
692
693 mlir::TypedAttr eltInit = mlir::cast<mlir::TypedAttr>(eltInitAttr);
694 if (!field->isBitField()) {
695 // Handle non-bitfield members.
696 if (!appendField(field, layout.getFieldOffset(index), eltInit,
697 allowOverwrite))
698 return false;
699 // After emitting a non-empty field with [[no_unique_address]], we may
700 // need to overwrite its tail padding.
701 if (field->hasAttr<NoUniqueAddressAttr>())
702 allowOverwrite = true;
703 } else {
704 // Otherwise we have a bitfield.
705 if (auto constInt = dyn_cast<cir::IntAttr>(eltInit)) {
706 if (!appendBitField(field, layout.getFieldOffset(index), constInt,
707 allowOverwrite))
708 return false;
709 } else {
710 // We are trying to initialize a bitfield with a non-trivial constant,
711 // this must require run-time code.
712 return false;
713 }
714 }
715 }
716
717 return !zeroInitPadding ||
718 applyZeroInitPadding(layout, allowOverwrite, sizeSoFar);
719}
720
721namespace {
722struct BaseInfo {
723 BaseInfo(const CXXRecordDecl *decl, CharUnits offset, unsigned index)
724 : decl(decl), offset(offset), index(index) {}
725
726 const CXXRecordDecl *decl;
727 CharUnits offset;
728 unsigned index;
729
730 bool operator<(const BaseInfo &o) const { return offset < o.offset; }
731};
732} // namespace
733
734bool ConstRecordBuilder::build(const APValue &val, const RecordDecl *rd,
735 bool isPrimaryBase,
736 const CXXRecordDecl *vTableClass,
737 CharUnits offset) {
738 const ASTRecordLayout &layout = cgm.getASTContext().getASTRecordLayout(rd);
739 if (const CXXRecordDecl *cd = dyn_cast<CXXRecordDecl>(rd)) {
740 // Add a vtable pointer, if we need one and it hasn't already been added.
741 if (layout.hasOwnVFPtr()) {
742 CIRGenBuilderTy &builder = cgm.getBuilder();
743 cir::GlobalOp vtable =
744 cgm.getCXXABI().getAddrOfVTable(vTableClass, CharUnits());
745 clang::VTableLayout::AddressPointLocation addressPoint =
747 .getVTableLayout(vTableClass)
748 .getAddressPoint(BaseSubobject(cd, offset));
750 mlir::ArrayAttr indices = builder.getArrayAttr({
751 builder.getI32IntegerAttr(addressPoint.VTableIndex),
752 builder.getI32IntegerAttr(addressPoint.AddressPointIndex),
753 });
754 cir::GlobalViewAttr vtableInit =
755 cgm.getBuilder().getGlobalViewAttr(vtable, indices);
756 if (!appendBytes(offset, vtableInit))
757 return false;
758 }
759
760 // Accumulate and sort bases, in order to visit them in address order, which
761 // may not be the same as declaration order.
762 SmallVector<BaseInfo> bases;
763 bases.reserve(cd->getNumBases());
764 for (auto [index, base] : llvm::enumerate(cd->bases())) {
765 assert(!base.isVirtual() && "should not have virtual bases here");
766 const CXXRecordDecl *bd = base.getType()->getAsCXXRecordDecl();
767 CharUnits baseOffset = layout.getBaseClassOffset(bd);
768 bases.push_back(BaseInfo(bd, baseOffset, index));
769 }
770#ifdef EXPENSIVE_CHECKS
771 assert(llvm::is_sorted(bases) && "bases not sorted by offset");
772#endif
773
774 for (BaseInfo &base : bases) {
775 bool isPrimaryBase = layout.getPrimaryBase() == base.decl;
776 build(val.getStructBase(base.index), base.decl, isPrimaryBase,
777 vTableClass, offset + base.offset);
778 }
779 }
780
781 uint64_t offsetBits = cgm.getASTContext().toBits(offset);
782
783 bool allowOverwrite = false;
784 for (auto [index, field] : llvm::enumerate(rd->fields())) {
785 // If this is a union, skip all the fields that aren't being initialized.
786 if (rd->isUnion() && !declaresSameEntity(val.getUnionField(), field))
787 continue;
788
789 // Don't emit anonymous bitfields or zero-sized fields.
790 if (field->isUnnamedBitField() || field->isZeroSize(cgm.getASTContext()))
791 continue;
792
793 // Emit the value of the initializer.
794 const APValue &fieldValue =
795 rd->isUnion() ? val.getUnionValue() : val.getStructField(index);
796 mlir::TypedAttr eltInit = mlir::cast<mlir::TypedAttr>(
797 emitter.tryEmitPrivateForMemory(fieldValue, field->getType()));
798 if (!eltInit)
799 return false;
800
801 if (!field->isBitField()) {
802 // Handle non-bitfield members.
803 if (!appendField(field, layout.getFieldOffset(index) + offsetBits,
804 eltInit, allowOverwrite))
805 return false;
806 // After emitting a non-empty field with [[no_unique_address]], we may
807 // need to overwrite its tail padding.
808 if (field->hasAttr<NoUniqueAddressAttr>())
809 allowOverwrite = true;
810 } else {
811 // Otherwise we have a bitfield.
812 if (auto constInt = dyn_cast<cir::IntAttr>(eltInit)) {
813 if (!appendBitField(field, layout.getFieldOffset(index) + offsetBits,
814 constInt, allowOverwrite))
815 return false;
816 } else {
817 // We are trying to initialize a bitfield with a non-trivial constant,
818 // this must require run-time code.
819 return false;
820 }
821 }
822 }
823
824 return true;
825}
826
827mlir::Attribute ConstRecordBuilder::finalize(QualType type) {
828 type = type.getNonReferenceType();
829 RecordDecl *rd =
830 type->castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();
831 mlir::Type valTy = cgm.convertType(type);
832 return builder.build(valTy, rd->hasFlexibleArrayMember());
833}
834
835mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,
836 InitListExpr *ile,
837 QualType valTy) {
838 ConstantAggregateBuilder constant(emitter.cgm);
839 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());
840
841 if (!builder.build(ile, /*allowOverwrite*/ false))
842 return nullptr;
843
844 return builder.finalize(valTy);
845}
846
847mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,
848 const APValue &val,
849 QualType valTy) {
850 ConstantAggregateBuilder constant(emitter.cgm);
851 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());
852
853 const RecordDecl *rd =
854 valTy->castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();
855 const CXXRecordDecl *cd = dyn_cast<CXXRecordDecl>(rd);
856 if (!builder.build(val, rd, false, cd, CharUnits::Zero()))
857 return nullptr;
858
859 return builder.finalize(valTy);
860}
861
862bool ConstRecordBuilder::updateRecord(ConstantEmitter &emitter,
863 ConstantAggregateBuilder &constant,
864 CharUnits offset, InitListExpr *updater) {
865 return ConstRecordBuilder(emitter, constant, offset)
866 .build(updater, /*allowOverwrite*/ true);
867}
868
869//===----------------------------------------------------------------------===//
870// ConstExprEmitter
871//===----------------------------------------------------------------------===//
872
873// This class only needs to handle arrays, structs and unions.
874//
875// In LLVM codegen, when outside C++11 mode, those types are not constant
876// folded, while all other types are handled by constant folding.
877//
878// In CIR codegen, instead of folding things here, we should defer that work
879// to MLIR: do not attempt to do much here.
880class ConstExprEmitter
881 : public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
882 CIRGenModule &cgm;
883 [[maybe_unused]] ConstantEmitter &emitter;
884
885public:
886 ConstExprEmitter(ConstantEmitter &emitter)
887 : cgm(emitter.cgm), emitter(emitter) {}
888
889 //===--------------------------------------------------------------------===//
890 // Visitor Methods
891 //===--------------------------------------------------------------------===//
892
893 mlir::Attribute VisitStmt(Stmt *s, QualType t) { return {}; }
894
895 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
896 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
897 return result;
898 return Visit(ce->getSubExpr(), t);
899 }
900
901 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
902 return Visit(pe->getSubExpr(), t);
903 }
904
905 mlir::Attribute
906 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
907 QualType t) {
908 return Visit(pe->getReplacement(), t);
909 }
910
911 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
912 QualType t) {
913 return Visit(ge->getResultExpr(), t);
914 }
915
916 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
917 return Visit(ce->getChosenSubExpr(), t);
918 }
919
920 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
921 return Visit(e->getInitializer(), t);
922 }
923
924 mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {
925 if (const auto *ece = dyn_cast<ExplicitCastExpr>(e))
927 const_cast<CIRGenFunction *>(emitter.cgf));
928
929 Expr *subExpr = e->getSubExpr();
930
931 switch (e->getCastKind()) {
932 case CK_ToUnion:
933 case CK_AddressSpaceConversion:
934 case CK_ReinterpretMemberPointer:
935 case CK_DerivedToBaseMemberPointer:
936 case CK_BaseToDerivedMemberPointer:
937 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");
938 return {};
939
940 case CK_LValueToRValue:
941 case CK_AtomicToNonAtomic:
942 case CK_NonAtomicToAtomic:
943 case CK_NoOp:
944 case CK_ConstructorConversion:
945 return Visit(subExpr, destType);
946
947 case CK_IntToOCLSampler:
948 llvm_unreachable("global sampler variables are not generated");
949
950 case CK_Dependent:
951 llvm_unreachable("saw dependent cast!");
952
953 case CK_BuiltinFnToFnPtr:
954 llvm_unreachable("builtin functions are handled elsewhere");
955
956 // These will never be supported.
957 case CK_ObjCObjectLValueCast:
958 case CK_ARCProduceObject:
959 case CK_ARCConsumeObject:
960 case CK_ARCReclaimReturnedObject:
961 case CK_ARCExtendBlockObject:
962 case CK_CopyAndAutoreleaseBlockObject:
963 return {};
964
965 // These don't need to be handled here because Evaluate knows how to
966 // evaluate them in the cases where they can be folded.
967 case CK_BitCast:
968 case CK_ToVoid:
969 case CK_Dynamic:
970 case CK_LValueBitCast:
971 case CK_LValueToRValueBitCast:
972 case CK_NullToMemberPointer:
973 case CK_UserDefinedConversion:
974 case CK_CPointerToObjCPointerCast:
975 case CK_BlockPointerToObjCPointerCast:
976 case CK_AnyPointerToBlockPointerCast:
977 case CK_ArrayToPointerDecay:
978 case CK_FunctionToPointerDecay:
979 case CK_BaseToDerived:
980 case CK_DerivedToBase:
981 case CK_UncheckedDerivedToBase:
982 case CK_MemberPointerToBoolean:
983 case CK_VectorSplat:
984 case CK_FloatingRealToComplex:
985 case CK_FloatingComplexToReal:
986 case CK_FloatingComplexToBoolean:
987 case CK_FloatingComplexCast:
988 case CK_FloatingComplexToIntegralComplex:
989 case CK_IntegralRealToComplex:
990 case CK_IntegralComplexToReal:
991 case CK_IntegralComplexToBoolean:
992 case CK_IntegralComplexCast:
993 case CK_IntegralComplexToFloatingComplex:
994 case CK_PointerToIntegral:
995 case CK_PointerToBoolean:
996 case CK_NullToPointer:
997 case CK_IntegralCast:
998 case CK_BooleanToSignedIntegral:
999 case CK_IntegralToPointer:
1000 case CK_IntegralToBoolean:
1001 case CK_IntegralToFloating:
1002 case CK_FloatingToIntegral:
1003 case CK_FloatingToBoolean:
1004 case CK_FloatingCast:
1005 case CK_FloatingToFixedPoint:
1006 case CK_FixedPointToFloating:
1007 case CK_FixedPointCast:
1008 case CK_FixedPointToBoolean:
1009 case CK_FixedPointToIntegral:
1010 case CK_IntegralToFixedPoint:
1011 case CK_ZeroToOCLOpaqueType:
1012 case CK_MatrixCast:
1013 case CK_HLSLArrayRValue:
1014 case CK_HLSLVectorTruncation:
1015 case CK_HLSLElementwiseCast:
1016 case CK_HLSLAggregateSplatCast:
1017 return {};
1018 }
1019 llvm_unreachable("Invalid CastKind");
1020 }
1021
1022 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
1023 // No need for a DefaultInitExprScope: we don't handle 'this' in a
1024 // constant expression.
1025 return Visit(die->getExpr(), t);
1026 }
1027
1028 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
1029 // Since this about constant emission no need to wrap this under a scope.
1030 return Visit(e->getSubExpr(), t);
1031 }
1032
1033 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
1034 QualType t) {
1035 return Visit(e->getSubExpr(), t);
1036 }
1037
1038 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
1039 QualType t) {
1040 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(t));
1041 }
1042
1043 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
1044 if (ile->isTransparent())
1045 return Visit(ile->getInit(0), t);
1046
1047 if (ile->getType()->isArrayType()) {
1048 // If we return null here, the non-constant initializer will take care of
1049 // it, but we would prefer to handle it here.
1051 return {};
1052 }
1053
1054 if (ile->getType()->isRecordType()) {
1055 return ConstRecordBuilder::buildRecord(emitter, ile, t);
1056 }
1057
1058 if (ile->getType()->isVectorType()) {
1059 // If we return null here, the non-constant initializer will take care of
1060 // it, but we would prefer to handle it here.
1062 return {};
1063 }
1064
1065 return {};
1066 }
1067
1068 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
1069 QualType destType) {
1070 mlir::Attribute c = Visit(e->getBase(), destType);
1071 if (!c)
1072 return {};
1073
1074 cgm.errorNYI(e->getBeginLoc(),
1075 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
1076 return {};
1077 }
1078
1079 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
1080 if (!e->getConstructor()->isTrivial())
1081 return {};
1082
1083 // Only default and copy/move constructors can be trivial.
1084 if (e->getNumArgs()) {
1085 assert(e->getNumArgs() == 1 && "trivial ctor with > 1 argument");
1086 assert(e->getConstructor()->isCopyOrMoveConstructor() &&
1087 "trivial ctor has argument but isn't a copy/move ctor");
1088
1089 Expr *arg = e->getArg(0);
1090 assert(cgm.getASTContext().hasSameUnqualifiedType(ty, arg->getType()) &&
1091 "argument to copy ctor is of wrong type");
1092
1093 // Look through the temporary; it's just converting the value to an lvalue
1094 // to pass it to the constructor.
1095 if (auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
1096 return Visit(mte->getSubExpr(), ty);
1097
1098 // TODO: Investigate whether there are cases that can fall through to here
1099 // that need to be handled. This is missing in classic codegen also.
1101
1102 // Don't try to support arbitrary lvalue-to-rvalue conversions for now.
1103 return {};
1104 }
1105
1106 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
1107 }
1108
1109 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
1110 // This is a string literal initializing an array in an initializer.
1112 }
1113
1114 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
1115 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");
1116 return {};
1117 }
1118
1119 mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {
1120 return Visit(e->getSubExpr(), t);
1121 }
1122
1123 // Utility methods
1124 mlir::Type convertType(QualType t) { return cgm.convertType(t); }
1125};
1126
1127// TODO(cir): this can be shared with LLVM's codegen
1128static QualType getNonMemoryType(CIRGenModule &cgm, QualType type) {
1129 if (const auto *at = type->getAs<AtomicType>()) {
1130 return cgm.getASTContext().getQualifiedType(at->getValueType(),
1131 type.getQualifiers());
1132 }
1133 return type;
1134}
1135
1136static mlir::Attribute
1137emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
1138 mlir::Type commonElementType, unsigned arrayBound,
1139 SmallVectorImpl<mlir::TypedAttr> &elements,
1140 mlir::TypedAttr filler) {
1141 CIRGenBuilderTy &builder = cgm.getBuilder();
1142
1143 unsigned nonzeroLength = arrayBound;
1144 if (elements.size() < nonzeroLength && builder.isNullValue(filler))
1145 nonzeroLength = elements.size();
1146
1147 if (nonzeroLength == elements.size()) {
1148 while (nonzeroLength > 0 &&
1149 builder.isNullValue(elements[nonzeroLength - 1]))
1150 --nonzeroLength;
1151 }
1152
1153 if (nonzeroLength == 0)
1154 return cir::ZeroAttr::get(desiredType);
1155
1156 const unsigned trailingZeroes = arrayBound - nonzeroLength;
1157
1158 // Add a zeroinitializer array filler if we have lots of trailing zeroes.
1159 if (trailingZeroes >= 8) {
1160 assert(elements.size() >= nonzeroLength &&
1161 "missing initializer for non-zero element");
1162
1163 if (commonElementType && nonzeroLength >= 8) {
1164 // If all the elements had the same type up to the trailing zeroes and
1165 // there are eight or more nonzero elements, emit a struct of two arrays
1166 // (the nonzero data and the zeroinitializer).
1167 SmallVector<mlir::Attribute> eles;
1168 eles.reserve(nonzeroLength);
1169 for (const auto &element : elements)
1170 eles.push_back(element);
1171 auto initial = cir::ConstArrayAttr::get(
1172 cir::ArrayType::get(commonElementType, nonzeroLength),
1173 mlir::ArrayAttr::get(builder.getContext(), eles));
1174 elements.resize(2);
1175 elements[0] = initial;
1176 } else {
1177 // Otherwise, emit a struct with individual elements for each nonzero
1178 // initializer, followed by a zeroinitializer array filler.
1179 elements.resize(nonzeroLength + 1);
1180 }
1181
1182 mlir::Type fillerType =
1183 commonElementType
1184 ? commonElementType
1185 : mlir::cast<cir::ArrayType>(desiredType).getElementType();
1186 fillerType = cir::ArrayType::get(fillerType, trailingZeroes);
1187 elements.back() = cir::ZeroAttr::get(fillerType);
1188 commonElementType = nullptr;
1189 } else if (elements.size() != arrayBound) {
1190 elements.resize(arrayBound, filler);
1191
1192 if (filler.getType() != commonElementType)
1193 commonElementType = {};
1194 }
1195
1196 if (commonElementType) {
1197 SmallVector<mlir::Attribute> eles;
1198 eles.reserve(elements.size());
1199
1200 for (const auto &element : elements)
1201 eles.push_back(element);
1202
1203 return cir::ConstArrayAttr::get(
1204 cir::ArrayType::get(commonElementType, arrayBound),
1205 mlir::ArrayAttr::get(builder.getContext(), eles));
1206 }
1207
1208 SmallVector<mlir::Attribute> eles;
1209 eles.reserve(elements.size());
1210 for (auto const &element : elements)
1211 eles.push_back(element);
1212
1213 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(), eles);
1214 return builder.getAnonConstRecord(arrAttr, /*packed=*/true);
1215}
1216
1217} // namespace
1218
1219//===----------------------------------------------------------------------===//
1220// ConstantLValueEmitter
1221//===----------------------------------------------------------------------===//
1222
1223namespace {
1224/// A struct which can be used to peephole certain kinds of finalization
1225/// that normally happen during l-value emission.
1226struct ConstantLValue {
1227 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
1228 bool hasOffsetApplied;
1229
1230 /*implicit*/ ConstantLValue(std::nullptr_t)
1231 : value(nullptr), hasOffsetApplied(false) {}
1232 /*implicit*/ ConstantLValue(cir::GlobalViewAttr address)
1233 : value(address), hasOffsetApplied(false) {}
1234
1235 ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
1236};
1237
1238/// A helper class for emitting constant l-values.
1239class ConstantLValueEmitter
1240 : public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {
1241 CIRGenModule &cgm;
1242 ConstantEmitter &emitter;
1243 const APValue &value;
1244 QualType destType;
1245
1246 // Befriend StmtVisitorBase so that we don't have to expose Visit*.
1247 friend StmtVisitorBase;
1248
1249public:
1250 ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
1251 QualType destType)
1252 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
1253
1254 mlir::Attribute tryEmit();
1255
1256private:
1257 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
1258 ConstantLValue tryEmitBase(const APValue::LValueBase &base);
1259
1260 ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }
1261 ConstantLValue VisitConstantExpr(const ConstantExpr *e);
1262 ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);
1263 ConstantLValue VisitStringLiteral(const StringLiteral *e);
1264 ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);
1265 ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);
1266 ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);
1267 ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);
1268 ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);
1269 ConstantLValue VisitCallExpr(const CallExpr *e);
1270 ConstantLValue VisitBlockExpr(const BlockExpr *e);
1271 ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);
1272 ConstantLValue
1273 VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
1274
1275 /// Return GEP-like value offset
1276 mlir::ArrayAttr getOffset(mlir::Type ty) {
1277 int64_t offset = value.getLValueOffset().getQuantity();
1278 cir::CIRDataLayout layout(cgm.getModule());
1279 SmallVector<int64_t, 3> idxVec;
1280 cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(offset, ty, layout,
1281 idxVec);
1282
1283 llvm::SmallVector<mlir::Attribute, 3> indices;
1284 for (int64_t i : idxVec) {
1285 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
1286 indices.push_back(intAttr);
1287 }
1288
1289 if (indices.empty())
1290 return {};
1291 return cgm.getBuilder().getArrayAttr(indices);
1292 }
1293
1294 /// Apply the value offset to the given constant.
1295 ConstantLValue applyOffset(ConstantLValue &c) {
1296 // Handle attribute constant LValues.
1297 if (auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {
1298 if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {
1299 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();
1300 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
1301 assert(!gv.getIndices() && "Global view is already indexed");
1302 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(),
1303 getOffset(baseTy));
1304 }
1305 llvm_unreachable("Unsupported attribute type to offset");
1306 }
1307
1308 cgm.errorNYI("ConstantLValue: non-attribute offset");
1309 return {};
1310 }
1311};
1312
1313} // namespace
1314
1315mlir::Attribute ConstantLValueEmitter::tryEmit() {
1316 const APValue::LValueBase &base = value.getLValueBase();
1317
1318 // The destination type should be a pointer or reference
1319 // type, but it might also be a cast thereof.
1320 //
1321 // FIXME: the chain of casts required should be reflected in the APValue.
1322 // We need this in order to correctly handle things like a ptrtoint of a
1323 // non-zero null pointer and addrspace casts that aren't trivially
1324 // represented in LLVM IR.
1325 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
1326 assert(mlir::isa<cir::PointerType>(destTy));
1327
1328 // If there's no base at all, this is a null or absolute pointer,
1329 // possibly cast back to an integer type.
1330 if (!base)
1331 return tryEmitAbsolute(destTy);
1332
1333 // Otherwise, try to emit the base.
1334 ConstantLValue result = tryEmitBase(base);
1335
1336 // If that failed, we're done.
1337 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
1338 if (!value)
1339 return {};
1340
1341 // Apply the offset if necessary and not already done.
1342 if (!result.hasOffsetApplied)
1343 value = applyOffset(result).value;
1344
1345 // Convert to the appropriate type; this could be an lvalue for
1346 // an integer. FIXME: performAddrSpaceCast
1347 if (mlir::isa<cir::PointerType>(destTy)) {
1348 if (auto attr = mlir::dyn_cast<mlir::Attribute>(value))
1349 return attr;
1350 cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");
1351 return {};
1352 }
1353
1354 cgm.errorNYI("ConstantLValueEmitter: other?");
1355 return {};
1356}
1357
1358/// Try to emit an absolute l-value, such as a null pointer or an integer
1359/// bitcast to pointer type.
1360mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
1361 // If we're producing a pointer, this is easy.
1362 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
1363 return cgm.getBuilder().getConstPtrAttr(
1364 destPtrTy, value.getLValueOffset().getQuantity());
1365}
1366
1367ConstantLValue
1368ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
1369 // Handle values.
1370 if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {
1371 // The constant always points to the canonical declaration. We want to look
1372 // at properties of the most recent declaration at the point of emission.
1373 d = cast<ValueDecl>(d->getMostRecentDecl());
1374
1375 if (d->hasAttr<WeakRefAttr>()) {
1376 cgm.errorNYI(d->getSourceRange(),
1377 "ConstantLValueEmitter: emit pointer base for weakref");
1378 return {};
1379 }
1380
1381 if (auto *fd = dyn_cast<FunctionDecl>(d)) {
1382 cir::FuncOp fop = cgm.getAddrOfFunction(fd);
1383 CIRGenBuilderTy &builder = cgm.getBuilder();
1384 mlir::MLIRContext *mlirContext = builder.getContext();
1385 return cir::GlobalViewAttr::get(
1386 builder.getPointerTo(fop.getFunctionType()),
1387 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
1388 }
1389
1390 if (auto *vd = dyn_cast<VarDecl>(d)) {
1391 // We can never refer to a variable with local storage.
1392 if (!vd->hasLocalStorage()) {
1393 if (vd->isFileVarDecl() || vd->hasExternalStorage())
1394 return cgm.getAddrOfGlobalVarAttr(vd);
1395
1396 if (vd->isLocalVarDecl()) {
1397 cgm.errorNYI(vd->getSourceRange(),
1398 "ConstantLValueEmitter: local var decl");
1399 return {};
1400 }
1401 }
1402 }
1403
1404 // Classic codegen handles MSGuidDecl,UnnamedGlobalConstantDecl, and
1405 // TemplateParamObjectDecl, but it can also fall through from VarDecl,
1406 // in which case it silently returns nullptr. For now, let's emit an
1407 // error to see what cases we need to handle.
1408 cgm.errorNYI(d->getSourceRange(),
1409 "ConstantLValueEmitter: unhandled value decl");
1410 return {};
1411 }
1412
1413 // Handle typeid(T).
1414 if (base.dyn_cast<TypeInfoLValue>()) {
1415 cgm.errorNYI("ConstantLValueEmitter: typeid");
1416 return {};
1417 }
1418
1419 // Otherwise, it must be an expression.
1420 return Visit(base.get<const Expr *>());
1421}
1422
1423ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {
1424 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: constant expr");
1425 return {};
1426}
1427
1428ConstantLValue
1429ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {
1430 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: compound literal");
1431 return {};
1432}
1433
1434ConstantLValue
1435ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {
1437}
1438
1439ConstantLValue
1440ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {
1441 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc encode expr");
1442 return {};
1443}
1444
1445ConstantLValue
1446ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {
1447 cgm.errorNYI(e->getSourceRange(),
1448 "ConstantLValueEmitter: objc string literal");
1449 return {};
1450}
1451
1452ConstantLValue
1453ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {
1454 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc boxed expr");
1455 return {};
1456}
1457
1458ConstantLValue
1459ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {
1460 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: predefined expr");
1461 return {};
1462}
1463
1464ConstantLValue
1465ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
1466 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");
1467 return {};
1468}
1469
1470ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
1471 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: call expr");
1472 return {};
1473}
1474
1475ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {
1476 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: block expr");
1477 return {};
1478}
1479
1480ConstantLValue
1481ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {
1482 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: cxx typeid expr");
1483 return {};
1484}
1485
1486ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
1487 const MaterializeTemporaryExpr *e) {
1488 cgm.errorNYI(e->getSourceRange(),
1489 "ConstantLValueEmitter: materialize temporary expr");
1490 return {};
1491}
1492
1493//===----------------------------------------------------------------------===//
1494// ConstantEmitter
1495//===----------------------------------------------------------------------===//
1496
1498 initializeNonAbstract();
1499 return markIfFailed(tryEmitPrivateForVarInit(d));
1500}
1501
1502void ConstantEmitter::finalize(cir::GlobalOp gv) {
1503 assert(initializedNonAbstract &&
1504 "finalizing emitter that was used for abstract emission?");
1505 assert(!finalized && "finalizing emitter multiple times");
1506 assert(!gv.isDeclaration());
1507#ifndef NDEBUG
1508 // Note that we might also be Failed.
1509 finalized = true;
1510#endif // NDEBUG
1511}
1512
1513mlir::Attribute
1515 AbstractStateRAII state(*this, true);
1516 return tryEmitPrivateForVarInit(d);
1517}
1518
1520 assert((!initializedNonAbstract || finalized || failed) &&
1521 "not finalized after being initialized for non-abstract emission");
1522}
1523
1525 // Make a quick check if variable can be default NULL initialized
1526 // and avoid going through rest of code which may do, for c++11,
1527 // initialization of memory to all NULLs.
1528 if (!d.hasLocalStorage()) {
1529 QualType ty = cgm.getASTContext().getBaseElementType(d.getType());
1530 if (ty->isRecordType()) {
1531 if (const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.getInit())) {
1532 const CXXConstructorDecl *cd = e->getConstructor();
1533 // FIXME: we should probably model this more closely to C++ than
1534 // just emitting a global with zero init (mimic what we do for trivial
1535 // assignments and whatnots). Since this is for globals shouldn't
1536 // be a problem for the near future.
1537 if (cd->isTrivial() && cd->isDefaultConstructor()) {
1538 const auto *cxxrd = ty->castAsCXXRecordDecl();
1539 if (cxxrd->getNumBases() != 0) {
1540 // There may not be anything additional to do here, but this will
1541 // force us to pause and test this path when it is supported.
1542 cgm.errorNYI("tryEmitPrivateForVarInit: cxx record with bases");
1543 return {};
1544 }
1545 if (!cgm.getTypes().isZeroInitializable(cxxrd)) {
1546 // To handle this case, we really need to go through
1547 // emitNullConstant, but we need an attribute, not a value
1548 cgm.errorNYI(
1549 "tryEmitPrivateForVarInit: non-zero-initializable cxx record");
1550 return {};
1551 }
1552 return cir::ZeroAttr::get(cgm.convertType(d.getType()));
1553 }
1554 }
1555 }
1556 }
1557 inConstantContext = d.hasConstantInitialization();
1558
1559 const Expr *e = d.getInit();
1560 assert(e && "No initializer to emit");
1561
1562 QualType destType = d.getType();
1563
1564 if (!destType->isReferenceType()) {
1565 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1566 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),
1567 nonMemoryDestType))
1568 return emitForMemory(c, destType);
1569 }
1570
1571 // Try to emit the initializer. Note that this can allow some things that
1572 // are not allowed by tryEmitPrivateForMemory alone.
1573 if (APValue *value = d.evaluateValue())
1574 return tryEmitPrivateForMemory(*value, destType);
1575
1576 return {};
1577}
1578
1580 if (!ce->hasAPValueResult())
1581 return {};
1582
1583 QualType retType = ce->getType();
1584 if (ce->isGLValue())
1585 retType = cgm.getASTContext().getLValueReferenceType(retType);
1586
1587 return emitAbstract(ce->getBeginLoc(), ce->getAPValueResult(), retType);
1588}
1589
1591 QualType destType) {
1592 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1593 mlir::TypedAttr c = tryEmitPrivate(e, nonMemoryDestType);
1594 if (c) {
1595 mlir::Attribute attr = emitForMemory(c, destType);
1596 return mlir::cast<mlir::TypedAttr>(attr);
1597 }
1598 return nullptr;
1599}
1600
1602 QualType destType) {
1603 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1604 mlir::Attribute c = tryEmitPrivate(value, nonMemoryDestType);
1605 return (c ? emitForMemory(c, destType) : nullptr);
1606}
1607
1608mlir::Attribute ConstantEmitter::emitAbstract(const Expr *e,
1609 QualType destType) {
1610 AbstractStateRAII state{*this, true};
1611 mlir::Attribute c = mlir::cast<mlir::Attribute>(tryEmitPrivate(e, destType));
1612 if (!c)
1613 cgm.errorNYI(e->getSourceRange(),
1614 "emitAbstract failed, emit null constaant");
1615 return c;
1616}
1617
1619 const APValue &value,
1620 QualType destType) {
1621 AbstractStateRAII state(*this, true);
1622 mlir::Attribute c = tryEmitPrivate(value, destType);
1623 if (!c)
1624 cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");
1625 return c;
1626}
1627
1628mlir::Attribute ConstantEmitter::emitNullForMemory(mlir::Location loc,
1630 QualType t) {
1631 cir::ConstantOp cstOp =
1632 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();
1633 assert(cstOp && "expected cir.const op");
1634 return emitForMemory(cgm, cstOp.getValue(), t);
1635}
1636
1637mlir::Attribute ConstantEmitter::emitForMemory(mlir::Attribute c,
1638 QualType destType) {
1639 // For an _Atomic-qualified constant, we may need to add tail padding.
1640 if (destType->getAs<AtomicType>()) {
1641 cgm.errorNYI("emitForMemory: atomic type");
1642 return {};
1643 }
1644
1645 return c;
1646}
1647
1649 mlir::Attribute c,
1650 QualType destType) {
1651 // For an _Atomic-qualified constant, we may need to add tail padding.
1652 if (destType->getAs<AtomicType>()) {
1653 cgm.errorNYI("atomic constants");
1654 }
1655
1656 return c;
1657}
1658
1659mlir::TypedAttr ConstantEmitter::tryEmitPrivate(const Expr *e,
1660 QualType destType) {
1661 assert(!destType->isVoidType() && "can't emit a void constant");
1662
1663 if (mlir::Attribute c =
1664 ConstExprEmitter(*this).Visit(const_cast<Expr *>(e), destType))
1665 return llvm::dyn_cast<mlir::TypedAttr>(c);
1666
1667 Expr::EvalResult result;
1668
1669 bool success = false;
1670
1671 if (destType->isReferenceType())
1672 success = e->EvaluateAsLValue(result, cgm.getASTContext());
1673 else
1674 success =
1675 e->EvaluateAsRValue(result, cgm.getASTContext(), inConstantContext);
1676
1677 if (success && !result.hasSideEffects()) {
1678 mlir::Attribute c = tryEmitPrivate(result.Val, destType);
1679 return llvm::dyn_cast<mlir::TypedAttr>(c);
1680 }
1681
1682 return nullptr;
1683}
1684
1685mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
1686 QualType destType) {
1687 auto &builder = cgm.getBuilder();
1688 switch (value.getKind()) {
1689 case APValue::None:
1691 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");
1692 return {};
1693 case APValue::Int: {
1694 mlir::Type ty = cgm.convertType(destType);
1695 if (mlir::isa<cir::BoolType>(ty))
1696 return builder.getCIRBoolAttr(value.getInt().getZExtValue());
1697 assert(mlir::isa<cir::IntType>(ty) && "expected integral type");
1698 return cir::IntAttr::get(ty, value.getInt());
1699 }
1700 case APValue::Float: {
1701 const llvm::APFloat &init = value.getFloat();
1702 if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
1703 !cgm.getASTContext().getLangOpts().NativeHalfType &&
1704 cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1705 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");
1706 return {};
1707 }
1708
1709 mlir::Type ty = cgm.convertType(destType);
1710 assert(mlir::isa<cir::FPTypeInterface>(ty) &&
1711 "expected floating-point type");
1712 return cir::FPAttr::get(ty, init);
1713 }
1714 case APValue::Array: {
1715 const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);
1716 const QualType arrayElementTy = arrayTy->getElementType();
1717 const unsigned numElements = value.getArraySize();
1718 const unsigned numInitElts = value.getArrayInitializedElts();
1719
1720 mlir::Attribute filler;
1721 if (value.hasArrayFiller()) {
1722 filler = tryEmitPrivate(value.getArrayFiller(), arrayElementTy);
1723 if (!filler)
1724 return {};
1725 }
1726
1728 if (filler && builder.isNullValue(filler))
1729 elements.reserve(numInitElts + 1);
1730 else
1731 elements.reserve(numInitElts);
1732
1733 mlir::Type commonElementType;
1734 for (unsigned i = 0; i < numInitElts; ++i) {
1735 const APValue &arrayElement = value.getArrayInitializedElt(i);
1736 const mlir::Attribute element =
1737 tryEmitPrivateForMemory(arrayElement, arrayElementTy);
1738 if (!element)
1739 return {};
1740
1741 const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);
1742 if (i == 0)
1743 commonElementType = elementTyped.getType();
1744 else if (elementTyped.getType() != commonElementType) {
1745 commonElementType = {};
1746 }
1747
1748 elements.push_back(elementTyped);
1749 }
1750
1751 mlir::TypedAttr typedFiller = llvm::cast_or_null<mlir::TypedAttr>(filler);
1752 if (filler && !typedFiller)
1753 cgm.errorNYI("array filler should always be typed");
1754
1755 mlir::Type desiredType = cgm.convertType(destType);
1756 return emitArrayConstant(cgm, desiredType, commonElementType, numElements,
1757 elements, typedFiller);
1758 }
1759 case APValue::Vector: {
1760 const QualType elementType =
1761 destType->castAs<VectorType>()->getElementType();
1762 const unsigned numElements = value.getVectorLength();
1763
1765 elements.reserve(numElements);
1766
1767 for (unsigned i = 0; i < numElements; ++i) {
1768 const mlir::Attribute element =
1769 tryEmitPrivateForMemory(value.getVectorElt(i), elementType);
1770 if (!element)
1771 return {};
1772 elements.push_back(element);
1773 }
1774
1775 const auto desiredVecTy =
1776 mlir::cast<cir::VectorType>(cgm.convertType(destType));
1777
1778 return cir::ConstVectorAttr::get(
1779 desiredVecTy,
1780 mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));
1781 }
1783 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
1784 return {};
1785 }
1786 case APValue::LValue:
1787 return ConstantLValueEmitter(*this, value, destType).tryEmit();
1788 case APValue::Struct:
1789 case APValue::Union:
1790 return ConstRecordBuilder::buildRecord(*this, value, destType);
1792 case APValue::ComplexFloat: {
1793 mlir::Type desiredType = cgm.convertType(destType);
1794 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);
1795
1796 mlir::Type complexElemTy = complexType.getElementType();
1797 if (isa<cir::IntType>(complexElemTy)) {
1798 const llvm::APSInt &real = value.getComplexIntReal();
1799 const llvm::APSInt &imag = value.getComplexIntImag();
1800 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1801 cir::IntAttr::get(complexElemTy, real),
1802 cir::IntAttr::get(complexElemTy, imag));
1803 }
1804
1805 assert(isa<cir::FPTypeInterface>(complexElemTy) &&
1806 "expected floating-point type");
1807 const llvm::APFloat &real = value.getComplexFloatReal();
1808 const llvm::APFloat &imag = value.getComplexFloatImag();
1809 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1810 cir::FPAttr::get(complexElemTy, real),
1811 cir::FPAttr::get(complexElemTy, imag));
1812 }
1815 cgm.errorNYI(
1816 "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");
1817 return {};
1818 }
1819 llvm_unreachable("Unknown APValue kind");
1820}
1821
1822mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
1823 if (t->getAs<PointerType>()) {
1824 return builder.getNullPtr(getTypes().convertTypeForMem(t), loc);
1825 }
1826
1827 if (getTypes().isZeroInitializable(t))
1828 return builder.getNullValue(getTypes().convertTypeForMem(t), loc);
1829
1830 if (getASTContext().getAsConstantArrayType(t)) {
1831 errorNYI("CIRGenModule::emitNullConstant ConstantArrayType");
1832 }
1833
1834 if (t->isRecordType())
1835 errorNYI("CIRGenModule::emitNullConstant RecordType");
1836
1837 assert(t->isMemberDataPointerType() &&
1838 "Should only see pointers to data members here!");
1839
1840 errorNYI("CIRGenModule::emitNullConstant unsupported type");
1841 return {};
1842}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static QualType getNonMemoryType(CodeGenModule &CGM, QualType type)
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::BoolAttr getCIRBoolAttr(bool state)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::TypedAttr getZeroInitAttr(mlir::Type ty)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
bool isBigEndian() const
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
bool hasArrayFiller() const
Definition APValue.h:584
const LValueBase getLValueBase() const
Definition APValue.cpp:983
APValue & getArrayInitializedElt(unsigned I)
Definition APValue.h:576
APSInt & getInt()
Definition APValue.h:489
APValue & getStructField(unsigned i)
Definition APValue.h:617
const FieldDecl * getUnionField() const
Definition APValue.h:629
APSInt & getComplexIntImag()
Definition APValue.h:527
ValueKind getKind() const
Definition APValue.h:461
unsigned getArrayInitializedElts() const
Definition APValue.h:595
APValue & getUnionValue()
Definition APValue.h:633
CharUnits & getLValueOffset()
Definition APValue.cpp:993
APValue & getVectorElt(unsigned I)
Definition APValue.h:563
APValue & getArrayFiller()
Definition APValue.h:587
unsigned getVectorLength() const
Definition APValue.h:571
unsigned getArraySize() const
Definition APValue.h:599
@ Indeterminate
This object has an indeterminate value (C++ [basic.indet]).
Definition APValue.h:131
@ None
There is no such object (it's outside its lifetime).
Definition APValue.h:129
APSInt & getComplexIntReal()
Definition APValue.h:519
APFloat & getComplexFloatImag()
Definition APValue.h:543
APFloat & getComplexFloatReal()
Definition APValue.h:535
APFloat & getFloat()
Definition APValue.h:503
APValue & getStructBase(unsigned i)
Definition APValue.h:612
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3722
QualType getElementType() const
Definition TypeBase.h:3734
cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type ty={})
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
bool isNullValue(mlir::Attribute attr) const
cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields, bool packed=false, bool padded=false, llvm::StringRef name="")
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
cir::IntType getUIntNTy(int n)
virtual cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd, CharUnits vptrOffset)=0
Get the address of the vtable for the given record decl which should be used for the vptr at the give...
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
mlir::Type convertType(clang::QualType type)
CIRGenBuilderTy & getBuilder()
ItaniumVTableContext & getItaniumVTableContext()
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
void emitExplicitCastExprType(const ExplicitCastExpr *e, CIRGenFunction *cgf=nullptr)
Emit type info if type of an expression is a variably modified type.
const cir::CIRDataLayout getDataLayout() const
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::ModuleOp getModule() const
CIRGenCXXABI & getCXXABI() const
cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e)
Return a constant array for the given string.
const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const
Return the BitFieldInfo that corresponds to the field FD.
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType)
mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t)
mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType)
mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d)
mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy)
mlir::Attribute emitAbstract(const Expr *e, QualType destType)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
mlir::Attribute tryEmitForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce)
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1692
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1612
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Definition ExprCXX.h:1689
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:2999
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Definition DeclCXX.cpp:3019
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1105
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprCXX.h:902
CastKind getCastKind() const
Definition Expr.h:3654
Expr * getSubExpr()
Definition Expr.h:3660
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
int64_t QuantityType
Definition CharUnits.h:40
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
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 ...
Definition CharUnits.h:201
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4818
const Expr * getInitializer() const
Definition Expr.h:3567
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition Expr.h:1082
APValue getAPValueResult() const
Definition Expr.cpp:409
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:1132
bool hasAPValueResult() const
Definition Expr.h:1157
bool hasAttr() const
Definition DeclBase.h:577
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.cpp:4827
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsLValue - Evaluate an expression to see if we can fold it to an lvalue with link time known ...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3665
QualType getType() const
Definition Expr.h:144
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3263
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4815
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3396
bool isZeroSize(const ASTContext &Ctx) const
Determine if this field is a subobject of zero size, that is, either a zero-length bit-field or a fie...
Definition Decl.cpp:4755
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Definition Decl.h:3266
const Expr * getSubExpr() const
Definition Expr.h:1062
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2377
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6396
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
Definition Expr.cpp:2457
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
Definition Expr.h:5359
const Expr * getInit(unsigned Init) const
Definition Expr.h:5287
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4939
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:162
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprObjC.h:436
const Expr * getSubExpr() const
Definition Expr.h:2199
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
A (possibly-)qualified type.
Definition TypeBase.h:937
bool hasFlexibleArrayMember() const
Definition Decl.h:4345
field_range fields() const
Definition Decl.h:4515
RecordDecl * getDefinitionOrSelf() const
Definition Decl.h:4500
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:350
bool isUnion() const
Definition Decl.h:3922
bool isVoidType() const
Definition TypeBase.h:8871
bool isArrayType() const
Definition TypeBase.h:8614
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9158
bool isReferenceType() const
Definition TypeBase.h:8539
bool isMemberDataPointerType() const
Definition TypeBase.h:8607
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isVectorType() const
Definition TypeBase.h:8654
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
bool isRecordType() const
Definition TypeBase.h:8642
Expr * getSubExpr() const
Definition Expr.h:2285
AddressPointLocation getAddressPoint(BaseSubobject Base) const
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
Definition Decl.cpp:2575
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
Definition Decl.cpp:2648
const Expr * getInit() const
Definition Decl.h:1368
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1184
Represents a GCC generic vector type.
Definition TypeBase.h:4175
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
const AstTypeMatcher< RecordType > recordType
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:185
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
Definition DeclBase.h:1288
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t
long int64_t
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
#define false
Definition stdbool.h:26
static bool ctorConstLvalueToRvalueConversion()
static bool addressPointerAuthInfo()
static bool constEmitterArrayILE()
static bool constEmitterVectorILE()
unsigned size
The total size of the bit-field, in bits.
mlir::Type uCharTy
ClangIR char.
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:639