Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<cir::GlobalOp>(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
Expand Down
51 changes: 38 additions & 13 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
Expand All @@ -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<mlir::TypedAttr>(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<mlir::Operation *>(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<cir::ArrayType>(gv.getSymType());
assert(arrayTy && "String literal must be array");
auto ptrTy = getBuilder().getPointerTo(arrayTy.getElementType(),
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ class CIRGenModule : public CIRGenTypeCache {
return !getLangOpts().CPlusPlus;
}

llvm::StringMap<unsigned> 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
Expand Down Expand Up @@ -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
Expand Down
Loading