18#include "mlir/IR/Attributes.h"
19#include "mlir/IR/BuiltinAttributeInterfaces.h"
20#include "mlir/IR/BuiltinAttributes.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/STLExtras.h"
34#include "llvm/Support/ErrorHandling.h"
49class RecordBuilderInitList {
52 std::variant<APValue, const InitListExpr *> value;
54 bool holdsExpr()
const {
55 return std::holds_alternative<const InitListExpr *>(value);
58 bool holdsAPValue()
const {
return std::holds_alternative<APValue>(value); }
62 return std::get<const InitListExpr *>(value)->getInit(initIdx);
67 return cgm.
getLoc(std::get<const InitListExpr *>(value)->getBeginLoc());
71 assert(holdsAPValue());
73 return std::get<APValue>(value).getUnionValue();
74 return std::get<APValue>(value).getStructField(initIdx);
79 : isUnion(rd->
isUnion()), value(val) {}
81 : isUnion(rd->
isUnion()), value(ile) {
86 if (
auto *
const *ile = std::get_if<const InitListExpr *>(&value))
87 return initIdx >= (*ile)->getNumInits();
92 return !std::get<APValue>(value).isUnion();
94 return initIdx >= std::get<APValue>(value).getStructNumFields();
97 const FieldDecl *getActiveUnionField()
const {
99 return std::get<const InitListExpr *>(value)
100 ->getInitializedFieldInUnion();
101 return std::get<APValue>(value).getUnionField();
110 if (holdsExpr() && isa_and_nonnull<NoInitExpr>(
getExpr()))
132 APValue getBase(
unsigned idx) {
137 assert(holdsAPValue());
139 return std::get<APValue>(value).getStructBase(idx);
143 if (holdsExpr() &&
getExpr()->HasSideEffects(ctx))
159mlir::Attribute updateBitfieldInit(
CIRGenModule &cgm, cir::IntAttr existingVal,
160 cir::IntAttr newVal,
bool isSigned,
164 result = existingVal.getValue();
166 llvm::APInt curValue = newVal.getValue();
171 curValue = curValue.sextOrTrunc(bfInfo.
size);
173 curValue = curValue.zextOrTrunc(bfInfo.
size);
178 unsigned offset = bfInfo.
offset;
182 curValue = curValue.shl(offset);
184 mask.setBits(offset, offset + bfInfo.
size);
189 return cir::IntAttr::get(bfInfo.
storageType, result);
195 mlir::Attribute existingVal, mlir::Attribute newVal) {
197 auto intAttr = mlir::dyn_cast<cir::IntAttr>(newVal);
201 auto boolAttr = mlir::cast<cir::BoolAttr>(newVal);
202 intAttr = cir::IntAttr::get(
203 builder.
getUIntNTy(1), llvm::APInt(1, boolAttr.getValue()));
206 return updateBitfieldInit(
207 cgm, dyn_cast_if_present<cir::IntAttr>(existingVal), intAttr,
214 RecordBuilderInitList
inits,
bool handleBases,
233 mlir::Attribute eltAttr =
inits.emit(emitter, activeField->
getType());
238 eltAttr = setBitfieldInit(cgm, cirLayout, builder, activeField,
241 return cir::ConstRecordAttr::get(recordTy, builder.getArrayAttr({eltAttr}));
246 if (
auto *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
254 auto apOp = addrPtr.getDefiningOp<cir::VTableAddrPointOp>();
255 mlir::ArrayAttr indices = builder.getArrayAttr(
256 {builder.getI32IntegerAttr(apOp.getAddressPoint().getIndex()),
257 builder.getI32IntegerAttr(apOp.getAddressPoint().getOffset())});
259 cir::GlobalViewAttr::get(cir::VPtrType::get(builder.getContext()),
260 apOp.getNameAttr(), indices);
263 for (
auto [idx, base] : llvm::enumerate(cxxrd->bases())) {
270 if (base.isVirtual())
273 const auto *baseDecl = base.getType()->castAsCXXRecordDecl();
286 elements[baseFieldIdx] = buildRecordHelper(
287 emitter, baseDecl, vtableBaseTy, RecordBuilderInitList(rd, baseValue),
288 handleBases, baseOff,
true);
291 if (cxxrd->getNumVBases()) {
292 cgm.
errorNYI(cxxrd->getSourceRange(),
293 "buildRecordHelper: virtual base classes");
306 if (
inits.shouldSkip(field)) {
307 inits.advanceSkip(field);
323 mlir::Attribute eltAttr =
inits.emit(emitter, field->
getType());
330 elements[fieldIdx] = setBitfieldInit(cgm, cirLayout, builder, field,
331 elements[fieldIdx], eltAttr);
333 elements[fieldIdx] = eltAttr;
340 for (
unsigned i = 0; i < elements.size(); ++i) {
360 const bool handleBases =
false;
362 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, ile),
370 valTy->
castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();
371 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, val),
388class ConstExprEmitter
389 :
public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
395 : cgm(emitter.cgm), emitter(emitter) {}
401 mlir::Attribute VisitStmt(Stmt *s, QualType t) {
return {}; }
403 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
404 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
409 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
414 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
419 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
424 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
428 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
432 mlir::Attribute VisitCastExpr(
CastExpr *e, QualType destType) {
433 if (
const auto *ece = dyn_cast<ExplicitCastExpr>(e))
434 cgm.emitExplicitCastExprType(ece,
435 const_cast<CIRGenFunction *
>(emitter.cgf));
441 case CK_AddressSpaceConversion:
442 case CK_ReinterpretMemberPointer:
443 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitCastExpr");
446 case CK_DerivedToBaseMemberPointer:
447 case CK_BaseToDerivedMemberPointer:
453 case CK_LValueToRValue:
454 case CK_AtomicToNonAtomic:
455 case CK_NonAtomicToAtomic:
457 case CK_ConstructorConversion:
458 return Visit(subExpr, destType);
460 case CK_IntToOCLSampler:
461 llvm_unreachable(
"global sampler variables are not generated");
464 llvm_unreachable(
"saw dependent cast!");
466 case CK_BuiltinFnToFnPtr:
467 llvm_unreachable(
"builtin functions are handled elsewhere");
470 case CK_ObjCObjectLValueCast:
471 case CK_ARCProduceObject:
472 case CK_ARCConsumeObject:
473 case CK_ARCReclaimReturnedObject:
474 case CK_ARCExtendBlockObject:
475 case CK_CopyAndAutoreleaseBlockObject:
483 case CK_LValueBitCast:
484 case CK_LValueToRValueBitCast:
485 case CK_NullToMemberPointer:
486 case CK_UserDefinedConversion:
487 case CK_CPointerToObjCPointerCast:
488 case CK_BlockPointerToObjCPointerCast:
489 case CK_AnyPointerToBlockPointerCast:
490 case CK_ArrayToPointerDecay:
491 case CK_FunctionToPointerDecay:
492 case CK_BaseToDerived:
493 case CK_DerivedToBase:
494 case CK_UncheckedDerivedToBase:
495 case CK_MemberPointerToBoolean:
497 case CK_FloatingRealToComplex:
498 case CK_FloatingComplexToReal:
499 case CK_FloatingComplexToBoolean:
500 case CK_FloatingComplexCast:
501 case CK_FloatingComplexToIntegralComplex:
502 case CK_IntegralRealToComplex:
503 case CK_IntegralComplexToReal:
504 case CK_IntegralComplexToBoolean:
505 case CK_IntegralComplexCast:
506 case CK_IntegralComplexToFloatingComplex:
507 case CK_PointerToIntegral:
508 case CK_PointerToBoolean:
509 case CK_NullToPointer:
510 case CK_IntegralCast:
511 case CK_BooleanToSignedIntegral:
512 case CK_IntegralToPointer:
513 case CK_IntegralToBoolean:
514 case CK_IntegralToFloating:
515 case CK_FloatingToIntegral:
516 case CK_FloatingToBoolean:
517 case CK_FloatingCast:
518 case CK_FloatingToFixedPoint:
519 case CK_FixedPointToFloating:
520 case CK_FixedPointCast:
521 case CK_FixedPointToBoolean:
522 case CK_FixedPointToIntegral:
523 case CK_IntegralToFixedPoint:
524 case CK_ZeroToOCLOpaqueType:
526 case CK_HLSLArrayRValue:
527 case CK_HLSLVectorTruncation:
528 case CK_HLSLMatrixTruncation:
529 case CK_HLSLElementwiseCast:
530 case CK_HLSLAggregateSplatCast:
533 llvm_unreachable(
"Invalid CastKind");
536 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
539 return Visit(die->
getExpr(), t);
542 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
547 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
552 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
554 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(t));
557 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
559 return Visit(ile->
getInit(0), t);
569 return ConstRecordBuilder::buildRecord(emitter, ile, t);
582 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
584 mlir::Attribute c = Visit(e->
getBase(), destType);
589 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
593 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
599 assert(e->
getNumArgs() == 1 &&
"trivial ctor with > 1 argument");
601 "trivial ctor has argument but isn't a copy/move ctor");
604 assert(cgm.getASTContext().hasSameUnqualifiedType(ty,
arg->getType()) &&
605 "argument to copy ctor is of wrong type");
609 if (
auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
610 return Visit(mte->getSubExpr(), ty);
620 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
623 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
625 return cgm.getConstantArrayFromStringLiteral(e);
628 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
629 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitObjCEncodeExpr");
633 mlir::Attribute VisitUnaryExtension(
const UnaryOperator *e, QualType t) {
638 mlir::Type convertType(QualType t) {
return cgm.convertType(t); }
645 type.getQualifiers());
658struct ConstantLValue {
659 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
660 bool hasOffsetApplied;
662 ConstantLValue(std::nullptr_t)
664 ConstantLValue(cir::GlobalViewAttr address)
665 : value(address), hasOffsetApplied(
false) {}
666 ConstantLValue(cir::BlockAddrInfoAttr address)
667 : value(address), hasOffsetApplied(
true) {}
669 ConstantLValue() : value(
nullptr), hasOffsetApplied(
false) {}
673class ConstantLValueEmitter
676 ConstantEmitter &emitter;
681 friend StmtVisitorBase;
684 ConstantLValueEmitter(ConstantEmitter &emitter,
const APValue &value,
686 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
688 mlir::Attribute tryEmit();
691 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
692 ConstantLValue tryEmitBase(
const APValue::LValueBase &base);
694 ConstantLValue VisitStmt(
const Stmt *s) {
return nullptr; }
695 ConstantLValue VisitConstantExpr(
const ConstantExpr *e);
696 ConstantLValue VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e);
697 ConstantLValue VisitStringLiteral(
const StringLiteral *e);
698 ConstantLValue VisitObjCBoxedExpr(
const ObjCBoxedExpr *e);
699 ConstantLValue VisitObjCEncodeExpr(
const ObjCEncodeExpr *e);
700 ConstantLValue VisitObjCStringLiteral(
const ObjCStringLiteral *e);
701 ConstantLValue VisitPredefinedExpr(
const PredefinedExpr *e);
702 ConstantLValue VisitAddrLabelExpr(
const AddrLabelExpr *e);
703 ConstantLValue VisitCallExpr(
const CallExpr *e);
704 ConstantLValue VisitBlockExpr(
const BlockExpr *e);
705 ConstantLValue VisitCXXTypeidExpr(
const CXXTypeidExpr *e);
707 VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e);
710 mlir::ArrayAttr getOffset(mlir::Type ty) {
711 int64_t offset = value.getLValueOffset().getQuantity();
712 cir::CIRDataLayout layout(cgm.getModule());
713 SmallVector<int64_t, 3> idxVec;
714 cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(offset, ty, layout,
717 llvm::SmallVector<mlir::Attribute, 3> indices;
718 for (int64_t i : idxVec) {
719 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
720 indices.push_back(intAttr);
725 return cgm.getBuilder().getArrayAttr(indices);
729 ConstantLValue applyOffset(ConstantLValue &c) {
731 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {
732 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {
733 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();
734 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
735 assert(!gv.getIndices() &&
"Global view is already indexed");
736 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(),
739 llvm_unreachable(
"Unsupported attribute type to offset");
742 cgm.errorNYI(
"ConstantLValue: non-attribute offset");
749mlir::Attribute ConstantLValueEmitter::tryEmit() {
760 assert(mlir::isa<cir::PointerType>(destTy));
765 return tryEmitAbsolute(destTy);
768 ConstantLValue result = tryEmitBase(base);
771 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
776 if (!result.hasOffsetApplied)
777 value = applyOffset(result).value;
781 if (mlir::isa<cir::PointerType>(destTy)) {
782 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(value))
784 cgm.
errorNYI(
"ConstantLValueEmitter: non-attribute pointer");
788 cgm.
errorNYI(
"ConstantLValueEmitter: other?");
794mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
796 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
798 destPtrTy, value.getLValueOffset().getQuantity());
802ConstantLValueEmitter::tryEmitBase(
const APValue::LValueBase &base) {
804 if (
const ValueDecl *d = base.
dyn_cast<
const ValueDecl *>()) {
809 if (d->hasAttr<WeakRefAttr>()) {
811 "ConstantLValueEmitter: emit pointer base for weakref");
815 if (
auto *fd = dyn_cast<FunctionDecl>(d)) {
818 mlir::MLIRContext *mlirContext = builder.getContext();
824 assert(mlir::isa<cir::PointerType>(ptrTy) &&
825 "function address in constant must be a pointer");
826 return cir::GlobalViewAttr::get(
828 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
831 if (
auto *vd = dyn_cast<VarDecl>(d)) {
833 if (!vd->hasLocalStorage()) {
834 if (vd->isFileVarDecl() || vd->hasExternalStorage())
837 if (vd->isLocalVarDecl()) {
846 cgm.
errorNYI(d->getSourceRange(),
"ConstantLValueEmitter: MSGuidDecl");
848 if (
const auto *gcd = dyn_cast<UnnamedGlobalConstantDecl>(d))
852 if (
const auto *tpo = dyn_cast<TemplateParamObjectDecl>(d))
860 if (TypeInfoLValue typeInfo = base.
dyn_cast<TypeInfoLValue>())
862 cgm.
getBuilder().getUnknownLoc(), QualType(typeInfo.getType(), 0)));
865 return Visit(base.
get<
const Expr *>());
868ConstantLValue ConstantLValueEmitter::VisitConstantExpr(
const ConstantExpr *e) {
873static cir::GlobalViewAttr
888 "file-scope compound literal did not have constant initializer!");
892 auto typedInit = mlir::cast<mlir::TypedAttr>(c);
901 gv.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
902 gv.setAlignment(align.getAsAlign().value());
911ConstantLValueEmitter::VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e) {
912 ConstantEmitter compoundLiteralEmitter(cgm, emitter.
cgf);
918ConstantLValueEmitter::VisitStringLiteral(
const StringLiteral *e) {
923ConstantLValueEmitter::VisitObjCEncodeExpr(
const ObjCEncodeExpr *e) {
929ConstantLValueEmitter::VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
931 "ConstantLValueEmitter: objc string literal");
936ConstantLValueEmitter::VisitObjCBoxedExpr(
const ObjCBoxedExpr *e) {
942ConstantLValueEmitter::VisitPredefinedExpr(
const PredefinedExpr *e) {
947ConstantLValueEmitter::VisitAddrLabelExpr(
const AddrLabelExpr *e) {
953 assert(emitter.
cgf &&
"label address in a constant requires a function");
954 CIRGenFunction &cgf = *
const_cast<CIRGenFunction *
>(emitter.
cgf);
956 cir::BlockAddrInfoAttr info = cir::BlockAddrInfoAttr::get(
962ConstantLValue ConstantLValueEmitter::VisitCallExpr(
const CallExpr *e) {
967ConstantLValue ConstantLValueEmitter::VisitBlockExpr(
const BlockExpr *e) {
973ConstantLValueEmitter::VisitCXXTypeidExpr(
const CXXTypeidExpr *e) {
982ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
983 const MaterializeTemporaryExpr *e) {
987 return ConstantLValue(
996 initializeNonAbstract();
1002 initializeNonAbstract();
1008 initializeNonAbstract();
1010 assert(c &&
"couldn't emit constant value non-abstractly?");
1015 assert(initializedNonAbstract &&
1016 "finalizing emitter that was used for abstract emission?");
1017 assert(!finalized &&
"finalizing emitter multiple times");
1018 assert(!gv.isDeclaration());
1027 AbstractStateRAII state(*
this,
true);
1032 assert((!initializedNonAbstract || finalized || failed) &&
1033 "not finalized after being initialized for non-abstract emission");
1037 mlir::Type baseType,
1041 bool asCompleteObject) {
1043 mlir::Type ty = (asCompleteObject ? layout.
getCIRType()
1045 auto recordTy = mlir::cast<cir::RecordType>(ty);
1047 unsigned numElements = recordTy.getNumElements();
1050 auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
1054 if (base.isVirtual()) {
1070 mlir::Type baseType = recordTy.getElementType(fieldIndex);
1079 if (!field->isBitField() &&
1087 if (field->getIdentifier())
1089 if (
const auto *fieldRD = field->getType()->getAsRecordDecl())
1090 if (fieldRD->findFirstNamedDataMember())
1096 if (cxxrd && asCompleteObject) {
1098 cgm.
errorNYI(vbase.getSourceRange(),
"emitNullConstant: virtual base");
1104 for (
unsigned i = 0; i != numElements; ++i) {
1110 mlir::MLIRContext *mlirContext = recordTy.getContext();
1111 return cir::ConstRecordAttr::get(recordTy,
1112 mlir::ArrayAttr::get(mlirContext, elements));
1117 mlir::Type baseType,
1137 if (
const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.
getInit())) {
1140 return cgm.emitNullConstantAttr(d.
getType());
1147 assert(e &&
"No initializer to emit");
1153 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e),
1168 AbstractStateRAII state{*
this,
true};
1178 retType =
cgm.getASTContext().getLValueReferenceType(retType);
1189 return mlir::cast<mlir::TypedAttr>(
attr);
1203 AbstractStateRAII state{*
this,
true};
1204 mlir::Attribute c = mlir::cast<mlir::Attribute>(
tryEmitPrivate(e, destType));
1207 "emitAbstract failed, emit null constaant");
1214 AbstractStateRAII state(*
this,
true);
1217 cgm.errorNYI(loc,
"emitAbstract failed, emit null constaant");
1224 cir::ConstantOp cstOp =
1225 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();
1226 assert(cstOp &&
"expected cir.const op");
1240 QualType destValueType = at->getValueType();
1243 uint64_t innerSize =
cgm.getASTContext().getTypeSize(destValueType);
1244 uint64_t outerSize =
cgm.getASTContext().getTypeSize(destType);
1245 if (innerSize == outerSize)
1248 assert(innerSize < outerSize &&
"emitted over-large constant for atomic");
1249 cgm.errorNYI(
"emitForMemory: tail padding in atomic initializer");
1255 cgm.errorNYI(
"emitForMemory: zero-extend HLSL bool vectors");
1259 cgm.errorNYI(
"emitForMemory: _BitInt type");
1267 assert(!destType->
isVoidType() &&
"can't emit a void constant");
1269 if (mlir::Attribute c =
1270 ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e), destType))
1271 return llvm::dyn_cast<mlir::TypedAttr>(c);
1275 bool success =
false;
1285 return llvm::dyn_cast<mlir::TypedAttr>(c);
1293 auto &builder =
cgm.getBuilder();
1297 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate none or indeterminate");
1300 mlir::Type ty =
cgm.convertType(destType);
1301 if (mlir::isa<cir::BoolType>(ty))
1303 assert(mlir::isa<cir::IntType>(ty) &&
"expected integral type");
1304 return cir::IntAttr::get(ty, value.
getInt());
1307 const llvm::APFloat &init = value.
getFloat();
1308 if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
1309 !
cgm.getASTContext().getLangOpts().NativeHalfType &&
1310 cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1311 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate half");
1315 mlir::Type ty =
cgm.convertType(destType);
1316 assert(mlir::isa<cir::FPTypeInterface>(ty) &&
1317 "expected floating-point type");
1318 return cir::FPAttr::get(ty, init);
1321 const ArrayType *arrayTy =
cgm.getASTContext().getAsArrayType(destType);
1326 mlir::TypedAttr filler;
1328 mlir::Attribute fillerTemp =
1332 filler = dyn_cast<mlir::TypedAttr>(fillerTemp);
1334 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate array filler should "
1341 cir::ArrayType desiredType =
1346 elts.reserve(numInitElts);
1348 elts.reserve(numElements);
1351 for (
unsigned i = 0; i < numInitElts; ++i) {
1353 const mlir::Attribute element =
1358 elts.push_back(element);
1363 elts.insert(elts.end(), numElements - elts.size(), filler);
1366 while (!elts.empty() && builder.
isNullValue(elts.back()))
1371 if (desiredType.getSize() == 0 && numElements > 0) {
1373 cir::ArrayType::get(desiredType.getElementType(), numElements);
1377 return cir::ZeroAttr::get(desiredType);
1379 return cir::ConstArrayAttr::get(
1380 desiredType, mlir::ArrayAttr::get(builder.getContext(), elts));
1388 elements.reserve(numElements);
1390 for (
unsigned i = 0; i < numElements; ++i) {
1391 const mlir::Attribute element =
1395 elements.push_back(element);
1398 const auto desiredVecTy =
1399 mlir::cast<cir::VectorType>(
cgm.convertType(destType));
1401 return cir::ConstVectorAttr::get(
1403 mlir::ArrayAttr::get(
cgm.getBuilder().getContext(), elements));
1412 if (
auto const *cxxDecl = dyn_cast<CXXMethodDecl>(memberDecl)) {
1413 auto ty = mlir::cast<cir::MethodType>(
cgm.convertType(destType));
1414 if (cxxDecl->isVirtual())
1415 return cgm.getCXXABI().buildVirtualMethodAttr(ty, cxxDecl);
1417 cir::FuncOp methodFuncOp =
1418 cgm.getAddrOfFunction(cxxDecl, ty.getMemberFuncTy());
1419 return cgm.getBuilder().getMethodAttr(ty, methodFuncOp);
1422 auto cirTy = mlir::cast<cir::DataMemberType>(
cgm.convertType(destType));
1426 std::optional<llvm::SmallVector<int32_t>> path =
1433 return ConstantLValueEmitter(*
this, value, destType).tryEmit();
1436 return ConstRecordBuilder::buildRecord(*
this, value, destType);
1439 mlir::Type desiredType =
cgm.convertType(destType);
1440 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);
1442 mlir::Type complexElemTy =
complexType.getElementType();
1446 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1447 cir::IntAttr::get(complexElemTy, real),
1448 cir::IntAttr::get(complexElemTy, imag));
1452 "expected floating-point type");
1455 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1456 cir::FPAttr::get(complexElemTy, real),
1457 cir::FPAttr::get(complexElemTy, imag));
1462 "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");
1465 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate matrix");
1468 llvm_unreachable(
"Unknown APValue kind");
1477 return builder.getConstNullPtrAttr(
getTypes().convertTypeForMem(t));
1479 if (
getTypes().isZeroInitializable(t))
1480 return builder.getZeroInitAttr(
getTypes().convertTypeForMem(t));
1483 errorNYI(
"CIRGenModule::emitNullConstantAttr ConstantArrayType");
1487 if (
const RecordType *rt = t->
getAs<RecordType>())
1488 return ::emitNullConstant(*
this, rt->getDecl(),
true);
1491 "Should only see pointers to data members here!");
1498 return ::emitNullConstant(*
this, record,
false);
Defines the clang::ASTContext interface.
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 cir::GlobalViewAttr tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter, const CompoundLiteralExpr *e)
static ParseState advance(ParseState S, size_t N)
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
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)
C++ view class that accepts both !cir.struct and !cir.union types.
mlir::Type getElementType(size_t idx) const
size_t getNumElements() const
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
bool hasArrayFiller() const
const LValueBase getLValueBase() const
APValue & getArrayInitializedElt(unsigned I)
APSInt & getComplexIntImag()
ValueKind getKind() const
unsigned getArrayInitializedElts() const
const ValueDecl * getMemberPointerDecl() const
APValue & getVectorElt(unsigned I)
APValue & getArrayFiller()
unsigned getVectorLength() const
unsigned getArraySize() const
@ Indeterminate
This object has an indeterminate value (C++ [basic.indet]).
@ None
There is no such object (it's outside its lifetime).
APSInt & getComplexIntReal()
APFloat & getComplexFloatImag()
APFloat & getComplexFloatReal()
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
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.
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...
LabelDecl * getLabel() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty, llvm::ArrayRef< int32_t > path)
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
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()
llvm::SmallVector< cir::BlockAddrInfoAttr > indirectGotoTargets
Labels whose address is taken in this function (via &&label, as either an operation or a constant ini...
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.
void finalize(cir::GlobalOp gv)
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.
bool isInConstantContext() const
mlir::Attribute tryEmitAbstract(const Expr *e, QualType destType)
const CIRGenFunction * cgf
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.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ constructor within a class.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Expr * getExpr()
Get the initialization expression that will be used.
Represents a C++ struct/union/class.
bool isTypeOperand() const
QualType getTypeOperand(const ASTContext &Context) const
Retrieves the type operand of this typeid() expression after various required adjustments (removing r...
Expr * getExprOperand() const
SourceRange getSourceRange() const LLVM_READONLY
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
CompoundLiteralExpr - [C99 6.5.2.5].
const Expr * getInitializer() const
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...
APValue getAPValueResult() const
SourceLocation getBeginLoc() const LLVM_READONLY
bool hasAPValueResult() const
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
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...
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...
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
bool isZeroSize(const ASTContext &Ctx) const
Determine if this field is a subobject of zero size, that is, either a zero-length bit-field or a fie...
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
const Expr * getSubExpr() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Expr * getResultExpr()
Return the result expression of this controlling expression.
Describes an C or C++ initializer list.
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
const Expr * getInit(unsigned Init) const
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
A pointer to member type per C++ 8.3.3 - Pointers to members.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
StringLiteral * getFunctionName()
A (possibly-)qualified type.
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Represents a struct/union/class.
field_range fields() const
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...
SourceLocation getBeginLoc() const LLVM_READONLY
Expr * getReplacement() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isPackedVectorBoolType(const ASTContext &ctx) const
CXXRecordDecl * castAsCXXRecordDecl() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isExtVectorBoolType() const
bool isMemberDataPointerType() const
bool isBitIntType() const
RecordDecl * castAsRecordDecl() const
bool isVectorType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Expr * getSubExpr() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
const Expr * getInit() const
const APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Represents a GCC generic vector type.
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
bool isEmptyRecordForLayout(const ASTContext &context, QualType t)
isEmptyRecordForLayout - Return true if a structure contains only empty base classes (per isEmptyReco...
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SD_Static
Static storage duration.
U cast(CodeGen::Address addr)
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
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.
APValue Val
Val - This is the value the expression can be folded to.
bool hasSideEffects() const
Return true if the evaluated expression has side effects.