clang 24.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#include <optional>
38
39using namespace clang;
40using namespace clang::CIRGen;
41
42/// Collects the initializer elements for the members of \p recordTy that are
43/// stored, in order, taking a zero initializer for any member left unset.
44/// \p elements is indexed by member, which is not the same as being indexed by
45/// stored element. A zero-width bit-field owns no bytes and so takes no
46/// element at all. Fails if a member has no zero initializer.
47static bool
51 for (auto [idx, memberTy] : llvm::enumerate(recordTy.getMembers())) {
52 if (!cir::memberOwnsBytes(memberTy))
53 continue;
54 mlir::Attribute elt = elements[idx];
55 if (!elt) {
56 elt = builder.getZeroInitAttr(memberTy);
57 if (!elt)
58 return false;
59 }
60 stored.push_back(elt);
61 }
62 return true;
63}
64
65//===----------------------------------------------------------------------===//
66// ConstantAggregateBuilder
67//===----------------------------------------------------------------------===//
68
69namespace {
71// A class to manage the list of 'initializers' for building the record
72// initialization. This abstracts out the APValue and the InitListExpr.
73class RecordBuilderInitList {
74 unsigned initIdx = 0;
75 bool isUnion = false;
76 std::variant<APValue, const InitListExpr *> value;
77
78 bool holdsExpr() const {
79 return std::holds_alternative<const InitListExpr *>(value);
80 }
81
82 bool holdsAPValue() const { return std::holds_alternative<APValue>(value); }
83
84 const Expr *getExpr() {
85 assert(holdsExpr());
86 return std::get<const InitListExpr *>(value)->getInit(initIdx);
87 }
88
89 mlir::Location getExprLoc(CIRGenModule &cgm) {
90 assert(holdsExpr());
91 return cgm.getLoc(std::get<const InitListExpr *>(value)->getBeginLoc());
92 }
93
94 const APValue getAPVal() {
95 assert(holdsAPValue());
96 if (isUnion)
97 return std::get<APValue>(value).getUnionValue();
98 return std::get<APValue>(value).getStructField(initIdx);
99 }
100
101public:
102 RecordBuilderInitList(const RecordDecl *rd, APValue val)
103 : isUnion(rd->isUnion()), value(val) {}
104 RecordBuilderInitList(const RecordDecl *rd, const InitListExpr *ile)
105 : isUnion(rd->isUnion()), value(ile) {
106 assert(ile);
107 }
108
109 bool empty() const {
110 if (auto *const *ile = std::get_if<const InitListExpr *>(&value))
111 return initIdx >= (*ile)->getNumInits();
112
113 // This branch is likely always true, but we guard against it being 'none'
114 // anyway.
115 if (isUnion)
116 return !std::get<APValue>(value).isUnion();
117
118 return initIdx >= std::get<APValue>(value).getStructNumFields();
119 }
120
121 const FieldDecl *getActiveUnionField() const {
122 if (holdsExpr())
123 return std::get<const InitListExpr *>(value)
124 ->getInitializedFieldInUnion();
125 return std::get<APValue>(value).getUnionField();
126 }
127
128 // Return whether this is a field that should be skipped for one reason or
129 // another.
130 bool shouldSkip(const FieldDecl *fd) {
131 if (fd->isUnnamedBitField())
132 return true;
133
134 if (holdsExpr() && isa_and_nonnull<NoInitExpr>(getExpr()))
135 return true;
136
137 return false;
138 }
139
140 // Advance the iterator on a 'skipped' field. Note in the case of an
141 // init-list this doesn't advance if its an unnamed bitfield, as those aren't
142 // represented in the AST.
143 void advanceSkip(const FieldDecl *fd) {
144 assert(!isUnion);
145 if (holdsExpr() && fd->isUnnamedBitField())
146 return;
147 ++initIdx;
148 }
149 // Advance the iterator on a 'normal' field, which always just increments the
150 // index.
151 void advance() {
152 assert(!isUnion);
153 ++initIdx;
154 }
155
156 APValue getBase(unsigned idx) {
157 // We could potentially handle this with init-list, but we just skip it
158 // because classic codegen does. If we decide to, we'll probably have to do
159 // something where we get through the init-list elements to make this work
160 // right (sub-init-list?).
161 assert(holdsAPValue());
162
163 return std::get<APValue>(value).getStructBase(idx);
164 }
165
166 bool hasSideEffects(const ASTContext &ctx) {
167 if (holdsExpr() && getExpr()->HasSideEffects(ctx))
168 return true;
169 // APValue never has side effects.
170 return false;
171 }
172
173 mlir::Attribute emit(ConstantEmitter &emitter, QualType fieldTy) {
174 if (holdsExpr()) {
175 const Expr *e = getExpr();
176 return e ? emitter.tryEmitPrivateForMemory(e, fieldTy)
177 : emitter.emitNullForMemory(getExprLoc(emitter.cgm), fieldTy);
178 }
179 return emitter.tryEmitPrivateForMemory(getAPVal(), fieldTy);
180 }
181};
182
183llvm::APInt bitfieldStorageToAPInt(mlir::Attribute attr, unsigned storageSize,
184 bool isBigEndian) {
185 // An empty attribute is just zero of the correct size.
186 if (!attr)
187 return llvm::APInt(storageSize, 0);
188 // An int type is just the value held in the attribute.
189 if (auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr))
190 return intAttr.getValue();
191
192 // Else we are in the array case, we have to create the big APInt, and fill it
193 // up.
194 llvm::APInt result(storageSize, 0);
195 auto elts = mlir::cast<mlir::ArrayAttr>(
196 mlir::cast<cir::ConstArrayAttr>(attr).getElts());
197
198 unsigned numBytes = elts.size();
199 for (unsigned i = 0; i != numBytes; ++i) {
200 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
201 llvm::APInt byte =
202 mlir::cast<cir::IntAttr>(elts[i]).getValue().zextOrTrunc(8);
203 result.insertBits(byte, byteIdx * 8);
204 }
205 return result;
206}
207
208mlir::Attribute apIntToBitfieldStorage(CIRGenModule &cgm,
209 mlir::Type storageType,
210 const llvm::APInt &value,
211 bool isBigEndian) {
212 // If we'ere an int, just return the new value.
213 if (mlir::isa<cir::IntTypeInterface>(storageType))
214 return cir::IntAttr::get(storageType, value);
215
216 // Array of bytes case, fill up an array.
217 CIRGenBuilderTy &builder = cgm.getBuilder();
218 auto arrayTy = mlir::cast<cir::ArrayType>(storageType);
219
220 unsigned numBytes = arrayTy.getSize();
221 cir::IntType byteTy = builder.getUInt8Ty();
223
224 for (unsigned i = 0; i != numBytes; ++i) {
225 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
226 bytes[i] = cir::IntAttr::get(byteTy, value.extractBits(8, byteIdx * 8));
227 }
228 return cir::ConstArrayAttr::get(
229 arrayTy, mlir::ArrayAttr::get(builder.getContext(), bytes));
230}
231
232// Bitfields are lowered to either an integer type, or a series of bytes, see
233// getBitfieldStorageType. Because of this, we have to figure out how to store
234// this init value in those. Do this by converting the current value in the
235// 'storage' type to an APInt so we can do our masking correctly, then convert
236// back. The int path is trivial (getValue/create a new one with the new
237// value). The array type requires breaking it up into its constituent values.
238mlir::Attribute updateBitfieldInit(CIRGenModule &cgm,
239 mlir::Attribute existingVal,
240 cir::IntAttr newVal, bool isSigned,
241 const CIRGenBitFieldInfo &bfInfo) {
242 bool isBigEndian = cgm.getDataLayout().isBigEndian();
243 llvm::APInt result =
244 bitfieldStorageToAPInt(existingVal, bfInfo.storageSize, isBigEndian);
245
246 llvm::APInt curValue = newVal.getValue();
247 // Make sure we truncate (or properly extend) the existing value for the
248 // number of bits in the bitfield. The AST/Sema doesn't do a good job of
249 // making sure this is done.
250 if (isSigned)
251 curValue = curValue.sextOrTrunc(bfInfo.size);
252 else
253 curValue = curValue.zextOrTrunc(bfInfo.size);
254
255 // Extend to the full storage size so we can shift/mask.
256 curValue = curValue.zext(bfInfo.storageSize);
257
258 // bfInfo.offset is already adjusted for endianness, so no endian-changes need
259 // to happen here.
260 curValue = curValue.shl(bfInfo.offset);
261 llvm::APInt mask(bfInfo.storageSize, 0);
262 mask.setBits(bfInfo.offset, bfInfo.offset + bfInfo.size);
263
264 result &= ~mask;
265 result |= curValue;
266
267 return apIntToBitfieldStorage(cgm, bfInfo.storageType, result, isBigEndian);
268}
269
270mlir::Attribute
271setBitfieldInit(CIRGenModule &cgm, const CIRGenRecordLayout &cirLayout,
272 CIRGenBuilderTy &builder, const FieldDecl *field,
273 mlir::Attribute existingVal, mlir::Attribute newVal) {
274 const CIRGenBitFieldInfo &info = cirLayout.getBitFieldInfo(field);
275 auto intAttr = mlir::dyn_cast<cir::IntAttr>(newVal);
276 // This could alternatively be a 'bool' attr here, so do a quick fixup to
277 // get the value correctly initialized.
278 if (!intAttr) {
279 auto boolAttr = mlir::cast<cir::BoolAttr>(newVal);
280 intAttr = cir::IntAttr::get(
281 builder.getUIntNTy(1), llvm::APInt(/*numBits=*/1, boolAttr.getValue()));
282 }
283
284 return updateBitfieldInit(
285 cgm, existingVal, intAttr,
286 field->getType()->isSignedIntegerOrEnumerationType(), info);
287}
288
289mlir::Attribute buildRecordHelper(ConstantEmitter &emitter,
290 const RecordDecl *rd,
291 const RecordDecl *vtableBaseTy,
292 RecordBuilderInitList inits, bool handleBases,
293 CharUnits offsetInDerived,
294 bool asBaseSubObj) {
295 CIRGenModule &cgm = emitter.cgm;
296 CIRGenBuilderTy &builder = cgm.getBuilder();
297 const CIRGenRecordLayout &cirLayout =
299 cir::RecordType recordTy = asBaseSubObj ? cirLayout.getBaseSubobjectCIRType()
300 : cirLayout.getCIRType();
301 // Unions in CIR are represented by all of their types, so we should be able
302 // to just initialize it with whatever the active field is.
303 if (rd->isUnion()) {
304 if (inits.empty())
305 return builder.getZeroInitAttr(recordTy);
306
307 const FieldDecl *activeField = inits.getActiveUnionField();
308 if (!activeField || activeField->isZeroSize(cgm.getASTContext()))
309 return builder.getZeroInitAttr(recordTy);
310
311 mlir::Attribute eltAttr = inits.emit(emitter, activeField->getType());
312 if (!eltAttr)
313 return {};
314
315 if (activeField->isBitField())
316 eltAttr = setBitfieldInit(cgm, cirLayout, builder, activeField,
317 /*existingVal=*/{}, eltAttr);
318
319 return cir::ConstRecordAttr::get(recordTy, builder.getArrayAttr({eltAttr}));
320 }
321
323
324 if (auto *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
325 const ASTRecordLayout &astLayout =
326 emitter.cgm.getASTContext().getASTRecordLayout(cxxrd);
327 if (astLayout.hasOwnVFPtr()) {
328 mlir::Value addrPtr = emitter.cgm.getCXXABI().getVTableAddressPoint(
329 BaseSubobject(cxxrd, offsetInDerived),
330 cast<CXXRecordDecl>(vtableBaseTy));
332 auto apOp = addrPtr.getDefiningOp<cir::VTableAddrPointOp>();
333 mlir::ArrayAttr indices = builder.getArrayAttr(
334 {builder.getI32IntegerAttr(apOp.getAddressPoint().getIndex()),
335 builder.getI32IntegerAttr(apOp.getAddressPoint().getOffset())});
336 elements[0] =
337 cir::GlobalViewAttr::get(cir::VPtrType::get(builder.getContext()),
338 apOp.getNameAttr(), indices);
339 }
340
341 for (auto [idx, base] : llvm::enumerate(cxxrd->bases())) {
342 // Our init-list implementation here just skips bases because classic
343 // compiler does (see the comment in buildRecord). We perhaps COULD do
344 // this, but for now we'll skip them.
345 if (!handleBases)
346 return {};
347
348 if (base.isVirtual())
349 continue;
350
351 const auto *baseDecl = base.getType()->castAsCXXRecordDecl();
352
353 if (!cirLayout.hasNonVirtualBaseCIRField(baseDecl))
354 continue;
355
356 APValue baseValue = inits.getBase(idx);
357
358 const ASTRecordLayout &derivedLayout =
360 CharUnits baseOff =
361 offsetInDerived + derivedLayout.getBaseClassOffset(baseDecl);
362
363 unsigned baseFieldIdx = cirLayout.getNonVirtualBaseCIRFieldNo(baseDecl);
364 elements[baseFieldIdx] = buildRecordHelper(
365 emitter, baseDecl, vtableBaseTy, RecordBuilderInitList(rd, baseValue),
366 handleBases, baseOff, /*asBaseSubObj=*/true);
367 }
368
369 if (cxxrd->getNumVBases()) {
370 cgm.errorNYI(cxxrd->getSourceRange(),
371 "buildRecordHelper: virtual base classes");
372 return {};
373 }
374 }
375
376 for (const FieldDecl *field : rd->fields()) {
377 // If we don't have any initializers left, we'll just zero-init below. This
378 // isn't perfectly accurate to classic compiler, since we are potentially
379 // zero-initing padding (instead of leaving it undef), but that is a
380 // complexity we can deal with later if we find it necessary.
381 if (inits.empty())
382 break;
383
384 if (inits.shouldSkip(field)) {
385 inits.advanceSkip(field);
386 continue;
387 }
388
389 // If we didn't lay it out, there is nothing to initialize. This is
390 // either zero size or nothing at all. IF our init has side effects, we
391 // cannot const init this.
392 if (!cirLayout.hasCIRField(field)) {
393 if (inits.hasSideEffects(cgm.getASTContext()))
394 return {};
395 inits.advance();
396 continue;
397 }
398
399 // A run of bit-fields shares one access unit, and every field of the run
400 // is numbered as that unit, so their bits pack into a single element.
401 unsigned fieldIdx = cirLayout.getCIRFieldNo(field);
402
403 mlir::Attribute eltAttr = inits.emit(emitter, field->getType());
404 inits.advance();
405
406 if (!eltAttr)
407 return {};
408
409 if (field->isBitField())
410 elements[fieldIdx] = setBitfieldInit(cgm, cirLayout, builder, field,
411 elements[fieldIdx], eltAttr);
412 else
413 elements[fieldIdx] = eltAttr;
414 }
415
416 // Anything we haven't initialized, we try to zero init. We could/should
417 // probably leave the padding as undef if !CGM.ZeroInitPadding, but that ends
418 // up being quite an additional bit of complexity (but could be implemented in
419 // the field searching above).
421 if (!collectStoredInitializers(builder, recordTy, elements, storedElements))
422 return {};
423
424 return builder.getConstRecordOrZeroAttr(builder.getArrayAttr(storedElements),
425 recordTy);
426}
427
428mlir::Attribute buildRecord(ConstantEmitter &emitter, InitListExpr *ile,
429 QualType valTy) {
430 // Bail out if we have base classes. We could support these, but they only
431 // arise in C++1z where we will have already constant folded most
432 // interesting cases. FIXME: There are still a few more cases we can handle
433 // this way.
434 const bool handleBases = false;
435 const RecordDecl *rd = ile->getType()->castAsRecordDecl();
436 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, ile),
437 handleBases, CharUnits::Zero(),
438 /*asBaseSubObj=*/false);
439}
440
441mlir::Attribute buildRecord(ConstantEmitter &emitter, const APValue &val,
442 QualType valTy) {
443 const RecordDecl *rd =
444 valTy->castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();
445 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, val),
446 /*handleBases=*/true, CharUnits::Zero(),
447 /*asBaseSubObj=*/false);
448}
449} // namespace ConstRecordBuilder
450
451//===----------------------------------------------------------------------===//
452// ConstExprEmitter
453//===----------------------------------------------------------------------===//
454
455// This class only needs to handle arrays, structs and unions.
456//
457// In LLVM codegen, when outside C++11 mode, those types are not constant
458// folded, while all other types are handled by constant folding.
459//
460// In CIR codegen, instead of folding things here, we should defer that work
461// to MLIR: do not attempt to do much here.
462class ConstExprEmitter
463 : public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
464 CIRGenModule &cgm;
465 [[maybe_unused]] ConstantEmitter &emitter;
466
467public:
468 ConstExprEmitter(ConstantEmitter &emitter)
469 : cgm(emitter.cgm), emitter(emitter) {}
470
471 //===--------------------------------------------------------------------===//
472 // Visitor Methods
473 //===--------------------------------------------------------------------===//
474
475 mlir::Attribute VisitStmt(Stmt *s, QualType t) { return {}; }
476
477 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
478 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
479 return result;
480 return Visit(ce->getSubExpr(), t);
481 }
482
483 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
484 return Visit(pe->getSubExpr(), t);
485 }
486
487 mlir::Attribute
488 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
489 QualType t) {
490 return Visit(pe->getReplacement(), t);
491 }
492
493 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
494 QualType t) {
495 return Visit(ge->getResultExpr(), t);
496 }
497
498 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
499 return Visit(ce->getChosenSubExpr(), t);
500 }
501
502 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
503 return Visit(e->getInitializer(), t);
504 }
505
506 mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {
507 if (const auto *ece = dyn_cast<ExplicitCastExpr>(e))
508 cgm.emitExplicitCastExprType(ece,
509 const_cast<CIRGenFunction *>(emitter.cgf));
510
511 Expr *subExpr = e->getSubExpr();
512
513 switch (e->getCastKind()) {
514 case CK_ToUnion:
515 case CK_AddressSpaceConversion:
516 case CK_ReinterpretMemberPointer:
517 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");
518 return {};
519
520 case CK_DerivedToBaseMemberPointer:
521 case CK_BaseToDerivedMemberPointer:
522 // Return {} to let the APValue evaluator handle member pointer type
523 // conversions. The APValue::MemberPointer case in tryEmitPrivate
524 // already builds the correct GEP path for cross-class member pointers.
525 return {};
526
527 case CK_LValueToRValue:
528 case CK_AtomicToNonAtomic:
529 case CK_NonAtomicToAtomic:
530 case CK_NoOp:
531 case CK_ConstructorConversion:
532 return Visit(subExpr, destType);
533
534 case CK_IntToOCLSampler:
535 llvm_unreachable("global sampler variables are not generated");
536
537 case CK_Dependent:
538 llvm_unreachable("saw dependent cast!");
539
540 case CK_BuiltinFnToFnPtr:
541 llvm_unreachable("builtin functions are handled elsewhere");
542
543 // These will never be supported.
544 case CK_ObjCObjectLValueCast:
545 case CK_ARCProduceObject:
546 case CK_ARCConsumeObject:
547 case CK_ARCReclaimReturnedObject:
548 case CK_ARCExtendBlockObject:
549 case CK_CopyAndAutoreleaseBlockObject:
550 return {};
551
552 // These don't need to be handled here because Evaluate knows how to
553 // evaluate them in the cases where they can be folded.
554 case CK_BitCast:
555 case CK_ToVoid:
556 case CK_Dynamic:
557 case CK_LValueBitCast:
558 case CK_LValueToRValueBitCast:
559 case CK_NullToMemberPointer:
560 case CK_UserDefinedConversion:
561 case CK_CPointerToObjCPointerCast:
562 case CK_BlockPointerToObjCPointerCast:
563 case CK_AnyPointerToBlockPointerCast:
564 case CK_ArrayToPointerDecay:
565 case CK_FunctionToPointerDecay:
566 case CK_BaseToDerived:
567 case CK_DerivedToBase:
568 case CK_UncheckedDerivedToBase:
569 case CK_MemberPointerToBoolean:
570 case CK_VectorSplat:
571 case CK_FloatingRealToComplex:
572 case CK_FloatingComplexToReal:
573 case CK_FloatingComplexToBoolean:
574 case CK_FloatingComplexCast:
575 case CK_FloatingComplexToIntegralComplex:
576 case CK_IntegralRealToComplex:
577 case CK_IntegralComplexToReal:
578 case CK_IntegralComplexToBoolean:
579 case CK_IntegralComplexCast:
580 case CK_IntegralComplexToFloatingComplex:
581 case CK_PointerToIntegral:
582 case CK_PointerToBoolean:
583 case CK_NullToPointer:
584 case CK_IntegralCast:
585 case CK_BooleanToSignedIntegral:
586 case CK_IntegralToPointer:
587 case CK_IntegralToBoolean:
588 case CK_IntegralToFloating:
589 case CK_FloatingToIntegral:
590 case CK_FloatingToBoolean:
591 case CK_FloatingCast:
592 case CK_FloatingToFixedPoint:
593 case CK_FixedPointToFloating:
594 case CK_FixedPointCast:
595 case CK_FixedPointToBoolean:
596 case CK_FixedPointToIntegral:
597 case CK_IntegralToFixedPoint:
598 case CK_ZeroToOCLOpaqueType:
599 case CK_MatrixCast:
600 case CK_HLSLArrayRValue:
601 case CK_HLSLVectorTruncation:
602 case CK_HLSLMatrixTruncation:
603 case CK_HLSLElementwiseCast:
604 case CK_HLSLAggregateSplatCast:
605 return {};
606 }
607 llvm_unreachable("Invalid CastKind");
608 }
609
610 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
611 // No need for a DefaultInitExprScope: we don't handle 'this' in a
612 // constant expression.
613 return Visit(die->getExpr(), t);
614 }
615
616 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
617 // Since this about constant emission no need to wrap this under a scope.
618 return Visit(e->getSubExpr(), t);
619 }
620
621 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
622 QualType t) {
623 return Visit(e->getSubExpr(), t);
624 }
625
626 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
627 QualType t) {
628 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(t));
629 }
630
631 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
632 if (ile->isTransparent())
633 return Visit(ile->getInit(0), t);
634
635 if (ile->getType()->isArrayType()) {
636 // If we return null here, the non-constant initializer will take care of
637 // it, but we would prefer to handle it here.
639 return {};
640 }
641
642 if (ile->getType()->isRecordType()) {
643 return ConstRecordBuilder::buildRecord(emitter, ile, t);
644 }
645
646 if (ile->getType()->isVectorType()) {
647 // If we return null here, the non-constant initializer will take care of
648 // it, but we would prefer to handle it here.
650 return {};
651 }
652
653 return {};
654 }
655
656 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
657 QualType destType) {
658 mlir::Attribute c = Visit(e->getBase(), destType);
659 if (!c)
660 return {};
661
662 cgm.errorNYI(e->getBeginLoc(),
663 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
664 return {};
665 }
666
667 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
668 if (!e->getConstructor()->isTrivial())
669 return {};
670
671 // Only default and copy/move constructors can be trivial.
672 if (e->getNumArgs()) {
673 assert(e->getNumArgs() == 1 && "trivial ctor with > 1 argument");
675 "trivial ctor has argument but isn't a copy/move ctor");
676
677 Expr *arg = e->getArg(0);
678 assert(cgm.getASTContext().hasSameUnqualifiedType(ty, arg->getType()) &&
679 "argument to copy ctor is of wrong type");
680
681 // Look through the temporary; it's just converting the value to an lvalue
682 // to pass it to the constructor.
683 if (auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
684 return Visit(mte->getSubExpr(), ty);
685
686 // TODO: Investigate whether there are cases that can fall through to here
687 // that need to be handled. This is missing in classic codegen also.
689
690 // Don't try to support arbitrary lvalue-to-rvalue conversions for now.
691 return {};
692 }
693
694 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
695 }
696
697 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
698 // This is a string literal initializing an array in an initializer.
699 return cgm.getConstantArrayFromStringLiteral(e);
700 }
701
702 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
703 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");
704 return {};
705 }
706
707 mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {
708 return Visit(e->getSubExpr(), t);
709 }
710
711 // Utility methods
712 mlir::Type convertType(QualType t) { return cgm.convertType(t); }
713};
714
715// TODO(cir): this can be shared with LLVM's codegen
717 if (const auto *at = type->getAs<AtomicType>()) {
718 return cgm.getASTContext().getQualifiedType(at->getValueType(),
719 type.getQualifiers());
720 }
721 return type;
722}
723} // namespace
724
725//===----------------------------------------------------------------------===//
726// ConstantLValueEmitter
727//===----------------------------------------------------------------------===//
728
729namespace {
730/// A struct which can be used to peephole certain kinds of finalization
731/// that normally happen during l-value emission.
732struct ConstantLValue {
733 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
734 bool hasOffsetApplied;
735
736 /*implicit*/ ConstantLValue(std::nullptr_t)
737 : value(nullptr), hasOffsetApplied(false) {}
738 /*implicit*/ ConstantLValue(cir::GlobalViewAttr address)
739 : value(address), hasOffsetApplied(false) {}
740 /*implicit*/ ConstantLValue(cir::GlobalOffsetAttr address)
741 : value(address), hasOffsetApplied(true) {}
742 /*implicit*/ ConstantLValue(cir::BlockAddrInfoAttr address)
743 : value(address), hasOffsetApplied(true) {}
744
745 ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
746};
747
748/// A helper class for emitting constant l-values.
749class ConstantLValueEmitter
750 : public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {
751 CIRGenModule &cgm;
752 ConstantEmitter &emitter;
753 const APValue &value;
754 QualType destType;
755
756 // Befriend StmtVisitorBase so that we don't have to expose Visit*.
757 friend StmtVisitorBase;
758
759public:
760 ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
761 QualType destType)
762 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
763
764 mlir::Attribute tryEmit();
765
766private:
767 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
768 ConstantLValue tryEmitBase(const APValue::LValueBase &base);
769
770 ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }
771 ConstantLValue VisitConstantExpr(const ConstantExpr *e);
772 ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);
773 ConstantLValue VisitStringLiteral(const StringLiteral *e);
774 ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);
775 ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);
776 ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);
777 ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);
778 ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);
779 ConstantLValue VisitCallExpr(const CallExpr *e);
780 ConstantLValue VisitBlockExpr(const BlockExpr *e);
781 ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);
782 ConstantLValue
783 VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);
784
785 /// Return GEP-like value offset, or std::nullopt if the offset doesn't
786 /// designate a subelement of \p ty and must be described as a byte offset.
787 /// A null ArrayAttr means the offset is zero, so no indexing is needed.
788 std::optional<mlir::ArrayAttr> getOffsetIndices(mlir::Type ty) {
789 int64_t offset = value.getLValueOffset().getQuantity();
790 cir::CIRDataLayout layout(cgm.getModule());
791 SmallVector<int64_t, 3> idxVec;
792 if (!cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(
793 offset, ty, layout, idxVec))
794 return std::nullopt;
795
796 llvm::SmallVector<mlir::Attribute, 3> indices;
797 for (int64_t i : idxVec) {
798 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
799 indices.push_back(intAttr);
800 }
801
802 if (indices.empty())
803 return mlir::ArrayAttr{};
804 return cgm.getBuilder().getArrayAttr(indices);
805 }
806
807 /// Apply the value offset to the given constant.
808 ConstantLValue applyOffset(ConstantLValue &c) {
809 // Handle attribute constant LValues.
810 if (auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {
811 if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {
812 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();
813 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
814 assert(!gv.getIndices() && "Global view is already indexed");
815 std::optional<mlir::ArrayAttr> indices = getOffsetIndices(baseTy);
816 if (!indices)
817 return cir::GlobalOffsetAttr::get(
818 destTy, gv.getSymbol(), value.getLValueOffset().getQuantity());
819 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(), *indices);
820 }
821 llvm_unreachable("Unsupported attribute type to offset");
822 }
823
824 cgm.errorNYI("ConstantLValue: non-attribute offset");
825 return {};
826 }
827};
828
829} // namespace
830
831mlir::Attribute ConstantLValueEmitter::tryEmit() {
832 const APValue::LValueBase &base = value.getLValueBase();
833
834 // The destination type should be a pointer or reference
835 // type, but it might also be a cast thereof.
836 //
837 // FIXME: the chain of casts required should be reflected in the APValue.
838 // We need this in order to correctly handle things like a ptrtoint of a
839 // non-zero null pointer and addrspace casts that aren't trivially
840 // represented in LLVM IR.
841 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
842 assert((mlir::isa<cir::PointerType>(destTy) ||
843 mlir::isa<cir::IntType>(destTy)) &&
844 "constant lvalue destination must be pointer or integer");
845
846 // If there's no base at all, this is a null or absolute pointer,
847 // possibly cast back to an integer type.
848 if (!base)
849 return tryEmitAbsolute(destTy);
850
851 // Otherwise, try to emit the base.
852 ConstantLValue result = tryEmitBase(base);
853
854 // If that failed, we're done.
855 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
856 if (!value)
857 return {};
858
859 // Apply the offset if necessary and not already done.
860 if (!result.hasOffsetApplied)
861 value = applyOffset(result).value;
862
863 // CIR does not yet support signing constant lvalue initializers with pointer
864 // authentication. Classic CodeGen signs the offset-adjusted pointer here
865 // before the final pointer cast or ptrtoint conversion.
866 if (PointerAuthQualifier pointerAuth = destType.getPointerAuth()) {
867 cgm.errorNYI("ConstantLValueEmitter: pointer authentication");
868 return {};
869 }
870
871 // Convert to the appropriate type; this could be an lvalue for
872 // an integer. FIXME: performAddrSpaceCast
873 if (auto attr = mlir::dyn_cast<mlir::Attribute>(value)) {
874 if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr))
875 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(), gv.getIndices());
876
877 if (mlir::isa<cir::PointerType>(destTy))
878 return attr;
879 }
880
881 cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer or integer");
882 return {};
883}
884
885/// Try to emit an absolute l-value, such as a null pointer or an integer
886/// bitcast to pointer type.
887mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
888 // If we're producing a pointer, this is easy.
889 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
890 return cgm.getBuilder().getConstPtrAttr(
891 destPtrTy, value.getLValueOffset().getQuantity());
892}
893
894ConstantLValue
895ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
896 // Handle values.
897 if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {
898 // The constant always points to the canonical declaration. We want to look
899 // at properties of the most recent declaration at the point of emission.
900 d = cast<ValueDecl>(d->getMostRecentDecl());
901
902 if (d->hasAttr<WeakRefAttr>()) {
903 cgm.errorNYI(d->getSourceRange(),
904 "ConstantLValueEmitter: emit pointer base for weakref");
905 return {};
906 }
907
908 if (auto *fd = dyn_cast<FunctionDecl>(d)) {
909 cir::FuncOp fop = cgm.getAddrOfFunction(fd);
910 CIRGenBuilderTy &builder = cgm.getBuilder();
911 mlir::MLIRContext *mlirContext = builder.getContext();
912 // Use the destination pointer type (e.g. struct field type), not
913 // fop.getFunctionType(), so initializers stay valid when a no-prototype
914 // FuncOp is later replaced by a prototyped definition with the same
915 // symbol. CIR allows the view type to differ from the symbol's type.
916 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
917 cir::PointerType ptrTy =
918 mlir::isa<cir::PointerType>(destTy)
919 ? mlir::cast<cir::PointerType>(destTy)
920 : cir::PointerType::get(fop.getFunctionType());
921 return cir::GlobalViewAttr::get(
922 ptrTy,
923 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
924 }
925
926 if (auto *vd = dyn_cast<VarDecl>(d)) {
927 // We can never refer to a variable with local storage.
928 if (!vd->hasLocalStorage()) {
929 if (vd->isFileVarDecl() || vd->hasExternalStorage())
930 return cgm.getAddrOfGlobalVarAttr(vd);
931
932 if (vd->isLocalVarDecl()) {
933 cir::GlobalLinkageKind linkage = cgm.getCIRLinkageVarDefinition(vd);
934 return cgm.getBuilder().getGlobalViewAttr(
935 cgm.getOrCreateStaticVarDecl(*vd, linkage));
936 }
937 }
938 }
939
940 if (isa<MSGuidDecl>(d))
941 cgm.errorNYI(d->getSourceRange(), "ConstantLValueEmitter: MSGuidDecl");
942
943 if (const auto *gcd = dyn_cast<UnnamedGlobalConstantDecl>(d))
944 return cgm.getBuilder().getGlobalViewAttr(
946
947 if (const auto *tpo = dyn_cast<TemplateParamObjectDecl>(d))
948 return cgm.getBuilder().getGlobalViewAttr(
950
951 return {};
952 }
953
954 // Handle typeid(T).
955 if (TypeInfoLValue typeInfo = base.dyn_cast<TypeInfoLValue>())
957 cgm.getBuilder().getUnknownLoc(), QualType(typeInfo.getType(), 0)));
958
959 // Otherwise, it must be an expression.
960 return Visit(base.get<const Expr *>());
961}
962
963ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {
964 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: constant expr");
965 return {};
966}
967
968static cir::GlobalViewAttr
970 const CompoundLiteralExpr *e) {
971 CIRGenModule &cgm = emitter.cgm;
972 CIRGenBuilderTy &builder = cgm.getBuilder();
974
975 if (cir::GlobalOp addr = cgm.getAddrOfConstantCompoundLiteralIfEmitted(e))
976 return builder.getGlobalViewAttr(addr);
977
979 mlir::Attribute c =
980 emitter.tryEmitForInitializer(e->getInitializer(), e->getType());
981 if (!c) {
982 assert(!e->isFileScope() &&
983 "file-scope compound literal did not have constant initializer!");
984 return {};
985 }
986
987 auto typedInit = mlir::cast<mlir::TypedAttr>(c);
988 bool isConstant = e->getType().isConstantStorage(cgm.getASTContext(),
989 /*ExcludeCtor=*/true,
990 /*ExcludeDtor=*/false);
991
992 std::string name = cgm.getUniqueGlobalName(".compoundliteral");
993 mlir::Location loc = cgm.getLoc(e->getSourceRange());
994 cir::GlobalOp gv =
995 cgm.createGlobalOp(loc, name, typedInit.getType(), isConstant);
996 gv.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
997 gv.setAlignment(align.getAsAlign().value());
999
1000 emitter.finalize(gv);
1002 return builder.getGlobalViewAttr(gv);
1003}
1004
1005ConstantLValue
1006ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {
1007 ConstantEmitter compoundLiteralEmitter(cgm, emitter.cgf);
1008 compoundLiteralEmitter.setInConstantContext(emitter.isInConstantContext());
1009 return tryEmitGlobalCompoundLiteral(compoundLiteralEmitter, e);
1010}
1011
1012ConstantLValue
1013ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {
1015}
1016
1017ConstantLValue
1018ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {
1019 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc encode expr");
1020 return {};
1021}
1022
1023ConstantLValue
1024ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {
1025 cgm.errorNYI(e->getSourceRange(),
1026 "ConstantLValueEmitter: objc string literal");
1027 return {};
1028}
1029
1030ConstantLValue
1031ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {
1032 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc boxed expr");
1033 return {};
1034}
1035
1036ConstantLValue
1037ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {
1039}
1040
1041ConstantLValue
1042ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
1043 // A label address taken in a constant context, e.g. a static computed-goto
1044 // dispatch table `static const void *tbl[] = {&&L1, &&L2}`. GotoSolver later
1045 // collects this block-address attribute (here, from a global initializer) so
1046 // the label survives and joins the indirect branch's successors. A label is
1047 // always function-local, so cgf is set here.
1048 assert(emitter.cgf && "label address in a constant requires a function");
1049 CIRGenFunction &cgf = *const_cast<CIRGenFunction *>(emitter.cgf);
1050 auto func = cast<cir::FuncOp>(cgf.curFn);
1051 return cir::BlockAddrInfoAttr::get(&cgf.getMLIRContext(), func.getSymName(),
1052 e->getLabel()->getName());
1053}
1054
1055ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
1056 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: call expr");
1057 return {};
1058}
1059
1060ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {
1061 cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: block expr");
1062 return {};
1063}
1064
1065ConstantLValue
1066ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {
1067 if (e->isTypeOperand())
1070 e->getTypeOperand(cgm.getASTContext())));
1072 cgm.getLoc(e->getSourceRange()), e->getExprOperand()->getType()));
1073}
1074
1075ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
1076 const MaterializeTemporaryExpr *e) {
1077 assert(e->getStorageDuration() == SD_Static);
1078 const Expr *inner = e->getSubExpr()->skipRValueSubobjectAdjustments();
1079 mlir::Operation *global = cgm.getAddrOfGlobalTemporary(e, inner);
1080 return ConstantLValue(
1081 cgm.getBuilder().getGlobalViewAttr(mlir::cast<cir::GlobalOp>(global)));
1082}
1083
1084//===----------------------------------------------------------------------===//
1085// ConstantEmitter
1086//===----------------------------------------------------------------------===//
1087
1089 initializeNonAbstract();
1090 return markIfFailed(tryEmitPrivateForVarInit(d));
1091}
1092
1094 QualType destType) {
1095 initializeNonAbstract();
1096 return markIfFailed(tryEmitPrivateForMemory(e, destType));
1097}
1098
1100 QualType destType) {
1101 initializeNonAbstract();
1102 auto c = tryEmitPrivateForMemory(value, destType);
1103 assert(c && "couldn't emit constant value non-abstractly?");
1104 return c;
1105}
1106
1107void ConstantEmitter::finalize(cir::GlobalOp gv) {
1108 assert(initializedNonAbstract &&
1109 "finalizing emitter that was used for abstract emission?");
1110 assert(!finalized && "finalizing emitter multiple times");
1111 assert(!gv.isDeclaration());
1112#ifndef NDEBUG
1113 // Note that we might also be Failed.
1114 finalized = true;
1115#endif // NDEBUG
1116}
1117
1118mlir::Attribute
1120 AbstractStateRAII state(*this, true);
1121 return tryEmitPrivateForVarInit(d);
1122}
1123
1125 assert((!initializedNonAbstract || finalized || failed) &&
1126 "not finalized after being initialized for non-abstract emission");
1127}
1128
1129static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm,
1130 mlir::Type baseType,
1131 const CXXRecordDecl *baseDecl);
1132
1133static mlir::TypedAttr emitNullConstant(CIRGenModule &cgm, const RecordDecl *rd,
1134 bool asCompleteObject) {
1135 const CIRGenRecordLayout &layout = cgm.getTypes().getCIRGenRecordLayout(rd);
1136 mlir::Type ty = (asCompleteObject ? layout.getCIRType()
1137 : layout.getBaseSubobjectCIRType());
1138 auto recordTy = mlir::cast<cir::RecordType>(ty);
1139
1140 unsigned numElements = rd->isUnion() ? 1 : recordTy.getNumElements();
1141 SmallVector<mlir::Attribute> elements(numElements);
1142
1143 auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
1144 // Fill in all the bases.
1145 if (cxxrd) {
1146 for (const CXXBaseSpecifier &base : cxxrd->bases()) {
1147 if (base.isVirtual()) {
1148 // Ignore virtual bases; if we're laying out for a complete
1149 // object, we'll lay these out later.
1150 continue;
1151 }
1152
1153 const auto *baseDecl = base.getType()->castAsCXXRecordDecl();
1154 // Ignore empty bases.
1155 if (isEmptyRecordForLayout(cgm.getASTContext(), base.getType()) ||
1156 cgm.getASTContext()
1157 .getASTRecordLayout(baseDecl)
1159 .isZero())
1160 continue;
1161
1162 unsigned fieldIndex = layout.getNonVirtualBaseCIRFieldNo(baseDecl);
1163 mlir::Type baseType = recordTy.getElementType(fieldIndex);
1164 elements[fieldIndex] = emitNullConstantForBase(cgm, baseType, baseDecl);
1165 }
1166 }
1167
1168 // Fill in all the fields.
1169 for (const FieldDecl *field : rd->fields()) {
1170 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
1171 // will fill in later.)
1172 if (!field->isBitField() &&
1173 !isEmptyFieldForLayout(cgm.getASTContext(), field)) {
1174 unsigned fieldIndex = layout.getCIRFieldNo(field);
1175 elements[fieldIndex] = cgm.emitNullConstantAttr(field->getType());
1176 }
1177
1178 // For unions, stop after the first named field.
1179 if (rd->isUnion()) {
1180 if (field->getIdentifier())
1181 break;
1182 if (const auto *fieldRD = field->getType()->getAsRecordDecl())
1183 if (fieldRD->findFirstNamedDataMember())
1184 break;
1185 }
1186 }
1187
1188 // Fill in the virtual bases, if we're working with the complete object.
1189 if (cxxrd && asCompleteObject) {
1190 for ([[maybe_unused]] const CXXBaseSpecifier &vbase : cxxrd->vbases()) {
1191 cgm.errorNYI(vbase.getSourceRange(), "emitNullConstant: virtual base");
1192 return {};
1193 }
1194 }
1195
1196 mlir::MLIRContext *mlirContext = recordTy.getContext();
1197
1198 // A union takes a single element, for whichever member stands in for the
1199 // active one.
1200 if (rd->isUnion()) {
1201 if (!elements[0])
1202 elements[0] =
1203 cgm.getBuilder().getZeroInitAttr(recordTy.getElementType(0));
1204 return cir::ConstRecordAttr::get(
1205 recordTy, mlir::ArrayAttr::get(mlirContext, elements));
1206 }
1207
1208 // Now go through all other fields and zero them out.
1210 if (!collectStoredInitializers(cgm.getBuilder(), recordTy, elements,
1211 storedElements))
1212 return {};
1213
1214 return cir::ConstRecordAttr::get(
1215 recordTy, mlir::ArrayAttr::get(mlirContext, storedElements));
1216}
1217
1218/// Emit the null constant for a base subobject.
1219static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm,
1220 mlir::Type baseType,
1221 const CXXRecordDecl *baseDecl) {
1222 const CIRGenRecordLayout &baseLayout =
1223 cgm.getTypes().getCIRGenRecordLayout(baseDecl);
1224
1225 // Just zero out bases that don't have any pointer to data members.
1226 if (baseLayout.isZeroInitializableAsBase())
1227 return cgm.getBuilder().getZeroInitAttr(baseType);
1228
1229 // Otherwise, we can just use its null constant.
1230 return emitNullConstant(cgm, baseDecl, /*asCompleteObject=*/false);
1231}
1232
1234 // Make a quick check if variable can be default NULL initialized
1235 // and avoid going through rest of code which may do, for c++11,
1236 // initialization of memory to all NULLs.
1237 if (!d.hasLocalStorage()) {
1238 QualType ty = cgm.getASTContext().getBaseElementType(d.getType());
1239 if (ty->isRecordType()) {
1240 if (const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.getInit())) {
1241 const CXXConstructorDecl *cd = e->getConstructor();
1242 if (cd->isTrivial() && cd->isDefaultConstructor())
1243 return cgm.emitNullConstantAttr(d.getType());
1244 }
1245 }
1246 }
1247 inConstantContext = d.hasConstantInitialization();
1248
1249 const Expr *e = d.getInit();
1250 assert(e && "No initializer to emit");
1251
1252 QualType destType = d.getType();
1253
1254 if (!destType->isReferenceType()) {
1255 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1256 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),
1257 nonMemoryDestType))
1258 return emitForMemory(c, destType);
1259 }
1260
1261 // Try to emit the initializer. Note that this can allow some things that
1262 // are not allowed by tryEmitPrivateForMemory alone.
1263 if (const APValue *value = d.evaluateValue())
1264 return tryEmitPrivateForMemory(*value, destType);
1265
1266 return {};
1267}
1268
1270 QualType destType) {
1271 AbstractStateRAII state{*this, true};
1272 return tryEmitPrivate(e, destType);
1273}
1274
1276 if (!ce->hasAPValueResult())
1277 return {};
1278
1279 QualType retType = ce->getType();
1280 if (ce->isGLValue())
1281 retType = cgm.getASTContext().getLValueReferenceType(retType);
1282
1283 return emitAbstract(ce->getBeginLoc(), ce->getAPValueResult(), retType);
1284}
1285
1287 QualType destType) {
1288 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1289 mlir::TypedAttr c = tryEmitPrivate(e, nonMemoryDestType);
1290 if (c) {
1291 mlir::Attribute attr = emitForMemory(c, destType);
1292 return mlir::cast<mlir::TypedAttr>(attr);
1293 }
1294 return nullptr;
1295}
1296
1298 QualType destType) {
1299 QualType nonMemoryDestType = getNonMemoryType(cgm, destType);
1300 mlir::Attribute c = tryEmitPrivate(value, nonMemoryDestType);
1301 return (c ? emitForMemory(c, destType) : nullptr);
1302}
1303
1304mlir::Attribute ConstantEmitter::emitAbstract(const Expr *e,
1305 QualType destType) {
1306 AbstractStateRAII state{*this, true};
1307 mlir::Attribute c = mlir::cast<mlir::Attribute>(tryEmitPrivate(e, destType));
1308 if (!c)
1309 cgm.errorNYI(e->getSourceRange(),
1310 "emitAbstract failed, emit null constaant");
1311 return c;
1312}
1313
1315 const APValue &value,
1316 QualType destType) {
1317 AbstractStateRAII state(*this, true);
1318 mlir::Attribute c = tryEmitPrivate(value, destType);
1319 if (!c)
1320 cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");
1321 return c;
1322}
1323
1324mlir::Attribute ConstantEmitter::emitNullForMemory(mlir::Location loc,
1326 QualType t) {
1327 cir::ConstantOp cstOp =
1328 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();
1329 assert(cstOp && "expected cir.const op");
1330 return emitForMemory(cgm, cstOp.getValue(), t);
1331}
1332
1333mlir::Attribute ConstantEmitter::emitForMemory(mlir::Attribute c,
1334 QualType destType) {
1335 return emitForMemory(cgm, c, destType);
1336}
1337
1339 mlir::Attribute c,
1340 QualType destType) {
1341 // For an _Atomic-qualified constant, we may need to add tail padding.
1342 if (const auto *at = destType->getAs<AtomicType>()) {
1343 QualType destValueType = at->getValueType();
1344 c = emitForMemory(cgm, c, destValueType);
1345
1346 uint64_t innerSize = cgm.getASTContext().getTypeSize(destValueType);
1347 uint64_t outerSize = cgm.getASTContext().getTypeSize(destType);
1348 if (innerSize == outerSize)
1349 return c;
1350
1351 assert(innerSize < outerSize && "emitted over-large constant for atomic");
1352 cgm.errorNYI("emitForMemory: tail padding in atomic initializer");
1353 }
1354
1355 // In HLSL bool vectors are stored in memory as a vector of i32
1356 if (destType->isExtVectorBoolType() &&
1357 !destType->isPackedVectorBoolType(cgm.getASTContext())) {
1358 cgm.errorNYI("emitForMemory: zero-extend HLSL bool vectors");
1359 }
1360
1361 // CIR represents source types as literally as possible. Some types, such as
1362 // bool and _BitInt(N), are kept at their literal width here and expanded to
1363 // their wider "in memory" types during lowering to the LLVM dialect, so the
1364 // constant is already in the right form and needs no adjustment.
1365
1366 return c;
1367}
1368
1369mlir::TypedAttr ConstantEmitter::tryEmitPrivate(const Expr *e,
1370 QualType destType) {
1371 assert(!destType->isVoidType() && "can't emit a void constant");
1372
1373 if (mlir::Attribute c =
1374 ConstExprEmitter(*this).Visit(const_cast<Expr *>(e), destType))
1375 return llvm::dyn_cast<mlir::TypedAttr>(c);
1376
1377 Expr::EvalResult result;
1378
1379 bool success = false;
1380
1381 if (destType->isReferenceType())
1382 success = e->EvaluateAsLValue(result, cgm.getASTContext());
1383 else
1384 success =
1385 e->EvaluateAsRValue(result, cgm.getASTContext(), inConstantContext);
1386
1387 if (success && !result.hasSideEffects()) {
1388 mlir::Attribute c = tryEmitPrivate(result.Val, destType);
1389 return llvm::dyn_cast<mlir::TypedAttr>(c);
1390 }
1391
1392 return nullptr;
1393}
1394
1395mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
1396 QualType destType) {
1397 auto &builder = cgm.getBuilder();
1398 switch (value.getKind()) {
1399 case APValue::None:
1401 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");
1402 return {};
1403 case APValue::Int: {
1404 mlir::Type ty = cgm.convertType(destType);
1405 if (mlir::isa<cir::BoolType>(ty))
1406 return builder.getCIRBoolAttr(value.getInt().getZExtValue());
1407 assert(mlir::isa<cir::IntType>(ty) && "expected integral type");
1408 return cir::IntAttr::get(ty, value.getInt());
1409 }
1410 case APValue::Float: {
1411 mlir::Type ty = cgm.convertType(destType);
1412 assert(mlir::isa<cir::FPTypeInterface>(ty) &&
1413 "expected floating-point type");
1414 return cir::FPAttr::get(ty, value.getFloat());
1415 }
1416 case APValue::Array: {
1417 const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);
1418 const QualType arrayElementTy = arrayTy->getElementType();
1419 const unsigned numElements = value.getArraySize();
1420 const unsigned numInitElts = value.getArrayInitializedElts();
1421
1422 mlir::TypedAttr filler;
1423 if (value.hasArrayFiller()) {
1424 mlir::Attribute fillerTemp =
1425 tryEmitPrivate(value.getArrayFiller(), arrayElementTy);
1426 if (!fillerTemp)
1427 return {};
1428 filler = dyn_cast<mlir::TypedAttr>(fillerTemp);
1429 if (!filler) {
1430 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate array filler should "
1431 "always be typed");
1432 return {};
1433 }
1434 }
1435
1436 CIRGenBuilderTy &builder = cgm.getBuilder();
1437 cir::ArrayType desiredType =
1438 cast<cir::ArrayType>(cgm.convertType(destType));
1439
1441 if (!filler || builder.isNullValue(filler))
1442 elts.reserve(numInitElts);
1443 else
1444 elts.reserve(numElements);
1445
1446 // Fill in the known values.
1447 for (unsigned i = 0; i < numInitElts; ++i) {
1448 const APValue &arrayElement = value.getArrayInitializedElt(i);
1449 const mlir::Attribute element =
1450 tryEmitPrivateForMemory(arrayElement, arrayElementTy);
1451 if (!element)
1452 return {};
1453
1454 elts.push_back(element);
1455 }
1456
1457 // If we have an actual value we have to insert for the filler, do so now.
1458 if (filler && !builder.isNullValue(filler))
1459 elts.insert(elts.end(), numElements - elts.size(), filler);
1460
1461 // Remove all null values at the end, so they become 'trailing zeroes'.
1462 while (!elts.empty() && builder.isNullValue(elts.back()))
1463 elts.pop_back();
1464
1465 // For flexible array members, we need to adjust the size of our result to
1466 // match this.
1467 if (desiredType.getSize() == 0 && numElements > 0) {
1468 desiredType =
1469 cir::ArrayType::get(desiredType.getElementType(), numElements);
1470 }
1471
1472 if (elts.empty())
1473 return cir::ZeroAttr::get(desiredType);
1474
1475 return cir::ConstArrayAttr::get(
1476 desiredType, mlir::ArrayAttr::get(builder.getContext(), elts));
1477 }
1478 case APValue::Vector: {
1479 const QualType elementType =
1480 destType->castAs<VectorType>()->getElementType();
1481 const unsigned numElements = value.getVectorLength();
1482
1484 elements.reserve(numElements);
1485
1486 for (unsigned i = 0; i < numElements; ++i) {
1487 const mlir::Attribute element =
1488 tryEmitPrivateForMemory(value.getVectorElt(i), elementType);
1489 if (!element)
1490 return {};
1491 elements.push_back(element);
1492 }
1493
1494 const auto desiredVecTy =
1495 mlir::cast<cir::VectorType>(cgm.convertType(destType));
1496
1497 return cir::ConstVectorAttr::get(
1498 desiredVecTy,
1499 mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));
1500 }
1503
1504 const ValueDecl *memberDecl = value.getMemberPointerDecl();
1505 if (!memberDecl)
1506 return builder.getZeroInitAttr(cgm.convertType(destType));
1507
1508 if (auto const *cxxDecl = dyn_cast<CXXMethodDecl>(memberDecl)) {
1509 auto ty = mlir::cast<cir::MethodType>(cgm.convertType(destType));
1510 if (cxxDecl->isVirtual())
1511 return cgm.getCXXABI().buildVirtualMethodAttr(ty, cxxDecl);
1512
1513 cir::FuncOp methodFuncOp =
1514 cgm.getAddrOfFunction(cxxDecl, ty.getMemberFuncTy());
1515 return cgm.getBuilder().getMethodAttr(ty, methodFuncOp);
1516 }
1517
1518 auto cirTy = mlir::cast<cir::DataMemberType>(cgm.convertType(destType));
1519 const auto *mpt = destType->castAs<MemberPointerType>();
1520 const auto *destClass = mpt->getMostRecentCXXRecordDecl();
1521
1522 // Empty [[no_unique_address]] fields have no CIR field index; represent the
1523 // pointer-to-data-member by its concrete byte offset.
1524 if (const auto *fieldDecl = dyn_cast<FieldDecl>(memberDecl);
1525 fieldDecl && cgm.isEmptyFieldForMemberPointer(fieldDecl)) {
1526 const ASTContext &astContext = cgm.getASTContext();
1527 CharUnits offset =
1528 astContext.getMemberPointerPathAdjustment(value) +
1529 astContext.toCharUnitsFromBits(astContext.getFieldOffset(fieldDecl));
1530 return cir::DataMemberOffsetAttr::get(cirTy, offset.getQuantity());
1531 }
1532
1533 std::optional<llvm::SmallVector<int32_t>> path =
1534 cgm.buildMemberPath(destClass, memberDecl);
1535 if (!path)
1536 return {};
1537 return builder.getDataMemberAttr(cirTy, *path);
1538 }
1539 case APValue::LValue:
1540 return ConstantLValueEmitter(*this, value, destType).tryEmit();
1541 case APValue::Struct:
1542 case APValue::Union:
1543 return ConstRecordBuilder::buildRecord(*this, value, destType);
1545 case APValue::ComplexFloat: {
1546 mlir::Type desiredType = cgm.convertType(destType);
1547 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);
1548
1549 mlir::Type complexElemTy = complexType.getElementType();
1550 if (isa<cir::IntType>(complexElemTy)) {
1551 const llvm::APSInt &real = value.getComplexIntReal();
1552 const llvm::APSInt &imag = value.getComplexIntImag();
1553 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1554 cir::IntAttr::get(complexElemTy, real),
1555 cir::IntAttr::get(complexElemTy, imag));
1556 }
1557
1558 assert(isa<cir::FPTypeInterface>(complexElemTy) &&
1559 "expected floating-point type");
1560 const llvm::APFloat &real = value.getComplexFloatReal();
1561 const llvm::APFloat &imag = value.getComplexFloatImag();
1562 return cir::ConstComplexAttr::get(builder.getContext(), complexType,
1563 cir::FPAttr::get(complexElemTy, real),
1564 cir::FPAttr::get(complexElemTy, imag));
1565 }
1566 case APValue::FixedPoint: {
1567 mlir::Type ty = cgm.convertType(destType);
1568 return cir::IntAttr::get(ty, value.getFixedPoint().getValue());
1569 }
1571 const AddrLabelExpr *lhsExpr = value.getAddrLabelDiffLHS();
1572 const AddrLabelExpr *rhsExpr = value.getAddrLabelDiffRHS();
1573
1574 // Both labels belong to the function currently being emitted. The actual
1575 // subtraction (ptrtoint of each block address, subtract, then truncate to
1576 // the result type) is deferred to the LowerToLLVM pass, which is where
1577 // block addresses are resolved to concrete basic blocks.
1578 mlir::Type resultType = cgm.getTypes().convertType(destType);
1579 auto intResultType = mlir::cast<cir::IntType>(resultType);
1580 auto func = cast<cir::FuncOp>(cgf->curFn);
1581 return cir::BlockAddrDiffAttr::get(
1582 builder.getContext(), intResultType, func.getSymName(),
1583 lhsExpr->getLabel()->getName(), rhsExpr->getLabel()->getName());
1584 }
1585
1586 case APValue::Matrix:
1587 cgm.errorNYI("ConstExprEmitter::tryEmitPrivate matrix");
1588 return {};
1589 }
1590 llvm_unreachable("Unknown APValue kind");
1591}
1592
1593mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
1594 return builder.getConstant(loc, emitNullConstantAttr(t));
1595}
1596
1598 if (t->getAs<PointerType>())
1599 return builder.getConstNullPtrAttr(getTypes().convertTypeForMem(t));
1600
1601 if (getTypes().isZeroInitializable(t))
1602 return builder.getZeroInitAttr(getTypes().convertTypeForMem(t));
1603
1604 if (getASTContext().getAsConstantArrayType(t)) {
1605 errorNYI("CIRGenModule::emitNullConstantAttr ConstantArrayType");
1606 return {};
1607 }
1608
1609 if (const RecordType *rt = t->getAs<RecordType>())
1610 return ::emitNullConstant(*this, rt->getDecl(), /*asCompleteObject=*/true);
1611
1612 assert(t->isMemberDataPointerType() &&
1613 "Should only see pointers to data members here!");
1614
1616}
1617
1618mlir::TypedAttr
1620 return ::emitNullConstant(*this, record, false);
1621}
Defines the clang::ASTContext interface.
static StringRef bytes(const std::vector< T, Allocator > &v)
Defines enum values for all the target-independent builtin functions.
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static QualType getNonMemoryType(CodeGenModule &CGM, QualType type)
static mlir::TypedAttr emitNullConstant(CIRGenModule &cgm, const RecordDecl *rd, bool asCompleteObject)
static mlir::TypedAttr emitNullConstantForBase(CIRGenModule &cgm, mlir::Type baseType, const CXXRecordDecl *baseDecl)
Emit the null constant for a base subobject.
static bool collectStoredInitializers(CIRGenBuilderTy &builder, cir::RecordType recordTy, llvm::ArrayRef< mlir::Attribute > elements, llvm::SmallVectorImpl< mlir::Attribute > &stored)
Collects the initializer elements for the members of recordTy that are stored, in order,...
static cir::GlobalViewAttr tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter, const CompoundLiteralExpr *e)
static ParseState advance(ParseState S, size_t N)
Definition Parsing.cpp:137
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)
mlir::TypedAttr getZeroInitAttr(mlir::Type ty)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
bool isBigEndian() const
C++ view class that accepts both !cir.struct and !cir.union types.
Definition CIRTypes.h:149
llvm::ArrayRef< mlir::Type > getMembers() const
Definition CIRTypes.cpp:609
size_t getNumElements() const
Definition CIRTypes.h:187
QualType getType() const
Definition APValue.cpp:63
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
bool hasArrayFiller() const
Definition APValue.h:637
const LValueBase getLValueBase() const
Definition APValue.cpp:1018
APValue & getArrayInitializedElt(unsigned I)
Definition APValue.h:629
APSInt & getInt()
Definition APValue.h:511
APSInt & getComplexIntImag()
Definition APValue.h:549
ValueKind getKind() const
Definition APValue.h:482
unsigned getArrayInitializedElts() const
Definition APValue.h:648
APFixedPoint & getFixedPoint()
Definition APValue.h:533
const ValueDecl * getMemberPointerDecl() const
Definition APValue.cpp:1101
const AddrLabelExpr * getAddrLabelDiffRHS() const
Definition APValue.h:715
APValue & getVectorElt(unsigned I)
Definition APValue.h:585
APValue & getArrayFiller()
Definition APValue.h:640
unsigned getVectorLength() const
Definition APValue.h:593
unsigned getArraySize() const
Definition APValue.h:652
@ 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:541
APFloat & getComplexFloatImag()
Definition APValue.h:565
APFloat & getComplexFloatReal()
Definition APValue.h:557
APFloat & getFloat()
Definition APValue.h:525
const AddrLabelExpr * getAddrLabelDiffLHS() const
Definition APValue.h:711
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
CharUnits getMemberPointerPathAdjustment(const APValue &MP) const
Find the 'this' offset for the member path in a pointer-to-member APValue.
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.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
AddrLabelExpr - The GNU address of label extension, representing &&label.
Definition Expr.h:4594
LabelDecl * getLabel() const
Definition Expr.h:4617
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3813
QualType getElementType() const
Definition TypeBase.h:3825
cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty, llvm::ArrayRef< int32_t > path)
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, cir::RecordType recordTy)
bool isNullValue(mlir::Attribute attr) const
cir::IntType getUIntNTy(int n)
virtual mlir::Value getVTableAddressPoint(BaseSubobject base, const CXXRecordDecl *vtableClass)=0
Get the address point of the vtable for the given base subobject.
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::MLIRContext & getMLIRContext()
This class organizes the cross-function state that is used while generating CIR code.
cir::GlobalOp getAddrOfUnnamedGlobalConstantDecl(const UnnamedGlobalConstantDecl *gcd)
cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
clang::ASTContext & getASTContext() const
CIRGenBuilderTy & getBuilder()
std::string getUniqueGlobalName(const std::string &baseName)
cir::GlobalOp getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo)
Get the GlobalOp of a template parameter object.
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record)
Return a null constant appropriate for zero-initializing a base class with the given type.
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)
const cir::CIRDataLayout getDataLayout() const
mlir::Operation * getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *mte, const Expr *init)
Returns a pointer to a global variable representing a temporary with static or thread storage duratio...
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
cir::GlobalOp createGlobalOp(mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
cir::GlobalOp getAddrOfConstantCompoundLiteralIfEmitted(const CompoundLiteralExpr *e)
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
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.
void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *e, cir::GlobalOp gv)
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.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
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 hasCIRField(const clang::FieldDecl *fd) const
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.
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 tryEmitAbstract(const Expr *e, QualType destType)
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 emitForInitializer(const APValue &value, QualType destType)
mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce)
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Expr * getArg(unsigned Arg)
Return the specified argument.
Definition ExprCXX.h:1695
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1615
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Definition ExprCXX.h:1692
Represents a C++ constructor within a class.
Definition DeclCXX.h:2642
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:3049
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Definition DeclCXX.cpp:3069
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1138
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isTypeOperand() const
Definition ExprCXX.h:888
QualType getTypeOperand(const ASTContext &Context) const
Retrieves the type operand of this typeid() expression after various required adjustments (removing r...
Definition ExprCXX.cpp:167
Expr * getExprOperand() const
Definition ExprCXX.h:899
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprCXX.h:906
CastKind getCastKind() const
Definition Expr.h:3764
Expr * getSubExpr()
Definition Expr.h:3770
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
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:4928
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3649
bool isFileScope() const
Definition Expr.h:3681
const Expr * getInitializer() const
Definition Expr.h:3677
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition Expr.h:1102
APValue getAPValueResult() const
Definition Expr.cpp:419
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:1152
bool hasAPValueResult() const
Definition Expr.h:1177
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.cpp:4988
This represents one expression.
Definition Expr.h:113
const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const
Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...
Definition Expr.cpp:85
bool isGLValue() const
Definition Expr.h:288
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...
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3295
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3398
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:4831
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Definition Decl.h:3401
const Expr * getSubExpr() const
Definition Expr.h:1082
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition Decl.h:2504
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6518
Describes an C or C++ initializer list.
Definition Expr.h:5352
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
Definition Expr.cpp:2495
const Expr * getInit(unsigned Init) const
Definition Expr.h:5407
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4998
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4990
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3744
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5827
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
SourceRange getSourceRange() const LLVM_READONLY
Definition ExprObjC.h:189
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprObjC.h:467
const Expr * getSubExpr() const
Definition Expr.h:2243
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3396
StringLiteral * getFunctionName()
Definition Expr.h:2093
A (possibly-)qualified type.
Definition TypeBase.h:938
PointerAuthQualifier getPointerAuth() const
Definition TypeBase.h:1469
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1037
Represents a struct/union/class.
Definition Decl.h:4460
field_range fields() const
Definition Decl.h:4663
Encodes a location in the source.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
bool isUnion() const
Definition Decl.h:4063
bool isVoidType() const
Definition TypeBase.h:9037
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2411
bool isPackedVectorBoolType(const ASTContext &ctx) const
Definition Type.cpp:538
bool isArrayType() const
Definition TypeBase.h:8764
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9331
bool isReferenceType() const
Definition TypeBase.h:8689
bool isExtVectorBoolType() const
Definition TypeBase.h:8812
bool isMemberDataPointerType() const
Definition TypeBase.h:8757
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isVectorType() const
Definition TypeBase.h:8804
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9264
bool isRecordType() const
Definition TypeBase.h:8792
Expr * getSubExpr() const
Definition Expr.h:2329
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
Definition Decl.cpp:2639
const Expr * getInit() const
Definition Decl.h:1392
const APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
Definition Decl.cpp:2555
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1191
Represents a GCC generic vector type.
Definition TypeBase.h:4266
bool memberOwnsBytes(mlir::Type memberTy)
Whether a record member occupies bytes of its record.
Definition CIRTypes.h:125
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.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SD_Static
Static storage duration.
Definition Specifiers.h:342
inits_range inits()
U cast(CodeGen::Address addr)
Definition Address.h:327
long int64_t
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25
static bool ctorConstLvalueToRvalueConversion()
static bool addressSpace()
static bool addressPointerAuthInfo()
static bool constEmitterArrayILE()
static bool constEmitterVectorILE()
Record with information about how a bitfield should be accessed.
unsigned offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
unsigned storageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned size
The total size of the bit-field, in bits.
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:666
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:668
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:660