Index: llvm/include/llvm/InterfaceStub/IFSHandler.h =================================================================== --- llvm/include/llvm/InterfaceStub/IFSHandler.h +++ llvm/include/llvm/InterfaceStub/IFSHandler.h @@ -51,9 +51,6 @@ void stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch, bool StripEndianness, bool StripBitWidth); -/// Strips symbols from IFS symbol table that are undefined. -void stripIFSUndefinedSymbols(IFSStub &Stub); - /// Parse llvm triple string into a IFSTarget struct. IFSTarget parseTriple(StringRef TripleStr); Index: llvm/lib/InterfaceStub/IFSHandler.cpp =================================================================== --- llvm/lib/InterfaceStub/IFSHandler.cpp +++ llvm/lib/InterfaceStub/IFSHandler.cpp @@ -327,13 +327,3 @@ Stub.Target.ObjectFormat.reset(); } } - -void ifs::stripIFSUndefinedSymbols(IFSStub &Stub) { - for (auto Iter = Stub.Symbols.begin(); Iter != Stub.Symbols.end();) { - if (Iter->Undefined) { - Iter = Stub.Symbols.erase(Iter); - } else { - Iter++; - } - } -} Index: llvm/test/tools/llvm-ifs/preserve.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-ifs/preserve.test @@ -0,0 +1,26 @@ +## Test --preserve flag + +# RUN: llvm-ifs --input-format=IFS --output-ifs=- --strip-undefined \ +# RUN: --preserve='keep_*' --preserve='diff_pattern_keep' %s | FileCheck %s + +# RUN: not llvm-ifs --input-format=IFS --output-ifs=- --preserve='[' %s 2>&1 | \ +# RUN: FileCheck %s --check-prefix=BAD-GLOB + +# BAD-GLOB: error: invalid glob pattern: [ + +--- !ifs-v1 +SoName: somelib.so +IfsVersion: 3.0 +Symbols: + - { Name: diff_pattern_keep, Type: Func, Undefined: true } + - { Name: dont_keep, Type: Func, Undefined: true } + - { Name: keep_1, Type: Func, Undefined: true } + - { Name: keep_2, Type: Func, Undefined: true } + - { Name: no_match_not_undef, Type: Func } +... + +# CHECK: - { Name: diff_pattern_keep, Type: Func, Undefined: true } +# CHECK-NOT: - { Name: dont_keep, Type: Func, Undefined: true } +# CHECK-NEXT: - { Name: keep_1, Type: Func, Undefined: true } +# CHECK-NEXT: - { Name: keep_2, Type: Func, Undefined: true } +# CHECK-NEXT: - { Name: no_match_not_undef, Type: Func } Index: llvm/tools/llvm-ifs/llvm-ifs.cpp =================================================================== --- llvm/tools/llvm-ifs/llvm-ifs.cpp +++ llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -7,6 +7,7 @@ //===-----------------------------------------------------------------------===/ #include "ErrorCollector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" @@ -19,6 +20,7 @@ #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/GlobPattern.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/VersionTuple.h" @@ -28,6 +30,7 @@ #include "llvm/TextAPI/InterfaceFile.h" #include "llvm/TextAPI/TextAPIReader.h" #include "llvm/TextAPI/TextAPIWriter.h" +#include #include #include #include @@ -103,6 +106,11 @@ StripUndefined("strip-undefined", cl::desc("Strip undefined symbols from IFS output"), cl::cat(IfsCategory)); +cl::list + PreserveSyms("preserve", + cl::desc("Keep symbols which might otherwise be removed by " + "--strip-undefined. Can be specified multiple times"), + cl::cat(IfsCategory)); cl::opt SoName("soname", @@ -287,6 +295,31 @@ return Error::success(); } +static Error stripSyms(IFSStub &Stub) { + std::function Filter = [](const IFSSymbol &) { + return false; + }; + + if (StripUndefined) { + Filter = [Filter](const IFSSymbol &Sym) { + return Sym.Undefined || Filter(Sym); + }; + } + + for (StringRef Glob : PreserveSyms) { + Expected PatternOrErr = GlobPattern::create(Glob); + if (!PatternOrErr) + return PatternOrErr.takeError(); + Filter = [Pattern = *PatternOrErr, Filter](const IFSSymbol &Sym) { + return !Pattern.match(Sym.Name) && Filter(Sym); + }; + } + + llvm::erase_if(Stub.Symbols, Filter); + + return Error::success(); +} + int main(int argc, char *argv[]) { // Parse arguments. cl::HideUnrelatedOptions({&IfsCategory, &getColorCategory()}); @@ -473,8 +506,8 @@ stripIFSTarget(Stub, StripIFSTarget, StripIFSArch, StripIFSEndiannessWidth, StripIFSBitWidth); } - if (StripUndefined) - stripIFSUndefinedSymbols(Stub); + if (Error E = stripSyms(Stub)) + fatalError(std::move(E)); Error IFSWriteError = writeIFS(OutputFilePath.getValue(), Stub); if (IFSWriteError) fatalError(std::move(IFSWriteError)); @@ -525,8 +558,8 @@ stripIFSTarget(Stub, StripIFSTarget, StripIFSArch, StripIFSEndiannessWidth, StripIFSBitWidth); } - if (StripUndefined) - stripIFSUndefinedSymbols(Stub); + if (Error E = stripSyms(Stub)) + fatalError(std::move(E)); Error IFSWriteError = writeIFS(OutputIFSFilePath.getValue(), Stub); if (IFSWriteError) fatalError(std::move(IFSWriteError));