@@ -3031,9 +3031,110 @@ void CIRGenModule::Release() {
30313031 // TODO: FINISH THE REST OF THIS
30323032}
30333033
3034- bool CIRGenModule::shouldEmitFunction (GlobalDecl GD) {
3035- // TODO: implement this -- requires defining linkage for CIR
3036- return true ;
3034+ namespace {
3035+ // TODO(cir): This should be a common helper shared with CodeGen.
3036+ struct FunctionIsDirectlyRecursive
3037+ : public ConstStmtVisitor<FunctionIsDirectlyRecursive, bool > {
3038+ const StringRef name;
3039+ const Builtin::Context &builtinCtx;
3040+ FunctionIsDirectlyRecursive (StringRef name,
3041+ const Builtin::Context &builtinCtx)
3042+ : name(name), builtinCtx(builtinCtx) {}
3043+
3044+ bool VisitCallExpr (const CallExpr *expr) {
3045+ const FunctionDecl *func = expr->getDirectCallee ();
3046+ if (!func)
3047+ return false ;
3048+ AsmLabelAttr *attr = func->getAttr <AsmLabelAttr>();
3049+ if (attr && name == attr->getLabel ())
3050+ return true ;
3051+ unsigned builtinId = func->getBuiltinID ();
3052+ if (!builtinId || !builtinCtx.isLibFunction (builtinId))
3053+ return false ;
3054+ StringRef builtinName = builtinCtx.getName (builtinId);
3055+ if (builtinName.starts_with (" __builtin_" ) &&
3056+ name == builtinName.slice (strlen (" __builtin_" ), StringRef::npos)) {
3057+ return true ;
3058+ }
3059+ return false ;
3060+ }
3061+
3062+ bool VisitStmt (const Stmt *stmt) {
3063+ for (const Stmt *child : stmt->children ())
3064+ if (child && this ->Visit (child))
3065+ return true ;
3066+ return false ;
3067+ }
3068+ };
3069+ } // namespace
3070+
3071+ // isTriviallyRecursive - Check if this function calls another
3072+ // decl that, because of the asm attribute or the other decl being a builtin,
3073+ // ends up pointing to itself.
3074+ // TODO(cir): This should be a common helper shared with CodeGen.
3075+ bool CIRGenModule::isTriviallyRecursive (const FunctionDecl *func) {
3076+ StringRef name;
3077+ if (getCXXABI ().getMangleContext ().shouldMangleDeclName (func)) {
3078+ // asm labels are a special kind of mangling we have to support.
3079+ AsmLabelAttr *attr = func->getAttr <AsmLabelAttr>();
3080+ if (!attr)
3081+ return false ;
3082+ name = attr->getLabel ();
3083+ } else {
3084+ name = func->getName ();
3085+ }
3086+
3087+ FunctionIsDirectlyRecursive walker (name, astCtx.BuiltinInfo );
3088+ const Stmt *body = func->getBody ();
3089+ return body ? walker.Visit (body) : false ;
3090+ }
3091+
3092+ // TODO(cir): This should be a common helper shared with CodeGen.
3093+ bool CIRGenModule::shouldEmitFunction (GlobalDecl globalDecl) {
3094+ if (getFunctionLinkage (globalDecl) !=
3095+ GlobalLinkageKind::AvailableExternallyLinkage)
3096+ return true ;
3097+
3098+ const auto *func = cast<FunctionDecl>(globalDecl.getDecl ());
3099+ // Inline builtins declaration must be emitted. They often are fortified
3100+ // functions.
3101+ if (func->isInlineBuiltinDeclaration ())
3102+ return true ;
3103+
3104+ if (codeGenOpts.OptimizationLevel == 0 && !func->hasAttr <AlwaysInlineAttr>())
3105+ return false ;
3106+
3107+ // We don't import function bodies from other named module units since that
3108+ // behavior may break ABI compatibility of the current unit.
3109+ if (const Module *mod = func->getOwningModule ();
3110+ mod && mod->getTopLevelModule ()->isNamedModule () &&
3111+ astCtx.getCurrentNamedModule () != mod->getTopLevelModule ()) {
3112+ // There are practices to mark template member function as always-inline
3113+ // and mark the template as extern explicit instantiation but not give
3114+ // the definition for member function. So we have to emit the function
3115+ // from explicitly instantiation with always-inline.
3116+ //
3117+ // See https://github.com/llvm/llvm-project/issues/86893 for details.
3118+ //
3119+ // TODO: Maybe it is better to give it a warning if we call a non-inline
3120+ // function from other module units which is marked as always-inline.
3121+ if (!func->isTemplateInstantiation () || !func->hasAttr <AlwaysInlineAttr>())
3122+ return false ;
3123+ }
3124+
3125+ if (func->hasAttr <NoInlineAttr>())
3126+ return false ;
3127+
3128+ if (func->hasAttr <DLLImportAttr>() && !func->hasAttr <AlwaysInlineAttr>())
3129+ assert (!MissingFeatures::setDLLImportDLLExport () &&
3130+ " shouldEmitFunction for dllimport is NYI" );
3131+
3132+ // PR9614. Avoid cases where the source code is lying to us. An available
3133+ // externally function should have an equivalent function somewhere else,
3134+ // but a function that calls itself through asm label/`__builtin_` trickery is
3135+ // clearly not equivalent to the real implementation.
3136+ // This happens in glibc's btowc and in some configure checks.
3137+ return !isTriviallyRecursive (func);
30373138}
30383139
30393140bool CIRGenModule::supportsCOMDAT () const {
0 commit comments