Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This contains code to emit Constant Expr nodes as LLVM code.9//10//===----------------------------------------------------------------------===//1112#include "Address.h"13#include "CIRGenConstantEmitter.h"14#include "CIRGenFunction.h"15#include "CIRGenModule.h"16#include "CIRGenRecordLayout.h"17#include "mlir/IR/Attributes.h"18#include "mlir/IR/BuiltinAttributeInterfaces.h"19#include "mlir/IR/BuiltinAttributes.h"20#include "clang/AST/APValue.h"21#include "clang/AST/ASTContext.h"22#include "clang/AST/Attr.h"23#include "clang/AST/OperationKinds.h"24#include "clang/AST/RecordLayout.h"25#include "clang/AST/StmtVisitor.h"26#include "clang/Basic/Builtins.h"27#include "clang/Basic/Specifiers.h"28#include "clang/CIR/Dialect/IR/CIRAttrs.h"29#include "clang/CIR/Dialect/IR/CIRTypes.h"30#include "llvm/ADT/STLExtras.h"31#include "llvm/ADT/Sequence.h"32#include "llvm/Support/ErrorHandling.h"3334using namespace clang;35using namespace clang::CIRGen;3637//===----------------------------------------------------------------------===//38// ConstExprEmitter39//===----------------------------------------------------------------------===//4041// This class only needs to handle arrays, structs and unions.42//43// In LLVM codegen, when outside C++11 mode, those types are not constant44// folded, while all other types are handled by constant folding.45//46// In CIR codegen, instead of folding things here, we should defer that work47// to MLIR: do not attempt to do much here.48class ConstExprEmitter49: public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {50CIRGenModule &cgm;51LLVM_ATTRIBUTE_UNUSED ConstantEmitter &emitter;5253public:54ConstExprEmitter(ConstantEmitter &emitter)55: cgm(emitter.cgm), emitter(emitter) {}5657//===--------------------------------------------------------------------===//58// Visitor Methods59//===--------------------------------------------------------------------===//6061mlir::Attribute VisitStmt(Stmt *S, QualType T) { return {}; }6263mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {64if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))65return result;66return Visit(ce->getSubExpr(), t);67}6869mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {70return Visit(pe->getSubExpr(), t);71}7273mlir::Attribute74VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,75QualType t) {76return Visit(pe->getReplacement(), t);77}7879mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,80QualType t) {81return Visit(ge->getResultExpr(), t);82}8384mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {85return Visit(ce->getChosenSubExpr(), t);86}8788mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {89return Visit(e->getInitializer(), t);90}9192mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {93if (isa<ExplicitCastExpr>(e))94cgm.errorNYI(e->getBeginLoc(),95"ConstExprEmitter::VisitCastExpr explicit cast");9697Expr *subExpr = e->getSubExpr();9899switch (e->getCastKind()) {100case CK_ToUnion:101case CK_AddressSpaceConversion:102case CK_ReinterpretMemberPointer:103case CK_DerivedToBaseMemberPointer:104case CK_BaseToDerivedMemberPointer:105cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");106return {};107108case CK_LValueToRValue:109case CK_AtomicToNonAtomic:110case CK_NonAtomicToAtomic:111case CK_NoOp:112case CK_ConstructorConversion:113return Visit(subExpr, destType);114115case CK_IntToOCLSampler:116llvm_unreachable("global sampler variables are not generated");117118case CK_Dependent:119llvm_unreachable("saw dependent cast!");120121case CK_BuiltinFnToFnPtr:122llvm_unreachable("builtin functions are handled elsewhere");123124// These will never be supported.125case CK_ObjCObjectLValueCast:126case CK_ARCProduceObject:127case CK_ARCConsumeObject:128case CK_ARCReclaimReturnedObject:129case CK_ARCExtendBlockObject:130case CK_CopyAndAutoreleaseBlockObject:131return {};132133// These don't need to be handled here because Evaluate knows how to134// evaluate them in the cases where they can be folded.135case CK_BitCast:136case CK_ToVoid:137case CK_Dynamic:138case CK_LValueBitCast:139case CK_LValueToRValueBitCast:140case CK_NullToMemberPointer:141case CK_UserDefinedConversion:142case CK_CPointerToObjCPointerCast:143case CK_BlockPointerToObjCPointerCast:144case CK_AnyPointerToBlockPointerCast:145case CK_ArrayToPointerDecay:146case CK_FunctionToPointerDecay:147case CK_BaseToDerived:148case CK_DerivedToBase:149case CK_UncheckedDerivedToBase:150case CK_MemberPointerToBoolean:151case CK_VectorSplat:152case CK_FloatingRealToComplex:153case CK_FloatingComplexToReal:154case CK_FloatingComplexToBoolean:155case CK_FloatingComplexCast:156case CK_FloatingComplexToIntegralComplex:157case CK_IntegralRealToComplex:158case CK_IntegralComplexToReal:159case CK_IntegralComplexToBoolean:160case CK_IntegralComplexCast:161case CK_IntegralComplexToFloatingComplex:162case CK_PointerToIntegral:163case CK_PointerToBoolean:164case CK_NullToPointer:165case CK_IntegralCast:166case CK_BooleanToSignedIntegral:167case CK_IntegralToPointer:168case CK_IntegralToBoolean:169case CK_IntegralToFloating:170case CK_FloatingToIntegral:171case CK_FloatingToBoolean:172case CK_FloatingCast:173case CK_FloatingToFixedPoint:174case CK_FixedPointToFloating:175case CK_FixedPointCast:176case CK_FixedPointToBoolean:177case CK_FixedPointToIntegral:178case CK_IntegralToFixedPoint:179case CK_ZeroToOCLOpaqueType:180case CK_MatrixCast:181case CK_HLSLArrayRValue:182case CK_HLSLVectorTruncation:183case CK_HLSLElementwiseCast:184case CK_HLSLAggregateSplatCast:185return {};186}187llvm_unreachable("Invalid CastKind");188}189190mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {191cgm.errorNYI(die->getBeginLoc(),192"ConstExprEmitter::VisitCXXDefaultInitExpr");193return {};194}195196mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {197// Since this about constant emission no need to wrap this under a scope.198return Visit(e->getSubExpr(), t);199}200201mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,202QualType t) {203return Visit(e->getSubExpr(), t);204}205206mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *E,207QualType T) {208cgm.errorNYI(E->getBeginLoc(),209"ConstExprEmitter::VisitImplicitValueInitExpr");210return {};211}212213mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {214if (ile->isTransparent())215return Visit(ile->getInit(0), t);216217if (ile->getType()->isArrayType()) {218// If we return null here, the non-constant initializer will take care of219// it, but we would prefer to handle it here.220assert(!cir::MissingFeatures::constEmitterArrayILE());221return {};222}223224if (ile->getType()->isRecordType()) {225cgm.errorNYI(ile->getBeginLoc(), "ConstExprEmitter: record ILE");226return {};227}228229if (ile->getType()->isVectorType()) {230// If we return null here, the non-constant initializer will take care of231// it, but we would prefer to handle it here.232assert(!cir::MissingFeatures::constEmitterVectorILE());233return {};234}235236return {};237}238239mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,240QualType destType) {241mlir::Attribute c = Visit(e->getBase(), destType);242if (!c)243return {};244245cgm.errorNYI(e->getBeginLoc(),246"ConstExprEmitter::VisitDesignatedInitUpdateExpr");247return {};248}249250mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {251cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCXXConstructExpr");252return {};253}254255mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {256// This is a string literal initializing an array in an initializer.257return cgm.getConstantArrayFromStringLiteral(e);258}259260mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {261cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");262return {};263}264265mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {266return Visit(e->getSubExpr(), t);267}268269// Utility methods270mlir::Type convertType(QualType t) { return cgm.convertType(t); }271};272273// TODO(cir): this can be shared with LLVM's codegen274static QualType getNonMemoryType(CIRGenModule &cgm, QualType type) {275if (const auto *at = type->getAs<AtomicType>()) {276return cgm.getASTContext().getQualifiedType(at->getValueType(),277type.getQualifiers());278}279return type;280}281282static mlir::Attribute283emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,284mlir::Type commonElementType, unsigned arrayBound,285SmallVectorImpl<mlir::TypedAttr> &elements,286mlir::TypedAttr filler) {287const CIRGenBuilderTy &builder = cgm.getBuilder();288289unsigned nonzeroLength = arrayBound;290if (elements.size() < nonzeroLength && builder.isNullValue(filler))291nonzeroLength = elements.size();292293if (nonzeroLength == elements.size()) {294while (nonzeroLength > 0 &&295builder.isNullValue(elements[nonzeroLength - 1]))296--nonzeroLength;297}298299if (nonzeroLength == 0)300return cir::ZeroAttr::get(desiredType);301302const unsigned trailingZeroes = arrayBound - nonzeroLength;303304// Add a zeroinitializer array filler if we have lots of trailing zeroes.305if (trailingZeroes >= 8) {306assert(elements.size() >= nonzeroLength &&307"missing initializer for non-zero element");308} else if (elements.size() != arrayBound) {309elements.resize(arrayBound, filler);310311if (filler.getType() != commonElementType)312commonElementType = {};313}314315if (commonElementType) {316SmallVector<mlir::Attribute, 4> eles;317eles.reserve(elements.size());318319for (const auto &element : elements)320eles.push_back(element);321322return cir::ConstArrayAttr::get(323cir::ArrayType::get(commonElementType, arrayBound),324mlir::ArrayAttr::get(builder.getContext(), eles));325}326327cgm.errorNYI("array with different type elements");328return {};329}330331//===----------------------------------------------------------------------===//332// ConstantLValueEmitter333//===----------------------------------------------------------------------===//334335namespace {336/// A struct which can be used to peephole certain kinds of finalization337/// that normally happen during l-value emission.338struct ConstantLValue {339llvm::PointerUnion<mlir::Value, mlir::Attribute> value;340bool hasOffsetApplied;341342ConstantLValue(std::nullptr_t) : value(nullptr), hasOffsetApplied(false) {}343ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}344};345346/// A helper class for emitting constant l-values.347class ConstantLValueEmitter348: public ConstStmtVisitor<ConstantLValueEmitter, ConstantLValue> {349CIRGenModule &cgm;350ConstantEmitter &emitter;351const APValue &value;352QualType destType;353354// Befriend StmtVisitorBase so that we don't have to expose Visit*.355friend StmtVisitorBase;356357public:358ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,359QualType destType)360: cgm(emitter.cgm), emitter(emitter), value(value), destType(destType) {}361362mlir::Attribute tryEmit();363364private:365mlir::Attribute tryEmitAbsolute(mlir::Type destTy);366ConstantLValue tryEmitBase(const APValue::LValueBase &base);367368ConstantLValue VisitStmt(const Stmt *s) { return nullptr; }369ConstantLValue VisitConstantExpr(const ConstantExpr *e);370ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *e);371ConstantLValue VisitStringLiteral(const StringLiteral *e);372ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *e);373ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *e);374ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *e);375ConstantLValue VisitPredefinedExpr(const PredefinedExpr *e);376ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *e);377ConstantLValue VisitCallExpr(const CallExpr *e);378ConstantLValue VisitBlockExpr(const BlockExpr *e);379ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *e);380ConstantLValue381VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *e);382};383384} // namespace385386mlir::Attribute ConstantLValueEmitter::tryEmit() {387const APValue::LValueBase &base = value.getLValueBase();388389// The destination type should be a pointer or reference390// type, but it might also be a cast thereof.391//392// FIXME: the chain of casts required should be reflected in the APValue.393// We need this in order to correctly handle things like a ptrtoint of a394// non-zero null pointer and addrspace casts that aren't trivially395// represented in LLVM IR.396mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);397assert(mlir::isa<cir::PointerType>(destTy));398399// If there's no base at all, this is a null or absolute pointer,400// possibly cast back to an integer type.401if (!base)402return tryEmitAbsolute(destTy);403404// Otherwise, try to emit the base.405ConstantLValue result = tryEmitBase(base);406407// If that failed, we're done.408llvm::PointerUnion<mlir::Value, mlir::Attribute> &value = result.value;409if (!value)410return {};411412// Apply the offset if necessary and not already done.413if (!result.hasOffsetApplied) {414cgm.errorNYI("ConstantLValueEmitter: apply offset");415return {};416}417418// Convert to the appropriate type; this could be an lvalue for419// an integer. FIXME: performAddrSpaceCast420if (mlir::isa<cir::PointerType>(destTy)) {421if (auto attr = mlir::dyn_cast<mlir::Attribute>(value))422return attr;423cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");424return {};425}426427cgm.errorNYI("ConstantLValueEmitter: other?");428return {};429}430431/// Try to emit an absolute l-value, such as a null pointer or an integer432/// bitcast to pointer type.433mlir::Attribute ConstantLValueEmitter::tryEmitAbsolute(mlir::Type destTy) {434// If we're producing a pointer, this is easy.435auto destPtrTy = mlir::cast<cir::PointerType>(destTy);436return cgm.getBuilder().getConstPtrAttr(437destPtrTy, value.getLValueOffset().getQuantity());438}439440ConstantLValue441ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {442// Handle values.443if (const ValueDecl *d = base.dyn_cast<const ValueDecl *>()) {444// The constant always points to the canonical declaration. We want to look445// at properties of the most recent declaration at the point of emission.446d = cast<ValueDecl>(d->getMostRecentDecl());447448if (d->hasAttr<WeakRefAttr>()) {449cgm.errorNYI(d->getSourceRange(),450"ConstantLValueEmitter: emit pointer base for weakref");451return {};452}453454if (auto *fd = dyn_cast<FunctionDecl>(d)) {455cgm.errorNYI(fd->getSourceRange(),456"ConstantLValueEmitter: function decl");457return {};458}459460if (auto *vd = dyn_cast<VarDecl>(d)) {461cgm.errorNYI(vd->getSourceRange(), "ConstantLValueEmitter: var decl");462return {};463}464}465466// Handle typeid(T).467if (base.dyn_cast<TypeInfoLValue>()) {468cgm.errorNYI("ConstantLValueEmitter: typeid");469return {};470}471472// Otherwise, it must be an expression.473return Visit(base.get<const Expr *>());474}475476ConstantLValue ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *e) {477cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: constant expr");478return {};479}480481ConstantLValue482ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *e) {483cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: compound literal");484return {};485}486487ConstantLValue488ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *e) {489cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: string literal");490return {};491}492493ConstantLValue494ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *e) {495cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc encode expr");496return {};497}498499ConstantLValue500ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *e) {501cgm.errorNYI(e->getSourceRange(),502"ConstantLValueEmitter: objc string literal");503return {};504}505506ConstantLValue507ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *e) {508cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: objc boxed expr");509return {};510}511512ConstantLValue513ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {514cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: predefined expr");515return {};516}517518ConstantLValue519ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {520cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");521return {};522}523524ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {525cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: call expr");526return {};527}528529ConstantLValue ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *e) {530cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: block expr");531return {};532}533534ConstantLValue535ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *e) {536cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: cxx typeid expr");537return {};538}539540ConstantLValue ConstantLValueEmitter::VisitMaterializeTemporaryExpr(541const MaterializeTemporaryExpr *e) {542cgm.errorNYI(e->getSourceRange(),543"ConstantLValueEmitter: materialize temporary expr");544return {};545}546547//===----------------------------------------------------------------------===//548// ConstantEmitter549//===----------------------------------------------------------------------===//550551mlir::Attribute ConstantEmitter::tryEmitForInitializer(const VarDecl &d) {552initializeNonAbstract();553return markIfFailed(tryEmitPrivateForVarInit(d));554}555556void ConstantEmitter::finalize(cir::GlobalOp gv) {557assert(initializedNonAbstract &&558"finalizing emitter that was used for abstract emission?");559assert(!finalized && "finalizing emitter multiple times");560assert(!gv.isDeclaration());561#ifndef NDEBUG562// Note that we might also be Failed.563finalized = true;564#endif // NDEBUG565}566567mlir::Attribute568ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &d) {569AbstractStateRAII state(*this, true);570return tryEmitPrivateForVarInit(d);571}572573ConstantEmitter::~ConstantEmitter() {574assert((!initializedNonAbstract || finalized || failed) &&575"not finalized after being initialized for non-abstract emission");576}577578mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &d) {579// Make a quick check if variable can be default NULL initialized580// and avoid going through rest of code which may do, for c++11,581// initialization of memory to all NULLs.582if (!d.hasLocalStorage()) {583QualType ty = cgm.getASTContext().getBaseElementType(d.getType());584if (ty->isRecordType()) {585if (const auto *e = dyn_cast_or_null<CXXConstructExpr>(d.getInit())) {586const CXXConstructorDecl *cd = e->getConstructor();587// FIXME: we should probably model this more closely to C++ than588// just emitting a global with zero init (mimic what we do for trivial589// assignments and whatnots). Since this is for globals shouldn't590// be a problem for the near future.591if (cd->isTrivial() && cd->isDefaultConstructor()) {592const auto *cxxrd =593cast<CXXRecordDecl>(ty->getAs<RecordType>()->getDecl());594if (cxxrd->getNumBases() != 0) {595// There may not be anything additional to do here, but this will596// force us to pause and test this path when it is supported.597cgm.errorNYI("tryEmitPrivateForVarInit: cxx record with bases");598return {};599}600if (!cgm.getTypes().isZeroInitializable(cxxrd)) {601// To handle this case, we really need to go through602// emitNullConstant, but we need an attribute, not a value603cgm.errorNYI(604"tryEmitPrivateForVarInit: non-zero-initializable cxx record");605return {};606}607return cir::ZeroAttr::get(cgm.convertType(d.getType()));608}609}610}611}612inConstantContext = d.hasConstantInitialization();613614const Expr *e = d.getInit();615assert(e && "No initializer to emit");616617QualType destType = d.getType();618619if (!destType->isReferenceType()) {620QualType nonMemoryDestType = getNonMemoryType(cgm, destType);621if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),622nonMemoryDestType))623return emitForMemory(c, destType);624}625626// Try to emit the initializer. Note that this can allow some things that627// are not allowed by tryEmitPrivateForMemory alone.628if (APValue *value = d.evaluateValue())629return tryEmitPrivateForMemory(*value, destType);630631return {};632}633634mlir::Attribute ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *ce) {635if (!ce->hasAPValueResult())636return {};637638QualType retType = ce->getType();639if (ce->isGLValue())640retType = cgm.getASTContext().getLValueReferenceType(retType);641642return emitAbstract(ce->getBeginLoc(), ce->getAPValueResult(), retType);643}644645mlir::Attribute ConstantEmitter::tryEmitPrivateForMemory(const APValue &value,646QualType destType) {647QualType nonMemoryDestType = getNonMemoryType(cgm, destType);648mlir::Attribute c = tryEmitPrivate(value, nonMemoryDestType);649return (c ? emitForMemory(c, destType) : nullptr);650}651652mlir::Attribute ConstantEmitter::emitAbstract(SourceLocation loc,653const APValue &value,654QualType destType) {655AbstractStateRAII state(*this, true);656mlir::Attribute c = tryEmitPrivate(value, destType);657if (!c)658cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");659return c;660}661662mlir::Attribute ConstantEmitter::emitForMemory(mlir::Attribute c,663QualType destType) {664// For an _Atomic-qualified constant, we may need to add tail padding.665if (destType->getAs<AtomicType>()) {666cgm.errorNYI("emitForMemory: atomic type");667return {};668}669670return c;671}672673mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,674QualType destType) {675auto &builder = cgm.getBuilder();676switch (value.getKind()) {677case APValue::None:678case APValue::Indeterminate:679cgm.errorNYI("ConstExprEmitter::tryEmitPrivate none or indeterminate");680return {};681case APValue::Int: {682mlir::Type ty = cgm.convertType(destType);683if (mlir::isa<cir::BoolType>(ty))684return builder.getCIRBoolAttr(value.getInt().getZExtValue());685assert(mlir::isa<cir::IntType>(ty) && "expected integral type");686return cir::IntAttr::get(ty, value.getInt());687}688case APValue::Float: {689const llvm::APFloat &init = value.getFloat();690if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&691!cgm.getASTContext().getLangOpts().NativeHalfType &&692cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {693cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");694return {};695}696697mlir::Type ty = cgm.convertType(destType);698assert(mlir::isa<cir::FPTypeInterface>(ty) &&699"expected floating-point type");700return cir::FPAttr::get(ty, init);701}702case APValue::Array: {703const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);704const QualType arrayElementTy = arrayTy->getElementType();705const unsigned numElements = value.getArraySize();706const unsigned numInitElts = value.getArrayInitializedElts();707708mlir::Attribute filler;709if (value.hasArrayFiller()) {710filler = tryEmitPrivate(value.getArrayFiller(), arrayElementTy);711if (!filler)712return {};713}714715SmallVector<mlir::TypedAttr, 16> elements;716if (filler && builder.isNullValue(filler))717elements.reserve(numInitElts + 1);718else719elements.reserve(numInitElts);720721mlir::Type commonElementType;722for (unsigned i = 0; i < numInitElts; ++i) {723const APValue &arrayElement = value.getArrayInitializedElt(i);724const mlir::Attribute element =725tryEmitPrivateForMemory(arrayElement, arrayElementTy);726if (!element)727return {};728729const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);730if (i == 0)731commonElementType = elementTyped.getType();732else if (elementTyped.getType() != commonElementType) {733commonElementType = {};734}735736elements.push_back(elementTyped);737}738739mlir::TypedAttr typedFiller = llvm::cast_or_null<mlir::TypedAttr>(filler);740if (filler && !typedFiller)741cgm.errorNYI("array filler should always be typed");742743mlir::Type desiredType = cgm.convertType(destType);744return emitArrayConstant(cgm, desiredType, commonElementType, numElements,745elements, typedFiller);746}747case APValue::Vector: {748const QualType elementType =749destType->castAs<VectorType>()->getElementType();750const unsigned numElements = value.getVectorLength();751752SmallVector<mlir::Attribute, 16> elements;753elements.reserve(numElements);754755for (unsigned i = 0; i < numElements; ++i) {756const mlir::Attribute element =757tryEmitPrivateForMemory(value.getVectorElt(i), elementType);758if (!element)759return {};760elements.push_back(element);761}762763const auto desiredVecTy =764mlir::cast<cir::VectorType>(cgm.convertType(destType));765766return cir::ConstVectorAttr::get(767desiredVecTy,768mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));769}770case APValue::MemberPointer: {771cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");772return {};773}774case APValue::LValue:775return ConstantLValueEmitter(*this, value, destType).tryEmit();776case APValue::Struct:777case APValue::Union:778cgm.errorNYI("ConstExprEmitter::tryEmitPrivate struct or union");779return {};780case APValue::ComplexInt:781case APValue::ComplexFloat: {782mlir::Type desiredType = cgm.convertType(destType);783cir::ComplexType complexType =784mlir::dyn_cast<cir::ComplexType>(desiredType);785786mlir::Type complexElemTy = complexType.getElementType();787if (isa<cir::IntType>(complexElemTy)) {788llvm::APSInt real = value.getComplexIntReal();789llvm::APSInt imag = value.getComplexIntImag();790return builder.getAttr<cir::ConstComplexAttr>(791complexType, cir::IntAttr::get(complexElemTy, real),792cir::IntAttr::get(complexElemTy, imag));793}794795assert(isa<cir::FPTypeInterface>(complexElemTy) &&796"expected floating-point type");797llvm::APFloat real = value.getComplexFloatReal();798llvm::APFloat imag = value.getComplexFloatImag();799return builder.getAttr<cir::ConstComplexAttr>(800complexType, cir::FPAttr::get(complexElemTy, real),801cir::FPAttr::get(complexElemTy, imag));802}803case APValue::FixedPoint:804case APValue::AddrLabelDiff:805cgm.errorNYI(806"ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");807return {};808}809llvm_unreachable("Unknown APValue kind");810}811812mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {813if (t->getAs<PointerType>()) {814return builder.getNullPtr(getTypes().convertTypeForMem(t), loc);815}816817if (getTypes().isZeroInitializable(t))818return builder.getNullValue(getTypes().convertTypeForMem(t), loc);819820if (getASTContext().getAsConstantArrayType(t)) {821errorNYI("CIRGenModule::emitNullConstant ConstantArrayType");822}823824if (t->getAs<RecordType>())825errorNYI("CIRGenModule::emitNullConstant RecordType");826827assert(t->isMemberDataPointerType() &&828"Should only see pointers to data members here!");829830errorNYI("CIRGenModule::emitNullConstant unsupported type");831return {};832}833834835