diff options
author | Andy Kaylor <akaylor@nvidia.com> | 2025-06-27 09:43:05 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-27 09:43:05 -0700 |
commit | 3e9fd4966d7333a0bd7fcf3b4a7828d0545af90b (patch) | |
tree | 25b5c681f01b80bc64febaeebac55da3347f44a4 /clang/lib/CIR/CodeGen/CIRGenModule.cpp | |
parent | 2557f9946373148664ce90dc6da5a6677424ac2c (diff) | |
download | llvm-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.cpp | 100 |
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); } |