From 9ca1b94a6d3f491f26ccbeacf910342e6861fc7f Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 11 Sep 2019 01:54:48 +0000 Subject: [CodeGen] Add alias for cpu_dispatch function with IFunc & Fix resolver linkage type Multi-versioned functions defined by cpu_dispatch and implemented with IFunc can not be called outside the translation units where they are defined due to lack of symbols. This patch add function aliases for these functions and thus make them visible outside. Differential Revision: https://reviews.llvm.org/D67058 Patch by Senran Zhang llvm-svn: 371586 --- clang/lib/CodeGen/CodeGenModule.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index eedf70b8d50d..be7dfc97a98a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2836,11 +2836,13 @@ void CodeGenModule::emitMultiVersionFunctions() { llvm::Function *ResolverFunc; const TargetInfo &TI = getTarget(); - if (TI.supportsIFunc() || FD->isTargetMultiVersion()) + if (TI.supportsIFunc() || FD->isTargetMultiVersion()) { ResolverFunc = cast( GetGlobalValue((getMangledName(GD) + ".resolver").str())); - else + ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage); + } else { ResolverFunc = cast(GetGlobalValue(getMangledName(GD))); + } if (supportsCOMDAT()) ResolverFunc->setComdat( @@ -2884,6 +2886,10 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { auto *ResolverFunc = cast(GetOrCreateLLVMFunction( ResolverName, ResolverType, ResolverGD, /*ForVTable=*/false)); + ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage); + if (supportsCOMDAT()) + ResolverFunc->setComdat( + getModule().getOrInsertComdat(ResolverFunc->getName())); SmallVector Options; const TargetInfo &Target = getTarget(); @@ -2948,6 +2954,21 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { CodeGenFunction CGF(*this); CGF.EmitMultiVersionResolver(ResolverFunc, Options); + + if (getTarget().supportsIFunc()) { + std::string AliasName = getMangledNameImpl( + *this, GD, FD, /*OmitMultiVersionMangling=*/true); + llvm::Constant *AliasFunc = GetGlobalValue(AliasName); + if (!AliasFunc) { + auto *IFunc = cast(GetOrCreateLLVMFunction( + AliasName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true, + /*IsThunk=*/false, llvm::AttributeList(), NotForDefinition)); + auto *GA = llvm::GlobalAlias::create( + DeclTy, 0, getFunctionLinkage(GD), AliasName, IFunc, &getModule()); + GA->setLinkage(llvm::Function::WeakODRLinkage); + SetCommonAttributes(GD, GA); + } + } } /// If a dispatcher for the specified mangled name is not in the module, create @@ -2984,7 +3005,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver( MangledName + ".resolver", ResolverType, GlobalDecl{}, /*ForVTable=*/false); llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create( - DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule()); + DeclTy, 0, llvm::Function::WeakODRLinkage, "", Resolver, &getModule()); GIF->setName(ResolverName); SetCommonAttributes(FD, GIF); -- cgit v1.2.3