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"
51 for (
auto [idx, memberTy] : llvm::enumerate(recordTy.
getMembers())) {
54 mlir::Attribute elt = elements[idx];
60 stored.push_back(elt);
73class RecordBuilderInitList {
76 std::variant<APValue, const InitListExpr *> value;
78 bool holdsExpr()
const {
79 return std::holds_alternative<const InitListExpr *>(value);
82 bool holdsAPValue()
const {
return std::holds_alternative<APValue>(value); }
84 const Expr *getExpr() {
86 return std::get<const InitListExpr *>(value)->getInit(initIdx);
91 return cgm.
getLoc(std::get<const InitListExpr *>(value)->getBeginLoc());
95 assert(holdsAPValue());
97 return std::get<APValue>(value).getUnionValue();
98 return std::get<APValue>(value).getStructField(initIdx);
103 : isUnion(rd->
isUnion()), value(val) {}
105 : isUnion(rd->
isUnion()), value(ile) {
110 if (
auto *
const *ile = std::get_if<const InitListExpr *>(&value))
111 return initIdx >= (*ile)->getNumInits();
116 return !std::get<APValue>(value).isUnion();
118 return initIdx >= std::get<APValue>(value).getStructNumFields();
121 const FieldDecl *getActiveUnionField()
const {
123 return std::get<const InitListExpr *>(value)
124 ->getInitializedFieldInUnion();
125 return std::get<APValue>(value).getUnionField();
134 if (holdsExpr() && isa_and_nonnull<NoInitExpr>(getExpr()))
156 APValue getBase(
unsigned idx) {
161 assert(holdsAPValue());
163 return std::get<APValue>(value).getStructBase(idx);
167 if (holdsExpr() && getExpr()->HasSideEffects(ctx))
175 const Expr *e = getExpr();
183llvm::APInt bitfieldStorageToAPInt(mlir::Attribute
attr,
unsigned storageSize,
187 return llvm::APInt(storageSize, 0);
189 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(
attr))
190 return intAttr.getValue();
194 llvm::APInt result(storageSize, 0);
195 auto elts = mlir::cast<mlir::ArrayAttr>(
196 mlir::cast<cir::ConstArrayAttr>(
attr).getElts());
198 unsigned numBytes = elts.size();
199 for (
unsigned i = 0; i != numBytes; ++i) {
200 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
202 mlir::cast<cir::IntAttr>(elts[i]).getValue().zextOrTrunc(8);
203 result.insertBits(
byte, byteIdx * 8);
208mlir::Attribute apIntToBitfieldStorage(
CIRGenModule &cgm,
209 mlir::Type storageType,
210 const llvm::APInt &value,
213 if (mlir::isa<cir::IntTypeInterface>(storageType))
214 return cir::IntAttr::get(storageType, value);
218 auto arrayTy = mlir::cast<cir::ArrayType>(storageType);
220 unsigned numBytes = arrayTy.getSize();
224 for (
unsigned i = 0; i != numBytes; ++i) {
225 unsigned byteIdx = isBigEndian ? numBytes - 1 - i : i;
226 bytes[i] = cir::IntAttr::get(byteTy, value.extractBits(8, byteIdx * 8));
228 return cir::ConstArrayAttr::get(
229 arrayTy, mlir::ArrayAttr::get(builder.getContext(),
bytes));
239 mlir::Attribute existingVal,
240 cir::IntAttr newVal,
bool isSigned,
244 bitfieldStorageToAPInt(existingVal, bfInfo.
storageSize, isBigEndian);
246 llvm::APInt curValue = newVal.getValue();
251 curValue = curValue.sextOrTrunc(bfInfo.
size);
253 curValue = curValue.zextOrTrunc(bfInfo.
size);
260 curValue = curValue.shl(bfInfo.
offset);
267 return apIntToBitfieldStorage(cgm, bfInfo.
storageType, result, isBigEndian);
273 mlir::Attribute existingVal, mlir::Attribute newVal) {
275 auto intAttr = mlir::dyn_cast<cir::IntAttr>(newVal);
279 auto boolAttr = mlir::cast<cir::BoolAttr>(newVal);
280 intAttr = cir::IntAttr::get(
281 builder.
getUIntNTy(1), llvm::APInt(1, boolAttr.getValue()));
284 return updateBitfieldInit(
285 cgm, existingVal, intAttr,
292 RecordBuilderInitList
inits,
bool handleBases,
311 mlir::Attribute eltAttr =
inits.emit(emitter, activeField->
getType());
316 eltAttr = setBitfieldInit(cgm, cirLayout, builder, activeField,
319 return cir::ConstRecordAttr::get(recordTy, builder.getArrayAttr({eltAttr}));
324 if (
auto *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
332 auto apOp = addrPtr.getDefiningOp<cir::VTableAddrPointOp>();
333 mlir::ArrayAttr indices = builder.getArrayAttr(
334 {builder.getI32IntegerAttr(apOp.getAddressPoint().getIndex()),
335 builder.getI32IntegerAttr(apOp.getAddressPoint().getOffset())});
337 cir::GlobalViewAttr::get(cir::VPtrType::get(builder.getContext()),
338 apOp.getNameAttr(), indices);
341 for (
auto [idx, base] : llvm::enumerate(cxxrd->bases())) {
348 if (base.isVirtual())
351 const auto *baseDecl = base.getType()->castAsCXXRecordDecl();
364 elements[baseFieldIdx] = buildRecordHelper(
365 emitter, baseDecl, vtableBaseTy, RecordBuilderInitList(rd, baseValue),
366 handleBases, baseOff,
true);
369 if (cxxrd->getNumVBases()) {
370 cgm.
errorNYI(cxxrd->getSourceRange(),
371 "buildRecordHelper: virtual base classes");
384 if (
inits.shouldSkip(field)) {
385 inits.advanceSkip(field);
403 mlir::Attribute eltAttr =
inits.emit(emitter, field->
getType());
410 elements[fieldIdx] = setBitfieldInit(cgm, cirLayout, builder, field,
411 elements[fieldIdx], eltAttr);
413 elements[fieldIdx] = eltAttr;
434 const bool handleBases =
false;
436 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, ile),
444 valTy->
castAs<clang::RecordType>()->getDecl()->getDefinitionOrSelf();
445 return buildRecordHelper(emitter, rd, rd, RecordBuilderInitList(rd, val),
462class ConstExprEmitter
463 :
public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
469 : cgm(emitter.cgm), emitter(emitter) {}
475 mlir::Attribute VisitStmt(Stmt *s, QualType t) {
return {}; }
477 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
478 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
483 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
488 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
493 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
498 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
502 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
506 mlir::Attribute VisitCastExpr(
CastExpr *e, QualType destType) {
507 if (
const auto *ece = dyn_cast<ExplicitCastExpr>(e))
508 cgm.emitExplicitCastExprType(ece,
509 const_cast<CIRGenFunction *
>(emitter.cgf));
515 case CK_AddressSpaceConversion:
516 case CK_ReinterpretMemberPointer:
517 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitCastExpr");
520 case CK_DerivedToBaseMemberPointer:
521 case CK_BaseToDerivedMemberPointer:
527 case CK_LValueToRValue:
528 case CK_AtomicToNonAtomic:
529 case CK_NonAtomicToAtomic:
531 case CK_ConstructorConversion:
532 return Visit(subExpr, destType);
534 case CK_IntToOCLSampler:
535 llvm_unreachable(
"global sampler variables are not generated");
538 llvm_unreachable(
"saw dependent cast!");
540 case CK_BuiltinFnToFnPtr:
541 llvm_unreachable(
"builtin functions are handled elsewhere");
544 case CK_ObjCObjectLValueCast:
545 case CK_ARCProduceObject:
546 case CK_ARCConsumeObject:
547 case CK_ARCReclaimReturnedObject:
548 case CK_ARCExtendBlockObject:
549 case CK_CopyAndAutoreleaseBlockObject:
557 case CK_LValueBitCast:
558 case CK_LValueToRValueBitCast:
559 case CK_NullToMemberPointer:
560 case CK_UserDefinedConversion:
561 case CK_CPointerToObjCPointerCast:
562 case CK_BlockPointerToObjCPointerCast:
563 case CK_AnyPointerToBlockPointerCast:
564 case CK_ArrayToPointerDecay:
565 case CK_FunctionToPointerDecay:
566 case CK_BaseToDerived:
567 case CK_DerivedToBase:
568 case CK_UncheckedDerivedToBase:
569 case CK_MemberPointerToBoolean:
571 case CK_FloatingRealToComplex:
572 case CK_FloatingComplexToReal:
573 case CK_FloatingComplexToBoolean:
574 case CK_FloatingComplexCast:
575 case CK_FloatingComplexToIntegralComplex:
576 case CK_IntegralRealToComplex:
577 case CK_IntegralComplexToReal:
578 case CK_IntegralComplexToBoolean:
579 case CK_IntegralComplexCast:
580 case CK_IntegralComplexToFloatingComplex:
581 case CK_PointerToIntegral:
582 case CK_PointerToBoolean:
583 case CK_NullToPointer:
584 case CK_IntegralCast:
585 case CK_BooleanToSignedIntegral:
586 case CK_IntegralToPointer:
587 case CK_IntegralToBoolean:
588 case CK_IntegralToFloating:
589 case CK_FloatingToIntegral:
590 case CK_FloatingToBoolean:
591 case CK_FloatingCast:
592 case CK_FloatingToFixedPoint:
593 case CK_FixedPointToFloating:
594 case CK_FixedPointCast:
595 case CK_FixedPointToBoolean:
596 case CK_FixedPointToIntegral:
597 case CK_IntegralToFixedPoint:
598 case CK_ZeroToOCLOpaqueType:
600 case CK_HLSLArrayRValue:
601 case CK_HLSLVectorTruncation:
602 case CK_HLSLMatrixTruncation:
603 case CK_HLSLElementwiseCast:
604 case CK_HLSLAggregateSplatCast:
607 llvm_unreachable(
"Invalid CastKind");
610 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
613 return Visit(die->
getExpr(), t);
616 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
621 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
626 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *e,
628 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(t));
631 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
633 return Visit(ile->
getInit(0), t);
643 return ConstRecordBuilder::buildRecord(emitter, ile, t);
656 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
658 mlir::Attribute c = Visit(e->
getBase(), destType);
663 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
667 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
673 assert(e->
getNumArgs() == 1 &&
"trivial ctor with > 1 argument");
675 "trivial ctor has argument but isn't a copy/move ctor");
678 assert(cgm.getASTContext().hasSameUnqualifiedType(ty,
arg->getType()) &&
679 "argument to copy ctor is of wrong type");
683 if (
auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
684 return Visit(mte->getSubExpr(), ty);
694 return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
697 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
699 return cgm.getConstantArrayFromStringLiteral(e);
702 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
703 cgm.errorNYI(e->
getBeginLoc(),
"ConstExprEmitter::VisitObjCEncodeExpr");
707 mlir::Attribute VisitUnaryExtension(
const UnaryOperator *e, QualType t) {
712 mlir::Type convertType(QualType t) {
return cgm.convertType(t); }
719 type.getQualifiers());
732struct ConstantLValue {
733 llvm::PointerUnion<mlir::Value, mlir::Attribute> value;
734 bool hasOffsetApplied;
736 ConstantLValue(std::nullptr_t)
738 ConstantLValue(cir::GlobalViewAttr address)
739 : value(address), hasOffsetApplied(
false) {}
740 ConstantLValue(cir::GlobalOffsetAttr address)
741 : value(address), hasOffsetApplied(
true) {}
742 ConstantLValue(cir::BlockAddrInfoAttr address)
743 : value(address), hasOffsetApplied(
true) {}
745 ConstantLValue() : value(
nullptr), hasOffsetApplied(
false) {}
749class ConstantLValueEmitter
752 ConstantEmitter &emitter;
757 friend StmtVisitorBase;
760 ConstantLValueEmitter(ConstantEmitter &emitter,
const APValue &value,
762 : cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}
764 mlir::Attribute tryEmit();
767 mlir::Attribute tryEmitAbsolute(mlir::Type destTy);
768 ConstantLValue tryEmitBase(
const APValue::LValueBase &base);
770 ConstantLValue VisitStmt(
const Stmt *s) {
return nullptr; }
771 ConstantLValue VisitConstantExpr(
const ConstantExpr *e);
772 ConstantLValue VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e);
773 ConstantLValue VisitStringLiteral(
const StringLiteral *e);
774 ConstantLValue VisitObjCBoxedExpr(
const ObjCBoxedExpr *e);
775 ConstantLValue VisitObjCEncodeExpr(
const ObjCEncodeExpr *e);
776 ConstantLValue VisitObjCStringLiteral(
const ObjCStringLiteral *e);
777 ConstantLValue VisitPredefinedExpr(
const PredefinedExpr *e);
778 ConstantLValue VisitAddrLabelExpr(
const AddrLabelExpr *e);
779 ConstantLValue VisitCallExpr(
const CallExpr *e);
780 ConstantLValue VisitBlockExpr(
const BlockExpr *e);
781 ConstantLValue VisitCXXTypeidExpr(
const CXXTypeidExpr *e);
783 VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e);
788 std::optional<mlir::ArrayAttr> getOffsetIndices(mlir::Type ty) {
789 int64_t offset = value.getLValueOffset().getQuantity();
790 cir::CIRDataLayout layout(cgm.getModule());
791 SmallVector<int64_t, 3> idxVec;
792 if (!cgm.getBuilder().computeGlobalViewIndicesFromFlatOffset(
793 offset, ty, layout, idxVec))
796 llvm::SmallVector<mlir::Attribute, 3> indices;
797 for (int64_t i : idxVec) {
798 mlir::IntegerAttr intAttr = cgm.getBuilder().getI32IntegerAttr(i);
799 indices.push_back(intAttr);
803 return mlir::ArrayAttr{};
804 return cgm.getBuilder().getArrayAttr(indices);
808 ConstantLValue applyOffset(ConstantLValue &c) {
810 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(c.value)) {
811 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr)) {
812 auto baseTy = mlir::cast<cir::PointerType>(gv.getType()).getPointee();
813 mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
814 assert(!gv.getIndices() &&
"Global view is already indexed");
815 std::optional<mlir::ArrayAttr> indices = getOffsetIndices(baseTy);
817 return cir::GlobalOffsetAttr::get(
818 destTy, gv.getSymbol(), value.getLValueOffset().getQuantity());
819 return cir::GlobalViewAttr::get(destTy, gv.getSymbol(), *indices);
821 llvm_unreachable(
"Unsupported attribute type to offset");
824 cgm.errorNYI(
"ConstantLValue: non-attribute offset");
831mlir::Attribute ConstantLValueEmitter::tryEmit() {
842 assert(mlir::isa<cir::PointerType>(destTy));
847 return tryEmitAbsolute(destTy);
850 ConstantLValue result = tryEmitBase(base);
853 llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;
858 if (!result.hasOffsetApplied)
859 value = applyOffset(result).value;
863 if (mlir::isa<cir::PointerType>(destTy)) {
864 if (
auto attr = mlir::dyn_cast<mlir::Attribute>(value))
866 cgm.
errorNYI(
"ConstantLValueEmitter: non-attribute pointer");
870 cgm.
errorNYI(
"ConstantLValueEmitter: other?");
876mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {
878 auto destPtrTy = mlir::cast<cir::PointerType>(destTy);
880 destPtrTy, value.getLValueOffset().getQuantity());
884ConstantLValueEmitter::tryEmitBase(
const APValue::LValueBase &base) {
886 if (
const ValueDecl *d = base.
dyn_cast<
const ValueDecl *>()) {
891 if (d->hasAttr<WeakRefAttr>()) {
893 "ConstantLValueEmitter: emit pointer base for weakref");
897 if (
auto *fd = dyn_cast<FunctionDecl>(d)) {
900 mlir::MLIRContext *mlirContext = builder.getContext();
906 assert(mlir::isa<cir::PointerType>(ptrTy) &&
907 "function address in constant must be a pointer");
908 return cir::GlobalViewAttr::get(
910 mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
913 if (
auto *vd = dyn_cast<VarDecl>(d)) {
915 if (!vd->hasLocalStorage()) {
916 if (vd->isFileVarDecl() || vd->hasExternalStorage())
919 if (vd->isLocalVarDecl()) {
928 cgm.
errorNYI(d->getSourceRange(),
"ConstantLValueEmitter: MSGuidDecl");
930 if (
const auto *gcd = dyn_cast<UnnamedGlobalConstantDecl>(d))
934 if (
const auto *tpo = dyn_cast<TemplateParamObjectDecl>(d))
942 if (TypeInfoLValue typeInfo = base.
dyn_cast<TypeInfoLValue>())
944 cgm.
getBuilder().getUnknownLoc(), QualType(typeInfo.getType(), 0)));
947 return Visit(base.
get<
const Expr *>());
950ConstantLValue ConstantLValueEmitter::VisitConstantExpr(
const ConstantExpr *e) {
955static cir::GlobalViewAttr
970 "file-scope compound literal did not have constant initializer!");
974 auto typedInit = mlir::cast<mlir::TypedAttr>(c);
983 gv.setLinkage(cir::GlobalLinkageKind::InternalLinkage);
984 gv.setAlignment(align.getAsAlign().value());
993ConstantLValueEmitter::VisitCompoundLiteralExpr(
const CompoundLiteralExpr *e) {
994 ConstantEmitter compoundLiteralEmitter(cgm, emitter.
cgf);
1000ConstantLValueEmitter::VisitStringLiteral(
const StringLiteral *e) {
1005ConstantLValueEmitter::VisitObjCEncodeExpr(
const ObjCEncodeExpr *e) {
1011ConstantLValueEmitter::VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1013 "ConstantLValueEmitter: objc string literal");
1018ConstantLValueEmitter::VisitObjCBoxedExpr(
const ObjCBoxedExpr *e) {
1024ConstantLValueEmitter::VisitPredefinedExpr(
const PredefinedExpr *e) {
1029ConstantLValueEmitter::VisitAddrLabelExpr(
const AddrLabelExpr *e) {
1035 assert(emitter.
cgf &&
"label address in a constant requires a function");
1036 CIRGenFunction &cgf = *
const_cast<CIRGenFunction *
>(emitter.
cgf);
1038 return cir::BlockAddrInfoAttr::get(&cgf.
getMLIRContext(), func.getSymName(),
1042ConstantLValue ConstantLValueEmitter::VisitCallExpr(
const CallExpr *e) {
1047ConstantLValue ConstantLValueEmitter::VisitBlockExpr(
const BlockExpr *e) {
1053ConstantLValueEmitter::VisitCXXTypeidExpr(
const CXXTypeidExpr *e) {
1062ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
1063 const MaterializeTemporaryExpr *e) {
1067 return ConstantLValue(
1076 initializeNonAbstract();
1082 initializeNonAbstract();
1088 initializeNonAbstract();
1090 assert(c &&
"couldn't emit constant value non-abstractly?");
1095 assert(initializedNonAbstract &&
1096 "finalizing emitter that was used for abstract emission?");
1097 assert(!finalized &&
"finalizing emitter multiple times");
1098 assert(!gv.isDeclaration());
1107 AbstractStateRAII state(*
this,
true);
1112 assert((!initializedNonAbstract || finalized || failed) &&
1113 "not finalized after being initialized for non-abstract emission");
1117 mlir::Type baseType,
1121 bool asCompleteObject) {
1123 mlir::Type ty = (asCompleteObject ? layout.
getCIRType()
1125 auto recordTy = mlir::cast<cir::RecordType>(ty);
1127 unsigned numElements = rd->
isUnion() ? 1 : recordTy.getNumElements();
1130 auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);
1134 if (base.isVirtual()) {
1150 mlir::Type baseType = recordTy.getElementType(fieldIndex);
1159 if (!field->isBitField() &&
1167 if (field->getIdentifier())
1169 if (
const auto *fieldRD = field->getType()->getAsRecordDecl())
1170 if (fieldRD->findFirstNamedDataMember())
1176 if (cxxrd && asCompleteObject) {
1178 cgm.
errorNYI(vbase.getSourceRange(),
"emitNullConstant: virtual base");
1183 mlir::MLIRContext *mlirContext = recordTy.getContext();
1191 return cir::ConstRecordAttr::get(
1192 recordTy, mlir::ArrayAttr::get(mlirContext, elements));
1201 return cir::ConstRecordAttr::get(
1202 recordTy, mlir::ArrayAttr::get(mlirContext, storedElements));
1207 mlir::Type baseType,
1227 if (
const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.
getInit())) {
1230 return cgm.emitNullConstantAttr(d.
getType());
1237 assert(e &&
"No initializer to emit");
1243 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e),
1258 AbstractStateRAII state{*
this,
true};
1268 retType =
cgm.getASTContext().getLValueReferenceType(retType);
1279 return mlir::cast<mlir::TypedAttr>(
attr);
1293 AbstractStateRAII state{*
this,
true};
1294 mlir::Attribute c = mlir::cast<mlir::Attribute>(
tryEmitPrivate(e, destType));
1297 "emitAbstract failed, emit null constaant");
1304 AbstractStateRAII state(*
this,
true);
1307 cgm.errorNYI(loc,
"emitAbstract failed, emit null constaant");
1314 cir::ConstantOp cstOp =
1315 cgm.emitNullConstant(t, loc).getDefiningOp<cir::ConstantOp>();
1316 assert(cstOp &&
"expected cir.const op");
1330 QualType destValueType = at->getValueType();
1333 uint64_t innerSize =
cgm.getASTContext().getTypeSize(destValueType);
1334 uint64_t outerSize =
cgm.getASTContext().getTypeSize(destType);
1335 if (innerSize == outerSize)
1338 assert(innerSize < outerSize &&
"emitted over-large constant for atomic");
1339 cgm.errorNYI(
"emitForMemory: tail padding in atomic initializer");
1345 cgm.errorNYI(
"emitForMemory: zero-extend HLSL bool vectors");
1358 assert(!destType->
isVoidType() &&
"can't emit a void constant");
1360 if (mlir::Attribute c =
1361 ConstExprEmitter(*this).Visit(
const_cast<Expr *
>(e), destType))
1362 return llvm::dyn_cast<mlir::TypedAttr>(c);
1366 bool success =
false;
1376 return llvm::dyn_cast<mlir::TypedAttr>(c);
1384 auto &builder =
cgm.getBuilder();
1388 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate none or indeterminate");
1391 mlir::Type ty =
cgm.convertType(destType);
1392 if (mlir::isa<cir::BoolType>(ty))
1394 assert(mlir::isa<cir::IntType>(ty) &&
"expected integral type");
1395 return cir::IntAttr::get(ty, value.
getInt());
1398 mlir::Type ty =
cgm.convertType(destType);
1399 assert(mlir::isa<cir::FPTypeInterface>(ty) &&
1400 "expected floating-point type");
1401 return cir::FPAttr::get(ty, value.
getFloat());
1404 const ArrayType *arrayTy =
cgm.getASTContext().getAsArrayType(destType);
1409 mlir::TypedAttr filler;
1411 mlir::Attribute fillerTemp =
1415 filler = dyn_cast<mlir::TypedAttr>(fillerTemp);
1417 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate array filler should "
1424 cir::ArrayType desiredType =
1429 elts.reserve(numInitElts);
1431 elts.reserve(numElements);
1434 for (
unsigned i = 0; i < numInitElts; ++i) {
1436 const mlir::Attribute element =
1441 elts.push_back(element);
1446 elts.insert(elts.end(), numElements - elts.size(), filler);
1449 while (!elts.empty() && builder.
isNullValue(elts.back()))
1454 if (desiredType.getSize() == 0 && numElements > 0) {
1456 cir::ArrayType::get(desiredType.getElementType(), numElements);
1460 return cir::ZeroAttr::get(desiredType);
1462 return cir::ConstArrayAttr::get(
1463 desiredType, mlir::ArrayAttr::get(builder.getContext(), elts));
1471 elements.reserve(numElements);
1473 for (
unsigned i = 0; i < numElements; ++i) {
1474 const mlir::Attribute element =
1478 elements.push_back(element);
1481 const auto desiredVecTy =
1482 mlir::cast<cir::VectorType>(
cgm.convertType(destType));
1484 return cir::ConstVectorAttr::get(
1486 mlir::ArrayAttr::get(
cgm.getBuilder().getContext(), elements));
1495 if (
auto const *cxxDecl = dyn_cast<CXXMethodDecl>(memberDecl)) {
1496 auto ty = mlir::cast<cir::MethodType>(
cgm.convertType(destType));
1497 if (cxxDecl->isVirtual())
1498 return cgm.getCXXABI().buildVirtualMethodAttr(ty, cxxDecl);
1500 cir::FuncOp methodFuncOp =
1501 cgm.getAddrOfFunction(cxxDecl, ty.getMemberFuncTy());
1502 return cgm.getBuilder().getMethodAttr(ty, methodFuncOp);
1505 auto cirTy = mlir::cast<cir::DataMemberType>(
cgm.convertType(destType));
1511 if (
const auto *
fieldDecl = dyn_cast<FieldDecl>(memberDecl);
1517 return cir::DataMemberOffsetAttr::get(cirTy, offset.
getQuantity());
1520 std::optional<llvm::SmallVector<int32_t>> path =
1521 cgm.buildMemberPath(destClass, memberDecl);
1527 return ConstantLValueEmitter(*
this, value, destType).tryEmit();
1530 return ConstRecordBuilder::buildRecord(*
this, value, destType);
1533 mlir::Type desiredType =
cgm.convertType(destType);
1534 auto complexType = mlir::dyn_cast<cir::ComplexType>(desiredType);
1536 mlir::Type complexElemTy =
complexType.getElementType();
1540 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1541 cir::IntAttr::get(complexElemTy, real),
1542 cir::IntAttr::get(complexElemTy, imag));
1546 "expected floating-point type");
1549 return cir::ConstComplexAttr::get(builder.getContext(),
complexType,
1550 cir::FPAttr::get(complexElemTy, real),
1551 cir::FPAttr::get(complexElemTy, imag));
1554 mlir::Type ty =
cgm.convertType(destType);
1555 return cir::IntAttr::get(ty, value.
getFixedPoint().getValue());
1565 mlir::Type resultType =
cgm.getTypes().convertType(destType);
1566 auto intResultType = mlir::cast<cir::IntType>(resultType);
1568 return cir::BlockAddrDiffAttr::get(
1569 builder.getContext(), intResultType, func.getSymName(),
1574 cgm.errorNYI(
"ConstExprEmitter::tryEmitPrivate matrix");
1577 llvm_unreachable(
"Unknown APValue kind");
1586 return builder.getConstNullPtrAttr(
getTypes().convertTypeForMem(t));
1588 if (
getTypes().isZeroInitializable(t))
1589 return builder.getZeroInitAttr(
getTypes().convertTypeForMem(t));
1592 errorNYI(
"CIRGenModule::emitNullConstantAttr ConstantArrayType");
1596 if (
const RecordType *rt = t->
getAs<RecordType>())
1597 return ::emitNullConstant(*
this, rt->getDecl(),
true);
1600 "Should only see pointers to data members here!");
1607 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 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)
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.
llvm::ArrayRef< mlir::Type > getMembers() 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
APFixedPoint & getFixedPoint()
const ValueDecl * getMemberPointerDecl() const
const AddrLabelExpr * getAddrLabelDiffRHS() 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()
const AddrLabelExpr * getAddrLabelDiffLHS() const
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...
AddrLabelExpr - The GNU address of label extension, representing &&label.
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, cir::RecordType recordTy)
bool isNullValue(mlir::Attribute attr) const
cir::IntType getUIntNTy(int n)
virtual mlir::Value getVTableAddressPoint(BaseSubobject base, const CXXRecordDecl *vtableClass)=0
Get the address point of the vtable for the given base subobject.
mlir::Operation * curFn
The current function or global initializer that is generated code for.
mlir::MLIRContext & getMLIRContext()
This class organizes the cross-function state that is used while generating CIR code.
cir::GlobalOp getAddrOfUnnamedGlobalConstantDecl(const UnnamedGlobalConstantDecl *gcd)
cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
clang::ASTContext & getASTContext() const
CIRGenBuilderTy & getBuilder()
std::string getUniqueGlobalName(const std::string &baseName)
cir::GlobalOp getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo)
Get the GlobalOp of a template parameter object.
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record)
Return a null constant appropriate for zero-initializing a base class with the given type.
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
mlir::TypedAttr emitNullConstantAttr(QualType t)
const cir::CIRDataLayout getDataLayout() const
mlir::Operation * getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *mte, const Expr *init)
Returns a pointer to a global variable representing a temporary with static or thread storage duratio...
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
cir::GlobalOp createGlobalOp(mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
cir::GlobalOp getAddrOfConstantCompoundLiteralIfEmitted(const CompoundLiteralExpr *e)
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
CIRGenCXXABI & getCXXABI() const
cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *e, cir::GlobalOp gv)
This class handles record and union layout info while lowering AST types to CIR types.
cir::RecordType getCIRType() const
Return the "complete object" LLVM type associated with this record.
cir::RecordType getBaseSubobjectCIRType() const
Return the "base subobject" LLVM type associated with this record.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
const CIRGenBitFieldInfo & getBitFieldInfo(const clang::FieldDecl *fd) const
Return the BitFieldInfo that corresponds to the field FD.
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool hasCIRField(const clang::FieldDecl *fd) const
bool isZeroInitializableAsBase() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer when considered as a bas...
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
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 memberOwnsBytes(mlir::Type memberTy)
Whether a record member occupies bytes of its record.
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
bool isEmptyRecordForLayout(const ASTContext &context, QualType t)
isEmptyRecordForLayout - Return true if a structure contains only empty base classes (per isEmptyReco...
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ComplexType > complexType
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
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.