]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-cxxmap / llvm-cxxmap.cpp
1 //===- llvm-cxxmap.cpp ----------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // llvm-cxxmap computes a correspondence between old symbol names and new
11 // symbol names based on a symbol equivalence file.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ADT/DenseSet.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Support/InitLLVM.h"
20 #include "llvm/Support/LineIterator.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/SymbolRemappingReader.h"
23 #include "llvm/Support/WithColor.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 using namespace llvm;
27
28 cl::opt<std::string> OldSymbolFile(cl::Positional, cl::Required,
29                                    cl::desc("<symbol-file>"));
30 cl::opt<std::string> NewSymbolFile(cl::Positional, cl::Required,
31                                    cl::desc("<symbol-file>"));
32 cl::opt<std::string> RemappingFile("remapping-file", cl::Required,
33                                    cl::desc("Remapping file"));
34 cl::alias RemappingFileA("r", cl::aliasopt(RemappingFile));
35 cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
36                                     cl::init("-"), cl::desc("Output file"));
37 cl::alias OutputFilenameA("o", cl::aliasopt(OutputFilename));
38
39 cl::opt<bool> WarnAmbiguous(
40     "Wambiguous",
41     cl::desc("Warn on equivalent symbols in the output symbol list"));
42 cl::opt<bool> WarnIncomplete(
43     "Wincomplete",
44     cl::desc("Warn on input symbols missing from output symbol list"));
45
46 static void warn(Twine Message, Twine Whence = "",
47                  std::string Hint = "") {
48   WithColor::warning();
49   std::string WhenceStr = Whence.str();
50   if (!WhenceStr.empty())
51     errs() << WhenceStr << ": ";
52   errs() << Message << "\n";
53   if (!Hint.empty())
54     WithColor::note() << Hint << "\n";
55 }
56
57 static void exitWithError(Twine Message, Twine Whence = "",
58                           std::string Hint = "") {
59   WithColor::error();
60   std::string WhenceStr = Whence.str();
61   if (!WhenceStr.empty())
62     errs() << WhenceStr << ": ";
63   errs() << Message << "\n";
64   if (!Hint.empty())
65     WithColor::note() << Hint << "\n";
66   ::exit(1);
67 }
68
69 static void exitWithError(Error E, StringRef Whence = "") {
70   exitWithError(toString(std::move(E)), Whence);
71 }
72
73 static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") {
74   exitWithError(EC.message(), Whence);
75 }
76
77 static void remapSymbols(MemoryBuffer &OldSymbolFile,
78                          MemoryBuffer &NewSymbolFile,
79                          MemoryBuffer &RemappingFile,
80                          raw_ostream &Out) {
81   // Load the remapping file and prepare to canonicalize symbols.
82   SymbolRemappingReader Reader;
83   if (Error E = Reader.read(RemappingFile))
84     exitWithError(std::move(E));
85
86   // Canonicalize the new symbols.
87   DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
88   DenseSet<StringRef> UnparseableSymbols;
89   for (line_iterator LineIt(NewSymbolFile, /*SkipBlanks=*/true, '#');
90        !LineIt.is_at_eof(); ++LineIt) {
91     StringRef Symbol = *LineIt;
92
93     auto K = Reader.insert(Symbol);
94     if (!K) {
95       UnparseableSymbols.insert(Symbol);
96       continue;
97     }
98
99     auto ItAndIsNew = MappedNames.insert({K, Symbol});
100     if (WarnAmbiguous && !ItAndIsNew.second &&
101         ItAndIsNew.first->second != Symbol) {
102       warn("symbol " + Symbol + " is equivalent to earlier symbol " +
103                ItAndIsNew.first->second,
104            NewSymbolFile.getBufferIdentifier() + ":" +
105                Twine(LineIt.line_number()),
106            "later symbol will not be the target of any remappings");
107     }
108   }
109
110   // Figure out which new symbol each old symbol is equivalent to.
111   for (line_iterator LineIt(OldSymbolFile, /*SkipBlanks=*/true, '#');
112        !LineIt.is_at_eof(); ++LineIt) {
113     StringRef Symbol = *LineIt;
114
115     auto K = Reader.lookup(Symbol);
116     StringRef NewSymbol = MappedNames.lookup(K);
117
118     if (NewSymbol.empty()) {
119       if (WarnIncomplete && !UnparseableSymbols.count(Symbol)) {
120         warn("no new symbol matches old symbol " + Symbol,
121              OldSymbolFile.getBufferIdentifier() + ":" +
122                  Twine(LineIt.line_number()));
123       }
124       continue;
125     }
126
127     Out << Symbol << " " << NewSymbol << "\n";
128   }
129 }
130
131 int main(int argc, const char *argv[]) {
132   InitLLVM X(argc, argv);
133
134   cl::ParseCommandLineOptions(argc, argv, "LLVM C++ mangled name remapper\n");
135
136   auto OldSymbolBufOrError = MemoryBuffer::getFileOrSTDIN(OldSymbolFile);
137   if (!OldSymbolBufOrError)
138     exitWithErrorCode(OldSymbolBufOrError.getError(), OldSymbolFile);
139
140   auto NewSymbolBufOrError = MemoryBuffer::getFileOrSTDIN(NewSymbolFile);
141   if (!NewSymbolBufOrError)
142     exitWithErrorCode(NewSymbolBufOrError.getError(), NewSymbolFile);
143
144   auto RemappingBufOrError = MemoryBuffer::getFileOrSTDIN(RemappingFile);
145   if (!RemappingBufOrError)
146     exitWithErrorCode(RemappingBufOrError.getError(), RemappingFile);
147
148   std::error_code EC;
149   raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::F_Text);
150   if (EC)
151     exitWithErrorCode(EC, OutputFilename);
152
153   remapSymbols(*OldSymbolBufOrError.get(), *NewSymbolBufOrError.get(),
154                *RemappingBufOrError.get(), OS);
155 }