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))
159llvm::APInt bitfieldStorageToAPInt(mlir::Attribute
attr,
unsigned storageSize,
163 return llvm::APInt(storageSize, 0);
165 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(
attr))
166 return intAttr.getValue();
170 llvm::APInt result(storageSize, 0);
171 auto elts = mlir::cast<mlir::ArrayAttr>(
172 mlir::cast<cir::ConstArrayAttr>(
attr).getElts());
174 unsigned numBytes = elts.size();
175 for (
unsigned i = 0; i != numBytes; ++i) {
176 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
178 mlir::cast<cir::IntAttr>(elts[i]).getValue().zextOrTrunc(8);
179 result.insertBits(
byte, byteIdx * 8);
184mlir::Attribute apIntToBitfieldStorage(
CIRGenModule &cgm,
185 mlir::Type storageType,
186 const llvm::APInt &value,
189 if (mlir::isa<cir::IntTypeInterface>(storageType))
190 return cir::IntAttr::get(storageType, value);
194 auto arrayTy = mlir::cast<cir::ArrayType>(storageType);
196 unsigned numBytes = arrayTy.getSize();
200 for (
unsigned i = 0; i != numBytes; ++i) {
201 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
202 bytes[i] = cir::IntAttr::get(byteTy, value.extractBits(8, byteIdx * 8));
204 return cir::ConstArrayAttr::get(
205 arrayTy, mlir::ArrayAttr::get(builder.getContext(),
bytes));
215 mlir::Attribute existingVal,
216 cir::IntAttr newVal,
bool isSigned,
220 bitfieldStorageToAPInt(existingVal, bfInfo.
storageSize, isBigEndian);
222 llvm::APInt curValue = newVal.getValue();
227 curValue = curValue.sextOrTrunc(bfInfo.
size);
229 curValue = curValue.zextOrTrunc(bfInfo.
size);
236 curValue = curValue.shl(bfInfo.
offset);
243 return apIntToBitfieldStorage(cgm, bfInfo.
storageType, result, isBigEndian);
249 mlir::Attribute existingVal, mlir::Attribute newVal) {
251 auto intAttr = mlir::dyn_cast<cir::IntAttr>(newVal);
255 auto boolAttr = mlir::cast<cir::BoolAttr>(newVal);
256 intAttr = cir::IntAttr::get(
257 builder.
getUIntNTy(1), llvm::APInt(1, boolAttr.getValue()));
260 return updateBitfieldInit(
261 cgm, existingVal, intAttr,
268 RecordBuilderInitList
inits,
bool handleBases,
287 mlir::Attribute eltAttr =
inits.emit(emitter, activeField->
getType());
292 eltAttr = setBitfieldInit(cgm, cirLayout, builder, activeField,
295 return cir::ConstRecordAttr::get(recordTy, builder.getArrayAttr({eltAttr}));
300 if (
auto *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
308 auto apOp = addrPtr.getDefiningOp<cir::VTableAddrPointOp>();
309 mlir::ArrayAttr indices = builder.getArrayAttr(
310 {builder.getI32IntegerAttr(apOp.getAddressPoint().getIndex()),
311 builder.getI32IntegerAttr(apOp.getAddressPoint().getOffset())});
313 cir::GlobalViewAttr::get(cir::VPtrType::get(builder.getContext()),
314 apOp.getNameAttr(), indices);
317 for (
auto [idx, base] : llvm::enumerate(cxxrd->bases())) {
324 if (base.isVirtual())
327 const auto *baseDecl = base.getType()->castAsCXXRecordDecl();
340 elements[baseFieldIdx] = buildRecordHelper(
341 emitter, baseDecl, vtableBaseTy, RecordBuilderInitList(rd, baseValue),
342 handleBases, baseOff,
true);
345 if (cxxrd->getNumVBases()) {
346 cgm.
errorNYI(cxxrd->getSourceRange(),
347 "buildRecordHelper: virtual base classes");
360 if (
inits.shouldSkip(field)) {
361 inits.advanceSkip(field);
377 mlir::Attribute eltAttr =
inits.emit(emitter, field->
getType());
384 elements[fieldIdx] = setBitfieldInit(cgm, cirLayout, builder, field,
385 elements[fieldIdx], eltAttr);
387 elements[fieldIdx] = eltAttr;
394 for (
unsigned i = 0; i < elements.size(); ++i) {
414 const bool handleBases =
false;
416 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, ile),
424 valTy->
castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();
425 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, val),
442class ConstExprEmitter
443 :
public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
449 : cgm(emitter.cgm), emitter(emitter) {}
455 mlir::Attribute VisitStmt(Stmt *s, QualType t) {
return {}; }
457 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
458 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
463 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
468 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
473 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
478 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
482 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
486 mlir::Attribute VisitCastExpr(
CastExpr *e, QualType destType) {
487 if (
const auto *ece = dyn_cast<ExplicitCastExpr>(e))
488 cgm.emitExplicitCastExprType(ece,
489 const_cast<CIRGenFunction *
>(emitter.cgf));
495 case CK_AddressSpaceConversion:
496 case CK_ReinterpretMemberPointer:
497 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitCastExpr");
500 case CK_DerivedToBaseMemberPointer:
501 case CK_BaseToDerivedMemberPointer:
507 case CK_LValueToRValue:
508 case CK_AtomicToNonAtomic:
509 case CK_NonAtomicToAtomic:
511 case CK_ConstructorConversion:
512 return Visit(subExpr, destType);
514 case CK_IntToOCLSampler:
515 llvm_unreachable(
"global sampler variables are not generated");
518 llvm_unreachable(
"saw dependent cast!");
520 case CK_BuiltinFnToFnPtr:
521 llvm_unreachable(
"builtin functions are handled elsewhere");
524 case CK_ObjCObjectLValueCast:
525 case CK_ARCProduceObject:
526 case CK_ARCConsumeObject:
527 case CK_ARCReclaimReturnedObject:
528 case CK_ARCExtendBlockObject:
529 case CK_CopyAndAutoreleaseBlockObject:
537 case CK_LValueBitCast:
538 case CK_LValueToRValueBitCast:
539 case CK_NullToMemberPointer:
540 case CK_UserDefinedConversion:
541 case CK_CPointerToObjCPointerCast:
542 case CK_BlockPointerToObjCPointerCast:
543 case CK_AnyPointerToBlockPointerCast:
544 case CK_ArrayToPointerDecay:
545 case CK_FunctionToPointerDecay:
546 case CK_BaseToDerived:
547 case CK_DerivedToBase:
548 case CK_UncheckedDerivedToBase:
549 case CK_MemberPointerToBoolean:
551 case CK_FloatingRealToComplex:
552 case CK_FloatingComplexToReal:
553 case CK_FloatingComplexToBoolean:
554 case CK_FloatingComplexCast:
555 case CK_FloatingComplexToIntegralComplex:
556 case CK_IntegralRealToComplex:
557 case CK_IntegralComplexToReal:
558 case CK_IntegralComplexToBoolean:
559 case CK_IntegralComplexCast:
560 case CK_IntegralComplexToFloatingComplex:
561 case CK_PointerToIntegral:
562 case CK_PointerToBoolean:
563 case CK_NullToPointer:
564 case CK_IntegralCast:
565 case CK_BooleanToSignedIntegral:
566 case CK_IntegralToPointer:
567 case CK_IntegralToBoolean:
568 case CK_IntegralToFloating:
569 case CK_FloatingToIntegral:
570 case CK_FloatingToBoolean:
571 case CK_FloatingCast:
572 case CK_FloatingToFixedPoint:
573 case CK_FixedPointToFloating:
574 case CK_FixedPointCast:
575 case CK_FixedPointToBoolean:
576 case CK_FixedPointToIntegral:
577 case CK_IntegralToFixedPoint:
578 case CK_ZeroToOCLOpaqueType:
580 case CK_HLSLArrayRValue:
581 case CK_HLSLVectorTruncation:
582 case CK_HLSLMatrixTruncation:
583 case CK_HLSLElementwiseCast:
584 case CK_HLSLAggregateSplatCast:
587 llvm_unreachable(
"Invalid CastKind");
590 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
593 return Visit(die->
getExpr(), t);
596 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
601 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
606 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
608 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(t));
611 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
613 return Visit(ile->
getInit(0), t);
623 return ConstRecordBuilder::buildRecord(emitter, ile, t);
636 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
638 mlir::Attribute c = Visit(e->
getBase(), destType);
643 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
647 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
653 assert(e->
getNumArgs() == 1 &&
"trivial ctor with > 1 argument");
655 "trivial ctor has argument but isn't a copy/move ctor");
658 assert(cgm.getASTContext().hasSameUnqualifiedType(ty,
arg->getType()) &&
659 "argument to copy ctor is of wrong type");
663 if (
auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
664 return Visit(mte->getSubExpr(), ty);
674 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
677 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
679 return cgm.getConstantArrayFromStringLiteral(e);
682 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
683 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitObjCEncodeExpr");
687 mlir::Attribute VisitUnaryExtension(
const UnaryOperator *e, QualType t) {
692 mlir::Type convertType(QualType t) {
return cgm.convertType(t); }
699 type.getQualifiers());
712struct ConstantLValue {
713 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
714 bool hasOffsetApplied;
716 ConstantLValue(std::nullptr_t)
718 ConstantLValue(cir::GlobalViewAttr address)
719 : value(address), hasOffsetApplied(
false) {}
720 ConstantLValue(cir::BlockAddrInfoAttr address)
721 : value(address), hasOffsetApplied(
true) {}
723 ConstantLValue() : value(
nullptr), hasOffsetApplied(
false) {}
727class ConstantLValueEmitter
730 ConstantEmitter &emitter;
735 friend StmtVisitorBase;
738 ConstantLValueEmitter(ConstantEmitter &emitter,
const APValue &value,
740 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
742 mlir::Attribute tryEmit();
745 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
746 ConstantLValue tryEmitBase(
const APValue::LValueBase &base);
748 ConstantLValue VisitStmt(
const Stmt *s) {
return nullptr; }
749 ConstantLValue VisitConstantExpr(
const ConstantExpr *e);
750 ConstantLValue VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e);
751 ConstantLValue VisitStringLiteral(
const StringLiteral *e);
752 ConstantLValue VisitObjCBoxedExpr(
const ObjCBoxedExpr *e);
753 ConstantLValue VisitObjCEncodeExpr(
const ObjCEncodeExpr *e);
754 ConstantLValue VisitObjCStringLiteral(
const ObjCStringLiteral *e);
755 ConstantLValue VisitPredefinedExpr(
const PredefinedExpr *e);
756 ConstantLValue VisitAddrLabelExpr(
const AddrLabelExpr *e);
757 ConstantLValue VisitCallExpr(
const CallExpr *e);
758 ConstantLValue VisitBlockExpr(
const BlockExpr *e);
759 ConstantLValue VisitCXXTypeidExpr(
const CXXTypeidExpr *e);
761 VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e);
764 mlir::ArrayAttr getOffset(mlir::Type ty) {
765 int64_t offset = value.getLValueOffset().getQuantity();
766 cir::CIRDataLayout layout(cgm.getModule());
767 SmallVector<int64_t, 3> idxVec;
768 cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(offset, ty, layout,
771 llvm::SmallVector<mlir::Attribute, 3> indices;
772 for (int64_t i : idxVec) {
773 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
774 indices.push_back(intAttr);
779 return cgm.getBuilder().getArrayAttr(indices);
783 ConstantLValue applyOffset(ConstantLValue &c) {
785 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {
786 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {
787 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();
788 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
789 assert(!gv.getIndices() &&
"Global view is already indexed");
790 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(),
793 llvm_unreachable(
"Unsupported attribute type to offset");
796 cgm.errorNYI(
"ConstantLValue: non-attribute offset");
803mlir::Attribute ConstantLValueEmitter::tryEmit() {
814 assert(mlir::isa<cir::PointerType>(destTy));
819 return tryEmitAbsolute(destTy);
822 ConstantLValue result = tryEmitBase(base);
825 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
830 if (!result.hasOffsetApplied)
831 value = applyOffset(result).value;
835 if (mlir::isa<cir::PointerType>(destTy)) {
836 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(value))
838 cgm.
errorNYI(
"ConstantLValueEmitter: non-attribute pointer");
842 cgm.
errorNYI(
"ConstantLValueEmitter: other?");
848mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
850 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
852 destPtrTy, value.getLValueOffset().getQuantity());
856ConstantLValueEmitter::tryEmitBase(
const APValue::LValueBase &base) {
858 if (
const ValueDecl *d = base.
dyn_cast<
const ValueDecl *>()) {
863 if (d->hasAttr<WeakRefAttr>()) {
865 "ConstantLValueEmitter: emit pointer base for weakref");
869 if (
auto *fd = dyn_cast<FunctionDecl>(d)) {
872 mlir::MLIRContext *mlirContext = builder.getContext();
878 assert(mlir::isa<cir::PointerType>(ptrTy) &&
879 "function address in constant must be a pointer");
880 return cir::GlobalViewAttr::get(
882 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
885 if (
auto *vd = dyn_cast<VarDecl>(d)) {
887 if (!vd->hasLocalStorage()) {
888 if (vd->isFileVarDecl() || vd->hasExternalStorage())
891 if (vd->isLocalVarDecl()) {
900 cgm.
errorNYI(d->getSourceRange(),
"ConstantLValueEmitter: MSGuidDecl");
902 if (
const auto *gcd = dyn_cast<UnnamedGlobalConstantDecl>(d))
906 if (
const auto *tpo = dyn_cast<TemplateParamObjectDecl>(d))
914 if (TypeInfoLValue typeInfo = base.
dyn_cast<TypeInfoLValue>())
916 cgm.
getBuilder().getUnknownLoc(), QualType(typeInfo.getType(), 0)));
919 return Visit(base.
get<
const Expr *>());
922ConstantLValue ConstantLValueEmitter::VisitConstantExpr(
const ConstantExpr *e) {
927static cir::GlobalViewAttr
942 "file-scope compound literal did not have constant initializer!");
946 auto typedInit = mlir::cast<mlir::TypedAttr>(c);
955 gv.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
956 gv.setAlignment(align.getAsAlign().value());
965ConstantLValueEmitter::VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e) {
966 ConstantEmitter compoundLiteralEmitter(cgm, emitter.
cgf);
972ConstantLValueEmitter::VisitStringLiteral(
const StringLiteral *e) {
977ConstantLValueEmitter::VisitObjCEncodeExpr(
const ObjCEncodeExpr *e) {
983ConstantLValueEmitter::VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
985 "ConstantLValueEmitter: objc string literal");
990ConstantLValueEmitter::VisitObjCBoxedExpr(
const ObjCBoxedExpr *e) {
996ConstantLValueEmitter::VisitPredefinedExpr(
const PredefinedExpr *e) {
1001ConstantLValueEmitter::VisitAddrLabelExpr(
const AddrLabelExpr *e) {
1007 assert(emitter.
cgf &&
"label address in a constant requires a function");
1008 CIRGenFunction &cgf = *
const_cast<CIRGenFunction *
>(emitter.
cgf);
1010 cir::BlockAddrInfoAttr info = cir::BlockAddrInfoAttr::get(
1016ConstantLValue ConstantLValueEmitter::VisitCallExpr(
const CallExpr *e) {
1021ConstantLValue ConstantLValueEmitter::VisitBlockExpr(
const BlockExpr *e) {
1027ConstantLValueEmitter::VisitCXXTypeidExpr(
const CXXTypeidExpr *e) {
1036ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
1037 const MaterializeTemporaryExpr *e) {
1041 return ConstantLValue(
1050 initializeNonAbstract();
1056 initializeNonAbstract();
1062 initializeNonAbstract();
1064 assert(c &&
"couldn't emit constant value non-abstractly?");
1069 assert(initializedNonAbstract &&
1070 "finalizing emitter that was used for abstract emission?");
1071 assert(!finalized &&
"finalizing emitter multiple times");
1072 assert(!gv.isDeclaration());
1081 AbstractStateRAII state(*
this,
true);
1086 assert((!initializedNonAbstract || finalized || failed) &&
1087 "not finalized after being initialized for non-abstract emission");
1091 mlir::Type baseType,
1095 bool asCompleteObject) {
1097 mlir::Type ty = (asCompleteObject ? layout.
getCIRType()
1099 auto recordTy = mlir::cast<cir::RecordType>(ty);
1101 unsigned numElements = rd->
isUnion() ? 1 : recordTy.getNumElements();
1104 auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
1108 if (base.isVirtual()) {
1124 mlir::Type baseType = recordTy.getElementType(fieldIndex);
1133 if (!field->isBitField() &&
1141 if (field->getIdentifier())
1143 if (
const auto *fieldRD = field->getType()->getAsRecordDecl())
1144 if (fieldRD->findFirstNamedDataMember())
1150 if (cxxrd && asCompleteObject) {
1152 cgm.
errorNYI(vbase.getSourceRange(),
"emitNullConstant: virtual base");
1158 for (
unsigned i = 0; i != numElements; ++i) {
1164 mlir::MLIRContext *mlirContext = recordTy.getContext();
1165 return cir::ConstRecordAttr::get(recordTy,
1166 mlir::ArrayAttr::get(mlirContext, elements));
1171 mlir::Type baseType,
1191 if (
const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.
getInit())) {
1194 return cgm.emitNullConstantAttr(d.
getType());
1201 assert(e &&
"No initializer to emit");
1207 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e),
1222 AbstractStateRAII state{*
this,
true};
1232 retType =
cgm.getASTContext().getLValueReferenceType(retType);
1243 return mlir::cast<mlir::TypedAttr>(
attr);
1257 AbstractStateRAII state{*
this,
true};
1258 mlir::Attribute c = mlir::cast<mlir::Attribute>(
tryEmitPrivate(e, destType));
1261 "emitAbstract failed, emit null constaant");
1268 AbstractStateRAII state(*
this,
true);
1271 cgm.errorNYI(loc,
"emitAbstract failed, emit null constaant");
1278 cir::ConstantOp cstOp =
1279 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();
1280 assert(cstOp &&
"expected cir.const op");
1294 QualType destValueType = at->getValueType();
1297 uint64_t innerSize =
cgm.getASTContext().getTypeSize(destValueType);
1298 uint64_t outerSize =
cgm.getASTContext().getTypeSize(destType);
1299 if (innerSize == outerSize)
1302 assert(innerSize < outerSize &&
"emitted over-large constant for atomic");
1303 cgm.errorNYI(
"emitForMemory: tail padding in atomic initializer");
1309 cgm.errorNYI(
"emitForMemory: zero-extend HLSL bool vectors");
1322 assert(!destType->
isVoidType() &&
"can't emit a void constant");
1324 if (mlir::Attribute c =
1325 ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e), destType))
1326 return llvm::dyn_cast<mlir::TypedAttr>(c);
1330 bool success =
false;
1340 return llvm::dyn_cast<mlir::TypedAttr>(c);
1348 auto &builder =
cgm.getBuilder();
1352 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate none or indeterminate");
1355 mlir::Type ty =
cgm.convertType(destType);
1356 if (mlir::isa<cir::BoolType>(ty))
1358 assert(mlir::isa<cir::IntType>(ty) &&
"expected integral type");
1359 return cir::IntAttr::get(ty, value.
getInt());
1362 mlir::Type ty =
cgm.convertType(destType);
1363 assert(mlir::isa<cir::FPTypeInterface>(ty) &&
1364 "expected floating-point type");
1365 return cir::FPAttr::get(ty, value.
getFloat());
1368 const ArrayType *arrayTy =
cgm.getASTContext().getAsArrayType(destType);
1373 mlir::TypedAttr filler;
1375 mlir::Attribute fillerTemp =
1379 filler = dyn_cast<mlir::TypedAttr>(fillerTemp);
1381 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate array filler should "
1388 cir::ArrayType desiredType =
1393 elts.reserve(numInitElts);
1395 elts.reserve(numElements);
1398 for (
unsigned i = 0; i < numInitElts; ++i) {
1400 const mlir::Attribute element =
1405 elts.push_back(element);
1410 elts.insert(elts.end(), numElements - elts.size(), filler);
1413 while (!elts.empty() && builder.
isNullValue(elts.back()))
1418 if (desiredType.getSize() == 0 && numElements > 0) {
1420 cir::ArrayType::get(desiredType.getElementType(), numElements);
1424 return cir::ZeroAttr::get(desiredType);
1426 return cir::ConstArrayAttr::get(
1427 desiredType, mlir::ArrayAttr::get(builder.getContext(), elts));
1435 elements.reserve(numElements);
1437 for (
unsigned i = 0; i < numElements; ++i) {
1438 const mlir::Attribute element =
1442 elements.push_back(element);
1445 const auto desiredVecTy =
1446 mlir::cast<cir::VectorType>(
cgm.convertType(destType));
1448 return cir::ConstVectorAttr::get(
1450 mlir::ArrayAttr::get(
cgm.getBuilder().getContext(), elements));
1459 if (
auto const *cxxDecl = dyn_cast<CXXMethodDecl>(memberDecl)) {
1460 auto ty = mlir::cast<cir::MethodType>(
cgm.convertType(destType));
1461 if (cxxDecl->isVirtual())
1462 return cgm.getCXXABI().buildVirtualMethodAttr(ty, cxxDecl);
1464 cir::FuncOp methodFuncOp =
1465 cgm.getAddrOfFunction(cxxDecl, ty.getMemberFuncTy());
1466 return cgm.getBuilder().getMethodAttr(ty, methodFuncOp);
1469 auto cirTy = mlir::cast<cir::DataMemberType>(
cgm.convertType(destType));
1481 return cir::DataMemberOffsetAttr::get(cirTy, offset.
getQuantity());
1484 std::optional<llvm::SmallVector<int32_t>> path =
1491 return ConstantLValueEmitter(*
this, value, destType).tryEmit();
1494 return ConstRecordBuilder::buildRecord(*
this, value, destType);
1497 mlir::Type desiredType =
cgm.convertType(destType);
1498 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);
1500 mlir::Type complexElemTy =
complexType.getElementType();
1504 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1505 cir::IntAttr::get(complexElemTy, real),
1506 cir::IntAttr::get(complexElemTy, imag));
1510 "expected floating-point type");
1513 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1514 cir::FPAttr::get(complexElemTy, real),
1515 cir::FPAttr::get(complexElemTy, imag));
1520 "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");
1523 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate matrix");
1526 llvm_unreachable(
"Unknown APValue kind");
1535 return builder.getConstNullPtrAttr(
getTypes().convertTypeForMem(t));
1537 if (
getTypes().isZeroInitializable(t))
1538 return builder.getZeroInitAttr(
getTypes().convertTypeForMem(t));
1541 errorNYI(
"CIRGenModule::emitNullConstantAttr ConstantArrayType");
1545 if (
const RecordType *rt = t->
getAs<RecordType>())
1546 return ::emitNullConstant(*
this, rt->getDecl(),
true);
1549 "Should only see pointers to data members here!");
1556 return ::emitNullConstant(*
this, record,
false);
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 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.
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...
LabelDecl * getLabel() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
cir::IntType getUInt8Ty()
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.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
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
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.