aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenModule.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp190
1 files changed, 158 insertions, 32 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index a6a4330..82bd139 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -269,6 +269,40 @@ mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
return mlir::SymbolTable::lookupSymbolIn(theModule, name);
}
+cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,
+ mlir::Location loc, StringRef name,
+ mlir::Type t,
+ mlir::Operation *insertPoint) {
+ cir::GlobalOp g;
+ CIRGenBuilderTy &builder = cgm.getBuilder();
+
+ {
+ mlir::OpBuilder::InsertionGuard guard(builder);
+
+ // Some global emissions are triggered while emitting a function, e.g.
+ // void s() { const char *s = "yolo"; ... }
+ //
+ // Be sure to insert global before the current function
+ CIRGenFunction *curCGF = cgm.curCGF;
+ if (curCGF)
+ builder.setInsertionPoint(curCGF->curFn);
+
+ g = builder.create<cir::GlobalOp>(loc, name, t);
+ if (!curCGF) {
+ if (insertPoint)
+ cgm.getModule().insert(insertPoint, g);
+ else
+ cgm.getModule().push_back(g);
+ }
+
+ // Default to private until we can judge based on the initializer,
+ // since MLIR doesn't allow public declarations.
+ mlir::SymbolTable::setSymbolVisibility(
+ g, mlir::SymbolTable::Visibility::Private);
+ }
+ return g;
+}
+
/// If the specified mangled name is not in the module,
/// create and return an mlir GlobalOp with the specified type (TODO(cir):
/// address space).
@@ -324,8 +358,15 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
return entry;
}
- errorNYI(d->getSourceRange(), "reference of undeclared global");
- return {};
+ mlir::Location loc = getLoc(d->getSourceRange());
+
+ // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
+ // mark it as such.
+ cir::GlobalOp gv =
+ CIRGenModule::createGlobalOp(*this, loc, mangledName, ty,
+ /*insertPoint=*/entry.getOperation());
+
+ return gv;
}
cir::GlobalOp
@@ -365,46 +406,125 @@ 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;
+ }
+
+ // Whether the definition of the variable is available externally.
+ // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
+ // since this is the job for its original source.
+ bool isDefinitionAvailableExternally =
+ astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
+ assert(!cir::MissingFeatures::needsGlobalCtorDtor());
+
+ // It is useless to emit the definition for an available_externally variable
+ // which can't be marked as const.
+ if (isDefinitionAvailableExternally &&
+ (!vd->hasConstantInitialization() ||
+ // TODO: Update this when we have interface to check constexpr
+ // destructor.
+ vd->needsDestruction(astContext) ||
+ !vd->getType().isConstantStorage(astContext, true, true)))
+ 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);
+ mlir::Attribute 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)
+ errorNYI(vd->getSourceRange(), "delayed destructor");
}
+ }
+
+ mlir::Type initType;
+ if (mlir::isa<mlir::SymbolRefAttr>(init)) {
+ errorNYI(vd->getSourceRange(), "global initializer is a symbol reference");
+ return;
+ } else {
+ assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
+ auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
+ initType = typedInitAttr.getType();
+ }
+ assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
+
+ cir::GlobalOp gv =
+ getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
+ // TODO(cir): Strip off pointer casts from Entry if we get them?
- varOp.setInitialValueAttr(initializer);
+ if (!gv || gv.getSymType() != initType) {
+ errorNYI(vd->getSourceRange(), "global initializer with type mismatch");
+ return;
+ }
- // Set CIR's linkage type as appropriate.
- cir::GlobalLinkageKind linkage =
- getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
+ assert(!cir::MissingFeatures::maybeHandleStaticInExternC());
- // Set CIR linkage and DLL storage class.
- varOp.setLinkage(linkage);
+ if (vd->hasAttr<AnnotateAttr>()) {
+ errorNYI(vd->getSourceRange(), "annotate global variable");
+ }
- if (linkage == cir::GlobalLinkageKind::CommonLinkage)
- errorNYI(initExpr->getSourceRange(), "common linkage");
+ assert(!cir::MissingFeatures::opGlobalLinkage());
- theModule.push_back(varOp);
- } else {
- errorNYI(vd->getSourceRange().getBegin(),
- "variable definition with a non-identifier for a name");
+ if (langOpts.CUDA) {
+ errorNYI(vd->getSourceRange(), "CUDA global variable");
}
+
+ // Set initializer and finalize emission
+ CIRGenModule::setInitializer(gv, init);
+ if (emitter)
+ emitter->finalize(gv);
+
+ // Set CIR's linkage type as appropriate.
+ cir::GlobalLinkageKind linkage =
+ getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
+
+ // Set CIR linkage and DLL storage class.
+ gv.setLinkage(linkage);
+
+ if (linkage == cir::GlobalLinkageKind::CommonLinkage)
+ errorNYI(initExpr->getSourceRange(), "common linkage");
}
void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
@@ -684,6 +804,12 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
}
}
+void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
+ // Recompute visibility when updating initializer.
+ op.setInitialValueAttr(value);
+ assert(!cir::MissingFeatures::opGlobalSetVisitibility());
+}
+
cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
mlir::Type funcType, bool forVTable,
bool dontDefer,