[llvm] 5b5ab80 - Reland "[llvm] llvm-tapi-diff"
Cyndy Ishida via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 9 21:21:16 PDT 2021
Author: Sam Powell
Date: 2021-06-09T21:17:34-07:00
New Revision: 5b5ab80e31958b3b4a52de13ce4306a2c6c8765d
URL: https://github.com/llvm/llvm-project/commit/5b5ab80e31958b3b4a52de13ce4306a2c6c8765d
DIFF: https://github.com/llvm/llvm-project/commit/5b5ab80e31958b3b4a52de13ce4306a2c6c8765d.diff
LOG: Reland "[llvm] llvm-tapi-diff"
This is relanding commit d1d36f7ad2ae82bea8a6fcc40d6c42a72e21f096 .
This patch additionally addresses failures found in buildbots due to unstable build ordering & post review comments.
This patch introduces a new tool, llvm-tapi-diff, that compares and returns the diff of two TBD files.
Reviewed By: ributzka, JDevlieghere
Differential Revision: https://reviews.llvm.org/D101835
Added:
llvm/test/tools/llvm-tapi-diff/Inputs/macho.yaml
llvm/test/tools/llvm-tapi-diff/Inputs/v4A.tbd
llvm/test/tools/llvm-tapi-diff/Inputs/v4B.tbd
llvm/test/tools/llvm-tapi-diff/Inputs/v4C.tbd
llvm/test/tools/llvm-tapi-diff/Inputs/v4D.tbd
llvm/test/tools/llvm-tapi-diff/Inputs/v4E.tbd
llvm/test/tools/llvm-tapi-diff/tapi-diff-incorrect-format.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-matching-tbd.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-mismatched-number-of-inlines.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-misspelled-tbd.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-no-inlines.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-same-number-of-inlines.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-tbd-has-multiple-inlines.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-tbd-has-single-inlineA.test
llvm/test/tools/llvm-tapi-diff/tapi-diff-tbd-has-single-inlineB.test
llvm/tools/llvm-tapi-diff/CMakeLists.txt
llvm/tools/llvm-tapi-diff/DiffEngine.cpp
llvm/tools/llvm-tapi-diff/DiffEngine.h
llvm/tools/llvm-tapi-diff/llvm-tapi-diff.cpp
Modified:
llvm/include/llvm/Object/TapiUniversal.h
llvm/include/llvm/TextAPI/Platform.h
llvm/include/llvm/TextAPI/Symbol.h
llvm/include/llvm/TextAPI/Target.h
llvm/lib/TextAPI/Platform.cpp
llvm/lib/TextAPI/Target.cpp
llvm/test/CMakeLists.txt
llvm/test/lit.cfg.py
Removed:
################################################################################
diff --git a/llvm/include/llvm/Object/TapiUniversal.h b/llvm/include/llvm/Object/TapiUniversal.h
index 8f716ace0206a..ab548aa5bb2ab 100644
--- a/llvm/include/llvm/Object/TapiUniversal.h
+++ b/llvm/include/llvm/Object/TapiUniversal.h
@@ -101,6 +101,8 @@ class TapiUniversal : public Binary {
return make_range(begin_objects(), end_objects());
}
+ const MachO::InterfaceFile &getInterfaceFile() { return *ParsedFile; }
+
uint32_t getNumberOfObjects() const { return Libraries.size(); }
static bool classof(const Binary *v) { return v->isTapiUniversal(); }
diff --git a/llvm/include/llvm/TextAPI/Platform.h b/llvm/include/llvm/TextAPI/Platform.h
index 0879039f994d0..3f052b7b8624d 100644
--- a/llvm/include/llvm/TextAPI/Platform.h
+++ b/llvm/include/llvm/TextAPI/Platform.h
@@ -40,6 +40,8 @@ PlatformKind mapToPlatformKind(const Triple &Target);
PlatformSet mapToPlatformSet(ArrayRef<Triple> Targets);
StringRef getPlatformName(PlatformKind Platform);
PlatformKind getPlatformFromName(StringRef Name);
+std::string getOSAndEnvironmentName(PlatformKind Platform,
+ std::string Version = "");
} // end namespace MachO.
} // end namespace llvm.
diff --git a/llvm/include/llvm/TextAPI/Symbol.h b/llvm/include/llvm/TextAPI/Symbol.h
index 878befcd90b7e..84fd83ae8e04a 100644
--- a/llvm/include/llvm/TextAPI/Symbol.h
+++ b/llvm/include/llvm/TextAPI/Symbol.h
@@ -105,12 +105,17 @@ class Symbol {
#endif
bool operator==(const Symbol &O) const {
- return (Kind == O.Kind) && (Name == O.Name) && (Targets == O.Targets) &&
- (Flags == O.Flags);
+ return std::tie(Name, Kind, Targets, Flags) ==
+ std::tie(O.Name, O.Kind, O.Targets, O.Flags);
}
bool operator!=(const Symbol &O) const { return !(*this == O); }
+ bool operator<(const Symbol &O) const {
+ return std::tie(Name, Kind, Targets, Flags) <
+ std::tie(O.Name, O.Kind, O.Targets, O.Flags);
+ }
+
private:
StringRef Name;
TargetList Targets;
diff --git a/llvm/include/llvm/TextAPI/Target.h b/llvm/include/llvm/TextAPI/Target.h
index c4c2a6d019cb9..53f56a6ee7b04 100644
--- a/llvm/include/llvm/TextAPI/Target.h
+++ b/llvm/include/llvm/TextAPI/Target.h
@@ -60,6 +60,8 @@ inline bool operator!=(const Target &LHS, const Architecture &RHS) {
PlatformSet mapToPlatformSet(ArrayRef<Target> Targets);
ArchitectureSet mapToArchitectureSet(ArrayRef<Target> Targets);
+std::string getTargetTripleName(const Target &Targ);
+
raw_ostream &operator<<(raw_ostream &OS, const Target &Target);
} // namespace MachO
diff --git a/llvm/lib/TextAPI/Platform.cpp b/llvm/lib/TextAPI/Platform.cpp
index 038ad9d4e0e07..a2ce6d0cac861 100644
--- a/llvm/lib/TextAPI/Platform.cpp
+++ b/llvm/lib/TextAPI/Platform.cpp
@@ -105,5 +105,34 @@ PlatformKind getPlatformFromName(StringRef Name) {
.Default(PlatformKind::unknown);
}
+std::string getOSAndEnvironmentName(PlatformKind Platform,
+ std::string Version) {
+ switch (Platform) {
+ case PlatformKind::unknown:
+ return "darwin" + Version;
+ case PlatformKind::macOS:
+ return "macos" + Version;
+ case PlatformKind::iOS:
+ return "ios" + Version;
+ case PlatformKind::tvOS:
+ return "tvos" + Version;
+ case PlatformKind::watchOS:
+ return "watchos" + Version;
+ case PlatformKind::bridgeOS:
+ return "bridgeos" + Version;
+ case PlatformKind::macCatalyst:
+ return "ios" + Version + "-macabi";
+ case PlatformKind::iOSSimulator:
+ return "ios" + Version + "-simulator";
+ case PlatformKind::tvOSSimulator:
+ return "tvos" + Version + "-simulator";
+ case PlatformKind::watchOSSimulator:
+ return "watchos" + Version + "-simulator";
+ case PlatformKind::driverKit:
+ return "driverkit" + Version;
+ }
+ llvm_unreachable("Unknown llvm::MachO::PlatformKind enum");
+}
+
} // end namespace MachO.
} // end namespace llvm.
diff --git a/llvm/lib/TextAPI/Target.cpp b/llvm/lib/TextAPI/Target.cpp
index 4c33a5883247e..35fe1bf65e6ff 100644
--- a/llvm/lib/TextAPI/Target.cpp
+++ b/llvm/lib/TextAPI/Target.cpp
@@ -72,5 +72,11 @@ ArchitectureSet mapToArchitectureSet(ArrayRef<Target> Targets) {
return Result;
}
+std::string getTargetTripleName(const Target &Targ) {
+ return (getArchitectureName(Targ.Arch) + "-apple-" +
+ getOSAndEnvironmentName(Targ.Platform))
+ .str();
+}
+
} // end namespace MachO.
} // end namespace llvm.
diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index 5b3e50706fcf5..8da840edf7cb6 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -116,6 +116,7 @@ set(LLVM_TEST_DEPENDS
llvm-strip
llvm-symbolizer
llvm-tblgen
+ llvm-tapi-
diff
llvm-undname
llvm-windres
llvm-xray
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index 8b28c6b5be2f0..d4e40263f40a8 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -164,7 +164,7 @@ def get_asan_rtlib():
'llvm-modextract', 'llvm-nm', 'llvm-objcopy', 'llvm-objdump', 'llvm-otool',
'llvm-pdbutil', 'llvm-profdata', 'llvm-profgen', 'llvm-ranlib', 'llvm-rc', 'llvm-readelf',
'llvm-readobj', 'llvm-rtdyld', 'llvm-size', 'llvm-split', 'llvm-strings',
- 'llvm-strip', 'llvm-tblgen', 'llvm-undname', 'llvm-windres',
+ 'llvm-strip', 'llvm-tblgen', 'llvm-tapi-
diff ', 'llvm-undname', 'llvm-windres',
'llvm-c-test', 'llvm-cxxfilt',
'llvm-xray', 'yaml2obj', 'obj2yaml', 'yaml-bench', 'verify-uselistorder',
'bugpoint', 'llc', 'llvm-symbolizer', 'opt', 'sancov', 'sanstats'])
diff --git a/llvm/test/tools/llvm-tapi-
diff /Inputs/macho.yaml b/llvm/test/tools/llvm-tapi-
diff /Inputs/macho.yaml
new file mode 100644
index 0000000000000..6a7813d6a3915
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /Inputs/macho.yaml
@@ -0,0 +1,141 @@
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x1000007
+ cpusubtype: 0x3
+ filetype: 0x6
+ ncmds: 13
+ sizeofcmds: 584
+ flags: 0x100085
+ reserved: 0x0
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 152
+ segname: __TEXT
+ vmaddr: 0
+ vmsize: 4096
+ fileoff: 0
+ filesize: 4096
+ maxprot: 7
+ initprot: 5
+ nsects: 1
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x1000
+ size: 0
+ offset: 0x1000
+ align: 0
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: ''
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 4096
+ vmsize: 4096
+ fileoff: 4096
+ filesize: 112
+ maxprot: 7
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_ID_DYLIB
+ cmdsize: 48
+ dylib:
+ name: 24
+ timestamp: 1
+ current_version: 65536
+ compatibility_version: 65536
+ PayloadString: macho-no-exports.dylib
+ ZeroPadBytes: 2
+ - cmd: LC_DYLD_INFO_ONLY
+ cmdsize: 48
+ rebase_off: 0
+ rebase_size: 0
+ bind_off: 0
+ bind_size: 0
+ weak_bind_off: 0
+ weak_bind_size: 0
+ lazy_bind_off: 0
+ lazy_bind_size: 0
+ export_off: 0
+ export_size: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 4168
+ nsyms: 1
+ stroff: 4184
+ strsize: 24
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 0
+ iundefsym: 0
+ nundefsym: 1
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+ - cmd: LC_UUID
+ cmdsize: 24
+ uuid: A24CBA21-865D-372D-B267-4964F4ADCDFC
+ - cmd: LC_VERSION_MIN_MACOSX
+ cmdsize: 16
+ version: 657920
+ sdk: 657920
+ - cmd: LC_SOURCE_VERSION
+ cmdsize: 16
+ version: 0
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 56
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 79495168
+ compatibility_version: 65536
+ PayloadString: '/usr/lib/libSystem.B.dylib'
+ ZeroPadBytes: 6
+ - cmd: LC_FUNCTION_STARTS
+ cmdsize: 16
+ dataoff: 4096
+ datasize: 8
+ - cmd: LC_DATA_IN_CODE
+ cmdsize: 16
+ dataoff: 4104
+ datasize: 0
+ - cmd: LC_DYLIB_CODE_SIGN_DRS
+ cmdsize: 16
+ dataoff: 4104
+ datasize: 64
+LinkEditData:
+ NameList:
+ - n_strx: 2
+ n_type: 0x1
+ n_sect: 0
+ n_desc: 256
+ n_value: 0
+ StringTable:
+ - ' '
+ - dyld_stub_binder
+ - ''
+ - ''
+ - ''
+ - ''
+ - ''
+...
diff --git a/llvm/test/tools/llvm-tapi-
diff /Inputs/v4A.tbd b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4A.tbd
new file mode 100644
index 0000000000000..7dba4d8430ca6
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4A.tbd
@@ -0,0 +1,49 @@
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-macos, x86_64-ios ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-macos
+ value: 11111111-1111-1111-1111-111111111111
+ - target: x86_64-ios
+ value: 11111111-1111-1111-1111-111111111111
+flags: [ flat_namespace, installapi ]
+install-name: Umbrella.framework/Umbrella
+current-version: 1.2.3
+compatibility-version: 1.2
+swift-abi-version: 5
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-macos, x86_64-ios ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos, x86_64-macos, x86_64-ios ]
+ clients: [ ClientA ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
+ - targets: [ x86_64-ios ]
+ symbols: [_symB]
+ - targets: [ x86_64-macos, x86_64-ios ]
+ symbols: [_symAB]
+reexports:
+ - targets: [ i386-macos ]
+ symbols: [_symC]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
+undefineds:
+ - targets: [ i386-macos ]
+ symbols: [ _symD ]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
diff --git a/llvm/test/tools/llvm-tapi-
diff /Inputs/v4B.tbd b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4B.tbd
new file mode 100644
index 0000000000000..6a831846951e7
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4B.tbd
@@ -0,0 +1,55 @@
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios-simulator ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-ios-simulator
+ value: 11111111-1111-1111-1111-111111111111
+flags: [ installapi ]
+install-name: 'Umbrella.framework/Umbrella'
+current-version: 1.2.3
+compatibility-version: 0
+swift-abi-version: 5
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos ]
+ clients: [ ClientA ]
+reexported-libraries:
+ - targets: [ i386-macos ]
+ libraries: [ 'Alpine.framework/Alpine' ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: [ Class1 ]
+ weak-symbols: [ _symC ]
+ - targets: [ x86_64-ios-simulator ]
+ symbols: [ _symB ]
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios-simulator ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-ios-simulator
+ value: 11111111-1111-1111-1111-111111111111
+flags: []
+install-name: 'Alpine.framework/Alpine'
+current-version: 1.2.3
+compatibility-version: 0
+swift-abi-version: 5
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos ]
+ clients: [ ClientD ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: [ Class1 ]
+ weak-symbols: [ _symC ]
+ - targets: [ x86_64-ios-simulator ]
+ symbols: [ _symB ]
diff --git a/llvm/test/tools/llvm-tapi-
diff /Inputs/v4C.tbd b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4C.tbd
new file mode 100644
index 0000000000000..b2641e2d9e7a2
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4C.tbd
@@ -0,0 +1,49 @@
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-macos
+ value: 11111111-1111-1111-1111-111111111111
+ - target: x86_64-ios
+ value: 22222222-2222-2222-2222-222222222222
+flags: [ installapi ]
+install-name: Umbrella.framework/Umbrella
+current-version: 1.3.3
+compatibility-version: 1.2
+swift-abi-version: 3
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos, x86_64-ios ]
+ clients: [ ClientA ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
+ - targets: [ x86_64-ios ]
+ symbols: [_symB]
+ - targets: [ x86_64-ios ]
+ symbols: [_symAB]
+reexports:
+ - targets: [ i386-macos ]
+ symbols: [_symC]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
+undefineds:
+ - targets: [ i386-macos ]
+ symbols: [ _symD ]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
diff --git a/llvm/test/tools/llvm-tapi-
diff /Inputs/v4D.tbd b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4D.tbd
new file mode 100644
index 0000000000000..1338f62bddfc4
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4D.tbd
@@ -0,0 +1,104 @@
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios-simulator ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-ios-simulator
+ value: 11111111-1111-1111-1111-111111111111
+flags: [ installapi ]
+install-name: 'Umbrella.framework/Umbrella'
+current-version: 1.2.3
+compatibility-version: 0
+swift-abi-version: 5
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos ]
+ clients: [ ClientA ]
+reexported-libraries:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ libraries: [ 'Alpine.framework/Alpine', 'System.framework/System' ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: [ Class1 ]
+ weak-symbols: [ _symC ]
+ - targets: [ x86_64-ios-simulator ]
+ symbols: [ _symB ]
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios-simulator ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-ios-simulator
+ value: 11111111-1111-1111-1111-111111111111
+flags: []
+install-name: 'Alpine.framework/Alpine'
+current-version: 1.2.3
+compatibility-version: 0
+swift-abi-version: 5
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos ]
+ clients: [ ClientD ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: [ Class1 ]
+ weak-symbols: [ _symC ]
+ - targets: [ x86_64-ios-simulator ]
+ symbols: [ _symB ]
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-macos
+ value: 11111111-1111-1111-1111-111111111111
+ - target: x86_64-ios
+ value: 22222222-2222-2222-2222-222222222222
+flags: []
+install-name: 'System.framework/System'
+current-version: 1.3.3
+compatibility-version: 1.2
+swift-abi-version: 3
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos, x86_64-ios ]
+ clients: [ ClientA ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
+ - targets: [ x86_64-ios ]
+ symbols: [_symB]
+ - targets: [ x86_64-ios ]
+ symbols: [_symAB]
+reexports:
+ - targets: [ i386-macos ]
+ symbols: [_symC]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
+undefineds:
+ - targets: [ i386-macos ]
+ symbols: [ _symD ]
+ objc-classes: []
+ objc-eh-types: []
+ objc-ivars: []
+ weak-symbols: []
+ thread-local-symbols: []
diff --git a/llvm/test/tools/llvm-tapi-
diff /Inputs/v4E.tbd b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4E.tbd
new file mode 100644
index 0000000000000..1d34b2d44c260
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /Inputs/v4E.tbd
@@ -0,0 +1,55 @@
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios-simulator ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-ios-simulator
+ value: 11111111-1111-1111-1111-111111111111
+flags: [ installapi ]
+install-name: 'Umbrella.framework/Umbrella'
+current-version: 1.2.3
+compatibility-version: 0
+swift-abi-version: 4
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos ]
+ clients: [ ClientC ]
+reexported-libraries:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ libraries: [ Alpine.framework/Alpine ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symA ]
+ objc-classes: [ Class1 ]
+ weak-symbols: [ _symQ ]
+ - targets: [ x86_64-ios-simulator ]
+ symbols: [ _symB ]
+--- !tapi-tbd
+tbd-version: 4
+targets: [ i386-macos, x86_64-ios-simulator ]
+uuids:
+ - target: i386-macos
+ value: 00000000-0000-0000-0000-000000000000
+ - target: x86_64-ios-simulator
+ value: 11111111-1111-1111-1111-111111111111
+flags: []
+install-name: 'Alpine.framework/Alpine'
+current-version: 1.4.3
+compatibility-version: 0
+swift-abi-version: 3
+parent-umbrella:
+ - targets: [ i386-macos, x86_64-ios-simulator ]
+ umbrella: System
+allowable-clients:
+ - targets: [ i386-macos ]
+ clients: [ ClientB ]
+exports:
+ - targets: [ i386-macos ]
+ symbols: [ _symE ]
+ objc-classes: [ Class1 ]
+ weak-symbols: [ _symC ]
+ - targets: [ x86_64-ios-simulator ]
+ symbols: [ _symB ]
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -incorrect-format.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -incorrect-format.test
new file mode 100644
index 0000000000000..4755f3abad3ba
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -incorrect-format.test
@@ -0,0 +1,7 @@
+; RUN: mkdir -p %t
+; RUN: yaml2obj %S/Inputs/macho.yaml -o %t/macho.dylib
+; RUN: not llvm-tapi-
diff %S/Inputs/v4A.tbd %t/macho.dylib 2>&1 | FileCheck %s
+
+; CHECK: {{.*}}: error: {{.*}}macho.dylib: Error when parsing file, unsupported file format
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -matching-tbd.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -matching-tbd.test
new file mode 100644
index 0000000000000..a98bc41ec6fd5
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -matching-tbd.test
@@ -0,0 +1,4 @@
+; RUN: llvm-tapi-
diff %S/Inputs/v4A.tbd %S/Inputs/v4A.tbd 2>&1 | FileCheck %s --allow-empty
+
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -mismatched-number-of-inlines.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -mismatched-number-of-inlines.test
new file mode 100644
index 0000000000000..3835bdaf1fb74
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -mismatched-number-of-inlines.test
@@ -0,0 +1,46 @@
+; RUN: not llvm-tapi-
diff %S/Inputs/v4B.tbd %S/Inputs/v4D.tbd 2>&1 | FileCheck %s
+
+; CHECK:< {{.*}}/Inputs/v4B.tbd
+; CHECK:> {{.*}}/Inputs/v4D.tbd
+
+; CHECK: Reexported Libraries
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > System.framework/System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > Alpine.framework/Alpine
+; CHECK-NEXT: > System.framework/System
+; CHECK-NEXT:Inlined Reexported Frameworks/Libraries
+; CHECK-NEXT: System.framework/System
+; CHECK-NEXT: Current Version
+; CHECK-NEXT: > 1.3.3
+; CHECK-NEXT: Compatibility Version
+; CHECK-NEXT: > 1.2
+; CHECK-NEXT: Swift ABI Version
+; CHECK-NEXT: > 3
+; CHECK-NEXT: InstallAPI
+; CHECK-NEXT: > false
+; CHECK-NEXT: Two Level Namespace
+; CHECK-NEXT: > true
+; CHECK-NEXT: Application Extension Safe
+; CHECK-NEXT: > true
+; CHECK-NEXT: Allowable Clients
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > ClientA
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > ClientA
+; CHECK-NEXT: Parent Umbrellas
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > System
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > System
+; CHECK-NEXT: Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > _symA
+; CHECK-NEXT: > _symC - Reexported
+; CHECK-NEXT: > _symD - Undefined
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > _symB
+; CHECK-NEXT: > _symAB
+
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -misspelled-tbd.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -misspelled-tbd.test
new file mode 100644
index 0000000000000..9f624467bc982
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -misspelled-tbd.test
@@ -0,0 +1,5 @@
+; RUN: not llvm-tapi-
diff %S/Inputs/v4A.tbd %S/Inputs/v4.tbd 2>&1 | FileCheck %s
+
+; CHECK: {{.*}}: error: {{.*}}v4.tbd: {{[Nn]}}o such file or directory
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -no-inlines.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -no-inlines.test
new file mode 100644
index 0000000000000..c46c91fd011ea
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -no-inlines.test
@@ -0,0 +1,26 @@
+; RUN: not llvm-tapi-
diff %S/Inputs/v4A.tbd %S/Inputs/v4C.tbd 2>&1 | FileCheck %s
+
+; CHECK:< {{.*}}/Inputs/v4A.tbd
+; CHECK:> {{.*}}/Inputs/v4C.tbd
+
+; CHECK:Current Version
+; CHECK-NEXT:< 1.2.3
+; CHECK-NEXT:> 1.3.3
+; CHECK-NEXT:Swift ABI Version
+; CHECK-NEXT:< 5
+; CHECK-NEXT:> 3
+; CHECK-NEXT:Two Level Namespace
+; CHECK-NEXT:< false
+; CHECK-NEXT:> true
+; CHECK-NEXT:Allowable Clients
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < ClientA
+; CHECK-NEXT:Parent Umbrellas
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < System
+; CHECK-NEXT:Symbols
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK: < _symAB
+
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -same-number-of-inlines.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -same-number-of-inlines.test
new file mode 100644
index 0000000000000..64bdd48ec06f8
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -same-number-of-inlines.test
@@ -0,0 +1,38 @@
+; RUN: not llvm-tapi-
diff %S/Inputs/v4B.tbd %S/Inputs/v4E.tbd 2>&1 | FileCheck %s
+
+; CHECK:< {{.*}}/Inputs/v4B.tbd
+; CHECK:> {{.*}}/Inputs/v4E.tbd
+
+; CHECK:Swift ABI Version
+; CHECK-NEXT:< 5
+; CHECK-NEXT:> 4
+; CHECK-NEXT:Reexported Libraries
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > Alpine.framework/Alpine
+; CHECK-NEXT:Allowable Clients
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < ClientA
+; CHECK-NEXT: > ClientC
+; CHECK-NEXT:Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < _symC - Weak-Defined
+; CHECK-NEXT: > _symQ - Weak-Defined
+; CHECK-NEXT:Inlined Reexported Frameworks/Libraries
+; CHECK-NEXT: Alpine.framework/Alpine
+; CHECK-NEXT: Current Version
+; CHECK-NEXT: < 1.2.3
+; CHECK-NEXT: > 1.4.3
+; CHECK-NEXT: Swift ABI Version
+; CHECK-NEXT: < 5
+; CHECK-NEXT: > 3
+; CHECK-NEXT: Allowable Clients
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < ClientD
+; CHECK-NEXT: > ClientB
+; CHECK-NEXT: Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < _symA
+; CHECK-NEXT: > _symE
+
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-multiple-inlines.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-multiple-inlines.test
new file mode 100644
index 0000000000000..34fbb08dda706
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-multiple-inlines.test
@@ -0,0 +1,106 @@
+; RUN: not llvm-tapi-
diff %S/Inputs/v4A.tbd %S/Inputs/v4D.tbd 2>&1 | FileCheck %s
+
+; CHECK:< {{.*}}/Inputs/v4A.tbd
+; CHECK:> {{.*}}/Inputs/v4D.tbd
+
+; CHECK:Compatibility Version
+; CHECK-NEXT:< 1.2
+; CHECK-NEXT:> 0
+; CHECK-NEXT:Two Level Namespace
+; CHECK-NEXT:< false
+; CHECK-NEXT:> true
+; CHECK-NEXT:Reexported Libraries
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > Alpine.framework/Alpine
+; CHECK-NEXT: > System.framework/System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > Alpine.framework/Alpine
+; CHECK-NEXT: > System.framework/System
+; CHECK-NEXT:Allowable Clients
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < ClientA
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: < ClientA
+; CHECK-NEXT:Parent Umbrellas
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < System
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: < System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > System
+; CHECK-NEXT:Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < _symC - Reexported
+; CHECK-NEXT: < _symD - Undefined
+; CHECK-NEXT: > .objc_class_name_Class1
+; CHECK-NEXT: > _symC - Weak-Defined
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < _symAB
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: < _symB
+; CHECK-NEXT: < _symAB
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > _symB
+; CHECK-NEXT:Inlined Reexported Frameworks/Libraries
+; CHECK-NEXT: Alpine.framework/Alpine
+; CHECK-NEXT: Current Version
+; CHECK-NEXT: > 1.2.3
+; CHECK-NEXT: Compatibility Version
+; CHECK-NEXT: > 0
+; CHECK-NEXT: Swift ABI Version
+; CHECK-NEXT: > 5
+; CHECK-NEXT: InstallAPI
+; CHECK-NEXT: > false
+; CHECK-NEXT: Two Level Namespace
+; CHECK-NEXT: > true
+; CHECK-NEXT: Application Extension Safe
+; CHECK-NEXT: > true
+; CHECK-NEXT: Allowable Clients
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > ClientD
+; CHECK-NEXT: Parent Umbrellas
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > System
+; CHECK-NEXT: Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > _symA
+; CHECK-NEXT: > .objc_class_name_Class1
+; CHECK-NEXT: > _symC - Weak-Defined
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > _symB
+; CHECK-NEXT: System.framework/System
+; CHECK-NEXT: Current Version
+; CHECK-NEXT: > 1.3.3
+; CHECK-NEXT: Compatibility Version
+; CHECK-NEXT: > 1.2
+; CHECK-NEXT: Swift ABI Version
+; CHECK-NEXT: > 3
+; CHECK-NEXT: InstallAPI
+; CHECK-NEXT: > false
+; CHECK-NEXT: Two Level Namespace
+; CHECK-NEXT: > true
+; CHECK-NEXT: Application Extension Safe
+; CHECK-NEXT: > true
+; CHECK-NEXT: Allowable Clients
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > ClientA
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > ClientA
+; CHECK-NEXT: Parent Umbrellas
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > System
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > System
+; CHECK-NEXT: Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > _symA
+; CHECK-NEXT: > _symC - Reexported
+; CHECK-NEXT: > _symD - Undefined
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > _symB
+; CHECK-NEXT: > _symAB
+
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-single-inlineA.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-single-inlineA.test
new file mode 100644
index 0000000000000..9e1b8b754360d
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-single-inlineA.test
@@ -0,0 +1,73 @@
+; RUN: not llvm-tapi-
diff %S/Inputs/v4A.tbd %S/Inputs/v4B.tbd 2>&1 | FileCheck %s
+
+; CHECK:< {{.*}}/Inputs/v4A.tbd
+; CHECK:> {{.*}}/Inputs/v4B.tbd
+
+; CHECK:Compatibility Version
+; CHECK-NEXT:< 1.2
+; CHECK-NEXT:> 0
+; CHECK-NEXT:Two Level Namespace
+; CHECK-NEXT:< false
+; CHECK-NEXT:> true
+; CHECK-NEXT:Reexported Libraries
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > Alpine.framework/Alpine
+; CHECK-NEXT:Allowable Clients
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < ClientA
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: < ClientA
+; CHECK-NEXT:Parent Umbrellas
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < System
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: < System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > System
+; CHECK-NEXT:Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < _symC - Reexported
+; CHECK-NEXT: < _symD - Undefined
+; CHECK-NEXT: > .objc_class_name_Class1
+; CHECK-NEXT: > _symC - Weak-Defined
+; CHECK-NEXT: x86_64-apple-macos
+; CHECK-NEXT: < _symAB
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: < _symB
+; CHECK-NEXT: < _symAB
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > _symB
+; CHECK-NEXT:Inlined Reexported Frameworks/Libraries
+; CHECK-NEXT: Alpine.framework/Alpine
+; CHECK-NEXT: Current Version
+; CHECK-NEXT: > 1.2.3
+; CHECK-NEXT: Compatibility Version
+; CHECK-NEXT: > 0
+; CHECK-NEXT: Swift ABI Version
+; CHECK-NEXT: > 5
+; CHECK-NEXT: InstallAPI
+; CHECK-NEXT: > false
+; CHECK-NEXT: Two Level Namespace
+; CHECK-NEXT: > true
+; CHECK-NEXT: Application Extension Safe
+; CHECK-NEXT: > true
+; CHECK-NEXT: Allowable Clients
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > ClientD
+; CHECK-NEXT: Parent Umbrellas
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > System
+; CHECK-NEXT: Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: > _symA
+; CHECK-NEXT: > .objc_class_name_Class1
+; CHECK-NEXT: > _symC - Weak-Defined
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: > _symB
+
+
+
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-single-inlineB.test b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-single-inlineB.test
new file mode 100644
index 0000000000000..4f5da809e30fd
--- /dev/null
+++ b/llvm/test/tools/llvm-tapi-
diff /tapi-
diff -tbd-has-single-inlineB.test
@@ -0,0 +1,68 @@
+; RUN: not llvm-tapi-
diff %S/Inputs/v4B.tbd %S/Inputs/v4C.tbd 2>&1 | FileCheck %s
+
+; CHECK:< {{.*}}/Inputs/v4B.tbd
+; CHECK:> {{.*}}/Inputs/v4C.tbd
+
+; CHECK:Current Version
+; CHECK-NEXT:< 1.2.3
+; CHECK-NEXT:> 1.3.3
+; CHECK-NEXT:Compatibility Version
+; CHECK-NEXT:< 0
+; CHECK-NEXT:> 1.2
+; CHECK-NEXT:Swift ABI Version
+; CHECK-NEXT:< 5
+; CHECK-NEXT:> 3
+; CHECK-NEXT:Reexported Libraries
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < Alpine.framework/Alpine
+; CHECK-NEXT:Allowable Clients
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > ClientA
+; CHECK-NEXT:Parent Umbrellas
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: < System
+; CHECK-NEXT:Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < .objc_class_name_Class1
+; CHECK-NEXT: < _symC - Weak-Defined
+; CHECK-NEXT: > _symC - Reexported
+; CHECK-NEXT: > _symD - Undefined
+; CHECK-NEXT: x86_64-apple-ios
+; CHECK-NEXT: > _symB
+; CHECK-NEXT: > _symAB
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: < _symB
+; CHECK-NEXT:Inlined Reexported Frameworks/Libraries
+; CHECK-NEXT: Alpine.framework/Alpine
+; CHECK-NEXT: Current Version
+; CHECK-NEXT: < 1.2.3
+; CHECK-NEXT: Compatibility Version
+; CHECK-NEXT: < 0
+; CHECK-NEXT: Swift ABI Version
+; CHECK-NEXT: < 5
+; CHECK-NEXT: InstallAPI
+; CHECK-NEXT: < false
+; CHECK-NEXT: Two Level Namespace
+; CHECK-NEXT: < true
+; CHECK-NEXT: Application Extension Safe
+; CHECK-NEXT: < true
+; CHECK-NEXT: Allowable Clients
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < ClientD
+; CHECK-NEXT: Parent Umbrellas
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < System
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: < System
+; CHECK-NEXT: Symbols
+; CHECK-NEXT: i386-apple-macos
+; CHECK-NEXT: < _symA
+; CHECK-NEXT: < .objc_class_name_Class1
+; CHECK-NEXT: < _symC - Weak-Defined
+; CHECK-NEXT: x86_64-apple-ios-simulator
+; CHECK-NEXT: < _symB
+
+; CHECK-NOT: error:
+; CHECK-NOT: warning:
diff --git a/llvm/tools/llvm-tapi-
diff /CMakeLists.txt b/llvm/tools/llvm-tapi-
diff /CMakeLists.txt
new file mode 100644
index 0000000000000..2870221dd18f3
--- /dev/null
+++ b/llvm/tools/llvm-tapi-
diff /CMakeLists.txt
@@ -0,0 +1,10 @@
+set(LLVM_LINK_COMPONENTS
+ Object
+ Support
+ TextAPI
+ )
+
+add_llvm_tool(llvm-tapi-
diff
+ llvm-tapi-
diff .cpp
+ DiffEngine.cpp
+ )
diff --git a/llvm/tools/llvm-tapi-
diff /DiffEngine.cpp b/llvm/tools/llvm-tapi-
diff /DiffEngine.cpp
new file mode 100644
index 0000000000000..b766cf14380fc
--- /dev/null
+++ b/llvm/tools/llvm-tapi-
diff /DiffEngine.cpp
@@ -0,0 +1,554 @@
+//===-- DiffEngine.cpp - Structural file comparison -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the implementation of the llvm-tapi
diff erence
+// engine, which structurally compares two tbd files.
+//
+//===----------------------------------------------------------------------===/
+#include "DiffEngine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TextAPI/InterfaceFile.h"
+#include "llvm/TextAPI/Target.h"
+
+using namespace llvm;
+using namespace MachO;
+using namespace object;
+
+StringRef setOrderIndicator(InterfaceInputOrder Order) {
+ return ((Order == lhs) ? "< " : "> ");
+}
+
+// The following template specialization implementations
+// need to be explicitly placed into the llvm namespace
+// to work around a GCC 4.8 bug.
+namespace llvm {
+
+template <typename T, DiffAttrKind U>
+inline void DiffScalarVal<T, U>::print(raw_ostream &OS, std::string Indent) {
+ OS << Indent << "\t" << setOrderIndicator(Order) << Val << "\n";
+}
+
+template <>
+inline void
+DiffScalarVal<StringRef, AD_Diff_Scalar_Str>::print(raw_ostream &OS,
+ std::string Indent) {
+ OS << Indent << "\t\t" << setOrderIndicator(Order) << Val << "\n";
+}
+
+template <>
+inline void
+DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>::print(raw_ostream &OS,
+ std::string Indent) {
+ OS << Indent << "\t" << setOrderIndicator(Order) << std::to_string(Val)
+ << "\n";
+}
+
+template <>
+inline void
+DiffScalarVal<bool, AD_Diff_Scalar_Bool>::print(raw_ostream &OS,
+ std::string Indent) {
+ OS << Indent << "\t" << setOrderIndicator(Order)
+ << ((Val == true) ? "true" : "false") << "\n";
+}
+
+} // end namespace llvm
+
+std::string SymScalar::stringifySymbolKind(MachO::SymbolKind Kind) {
+ switch (Kind) {
+ case MachO::SymbolKind::GlobalSymbol:
+ return "";
+ case MachO::SymbolKind::ObjectiveCClass:
+ return "_OBJC_METACLASS_$_";
+ case MachO::SymbolKind ::ObjectiveCClassEHType:
+ return "_OBJC_EHTYPE_$_";
+ case MachO::SymbolKind ::ObjectiveCInstanceVariable:
+ return "_OBJC_IVAR_$_";
+ }
+ llvm_unreachable("Unknown llvm::MachO::SymbolKind enum");
+}
+
+std::string SymScalar::stringifySymbolFlag(MachO::SymbolFlags Flag) {
+ switch (Flag) {
+ case MachO::SymbolFlags::None:
+ return "";
+ case MachO::SymbolFlags::ThreadLocalValue:
+ return "Thread-Local";
+ case MachO::SymbolFlags::WeakDefined:
+ return "Weak-Defined";
+ case MachO::SymbolFlags::WeakReferenced:
+ return "Weak-Referenced";
+ case MachO::SymbolFlags::Undefined:
+ return "Undefined";
+ case MachO::SymbolFlags::Rexported:
+ return "Reexported";
+ }
+ llvm_unreachable("Unknown llvm::MachO::SymbolFlags enum");
+}
+
+void SymScalar::print(raw_ostream &OS, std::string Indent, MachO::Target Targ) {
+ if (Val->getKind() == MachO::SymbolKind::ObjectiveCClass) {
+ if (Targ.Arch == MachO::AK_i386 &&
+ Targ.Platform == MachO::PlatformKind::macOS) {
+ OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
+ << ".objc_class_name_" << Val->getName()
+ << getFlagString(Val->getFlags()) << "\n";
+ return;
+ }
+ OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ") << "_OBJC_CLASS_$_"
+ << Val->getName() << getFlagString(Val->getFlags()) << "\n";
+ }
+ OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
+ << stringifySymbolKind(Val->getKind()) << Val->getName()
+ << getFlagString(Val->getFlags()) << "\n";
+}
+
+bool checkSymbolEquality(llvm::MachO::InterfaceFile::const_symbol_range LHS,
+ llvm::MachO::InterfaceFile::const_symbol_range RHS) {
+ return std::equal(LHS.begin(), LHS.end(), RHS.begin(),
+ [&](auto LHS, auto RHS) { return *LHS == *RHS; });
+}
+
+template <typename TargetVecT, typename ValTypeT, typename V>
+void addDiffForTargSlice(V Val, Target Targ, DiffOutput &Diff,
+ InterfaceInputOrder Order) {
+ auto TargetVector = llvm::find_if(
+ Diff.Values, [&](const std::unique_ptr<AttributeDiff> &RawTVec) {
+ if (TargetVecT *TVec = dyn_cast<TargetVecT>(RawTVec.get()))
+ return TVec->Targ == Targ;
+ return false;
+ });
+ if (TargetVector != Diff.Values.end()) {
+ ValTypeT NewVal(Order, Val);
+ cast<TargetVecT>(TargetVector->get())->TargValues.push_back(NewVal);
+ } else {
+ auto NewTargetVec = std::make_unique<TargetVecT>(Targ);
+ ValTypeT NewVal(Order, Val);
+ NewTargetVec->TargValues.push_back(NewVal);
+ Diff.Values.push_back(std::move(NewTargetVec));
+ }
+}
+
+DiffOutput getSingleAttrDiff(const std::vector<InterfaceFileRef> &IRefVec,
+ std::string Name, InterfaceInputOrder Order) {
+ DiffOutput Diff(Name);
+ Diff.Kind = AD_Str_Vec;
+ for (const auto &IRef : IRefVec)
+ for (auto Targ : IRef.targets())
+ addDiffForTargSlice<DiffStrVec,
+ DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+ IRef.getInstallName(), Targ, Diff, Order);
+ return Diff;
+}
+
+DiffOutput
+getSingleAttrDiff(const std::vector<std::pair<Target, std::string>> &PairVec,
+ std::string Name, InterfaceInputOrder Order) {
+ DiffOutput Diff(Name);
+ Diff.Kind = AD_Str_Vec;
+ for (const auto &Pair : PairVec)
+ addDiffForTargSlice<DiffStrVec,
+ DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+ StringRef(Pair.second), Pair.first, Diff, Order);
+ return Diff;
+}
+
+DiffOutput getSingleAttrDiff(InterfaceFile::const_symbol_range SymRange,
+ std::string Name, InterfaceInputOrder Order) {
+ DiffOutput Diff(Name);
+ Diff.Kind = AD_Sym_Vec;
+ for (const auto *Sym : SymRange)
+ for (auto Targ : Sym->targets())
+ addDiffForTargSlice<DiffSymVec, SymScalar>(Sym, Targ, Diff, Order);
+ return Diff;
+}
+
+template <typename T>
+DiffOutput getSingleAttrDiff(T SingleAttr, std::string Attribute) {
+ DiffOutput Diff(Attribute);
+ Diff.Kind = SingleAttr.getKind();
+ Diff.Values.push_back(std::make_unique<T>(SingleAttr));
+ return Diff;
+}
+
+template <typename T, DiffAttrKind U>
+void
diff Attribute(std::string Name, std::vector<DiffOutput> &Output,
+ DiffScalarVal<T, U> Attr) {
+ Output.push_back(getSingleAttrDiff(Attr, Name));
+}
+
+template <typename T>
+void
diff Attribute(std::string Name, std::vector<DiffOutput> &Output,
+ const T &Val, InterfaceInputOrder Order) {
+ Output.push_back(getSingleAttrDiff(Val, Name, Order));
+}
+
+std::vector<DiffOutput> getSingleIF(InterfaceFile *Interface,
+ InterfaceInputOrder Order) {
+ std::vector<DiffOutput> Output;
+
diff Attribute("Install Name", Output,
+ DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(
+ Order, Interface->getInstallName()));
+
diff Attribute("Current Version", Output,
+ DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+ Order, Interface->getCurrentVersion()));
+
diff Attribute("Compatibility Version", Output,
+ DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+ Order, Interface->getCompatibilityVersion()));
+
diff Attribute("Swift ABI Version", Output,
+ DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
+ Order, Interface->getSwiftABIVersion()));
+
diff Attribute("InstallAPI", Output,
+ DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+ Order, Interface->isInstallAPI()));
+
diff Attribute("Two Level Namespace", Output,
+ DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+ Order, Interface->isTwoLevelNamespace()));
+
diff Attribute("Application Extension Safe", Output,
+ DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+ Order, Interface->isApplicationExtensionSafe()));
+
diff Attribute("Reexported Libraries", Output,
+ Interface->reexportedLibraries(), Order);
+
diff Attribute("Allowable Clients", Output, Interface->allowableClients(),
+ Order);
+
diff Attribute("Parent Umbrellas", Output, Interface->umbrellas(), Order);
+
diff Attribute("Symbols", Output, Interface->symbols(), Order);
+ for (auto Doc : Interface->documents()) {
+ DiffOutput Documents("Inlined Reexported Frameworks/Libraries");
+ Documents.Kind = AD_Inline_Doc;
+ Documents.Values.push_back(std::make_unique<InlineDoc>(
+ InlineDoc(Doc->getInstallName(), getSingleIF(Doc.get(), Order))));
+ Output.push_back(std::move(Documents));
+ }
+ return Output;
+}
+
+void findAndAddDiff(const std::vector<InterfaceFileRef> &CollectedIRefVec,
+ const std::vector<InterfaceFileRef> &LookupIRefVec,
+ DiffOutput &Result, InterfaceInputOrder Order) {
+ Result.Kind = AD_Str_Vec;
+ for (const auto &IRef : CollectedIRefVec)
+ for (auto Targ : IRef.targets()) {
+ auto FoundIRef = llvm::find_if(LookupIRefVec, [&](const auto LIRef) {
+ auto FoundTarg = llvm::find(LIRef.targets(), Targ);
+ return (FoundTarg != LIRef.targets().end() &&
+ IRef.getInstallName() == LIRef.getInstallName());
+ });
+ if (FoundIRef == LookupIRefVec.end())
+ addDiffForTargSlice<DiffStrVec,
+ DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+ IRef.getInstallName(), Targ, Result, Order);
+ }
+}
+
+void findAndAddDiff(
+ const std::vector<std::pair<Target, std::string>> &CollectedPairs,
+ const std::vector<std::pair<Target, std::string>> &LookupPairs,
+ DiffOutput &Result, InterfaceInputOrder Order) {
+ Result.Kind = AD_Str_Vec;
+ for (const auto &Pair : CollectedPairs) {
+ auto FoundPair = llvm::find(LookupPairs, Pair);
+ if (FoundPair == LookupPairs.end())
+ addDiffForTargSlice<DiffStrVec,
+ DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+ StringRef(Pair.second), Pair.first, Result, Order);
+ }
+}
+
+void findAndAddDiff(InterfaceFile::const_symbol_range CollectedSyms,
+ InterfaceFile::const_symbol_range LookupSyms,
+ DiffOutput &Result, InterfaceInputOrder Order) {
+ Result.Kind = AD_Sym_Vec;
+ for (const auto *Sym : CollectedSyms)
+ for (const auto Targ : Sym->targets()) {
+ auto FoundSym = llvm::find_if(LookupSyms, [&](const auto LSym) {
+ auto FoundTarg = llvm::find(LSym->targets(), Targ);
+ return (Sym->getName() == LSym->getName() &&
+ Sym->getKind() == LSym->getKind() &&
+ Sym->getFlags() == LSym->getFlags() &&
+ FoundTarg != LSym->targets().end());
+ });
+ if (FoundSym == LookupSyms.end())
+ addDiffForTargSlice<DiffSymVec, SymScalar>(Sym, Targ, Result, Order);
+ }
+}
+
+template <typename T>
+DiffOutput recordDifferences(T LHS, T RHS, std::string Attr) {
+ DiffOutput Diff(Attr);
+ if (LHS.getKind() == RHS.getKind()) {
+ Diff.Kind = LHS.getKind();
+ Diff.Values.push_back(std::make_unique<T>(LHS));
+ Diff.Values.push_back(std::make_unique<T>(RHS));
+ }
+ return Diff;
+}
+
+template <typename T>
+DiffOutput recordDifferences(const std::vector<T> &LHS,
+ const std::vector<T> &RHS, std::string Attr) {
+ DiffOutput Diff(Attr);
+ Diff.Kind = AD_Str_Vec;
+ findAndAddDiff(LHS, RHS, Diff, lhs);
+ findAndAddDiff(RHS, LHS, Diff, rhs);
+ return Diff;
+}
+
+DiffOutput recordDifferences(llvm::MachO::InterfaceFile::const_symbol_range LHS,
+ llvm::MachO::InterfaceFile::const_symbol_range RHS,
+ std::string Attr) {
+ DiffOutput Diff(Attr);
+ Diff.Kind = AD_Sym_Vec;
+ findAndAddDiff(LHS, RHS, Diff, lhs);
+ findAndAddDiff(RHS, LHS, Diff, rhs);
+ return Diff;
+}
+
+std::vector<DiffOutput>
+DiffEngine::findDifferences(const InterfaceFile *IFLHS,
+ const InterfaceFile *IFRHS) {
+ std::vector<DiffOutput> Output;
+ if (IFLHS->getInstallName() != IFRHS->getInstallName())
+ Output.push_back(recordDifferences(
+ DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(lhs,
+ IFLHS->getInstallName()),
+ DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(rhs,
+ IFRHS->getInstallName()),
+ "Install Name"));
+
+ if (IFLHS->getCurrentVersion() != IFRHS->getCurrentVersion())
+ Output.push_back(recordDifferences(
+ DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+ lhs, IFLHS->getCurrentVersion()),
+ DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+ rhs, IFRHS->getCurrentVersion()),
+ "Current Version"));
+ if (IFLHS->getCompatibilityVersion() != IFRHS->getCompatibilityVersion())
+ Output.push_back(recordDifferences(
+ DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+ lhs, IFLHS->getCompatibilityVersion()),
+ DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+ rhs, IFRHS->getCompatibilityVersion()),
+ "Compatibility Version"));
+ if (IFLHS->getSwiftABIVersion() != IFRHS->getSwiftABIVersion())
+ Output.push_back(
+ recordDifferences(DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
+ lhs, IFLHS->getSwiftABIVersion()),
+ DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
+ rhs, IFRHS->getSwiftABIVersion()),
+ "Swift ABI Version"));
+ if (IFLHS->isInstallAPI() != IFRHS->isInstallAPI())
+ Output.push_back(recordDifferences(
+ DiffScalarVal<bool, AD_Diff_Scalar_Bool>(lhs, IFLHS->isInstallAPI()),
+ DiffScalarVal<bool, AD_Diff_Scalar_Bool>(rhs, IFRHS->isInstallAPI()),
+ "InstallAPI"));
+
+ if (IFLHS->isTwoLevelNamespace() != IFRHS->isTwoLevelNamespace())
+ Output.push_back(recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+ lhs, IFLHS->isTwoLevelNamespace()),
+ DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+ rhs, IFRHS->isTwoLevelNamespace()),
+ "Two Level Namespace"));
+
+ if (IFLHS->isApplicationExtensionSafe() !=
+ IFRHS->isApplicationExtensionSafe())
+ Output.push_back(
+ recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+ lhs, IFLHS->isApplicationExtensionSafe()),
+ DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+ rhs, IFRHS->isApplicationExtensionSafe()),
+ "Application Extension Safe"));
+
+ if (IFLHS->reexportedLibraries() != IFRHS->reexportedLibraries())
+ Output.push_back(recordDifferences(IFLHS->reexportedLibraries(),
+ IFRHS->reexportedLibraries(),
+ "Reexported Libraries"));
+
+ if (IFLHS->allowableClients() != IFRHS->allowableClients())
+ Output.push_back(recordDifferences(IFLHS->allowableClients(),
+ IFRHS->allowableClients(),
+ "Allowable Clients"));
+
+ if (IFLHS->umbrellas() != IFRHS->umbrellas())
+ Output.push_back(recordDifferences(IFLHS->umbrellas(), IFRHS->umbrellas(),
+ "Parent Umbrellas"));
+
+ if (!checkSymbolEquality(IFLHS->symbols(), IFRHS->symbols()))
+ Output.push_back(
+ recordDifferences(IFLHS->symbols(), IFRHS->symbols(), "Symbols"));
+
+ if (IFLHS->documents() != IFRHS->documents()) {
+ DiffOutput Docs("Inlined Reexported Frameworks/Libraries");
+ Docs.Kind = AD_Inline_Doc;
+ std::vector<StringRef> DocsInserted;
+ // Iterate through inline frameworks/libraries from interface file and find
+ // match based on install name.
+ for (auto DocLHS : IFLHS->documents()) {
+ auto Pair = llvm::find_if(IFRHS->documents(), [&](const auto &DocRHS) {
+ return (DocLHS->getInstallName() == DocRHS->getInstallName());
+ });
+ // If a match found, recursively get
diff erences between the pair.
+ if (Pair != IFRHS->documents().end()) {
+ InlineDoc PairDiff =
+ InlineDoc(DocLHS->getInstallName(),
+ findDifferences(DocLHS.get(), Pair->get()));
+ if (!PairDiff.DocValues.empty())
+ Docs.Values.push_back(
+ std::make_unique<InlineDoc>(std::move(PairDiff)));
+ }
+ // If a match is not found, get attributes from single item.
+ else
+ Docs.Values.push_back(std::make_unique<InlineDoc>(InlineDoc(
+ DocLHS->getInstallName(), getSingleIF(DocLHS.get(), lhs))));
+ DocsInserted.push_back(DocLHS->getInstallName());
+ }
+ for (auto DocRHS : IFRHS->documents()) {
+ auto WasGathered =
+ llvm::find_if(DocsInserted, [&](const auto &GatheredDoc) {
+ return (GatheredDoc == DocRHS->getInstallName());
+ });
+ if (WasGathered == DocsInserted.end())
+ Docs.Values.push_back(std::make_unique<InlineDoc>(InlineDoc(
+ DocRHS->getInstallName(), getSingleIF(DocRHS.get(), rhs))));
+ }
+ if (!Docs.Values.empty())
+ Output.push_back(std::move(Docs));
+ }
+ return Output;
+}
+
+template <typename T>
+void printSingleVal(std::string Indent, const DiffOutput &Attr,
+ raw_ostream &OS) {
+ if (Attr.Values.empty())
+ return;
+ OS << Indent << Attr.Name << "\n";
+ for (auto &RawItem : Attr.Values)
+ if (T *Item = dyn_cast<T>(RawItem.get()))
+ Item->print(OS, Indent);
+}
+
+template <typename T>
+T *castValues(const std::unique_ptr<AttributeDiff> &RawAttr) {
+ T *CastAttr = cast<T>(RawAttr.get());
+ return CastAttr;
+}
+
+template <typename T> void sortTargetValues(std::vector<T> &TargValues) {
+ llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) {
+ return ValA.getOrder() < ValB.getOrder();
+ });
+ llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) {
+ return ValA.getOrder() == ValB.getOrder() && ValA.getVal() < ValB.getVal();
+ });
+}
+
+template <typename T>
+void printVecVal(std::string Indent, const DiffOutput &Attr, raw_ostream &OS) {
+ if (Attr.Values.empty())
+ return;
+
+ OS << Indent << Attr.Name << "\n";
+
+ std::vector<T *> SortedAttrs;
+
+ llvm::transform(Attr.Values, std::back_inserter(SortedAttrs), castValues<T>);
+
+ llvm::sort(SortedAttrs, [&](const auto &ValA, const auto &ValB) {
+ return ValA->Targ < ValB->Targ;
+ });
+
+ for (auto *Vec : SortedAttrs) {
+ sortTargetValues<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+ Vec->TargValues);
+ OS << Indent << "\t" << getTargetTripleName(Vec->Targ) << "\n";
+ for (auto &Item : Vec->TargValues)
+ Item.print(OS, Indent);
+ }
+}
+
+template <>
+void printVecVal<DiffSymVec>(std::string Indent, const DiffOutput &Attr,
+ raw_ostream &OS) {
+ if (Attr.Values.empty())
+ return;
+
+ OS << Indent << Attr.Name << "\n";
+
+ std::vector<DiffSymVec *> SortedAttrs;
+
+ llvm::transform(Attr.Values, std::back_inserter(SortedAttrs),
+ castValues<DiffSymVec>);
+
+ llvm::sort(SortedAttrs, [&](const auto &ValA, const auto &ValB) {
+ return ValA->Targ < ValB->Targ;
+ });
+ for (auto *SymVec : SortedAttrs) {
+ sortTargetValues<SymScalar>(SymVec->TargValues);
+ OS << Indent << "\t" << getTargetTripleName(SymVec->Targ) << "\n";
+ for (auto &Item : SymVec->TargValues)
+ Item.print(OS, Indent, SymVec->Targ);
+ }
+}
+
+void DiffEngine::printDifferences(raw_ostream &OS,
+ const std::vector<DiffOutput> &Diffs,
+ int IndentCounter) {
+ std::string Indent = std::string(IndentCounter, '\t');
+ for (auto &Attr : Diffs) {
+ switch (Attr.Kind) {
+ case AD_Diff_Scalar_Str:
+ if (IndentCounter == 0)
+ printSingleVal<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(Indent,
+ Attr, OS);
+ break;
+ case AD_Diff_Scalar_PackedVersion:
+ printSingleVal<
+ DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>>(Indent,
+ Attr, OS);
+ break;
+ case AD_Diff_Scalar_Unsigned:
+ printSingleVal<DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>>(Indent,
+ Attr, OS);
+ break;
+ case AD_Diff_Scalar_Bool:
+ printSingleVal<DiffScalarVal<bool, AD_Diff_Scalar_Bool>>(Indent, Attr,
+ OS);
+ break;
+ case AD_Str_Vec:
+ printVecVal<DiffStrVec>(Indent, Attr, OS);
+ break;
+ case AD_Sym_Vec:
+ printVecVal<DiffSymVec>(Indent, Attr, OS);
+ break;
+ case AD_Inline_Doc:
+ if (!Attr.Values.empty()) {
+ OS << Indent << Attr.Name << "\n";
+ for (auto &Item : Attr.Values)
+ if (InlineDoc *Doc = dyn_cast<InlineDoc>(Item.get()))
+ if (!Doc->DocValues.empty()) {
+ OS << Indent << "\t" << Doc->InstallName << "\n";
+ printDifferences(OS, std::move(Doc->DocValues), 2);
+ }
+ }
+ break;
+ }
+ }
+}
+
+bool DiffEngine::compareFiles(raw_ostream &OS) {
+ const auto *IFLHS = &(FileLHS->getInterfaceFile());
+ const auto *IFRHS = &(FileRHS->getInterfaceFile());
+ if (*IFLHS == *IFRHS)
+ return false;
+ OS << "< " << std::string(IFLHS->getPath().data()) << "\n> "
+ << std::string(IFRHS->getPath().data()) << "\n\n";
+ std::vector<DiffOutput> Diffs = findDifferences(IFLHS, IFRHS);
+ printDifferences(OS, Diffs, 0);
+ return true;
+}
diff --git a/llvm/tools/llvm-tapi-
diff /DiffEngine.h b/llvm/tools/llvm-tapi-
diff /DiffEngine.h
new file mode 100644
index 0000000000000..eea6c70885ab0
--- /dev/null
+++ b/llvm/tools/llvm-tapi-
diff /DiffEngine.h
@@ -0,0 +1,169 @@
+//===-- DiffEngine.h - File comparator --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the interface to the llvm-tapi
diff erence engine,
+// which structurally compares two tbd files.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
+#define LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Object/TapiUniversal.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TextAPI/Symbol.h"
+#include "llvm/TextAPI/Target.h"
+
+namespace llvm {
+
+/// InterfaceInputOrder determines from which file the
diff attribute belongs
+/// to.
+enum InterfaceInputOrder { lhs, rhs };
+
+/// DiffAttrKind is the enum that holds the concrete bases for RTTI.
+enum DiffAttrKind {
+ AD_Diff_Scalar_PackedVersion,
+ AD_Diff_Scalar_Unsigned,
+ AD_Diff_Scalar_Bool,
+ AD_Diff_Scalar_Str,
+ AD_Str_Vec,
+ AD_Sym_Vec,
+ AD_Inline_Doc,
+};
+
+/// AttributeDiff is the abstract class for RTTI.
+class AttributeDiff {
+public:
+ AttributeDiff(DiffAttrKind Kind) : Kind(Kind){};
+ virtual ~AttributeDiff(){};
+ DiffAttrKind getKind() const { return Kind; }
+
+private:
+ DiffAttrKind Kind;
+};
+
+/// DiffOutput is the representation of a
diff for a single attribute.
+struct DiffOutput {
+ /// The name of the attribute.
+ std::string Name;
+ /// The kind for RTTI
+ DiffAttrKind Kind;
+ /// Different values for the attribute
+ /// from each file where a
diff is present.
+ std::vector<std::unique_ptr<AttributeDiff>> Values;
+ DiffOutput(std::string Name) : Name(Name){};
+};
+
+/// DiffScalarVal is a template class for the
diff erent types of scalar values.
+template <class T, DiffAttrKind U> class DiffScalarVal : public AttributeDiff {
+public:
+ DiffScalarVal(InterfaceInputOrder Order, T Val)
+ : AttributeDiff(U), Order(Order), Val(Val){};
+
+ static bool classof(const AttributeDiff *A) { return A->getKind() == U; }
+
+ void print(raw_ostream &, std::string);
+
+ T getVal() const { return Val; }
+ InterfaceInputOrder getOrder() const { return Order; }
+
+private:
+ /// The order is the file from which the
diff is found.
+ InterfaceInputOrder Order;
+ T Val;
+};
+
+/// SymScalar is the
diff symbol and the order.
+class SymScalar {
+public:
+ SymScalar(InterfaceInputOrder Order, const MachO::Symbol *Sym)
+ : Order(Order), Val(Sym){};
+
+ std::string getFlagString(MachO::SymbolFlags Flags) {
+ return Flags != MachO::SymbolFlags::None
+ ? " - " + stringifySymbolFlag(Flags)
+ : stringifySymbolFlag(Flags);
+ }
+
+ void print(raw_ostream &OS, std::string Indent, MachO::Target Targ);
+
+ const MachO::Symbol *getVal() const { return Val; }
+ InterfaceInputOrder getOrder() const { return Order; }
+
+private:
+ /// The order is the file from which the
diff is found.
+ InterfaceInputOrder Order;
+ const MachO::Symbol *Val;
+ std::string stringifySymbolKind(MachO::SymbolKind Kind);
+ std::string stringifySymbolFlag(MachO::SymbolFlags Flag);
+};
+
+class DiffStrVec : public AttributeDiff {
+public:
+ MachO::Target Targ;
+ /// Values is a vector of StringRef values associated with the target.
+ std::vector<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>> TargValues;
+ DiffStrVec(MachO::Target Targ) : AttributeDiff(AD_Str_Vec), Targ(Targ){};
+
+ static bool classof(const AttributeDiff *A) {
+ return A->getKind() == AD_Str_Vec;
+ }
+};
+
+class DiffSymVec : public AttributeDiff {
+public:
+ MachO::Target Targ;
+ /// Values is a vector of symbol values associated with the target.
+ std::vector<SymScalar> TargValues;
+ DiffSymVec(MachO::Target Targ) : AttributeDiff(AD_Sym_Vec), Targ(Targ){};
+
+ static bool classof(const AttributeDiff *A) {
+ return A->getKind() == AD_Sym_Vec;
+ }
+};
+
+/// InlineDoc represents an inlined framework/library in a TBD File.
+class InlineDoc : public AttributeDiff {
+public:
+ /// Install name of the framework/library.
+ std::string InstallName;
+ /// Differences found from each file.
+ std::vector<DiffOutput> DocValues;
+ InlineDoc(StringRef InstName, std::vector<DiffOutput> Diff)
+ : AttributeDiff(AD_Inline_Doc), InstallName(InstName),
+ DocValues(std::move(Diff)){};
+
+ static bool classof(const AttributeDiff *A) {
+ return A->getKind() == AD_Inline_Doc;
+ }
+};
+
+/// DiffEngine contains the methods to compare the input files and print the
+/// output of the
diff erences found in the files.
+class DiffEngine {
+public:
+ DiffEngine(object::TapiUniversal *InputFileNameLHS,
+ object::TapiUniversal *InputFileNameRHS)
+ : FileLHS(InputFileNameLHS), FileRHS(InputFileNameRHS){};
+ bool compareFiles(raw_ostream &);
+
+private:
+ object::TapiUniversal *FileLHS;
+ object::TapiUniversal *FileRHS;
+
+ /// Function that prints the
diff erences found in the files.
+ void printDifferences(raw_ostream &, const std::vector<DiffOutput> &, int);
+ /// Function that does the comparison of the TBD files and returns the
+ ///
diff erences.
+ std::vector<DiffOutput> findDifferences(const MachO::InterfaceFile *,
+ const MachO::InterfaceFile *);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/tools/llvm-tapi-
diff /llvm-tapi-
diff .cpp b/llvm/tools/llvm-tapi-
diff /llvm-tapi-
diff .cpp
new file mode 100644
index 0000000000000..40f1eec162be5
--- /dev/null
+++ b/llvm/tools/llvm-tapi-
diff /llvm-tapi-
diff .cpp
@@ -0,0 +1,89 @@
+//===-- llvm-tapi-
diff .cpp - tbd comparator command-line driver ---*-
+// C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the command-line driver for the llvm-tapi
diff erence
+// engine.
+//
+//===----------------------------------------------------------------------===//
+#include "DiffEngine.h"
+#include "llvm/Object/TapiUniversal.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
+
+using namespace llvm;
+using namespace MachO;
+using namespace object;
+
+namespace {
+cl::OptionCategory NMCat("llvm-tapi-
diff Options");
+cl::opt<std::string> InputFileNameLHS(cl::Positional, cl::desc("<first file>"),
+ cl::cat(NMCat));
+cl::opt<std::string> InputFileNameRHS(cl::Positional, cl::desc("<second file>"),
+ cl::cat(NMCat));
+
+std::string ToolName;
+} // anonymous namespace
+
+ExitOnError ExitOnErr;
+
+void setErrorBanner(ExitOnError &ExitOnErr, std::string InputFile) {
+ ExitOnErr.setBanner(ToolName + ": error: " + InputFile + ": ");
+}
+
+Expected<std::unique_ptr<Binary>> convertFileToBinary(std::string &Filename) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+ MemoryBuffer::getFileOrSTDIN(Filename);
+ if (BufferOrErr.getError())
+ return errorCodeToError(BufferOrErr.getError());
+ return createBinary(BufferOrErr.get()->getMemBufferRef());
+}
+
+int main(int Argc, char **Argv) {
+ InitLLVM X(Argc, Argv);
+ cl::HideUnrelatedOptions(NMCat);
+ cl::ParseCommandLineOptions(
+ Argc, Argv,
+ "This tool will compare two tbd files and return the "
+ "
diff erences in those files.");
+ if (InputFileNameLHS.empty() || InputFileNameRHS.empty()) {
+ cl::PrintHelpMessage();
+ return EXIT_FAILURE;
+ }
+
+ ToolName = Argv[0];
+
+ setErrorBanner(ExitOnErr, InputFileNameLHS);
+ auto BinLHS = ExitOnErr(convertFileToBinary(InputFileNameLHS));
+
+ TapiUniversal *FileLHS = dyn_cast<TapiUniversal>(BinLHS.get());
+ if (!FileLHS) {
+ ExitOnErr(
+ createStringError(std::errc::executable_format_error,
+ "Error when parsing file, unsupported file format"));
+ }
+
+ setErrorBanner(ExitOnErr, InputFileNameRHS);
+ auto BinRHS = ExitOnErr(convertFileToBinary(InputFileNameRHS));
+
+ TapiUniversal *FileRHS = dyn_cast<TapiUniversal>(BinRHS.get());
+ if (!FileRHS) {
+ ExitOnErr(
+ createStringError(std::errc::executable_format_error,
+ "Error when parsing file, unsupported file format"));
+ }
+
+ raw_ostream &OS = outs();
+
+ return DiffEngine(FileLHS, FileRHS).compareFiles(OS);
+}
More information about the llvm-commits
mailing list