================ @@ -365,46 +406,108 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty, void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd, bool isTentative) { const QualType astTy = vd->getType(); - const mlir::Type type = convertType(vd->getType()); - if (vd->getIdentifier()) { - StringRef name = getMangledName(GlobalDecl(vd)); - auto varOp = - builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()), name, type); - // TODO(CIR): This code for processing initial values is a placeholder - // until class ConstantEmitter is upstreamed and the code for processing - // constant expressions is filled out. Only the most basic handling of - // certain constant expressions is implemented for now. - const VarDecl *initDecl; - const Expr *initExpr = vd->getAnyInitializer(initDecl); - mlir::Attribute initializer; - if (initExpr) { - if (APValue *value = initDecl->evaluateValue()) { - ConstantEmitter emitter(*this); - initializer = emitter.tryEmitPrivateForMemory(*value, astTy); + + if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) { + errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable"); + return; + } + + mlir::Attribute init; + const VarDecl *initDecl; + const Expr *initExpr = vd->getAnyInitializer(initDecl); + + std::optional<ConstantEmitter> emitter; + + assert(!cir::MissingFeatures::cudaSupport()); + + if (vd->hasAttr<LoaderUninitializedAttr>()) { + errorNYI(vd->getSourceRange(), "loader uninitialized attribute"); + return; + } else if (!initExpr) { + // This is a tentative definition; tentative definitions are + // implicitly initialized with { 0 }. + // + // Note that tentative definitions are only emitted at the end of + // a translation unit, so they should never have incomplete + // type. In addition, EmitTentativeDefinition makes sure that we + // never attempt to emit a tentative definition if a real one + // exists. A use may still exists, however, so we still may need + // to do a RAUW. + assert(!astTy->isIncompleteType() && "Unexpected incomplete type"); + init = builder.getZeroInitAttr(convertType(vd->getType())); + } else { + emitter.emplace(*this); + auto initializer = emitter->tryEmitForInitializer(*initDecl); + if (!initializer) { + QualType qt = initExpr->getType(); + if (vd->getType()->isReferenceType()) + qt = vd->getType(); + + if (getLangOpts().CPlusPlus) { + if (initDecl->hasFlexibleArrayInit(astContext)) + errorNYI(vd->getSourceRange(), "flexible array initializer"); + init = builder.getZeroInitAttr(convertType(qt)); + if (astContext.GetGVALinkageForVariable(vd) != GVA_AvailableExternally) + errorNYI(vd->getSourceRange(), "global constructor"); } else { - errorNYI(initExpr->getSourceRange(), "non-constant initializer"); + errorNYI(vd->getSourceRange(), "static initializer"); } } else { - initializer = builder.getZeroInitAttr(convertType(astTy)); + init = initializer; + // We don't need an initializer, so remove the entry for the delayed + // initializer position (just in case this entry was delayed) if we + // also don't need to register a destructor. + if (vd->needsDestruction(astContext) == QualType::DK_cxx_destructor) ---------------- andykaylor wrote:
I think it's only used in conjunction with constructors and destructors, so it isn't needed yet. I should probably drop an errorNYI or two for that. https://github.com/llvm/llvm-project/pull/138222 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits