aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenModule.cpp
diff options
context:
space:
mode:
authorAndy Kaylor <akaylor@nvidia.com>2025-06-27 09:43:05 -0700
committerGitHub <noreply@github.com>2025-06-27 09:43:05 -0700
commit3e9fd4966d7333a0bd7fcf3b4a7828d0545af90b (patch)
tree25b5c681f01b80bc64febaeebac55da3347f44a4 /clang/lib/CIR/CodeGen/CIRGenModule.cpp
parent2557f9946373148664ce90dc6da5a6677424ac2c (diff)
downloadllvm-3e9fd4966d7333a0bd7fcf3b4a7828d0545af90b.zip
llvm-3e9fd4966d7333a0bd7fcf3b4a7828d0545af90b.tar.gz
llvm-3e9fd4966d7333a0bd7fcf3b4a7828d0545af90b.tar.bz2
[CIR] Add support for constructor aliases (#145792)
This change adds support for handling the -mconstructor-aliases option in CIR. Aliases are not yet correctly lowered to LLVM IR. That will be implemented in a future change.
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenModule.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 44ec99b..63cd55a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -888,6 +888,65 @@ void CIRGenModule::updateCompletedType(const TagDecl *td) {
genTypes.updateCompletedType(td);
}
+void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
+ replacements[name] = op;
+}
+
+void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {
+ std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
+ oldF.getSymbolUses(theModule);
+ if (!optionalUseRange)
+ return;
+
+ for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
+ // CallTryOp only shows up after FlattenCFG.
+ auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
+ if (!call)
+ continue;
+
+ for (const auto [argOp, fnArgType] :
+ llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
+ if (argOp.getType() == fnArgType)
+ continue;
+
+ // The purpose of this entire function is to insert bitcasts in the case
+ // where these types don't match, but I haven't seen a case where that
+ // happens.
+ errorNYI(call.getLoc(), "replace call with mismatched types");
+ }
+ }
+}
+
+void CIRGenModule::applyReplacements() {
+ for (auto &i : replacements) {
+ StringRef mangledName = i.first();
+ mlir::Operation *replacement = i.second;
+ mlir::Operation *entry = getGlobalValue(mangledName);
+ if (!entry)
+ continue;
+ assert(isa<cir::FuncOp>(entry) && "expected function");
+ auto oldF = cast<cir::FuncOp>(entry);
+ auto newF = dyn_cast<cir::FuncOp>(replacement);
+ if (!newF) {
+ // In classic codegen, this can be a global alias, a bitcast, or a GEP.
+ errorNYI(replacement->getLoc(), "replacement is not a function");
+ continue;
+ }
+
+ // LLVM has opaque pointer but CIR not. So we may have to handle these
+ // different pointer types when performing replacement.
+ replacePointerTypeArgs(oldF, newF);
+
+ // Replace old with new, but keep the old order.
+ if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
+ llvm_unreachable("internal error, cannot RAUW symbol");
+ if (newF) {
+ newF->moveBefore(oldF);
+ oldF->erase();
+ }
+ }
+}
+
// TODO(CIR): this could be a common method between LLVM codegen.
static bool isVarDeclStrongDefinition(const ASTContext &astContext,
CIRGenModule &cgm, const VarDecl *vd,
@@ -1797,11 +1856,52 @@ CIRGenModule::getGlobalVisibilityAttrFromDecl(const Decl *decl) {
void CIRGenModule::release() {
emitDeferred();
+ applyReplacements();
// There's a lot of code that is not implemented yet.
assert(!cir::MissingFeatures::cgmRelease());
}
+void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
+ mlir::Operation *op, GlobalDecl aliasGD,
+ cir::FuncOp aliasee,
+ cir::GlobalLinkageKind linkage) {
+
+ auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
+ assert(aliasFD && "expected FunctionDecl");
+
+ // The aliasee function type is different from the alias one, this difference
+ // is specific to CIR because in LLVM the ptr types are already erased at this
+ // point.
+ const CIRGenFunctionInfo &fnInfo =
+ getTypes().arrangeCXXStructorDeclaration(aliasGD);
+ cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
+
+ cir::FuncOp alias =
+ createCIRFunction(getLoc(aliasGD.getDecl()->getSourceRange()),
+ mangledName, fnType, aliasFD);
+ alias.setAliasee(aliasee.getName());
+ alias.setLinkage(linkage);
+ // Declarations cannot have public MLIR visibility, just mark them private
+ // but this really should have no meaning since CIR should not be using
+ // this information to derive linkage information.
+ mlir::SymbolTable::setSymbolVisibility(
+ alias, mlir::SymbolTable::Visibility::Private);
+
+ // Alias constructors and destructors are always unnamed_addr.
+ assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
+
+ // Switch any previous uses to the alias.
+ if (op) {
+ errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
+ } else {
+ // Name already set by createCIRFunction
+ }
+
+ // Finally, set up the alias with its proper name and attributes.
+ setCommonAttributes(aliasGD, alias);
+}
+
mlir::Type CIRGenModule::convertType(QualType type) {
return genTypes.convertType(type);
}