clang: lib/CIR/CodeGen/CIRGenExprConstant.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
18#include "mlir/IR/Attributes.h"
19#include "mlir/IR/BuiltinAttributeInterfaces.h"
20#include "mlir/IR/BuiltinAttributes.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/STLExtras.h"
34#include "llvm/Support/ErrorHandling.h"
35#include
36#include
37
38using namespace clang;
40
41
42
43
44
45namespace {
46class ConstExprEmitter;
47
49 mlir::Type eltTy = cgm.uCharTy;
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(), true));
77 }
78
79 CharUnits getSize(mlir::Type ty) const {
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
93
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
101 CharUnits offset;
102 };
103
104
105
106
107
108
109
110 llvm::SmallVector<Element, 32> elements;
111
112
113
114
116
117
118
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 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
134
135
136
137
138 bool add(mlir::TypedAttr typedAttr, CharUnits offset, bool allowOverwrite);
139
140
141 bool addBits(llvm::APInt bits, uint64_t offsetInBits, bool allowOverwrite);
142
143
144
145 void condense(CharUnits offset, mlir::Type desiredTy);
146
147
148
149
150
151
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
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
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();
206
207
208
209 unsigned offsetWithinChar = offsetInBits % charWidth;
210
211
212
213 for (CharUnits offsetInChars =
215 ; ++offsetInChars) {
216
217 unsigned wantedBits =
218 std::min((uint64_t)bits.getBitWidth(), charWidth - offsetWithinChar);
219
220
221
222 llvm::APInt bitsThisChar = bits;
223 if (bitsThisChar.getBitWidth() < charWidth)
224 bitsThisChar = bitsThisChar.zext(charWidth);
226
227
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
241 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,
242 allowOverwrite);
243 } else {
244
245
246
247 std::optional<size_t> firstElemToUpdate = splitAt(offsetInChars);
248 if (!firstElemToUpdate)
249 return false;
250 std::optional<size_t> lastElemToUpdate =
252 if (!lastElemToUpdate)
253 return false;
254 assert(*lastElemToUpdate - *firstElemToUpdate < 2 &&
255 "should have at most one element covering one byte");
256
257
258 llvm::APInt updateMask(charWidth, 0);
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_castcir::IntAttr(elements[*firstElemToUpdate].element);
269 isNull = firstEltToUpdate && firstEltToUpdate.isNullValue();
270 }
271
272 if (*firstElemToUpdate == *lastElemToUpdate || isNull) {
273
274 add(cir::IntAttr::get(charTy, bitsThisChar), offsetInChars,
275 true);
276 } else {
277 cir::IntAttr ci =
278 mlir::dyn_castcir::IntAttr(elements[*firstElemToUpdate].element);
279
280
281 if (!ci)
282 return false;
283
284
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
295 if (wantedBits == bits.getBitWidth())
296 break;
297
298
300 bits.lshrInPlace(wantedBits);
301 bits = bits.trunc(bits.getBitWidth() - wantedBits);
302
303
304 offsetWithinChar = 0;
305 }
306
307 return true;
308}
309
310
311
312
313
314std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits pos) {
315 if (pos >= size)
316 return elements.size();
317
318 while (true) {
319
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
332 if (elt.offset == pos)
333 return index;
334
335
336 CharUnits eltEnd = elt.offset + getSize(elt.element);
337 if (eltEnd <= pos)
338 return index + 1;
339
340
341 if (!split(index, pos))
342 return std::nullopt;
343 }
344}
345
346
347
348
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;
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
379 SmallVector subElems(elements.begin() + first,
380 elements.begin() + last);
381 mlir::Attribute replacement =
382 buildFrom(cgm, subElems, offset, desiredSize,
383 false, desiredTy, false);
384
385
386 Element newElt(mlir::castmlir::TypedAttr(replacement), offset);
387 replace(elements, first, last, {newElt});
388}
389
390mlir::Attribute
391ConstantAggregateBuilder::buildFrom(CIRGenModule &cgm, ArrayRef 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
401
402 if (mlir::isacir::ArrayType(desiredTy)) {
403 cgm.errorNYI("array aggregate constants");
404 return {};
405 }
406
407
408
409
410 CharUnits desiredSize = utils.getSize(desiredTy);
411 if (size > desiredSize) {
412 assert(allowOversized && "elems are oversized");
413 desiredSize = size;
414 }
415
416
418 for (auto [e, offset] : elems)
419 align = std::max(align, utils.getAlignment(e));
420
421
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
433
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
442
443
444 llvm::SmallVector<mlir::Attribute, 32> packedElems;
445 packedElems.reserve(elems.size());
446 if (!naturalLayout) {
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
462
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
477 if (auto desired = mlir::dyn_castcir::RecordType(desiredTy))
478 if (desired.isLayoutIdentical(recordType))
480
482}
483
484
485
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
519
520
521
522
523
524
525
526 bool applyZeroInitPadding(const ASTRecordLayout &layout, unsigned fieldNo,
527 const FieldDecl &field, bool allowOverwrite,
528 CharUnits &sizeSoFar, bool &zeroFieldSize);
529
530
531
532
533
534
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
571
572
573
574 if (info.size > fieldValue.getBitWidth())
575 fieldValue = fieldValue.zext(info.size);
576
577
578 if (info.size < fieldValue.getBitWidth())
579 fieldValue = fieldValue.trunc(info.size);
580
581 return builder.addBits(fieldValue,
583 allowOverwrite);
584}
585
586bool ConstRecordBuilder::applyZeroInitPadding(
587 const ASTRecordLayout &layout, unsigned fieldNo, const FieldDecl &field,
588 bool allowOverwrite, CharUnits &sizeSoFar, bool &zeroFieldSize) {
590 CharUnits startOffset =
592 if (sizeSoFar < startOffset) {
593 if (!appendBytes(sizeSoFar, computePadding(cgm, startOffset - sizeSoFar),
594 allowOverwrite))
595 return false;
596 }
597
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;
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) {
632
633
634
635
636 if (auto *cxxrd = dyn_cast(rd))
637 if (cxxrd->getNumBases())
638 return false;
639
641 bool zeroFieldSize = false;
643
644 unsigned elementNo = 0;
645 for (auto [index, field] : llvm::enumerate(rd->fields())) {
646
647
650 continue;
651
652
654 continue;
655
656
657
658 Expr *init = nullptr;
659 if (elementNo < ile->getNumInits())
660 init = ile->getInit(elementNo++);
661 if (isa_and_nonnull(init))
662 continue;
663
664
665
668 return false;
669 continue;
670 }
671
672 if (zeroInitPadding &&
673 !applyZeroInitPadding(layout, index, *field, allowOverwrite, sizeSoFar,
674 zeroFieldSize))
675 return false;
676
677
678
679
680 if (allowOverwrite &&
683 return false;
684 }
685
686 mlir::Attribute eltInitAttr =
690 if (!eltInitAttr)
691 return false;
692
693 mlir::TypedAttr eltInit = mlir::castmlir::TypedAttr(eltInitAttr);
695
696 if (!appendField(field, layout.getFieldOffset(index), eltInit,
697 allowOverwrite))
698 return false;
699
700
701 if (field->hasAttr())
702 allowOverwrite = true;
703 } else {
704
705 if (auto constInt = dyn_castcir::IntAttr(eltInit)) {
706 if (!appendBitField(field, layout.getFieldOffset(index), constInt,
707 allowOverwrite))
708 return false;
709 } else {
710
711
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}
733
734bool ConstRecordBuilder::build(const APValue &val, const RecordDecl *rd,
735 bool isPrimaryBase,
736 const CXXRecordDecl *vTableClass,
737 CharUnits offset) {
739 if (const CXXRecordDecl *cd = dyn_cast(rd)) {
740
742 CIRGenBuilderTy &builder = cgm.getBuilder();
743 cir::GlobalOp vtable =
745 clang::VTableLayout::AddressPointLocation addressPoint =
750 mlir::ArrayAttr indices = builder.getArrayAttr({
751 builder.getI32IntegerAttr(addressPoint.VTableIndex),
753 });
754 cir::GlobalViewAttr vtableInit =
756 if (!appendBytes(offset, vtableInit))
757 return false;
758 }
759
760
761
762 SmallVector 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();
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
782
783 bool allowOverwrite = false;
784 for (auto [index, field] : llvm::enumerate(rd->fields())) {
785
787 continue;
788
789
791 continue;
792
793
794 const APValue &fieldValue =
796 mlir::TypedAttr eltInit = mlir::castmlir::TypedAttr(
798 if (!eltInit)
799 return false;
800
802
803 if (!appendField(field, layout.getFieldOffset(index) + offsetBits,
804 eltInit, allowOverwrite))
805 return false;
806
807
808 if (field->hasAttr())
809 allowOverwrite = true;
810 } else {
811
812 if (auto constInt = dyn_castcir::IntAttr(eltInit)) {
813 if (!appendBitField(field, layout.getFieldOffset(index) + offsetBits,
814 constInt, allowOverwrite))
815 return false;
816 } else {
817
818
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 =
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, false))
842 return nullptr;
843
844 return builder.finalize(valTy);
845}
846
847mlir::Attribute ConstRecordBuilder::buildRecord(ConstantEmitter &emitter,
849 QualType valTy) {
850 ConstantAggregateBuilder constant(emitter.cgm);
851 ConstRecordBuilder builder(emitter, constant, CharUnits::Zero());
852
853 const RecordDecl *rd =
854 valTy->castAsclang::RecordType()->getDecl()->getDefinitionOrSelf();
855 const CXXRecordDecl *cd = dyn_cast(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, true);
867}
868
869
870
871
872
873
874
875
876
877
878
879
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
891
892
893 mlir::Attribute VisitStmt(Stmt *s, QualType t) { return {}; }
894
895 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
897 return result;
899 }
900
901 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
903 }
904
905 mlir::Attribute
906 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
907 QualType t) {
909 }
910
911 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
912 QualType t) {
914 }
915
916 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
918 }
919
920 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
922 }
923
924 mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {
925 if (const auto *ece = dyn_cast(e))
927 const_cast<CIRGenFunction *>(emitter.cgf));
928
930
932 case CK_ToUnion:
933 case CK_AddressSpaceConversion:
934 case CK_ReinterpretMemberPointer:
935 case CK_DerivedToBaseMemberPointer:
936 case CK_BaseToDerivedMemberPointer:
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
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
966
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_HLSLMatrixTruncation:
1016 case CK_HLSLElementwiseCast:
1017 case CK_HLSLAggregateSplatCast:
1018 return {};
1019 }
1020 llvm_unreachable("Invalid CastKind");
1021 }
1022
1023 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
1024
1025
1026 return Visit(die->getExpr(), t);
1027 }
1028
1029 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
1030
1032 }
1033
1034 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
1035 QualType t) {
1037 }
1038
1039 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
1040 QualType t) {
1042 }
1043
1044 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
1046 return Visit(ile->getInit(0), t);
1047
1049
1050
1052 return {};
1053 }
1054
1056 return ConstRecordBuilder::buildRecord(emitter, ile, t);
1057 }
1058
1060
1061
1063 return {};
1064 }
1065
1066 return {};
1067 }
1068
1069 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
1070 QualType destType) {
1071 mlir::Attribute c = Visit(e->getBase(), destType);
1072 if ()
1073 return {};
1074
1076 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
1077 return {};
1078 }
1079
1080 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
1082 return {};
1083
1084
1086 assert(e->getNumArgs() == 1 && "trivial ctor with > 1 argument");
1088 "trivial ctor has argument but isn't a copy/move ctor");
1089
1092 "argument to copy ctor is of wrong type");
1093
1094
1095
1096 if (auto const *mte = dyn_cast(arg))
1097 return Visit(mte->getSubExpr(), ty);
1098
1099
1100
1102
1103
1104 return {};
1105 }
1106
1108 }
1109
1110 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
1111
1113 }
1114
1115 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
1116 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");
1117 return {};
1118 }
1119
1120 mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {
1122 }
1123
1124
1125 mlir::Type convertType(QualType t) { return cgm.convertType(t); }
1126};
1127
1128
1130 if (const auto *at = type->getAs()) {
1132 type.getQualifiers());
1133 }
1134 return type;
1135}
1136
1137static mlir::Attribute
1138emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
1139 mlir::Type commonElementType, unsigned arrayBound,
1140 SmallVectorImplmlir::TypedAttr &elements,
1141 mlir::TypedAttr filler) {
1142 CIRGenBuilderTy &builder = cgm.getBuilder();
1143
1144 unsigned nonzeroLength = arrayBound;
1145 if (elements.size() < nonzeroLength && builder.isNullValue(filler))
1146 nonzeroLength = elements.size();
1147
1148 if (nonzeroLength == elements.size()) {
1149 while (nonzeroLength > 0 &&
1150 builder.isNullValue(elements[nonzeroLength - 1]))
1151 --nonzeroLength;
1152 }
1153
1154 if (nonzeroLength == 0)
1155 return cir::ZeroAttr::get(desiredType);
1156
1157 const unsigned trailingZeroes = arrayBound - nonzeroLength;
1158
1159
1160 if (trailingZeroes >= 8) {
1161 assert(elements.size() >= nonzeroLength &&
1162 "missing initializer for non-zero element");
1163
1164 if (commonElementType && nonzeroLength >= 8) {
1165
1166
1167
1168 SmallVectormlir::Attribute eles;
1169 eles.reserve(nonzeroLength);
1170 for (const auto &element : elements)
1171 eles.push_back(element);
1172 auto initial = cir::ConstArrayAttr::get(
1173 cir::ArrayType::get(commonElementType, nonzeroLength),
1174 mlir::ArrayAttr::get(builder.getContext(), eles));
1175 elements.resize(2);
1176 elements[0] = initial;
1177 } else {
1178
1179
1180 elements.resize(nonzeroLength + 1);
1181 }
1182
1183 mlir::Type fillerType =
1184 commonElementType
1185 ? commonElementType
1186 : mlir::castcir::ArrayType(desiredType).getElementType();
1187 fillerType = cir::ArrayType::get(fillerType, trailingZeroes);
1188 elements.back() = cir::ZeroAttr::get(fillerType);
1189 commonElementType = nullptr;
1190 } else if (elements.size() != arrayBound) {
1191 elements.resize(arrayBound, filler);
1192
1193 if (filler.getType() != commonElementType)
1194 commonElementType = {};
1195 }
1196
1197 if (commonElementType) {
1198 SmallVectormlir::Attribute eles;
1199 eles.reserve(elements.size());
1200
1201 for (const auto &element : elements)
1202 eles.push_back(element);
1203
1204 return cir::ConstArrayAttr::get(
1205 cir::ArrayType::get(commonElementType, arrayBound),
1206 mlir::ArrayAttr::get(builder.getContext(), eles));
1207 }
1208
1209 SmallVectormlir::Attribute eles;
1210 eles.reserve(elements.size());
1211 for (auto const &element : elements)
1212 eles.push_back(element);
1213
1214 auto arrAttr = mlir::ArrayAttr::get(builder.getContext(), eles);
1216}
1217
1218}
1219
1220
1221
1222
1223
1224namespace {
1225
1226
1227struct ConstantLValue {
1228 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
1229 bool hasOffsetApplied;
1230
1231 ConstantLValue(std::nullptr_t)
1232 : value(nullptr), hasOffsetApplied(false) {}
1233 ConstantLValue(cir::GlobalViewAttr address)
1234 : value(address), hasOffsetApplied(false) {}
1235
1236 ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
1237};
1238
1239
1240class ConstantLValueEmitter
1241 : public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {
1242 CIRGenModule &cgm;
1243 ConstantEmitter &emitter;
1245 QualType destType;
1246
1247
1248 friend StmtVisitorBase;
1249
1250public:
1251 ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
1252 QualType destType)
1253 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
1254
1255 mlir::Attribute tryEmit();
1256
1257private:
1258 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
1259 ConstantLValue tryEmitBase(const APValue::LValueBase &base);
1260
1261 ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }
1262 ConstantLValue VisitConstantExpr(const ConstantExpr *e);
1263 ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);
1264 ConstantLValue VisitStringLiteral(const StringLiteral *e);
1265 ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);
1266 ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);
1267 ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);
1268 ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);
1269 ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);
1270 ConstantLValue VisitCallExpr(const CallExpr *e);
1271 ConstantLValue VisitBlockExpr(const BlockExpr *e);
1272 ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);
1273 ConstantLValue
1274 VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
1275
1276
1277 mlir::ArrayAttr getOffset(mlir::Type ty) {
1279 cir::CIRDataLayout layout(cgm.getModule());
1280 SmallVector<int64_t, 3> idxVec;
1282 idxVec);
1283
1284 llvm::SmallVector<mlir::Attribute, 3> indices;
1285 for (int64_t i : idxVec) {
1286 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
1287 indices.push_back(intAttr);
1288 }
1289
1290 if (indices.empty())
1291 return {};
1292 return cgm.getBuilder().getArrayAttr(indices);
1293 }
1294
1295
1296 ConstantLValue applyOffset(ConstantLValue &c) {
1297
1298 if (auto attr = mlir::dyn_castmlir::Attribute(c.value)) {
1299 if (auto gv = mlir::dyn_castcir::GlobalViewAttr(attr)) {
1300 auto baseTy = mlir::castcir::PointerType(gv.getType()).getPointee();
1302 assert(!gv.getIndices() && "Global view is already indexed");
1303 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(),
1304 getOffset(baseTy));
1305 }
1306 llvm_unreachable("Unsupported attribute type to offset");
1307 }
1308
1309 cgm.errorNYI("ConstantLValue: non-attribute offset");
1310 return {};
1311 }
1312};
1313
1314}
1315
1316mlir::Attribute ConstantLValueEmitter::tryEmit() {
1317 const APValue::LValueBase &base = value.getLValueBase();
1318
1319
1320
1321
1322
1323
1324
1325
1327 assert(mlir::isacir::PointerType(destTy));
1328
1329
1330
1331 if (!base)
1332 return tryEmitAbsolute(destTy);
1333
1334
1335 ConstantLValue result = tryEmitBase(base);
1336
1337
1338 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
1339 if (!value)
1340 return {};
1341
1342
1343 if (!result.hasOffsetApplied)
1344 value = applyOffset(result).value;
1345
1346
1347
1348 if (mlir::isacir::PointerType(destTy)) {
1349 if (auto attr = mlir::dyn_castmlir::Attribute(value))
1350 return attr;
1351 cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");
1352 return {};
1353 }
1354
1355 cgm.errorNYI("ConstantLValueEmitter: other?");
1356 return {};
1357}
1358
1359
1360
1361mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
1362
1363 auto destPtrTy = mlir::castcir::PointerType(destTy);
1365 destPtrTy, value.getLValueOffset().getQuantity());
1366}
1367
1368ConstantLValue
1369ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
1370
1371 if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {
1372
1373
1375
1376 if (d->hasAttr()) {
1377 cgm.errorNYI(d->getSourceRange(),
1378 "ConstantLValueEmitter: emit pointer base for weakref");
1379 return {};
1380 }
1381
1382 if (auto *fd = dyn_cast(d)) {
1384 CIRGenBuilderTy &builder = cgm.getBuilder();
1385 mlir::MLIRContext *mlirContext = builder.getContext();
1386 return cir::GlobalViewAttr::get(
1387 builder.getPointerTo(fop.getFunctionType()),
1388 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
1389 }
1390
1391 if (auto *vd = dyn_cast(d)) {
1392
1393 if (!vd->hasLocalStorage()) {
1394 if (vd->isFileVarDecl() || vd->hasExternalStorage())
1396
1397 if (vd->isLocalVarDecl()) {
1398 cgm.errorNYI(vd->getSourceRange(),
1399 "ConstantLValueEmitter: local var decl");
1400 return {};
1401 }
1402 }
1403 }
1404
1405
1406
1407
1408
1409 cgm.errorNYI(d->getSourceRange(),
1410 "ConstantLValueEmitter: unhandled value decl");
1411 return {};
1412 }
1413
1414
1415 if (base.dyn_cast()) {
1416 cgm.errorNYI("ConstantLValueEmitter: typeid");
1417 return {};
1418 }
1419
1420
1421 return Visit(base.get<const Expr *>());
1422}
1423
1424ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {
1426 return {};
1427}
1428
1429ConstantLValue
1430ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {
1432 return {};
1433}
1434
1435ConstantLValue
1436ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {
1438}
1439
1440ConstantLValue
1441ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {
1443 return {};
1444}
1445
1446ConstantLValue
1447ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {
1449 "ConstantLValueEmitter: objc string literal");
1450 return {};
1451}
1452
1453ConstantLValue
1454ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {
1456 return {};
1457}
1458
1459ConstantLValue
1460ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {
1462 return {};
1463}
1464
1465ConstantLValue
1466ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
1468 return {};
1469}
1470
1471ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
1473 return {};
1474}
1475
1476ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {
1478 return {};
1479}
1480
1481ConstantLValue
1482ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {
1484 return {};
1485}
1486
1487ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
1488 const MaterializeTemporaryExpr *e) {
1490 "ConstantLValueEmitter: materialize temporary expr");
1491 return {};
1492}
1493
1494
1495
1496
1497
1499 initializeNonAbstract();
1501}
1502
1504 assert(initializedNonAbstract &&
1505 "finalizing emitter that was used for abstract emission?");
1506 assert(!finalized && "finalizing emitter multiple times");
1507 assert(!gv.isDeclaration());
1508#ifndef NDEBUG
1509
1510 finalized = true;
1511#endif
1512}
1513
1514mlir::Attribute
1516 AbstractStateRAII state(*this, true);
1518}
1519
1521 assert((!initializedNonAbstract || finalized || failed) &&
1522 "not finalized after being initialized for non-abstract emission");
1523}
1524
1526 mlir::Type baseType,
1528
1530 bool asCompleteObject) {
1532 mlir::Type ty = (asCompleteObject ? layout.getCIRType()
1534 auto recordTy = mlir::castcir::RecordType(ty);
1535
1536 unsigned numElements = recordTy.getNumElements();
1538
1539 auto *cxxrd = dyn_cast(rd);
1540
1541 if (cxxrd) {
1543 if (base.isVirtual()) {
1544
1545
1546 continue;
1547 }
1548
1550
1556 continue;
1557
1559 mlir::Type baseType = recordTy.getElementType(fieldIndex);
1561 }
1562 }
1563
1564
1566
1567
1570 unsigned fieldIndex = layout.getCIRFieldNo(field);
1572 }
1573
1574
1577 break;
1579 if (fieldRD->findFirstNamedDataMember())
1580 break;
1581 }
1582 }
1583
1584
1585 if (cxxrd && asCompleteObject) {
1586 for ([[maybe_unused]] const CXXBaseSpecifier &vbase : cxxrd->vbases()) {
1587 cgm.errorNYI(vbase.getSourceRange(), "emitNullConstant: virtual base");
1588 return {};
1589 }
1590 }
1591
1592
1593 for (unsigned i = 0; i != numElements; ++i) {
1594 if (!elements[i]) {
1596 return {};
1597 }
1598 }
1599
1600 mlir::MLIRContext *mlirContext = recordTy.getContext();
1601 return cir::ConstRecordAttr::get(recordTy,
1602 mlir::ArrayAttr::get(mlirContext, elements));
1603}
1604
1605
1607 mlir::Type baseType,
1611
1612
1615
1616
1617 return emitNullConstant(cgm, baseDecl, false);
1618}
1619
1621
1622
1623
1627 if (const auto *e = dyn_cast_or_null(d.getInit())) {
1629
1630
1631
1632
1635 if (cxxrd->getNumBases() != 0) {
1636
1637
1638 cgm.errorNYI("tryEmitPrivateForVarInit: cxx record with bases");
1639 return {};
1640 }
1641 if (.getTypes().isZeroInitializable(cxxrd)) {
1642
1643
1644 cgm.errorNYI(
1645 "tryEmitPrivateForVarInit: non-zero-initializable cxx record");
1646 return {};
1647 }
1648 return cir::ZeroAttr::get(cgm.convertType(d.getType()));
1649 }
1650 }
1651 }
1652 }
1654
1656 assert(e && "No initializer to emit");
1657
1659
1662 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),
1663 nonMemoryDestType))
1665 }
1666
1667
1668
1671
1672 return {};
1673}
1674
1677 return {};
1678
1681 retType = cgm.getASTContext().getLValueReferenceType(retType);
1682
1684}
1685
1689 mlir::TypedAttr c = tryEmitPrivate(e, nonMemoryDestType);
1690 if (c) {
1692 return mlir::castmlir::TypedAttr(attr);
1693 }
1694 return nullptr;
1695}
1696
1703
1706 AbstractStateRAII state{*this, true};
1707 mlir::Attribute c = mlir::castmlir::Attribute(tryEmitPrivate(e, destType));
1708 if ()
1710 "emitAbstract failed, emit null constaant");
1711 return c;
1712}
1713
1717 AbstractStateRAII state(*this, true);
1719 if ()
1720 cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");
1721 return c;
1722}
1723
1727 cir::ConstantOp cstOp =
1728 cgm.emitNullConstant(t, loc).getDefiningOpcir::ConstantOp();
1729 assert(cstOp && "expected cir.const op");
1731}
1732
1735
1737 cgm.errorNYI("emitForMemory: atomic type");
1738 return {};
1739 }
1740
1741 return c;
1742}
1743
1745 mlir::Attribute c,
1747
1749 cgm.errorNYI("atomic constants");
1750 }
1751
1752 return c;
1753}
1754
1757 assert(!destType->isVoidType() && "can't emit a void constant");
1758
1759 if (mlir::Attribute c =
1760 ConstExprEmitter(*this).Visit(const_cast<Expr *>(e), destType))
1761 return llvm::dyn_castmlir::TypedAttr(c);
1762
1764
1765 bool success = false;
1766
1769 else
1770 success =
1772
1775 return llvm::dyn_castmlir::TypedAttr(c);
1776 }
1777
1778 return nullptr;
1779}
1780
1783 auto &builder = cgm.getBuilder();
1784 switch (value.getKind()) {
1787 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");
1788 return {};
1790 mlir::Type ty = cgm.convertType(destType);
1791 if (mlir::isacir::BoolType(ty))
1793 assert(mlir::isacir::IntType(ty) && "expected integral type");
1794 return cir::IntAttr::get(ty, value.getInt());
1795 }
1797 const llvm::APFloat &init = value.getFloat();
1798 if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
1799 .getASTContext().getLangOpts().NativeHalfType &&
1800 cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1801 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");
1802 return {};
1803 }
1804
1805 mlir::Type ty = cgm.convertType(destType);
1806 assert(mlir::isacir::FPTypeInterface(ty) &&
1807 "expected floating-point type");
1808 return cir::FPAttr::get(ty, init);
1809 }
1811 const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);
1813 const unsigned numElements = value.getArraySize();
1815
1816 mlir::Attribute filler;
1819 if (!filler)
1820 return {};
1821 }
1822
1824 if (filler && builder.isNullValue(filler))
1825 elements.reserve(numInitElts + 1);
1826 else
1827 elements.reserve(numInitElts);
1828
1829 mlir::Type commonElementType;
1830 for (unsigned i = 0; i < numInitElts; ++i) {
1832 const mlir::Attribute element =
1834 if (!element)
1835 return {};
1836
1837 const mlir::TypedAttr elementTyped = mlir::castmlir::TypedAttr(element);
1838 if (i == 0)
1839 commonElementType = elementTyped.getType();
1840 else if (elementTyped.getType() != commonElementType) {
1841 commonElementType = {};
1842 }
1843
1844 elements.push_back(elementTyped);
1845 }
1846
1847 mlir::TypedAttr typedFiller = llvm::cast_or_nullmlir::TypedAttr(filler);
1848 if (filler && !typedFiller)
1849 cgm.errorNYI("array filler should always be typed");
1850
1851 mlir::Type desiredType = cgm.convertType(destType);
1852 return emitArrayConstant(cgm, desiredType, commonElementType, numElements,
1853 elements, typedFiller);
1854 }
1856 const QualType elementType =
1859
1861 elements.reserve(numElements);
1862
1863 for (unsigned i = 0; i < numElements; ++i) {
1864 const mlir::Attribute element =
1866 if (!element)
1867 return {};
1868 elements.push_back(element);
1869 }
1870
1871 const auto desiredVecTy =
1872 mlir::castcir::VectorType(cgm.convertType(destType));
1873
1874 return cir::ConstVectorAttr::get(
1875 desiredVecTy,
1876 mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));
1877 }
1880
1883 cgm.errorNYI(
1884 "ConstExprEmitter::tryEmitPrivate member pointer to derived member");
1885 return {};
1886 }
1887
1889 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer to method");
1890 return {};
1891 }
1892
1893 auto cirTy = mlir::castcir::DataMemberType(cgm.convertType(destType));
1894
1897 }
1899 return ConstantLValueEmitter(*this, value, destType).tryEmit();
1902 return ConstRecordBuilder::buildRecord(*this, value, destType);
1905 mlir::Type desiredType = cgm.convertType(destType);
1906 auto complexType = mlir::dyn_castcir::ComplexType(desiredType);
1907
1908 mlir::Type complexElemTy = complexType.getElementType();
1912 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1913 cir::IntAttr::get(complexElemTy, real),
1914 cir::IntAttr::get(complexElemTy, imag));
1915 }
1916
1918 "expected floating-point type");
1921 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1922 cir::FPAttr::get(complexElemTy, real),
1923 cir::FPAttr::get(complexElemTy, imag));
1924 }
1927 cgm.errorNYI(
1928 "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");
1929 return {};
1930 }
1931 llvm_unreachable("Unknown APValue kind");
1932}
1933
1937
1940 return builder.getConstNullPtrAttr(getTypes().convertTypeForMem(t));
1941
1942 if (getTypes().isZeroInitializable(t))
1943 return builder.getZeroInitAttr(getTypes().convertTypeForMem(t));
1944
1945 if (getASTContext().getAsConstantArrayType(t)) {
1946 errorNYI("CIRGenModule::emitNullConstantAttr ConstantArrayType");
1947 return {};
1948 }
1949
1950 if (const RecordType *rt = t->getAs())
1951 return ::emitNullConstant(*this, rt->getDecl(), true);
1952
1954 "Should only see pointers to data members here!");
1955
1956 errorNYI("CIRGenModule::emitNullConstantAttr unsupported type");
1957 return {};
1958}
1959
1960mlir::TypedAttr
1962 return ::emitNullConstant(*this, record, false);
1963}
Defines the clang::ASTContext interface.
Defines enum values for all the target-independent builtin functions.
static QualType getNonMemoryType(CodeGenModule &CGM, QualType type)
static mlir::TypedAttr emitNullConstant(CIRGenModule &cgm, const RecordDecl *rd, bool asCompleteObject)
Definition CIRGenExprConstant.cpp:1529
static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm, mlir::Type baseType, const CXXRecordDecl *baseDecl)
Emit the null constant for a base subobject.
Definition CIRGenExprConstant.cpp:1606
__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)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool hasArrayFiller() const
const LValueBase getLValueBase() const
APValue & getArrayInitializedElt(unsigned I)
APValue & getStructField(unsigned i)
const FieldDecl * getUnionField() const
APSInt & getComplexIntImag()
ValueKind getKind() const
bool isMemberPointerToDerivedMember() const
unsigned getArrayInitializedElts() const
const ValueDecl * getMemberPointerDecl() const
APValue & getUnionValue()
CharUnits & getLValueOffset()
APValue & getVectorElt(unsigned I)
APValue & getArrayFiller()
unsigned getVectorLength() const
unsigned getArraySize() const
@ Indeterminate
This object has an indeterminate value (C++ [basic.indet]).
@ None
There is no such object (it's outside its lifetime).
APSInt & getComplexIntReal()
APFloat & getComplexFloatImag()
APFloat & getComplexFloatReal()
APValue & getStructBase(unsigned i)
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.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
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)
cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty, unsigned memberIndex)
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()
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record)
Return a null constant appropriate for zero-initializing a base class with the given type.
Definition CIRGenExprConstant.cpp:1961
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.
mlir::TypedAttr emitNullConstantAttr(QualType t)
Definition CIRGenExprConstant.cpp:1938
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.
Definition CIRGenExprConstant.cpp:1934
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.
bool shouldZeroInitPadding() const
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e)
Return a constant array for the given string.
This class handles record and union layout info while lowering AST types to CIR types.
cir::RecordType getCIRType() const
Return the "complete object" LLVM type associated with this record.
cir::RecordType getBaseSubobjectCIRType() const
Return the "base subobject" LLVM type associated with this record.
const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const
Return the BitFieldInfo that corresponds to the field FD.
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool isZeroInitializableAsBase() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer when considered as a bas...
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
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.
void finalize(cir::GlobalOp gv)
Definition CIRGenExprConstant.cpp:1503
mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType)
Definition CIRGenExprConstant.cpp:1733
mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t)
mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType)
Definition CIRGenExprConstant.cpp:1755
mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d)
Definition CIRGenExprConstant.cpp:1620
mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy)
Definition CIRGenExprConstant.cpp:1686
mlir::Attribute emitAbstract(const Expr *e, QualType destType)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
Definition CIRGenExprConstant.cpp:1704
~ConstantEmitter()
Definition CIRGenExprConstant.cpp:1520
const CIRGenFunction * cgf
mlir::Attribute tryEmitForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
Definition CIRGenExprConstant.cpp:1498
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
Definition CIRGenExprConstant.cpp:1515
mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce)
Definition CIRGenExprConstant.cpp:1675
Represents a base class of a C++ class.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ constructor within a class.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Expr * getExpr()
Get the initialization expression that will be used.
Represents a C++ struct/union/class.
SourceRange getSourceRange() const LLVM_READONLY
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
const Expr * getInitializer() const
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
APValue getAPValueResult() const
SourceLocation getBeginLoc() const LLVM_READONLY
bool hasAPValueResult() const
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
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...
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
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...
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
const Expr * getSubExpr() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Expr * getResultExpr()
Return the result expression of this controlling expression.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
const Expr * getInit(unsigned Init) const
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
Represents a struct/union/class.
bool hasFlexibleArrayMember() const
field_range fields() const
RecordDecl * getDefinitionOrSelf() const
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...
SourceLocation getBeginLoc() const LLVM_READONLY
Expr * getReplacement() const
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
CXXRecordDecl * castAsCXXRecordDecl() const
const T * castAs() const
Member-template castAs.
bool isReferenceType() const
bool isMemberDataPointerType() const
RecordDecl * castAsRecordDecl() const
bool isVectorType() const
const T * getAs() const
Member-template getAs'.
bool isRecordType() const
Expr * getSubExpr() const
AddressPointLocation getAddressPoint(BaseSubobject Base) const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Represents a GCC generic vector type.
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
bool isEmptyRecordForLayout(const ASTContext &context, QualType t)
isEmptyRecordForLayout - Return true if a structure contains only empty base classes (per isEmptyReco...
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const AstTypeMatcher< RecordType > recordType
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
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.
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
U cast(CodeGen::Address addr)
__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 + ...)
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.
APValue Val
Val - This is the value the expression can be folded to.
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
unsigned AddressPointIndex