diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index a320dc211ac4..86da04457266 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -1884,21 +1884,14 @@ LValue CIRGenFunction::emitArraySubscriptExpr(const ArraySubscriptExpr *E, return LV; } -LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *E) { - auto sym = CGM.getAddrOfConstantStringFromLiteral(E).getSymbol(); - - auto cstGlobal = mlir::SymbolTable::lookupSymbolIn(CGM.getModule(), sym); - assert(cstGlobal && "Expected global"); - - auto g = dyn_cast(cstGlobal); - assert(g && "unaware of other symbol providers"); - +LValue CIRGenFunction::emitStringLiteralLValue(const StringLiteral *e) { + auto g = CGM.getGlobalForStringLiteral(e); assert(g.getAlignment() && "expected alignment for string literal"); auto align = *g.getAlignment(); - auto addr = builder.createGetGlobal(getLoc(E->getSourceRange()), g); + auto addr = builder.createGetGlobal(getLoc(e->getSourceRange()), g); return makeAddrLValue( Address(addr, g.getSymType(), CharUnits::fromQuantity(align)), - E->getType(), AlignmentSource::Decl); + e->getType(), AlignmentSource::Decl); } /// Casts are never lvalues unless that cast is to a reference type. If the cast diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 3f351d75854b..96be3606c4cc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -1783,10 +1783,32 @@ generateStringLiteral(mlir::Location loc, mlir::TypedAttr c, return gv; } -/// Return a pointer to a constant array for the given string literal. -cir::GlobalViewAttr -CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s, - StringRef name) { +// LLVM IR automatically uniques names when new llvm::GlobalVariables are +// created. This is handy, for example, when creating globals for string +// literals. Since we don't do that when creating cir::GlobalOp's, we need +// a mechanism to generate a unique name in advance. +// +// For now, this mechanism is only used in cases where we know that the +// name is compiler-generated, so we don't use the MLIR symbol table for +// the lookup. +std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) { + // If this is the first time we've generated a name for this basename, use + // it as is and start a counter for this base name. + auto it = cgGlobalNames.find(baseName); + if (it == cgGlobalNames.end()) { + cgGlobalNames[baseName] = 1; + return baseName; + } + + std::string result = + baseName + "." + std::to_string(cgGlobalNames[baseName]++); + // There should not be any symbol with this name in the module. + assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result)); + return result; +} + +cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s, + StringRef name) { CharUnits alignment = astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr); @@ -1800,13 +1822,6 @@ CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s, uint64_t(alignment.getQuantity()) > *gv.getAlignment()) gv.setAlignmentAttr(getSize(alignment)); } else { - SmallString<256> stringNameBuffer = name; - llvm::raw_svector_ostream out(stringNameBuffer); - if (StringLiteralCnt) - out << '.' << StringLiteralCnt; - name = out.str(); - StringLiteralCnt++; - SmallString<256> mangledNameBuffer; StringRef globalVariableName; auto lt = cir::GlobalLinkageKind::ExternalLinkage; @@ -1822,18 +1837,28 @@ CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s, globalVariableName = name; } + // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so + // we need to do that explicitly. + std::string uniqueName = getUniqueGlobalName(globalVariableName.str()); auto loc = getLoc(s->getSourceRange()); auto typedC = llvm::dyn_cast(c); if (!typedC) llvm_unreachable("this should never be untyped at this point"); - gv = generateStringLiteral(loc, typedC, lt, *this, globalVariableName, - alignment); + gv = generateStringLiteral(loc, typedC, lt, *this, uniqueName, alignment); setDSOLocal(static_cast(gv)); ConstantStringMap[c] = gv; assert(!cir::MissingFeatures::reportGlobalToASan() && "NYI"); } + return gv; +} + +/// Return a pointer to a constant array for the given string literal. +cir::GlobalViewAttr +CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s, + StringRef name) { + auto gv = getGlobalForStringLiteral(s, name); auto arrayTy = mlir::dyn_cast(gv.getSymType()); assert(arrayTy && "String literal must be array"); auto ptrTy = getBuilder().getPointerTo(arrayTy.getElementType(), diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index b3e5e104cf43..e96220ea395a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -338,6 +338,9 @@ class CIRGenModule : public CIRGenTypeCache { return !getLangOpts().CPlusPlus; } + llvm::StringMap cgGlobalNames; + std::string getUniqueGlobalName(const std::string &baseName); + /// Return the mlir::Value for the address of the given global variable. /// If Ty is non-null and if the global doesn't exist, then it will be created /// with the specified type instead of whatever the normal requested type @@ -444,12 +447,15 @@ class CIRGenModule : public CIRGenTypeCache { /// Return a constant array for the given string. mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *E); + /// Return a global op for the given string literal. + cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s, + llvm::StringRef name = ".str"); + /// Return a global symbol reference to a constant array for the given string /// literal. cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *S, llvm::StringRef Name = ".str"); - unsigned StringLiteralCnt = 0; unsigned CompoundLitaralCnt = 0; /// Return the unique name for global compound literal