diff --git a/include/llvm/Transforms/Utils/SpecialCaseList.h b/include/llvm/Transforms/Utils/SpecialCaseList.h index 90eace1aa04..34c28fc1caf 100644 --- a/include/llvm/Transforms/Utils/SpecialCaseList.h +++ b/include/llvm/Transforms/Utils/SpecialCaseList.h @@ -49,6 +49,7 @@ namespace llvm { class Function; +class GlobalAlias; class GlobalVariable; class MemoryBuffer; class Module; @@ -79,6 +80,14 @@ class SpecialCaseList { bool isIn(const GlobalVariable &G, const StringRef Category = StringRef()) const; + /// Returns whether this global alias is listed in the given category, which + /// may be omitted to search the empty category. + /// + /// If GA aliases a function, the alias's name is matched as a function name + /// would be. Similarly, aliases of globals are matched like globals. + bool isIn(const GlobalAlias &GA, + const StringRef Category = StringRef()) const; + /// Returns whether this module is listed in the given category, which may be /// omitted to search the empty category. bool isIn(const Module &M, const StringRef Category = StringRef()) const; diff --git a/lib/Transforms/Utils/SpecialCaseList.cpp b/lib/Transforms/Utils/SpecialCaseList.cpp index cf12bbfe3d7..2ef692c564c 100644 --- a/lib/Transforms/Utils/SpecialCaseList.cpp +++ b/lib/Transforms/Utils/SpecialCaseList.cpp @@ -174,7 +174,7 @@ bool SpecialCaseList::isIn(const Function& F, const StringRef Category) const { inSectionCategory("fun", F.getName(), Category); } -static StringRef GetGVTypeString(const GlobalVariable &G) { +static StringRef GetGlobalTypeString(const GlobalValue &G) { // Types of GlobalVariables are always pointer types. Type *GType = G.getType()->getElementType(); // For now we support blacklisting struct types only. @@ -189,7 +189,19 @@ bool SpecialCaseList::isIn(const GlobalVariable &G, const StringRef Category) const { return isIn(*G.getParent(), Category) || inSectionCategory("global", G.getName(), Category) || - inSectionCategory("type", GetGVTypeString(G), Category); + inSectionCategory("type", GetGlobalTypeString(G), Category); +} + +bool SpecialCaseList::isIn(const GlobalAlias &GA, + const StringRef Category) const { + if (isIn(*GA.getParent(), Category)) + return true; + + if (isa(GA.getType()->getElementType())) + return inSectionCategory("fun", GA.getName(), Category); + + return inSectionCategory("global", GA.getName(), Category) || + inSectionCategory("type", GetGlobalTypeString(GA), Category); } bool SpecialCaseList::isIn(const Module &M, const StringRef Category) const { diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp index 92a730d5992..07ac908caab 100644 --- a/unittests/Transforms/Utils/SpecialCaseList.cpp +++ b/unittests/Transforms/Utils/SpecialCaseList.cpp @@ -34,6 +34,11 @@ protected: M, ST, false, GlobalValue::ExternalLinkage, 0, Name); } + GlobalAlias *makeAlias(StringRef Name, GlobalValue *Aliasee) { + return new GlobalAlias(Aliasee->getType(), GlobalValue::ExternalLinkage, + Name, Aliasee, Aliasee->getParent()); + } + SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { OwningPtr MB(MemoryBuffer::getMemBuffer(List)); return SpecialCaseList::create(MB.get(), Error); @@ -145,10 +150,48 @@ TEST_F(SpecialCaseListTest, GlobalIsIn) { EXPECT_TRUE(SCL->isIn(*Bar, "init")); } +TEST_F(SpecialCaseListTest, AliasIsIn) { + Module M("hello", Ctx); + Function *Foo = makeFunction("foo", M); + GlobalVariable *Bar = makeGlobal("bar", "t", M); + GlobalAlias *FooAlias = makeAlias("fooalias", Foo); + GlobalAlias *BarAlias = makeAlias("baralias", Bar); + + OwningPtr SCL(makeSpecialCaseList("fun:foo\n")); + EXPECT_FALSE(SCL->isIn(*FooAlias)); + EXPECT_FALSE(SCL->isIn(*BarAlias)); + + SCL.reset(makeSpecialCaseList("global:bar\n")); + EXPECT_FALSE(SCL->isIn(*FooAlias)); + EXPECT_FALSE(SCL->isIn(*BarAlias)); + + SCL.reset(makeSpecialCaseList("global:fooalias\n")); + EXPECT_FALSE(SCL->isIn(*FooAlias)); + EXPECT_FALSE(SCL->isIn(*BarAlias)); + + SCL.reset(makeSpecialCaseList("fun:fooalias\n")); + EXPECT_TRUE(SCL->isIn(*FooAlias)); + EXPECT_FALSE(SCL->isIn(*BarAlias)); + + SCL.reset(makeSpecialCaseList("global:baralias=init\n")); + EXPECT_FALSE(SCL->isIn(*FooAlias, "init")); + EXPECT_TRUE(SCL->isIn(*BarAlias, "init")); + + SCL.reset(makeSpecialCaseList("type:t=init\n")); + EXPECT_FALSE(SCL->isIn(*FooAlias, "init")); + EXPECT_TRUE(SCL->isIn(*BarAlias, "init")); + + SCL.reset(makeSpecialCaseList("fun:baralias=init\n")); + EXPECT_FALSE(SCL->isIn(*FooAlias, "init")); + EXPECT_FALSE(SCL->isIn(*BarAlias, "init")); +} + TEST_F(SpecialCaseListTest, Substring) { Module M("othello", Ctx); Function *F = makeFunction("tomfoolery", M); GlobalVariable *GV = makeGlobal("bartender", "t", M); + GlobalAlias *GA1 = makeAlias("buffoonery", F); + GlobalAlias *GA2 = makeAlias("foobar", GV); OwningPtr SCL(makeSpecialCaseList("src:hello\n" "fun:foo\n" @@ -156,9 +199,12 @@ TEST_F(SpecialCaseListTest, Substring) { EXPECT_FALSE(SCL->isIn(M)); EXPECT_FALSE(SCL->isIn(*F)); EXPECT_FALSE(SCL->isIn(*GV)); + EXPECT_FALSE(SCL->isIn(*GA1)); + EXPECT_FALSE(SCL->isIn(*GA2)); SCL.reset(makeSpecialCaseList("fun:*foo*\n")); EXPECT_TRUE(SCL->isIn(*F)); + EXPECT_TRUE(SCL->isIn(*GA1)); } TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {