4747#include " llvm/IR/GlobalValue.h"
4848#include " llvm/IR/GlobalVariable.h"
4949#include " llvm/IR/Module.h"
50+ #include " llvm/IR/PatternMatch.h"
5051#include " llvm/MC/MCAsmInfo.h"
5152#include " llvm/MC/MCContext.h"
5253#include " llvm/MC/MCDirectives.h"
8283
8384using namespace llvm ;
8485using namespace llvm ::XCOFF;
86+ using namespace PatternMatch ;
8587
8688#define DEBUG_TYPE " asmprinter"
8789
@@ -3384,13 +3386,9 @@ void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {
33843386 OutStreamer->emitXCOFFCInfoSym (" .GCC.command.line" , RSOS.str ());
33853387}
33863388
3387-
33883389static bool TOCRestoreNeededForCallToImplementation (const GlobalIFunc &GI) {
3389- auto IsLocalFunc = [&](const Value *V) {
3390- if (!isa<Function>(V))
3391- return false ;
3392- auto *F = cast<Function>(V);
3393-
3390+ // Query if the given function is local to the load module.
3391+ auto IsLocalFunc = [](const Function *F) {
33943392 // Static functions are local
33953393 if (F->getLinkage () == GlobalValue::InternalLinkage)
33963394 return true ;
@@ -3406,6 +3404,42 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
34063404
34073405 return false ;
34083406 };
3407+ // Recursive walker that checks if all possible runtime values of the given
3408+ // llvm::Value are addresses of local functions.
3409+ std::function<bool (const Value*)> ValueIsALocalFunc = [&IsLocalFunc, &ValueIsALocalFunc](const Value *V) -> bool {
3410+ if (auto *F = dyn_cast<Function>(V))
3411+ return IsLocalFunc (F);
3412+ if (!isa<Instruction>(V))
3413+ return false ;
3414+
3415+ Value *Op;
3416+ auto *I = cast<Instruction>(V);
3417+ // return isP9 ? foo_p9 : foo_default;
3418+ if (auto *SI = dyn_cast<SelectInst>(I))
3419+ return ValueIsALocalFunc (SI->getTrueValue ()) && ValueIsALocalFunc (SI->getFalseValue ());
3420+ else if (auto *PN = dyn_cast<PHINode>(I)) {
3421+ for (unsigned i = 0 , e = PN->getNumIncomingValues (); i != e; ++i)
3422+ if (!ValueIsALocalFunc (PN->getIncomingValue (i)))
3423+ return false ;
3424+ return true ;
3425+ }
3426+ // @switch.table.resolve_foo = private unnamed_addr constant [3 x ptr] [ptr @foo_static, ptr @foo_hidden, ptr @foo_protected]
3427+ // %switch.gep = getelementptr inbounds nuw ptr, ptr @switch.table, i64 %2
3428+ // V = load ptr, ptr %switch.gep,
3429+ else if (match (I, m_Load (m_GEP (m_Value (Op), m_Value ())))) {
3430+ if (!isa<GlobalVariable>(Op))
3431+ return false ;
3432+ auto *GV = dyn_cast<GlobalVariable>(Op);
3433+ if (!GV->hasInitializer () || !isa<ConstantArray>(GV->getInitializer ()))
3434+ return false ;
3435+ auto *Initializer = cast<ConstantArray>(GV->getInitializer ());
3436+ for (unsigned Idx = 0 , End = Initializer->getNumOperands (); Idx != End; ++Idx)
3437+ if (!ValueIsALocalFunc (Initializer->getOperand (Idx)))
3438+ return false ;
3439+ return true ;
3440+ }
3441+ return false ;
3442+ };
34093443
34103444 if (!IFuncLocal.empty ()) {
34113445 ArrayRef<std::string> List = IFuncLocal;
@@ -3422,31 +3456,15 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
34223456
34233457 auto *Resolver = GI.getResolverFunction ();
34243458 // If the resolver is preemptible then we cannot rely on its implementation.
3425- if (!isLocalFunc (Resolver))
3459+ if (!IsLocalFunc (Resolver))
34263460 return true ;
34273461 // If one of the return values of the resolver function is not a
34283462 // local function, then we have to conservatively do a TOC save/restore.
34293463 for (auto &BB : *Resolver) {
34303464 if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator ())) {
34313465 Value *RV = Ret->getReturnValue ();
34323466 assert (RV);
3433- // return &foo_p9;
3434- if (auto *F = dyn_cast<Function>(RV)) {
3435- if (!IsLocalFunc (F))
3436- return true ;
3437- } else if (auto *I = dyn_cast<Instruction>(RV)) {
3438- // return isP9 ? foo_p9 : foo_default;
3439- if (auto *SI = dyn_cast<SelectInst>(I)) {
3440- if (!IsLocalFunc (SI->getTrueValue ()) ||
3441- !IsLocalFunc (SI->getFalseValue ()))
3442- return true ;
3443- } else if (auto *PN = dyn_cast<PHINode>(I)) {
3444- for (unsigned i = 1 , e = PN->getNumIncomingValues (); i != e; ++i)
3445- if (!IsLocalFunc (PN->getIncomingValue (i)))
3446- return true ;
3447- } else
3448- return true ;
3449- } else
3467+ if (!ValueIsALocalFunc (RV))
34503468 return true ;
34513469 }
34523470 }
0 commit comments