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