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