blob: 626903bce76990e499323c4e91e59c1be4f5974e [file] [log] [blame]
Teresa Johnson9ba95f92016-08-11 14:58:12 +00001//===-- llvm-lto2: test harness for the resolution-based LTO interface ----===//
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// This program takes in a list of bitcode files, links them and performs
11// link-time optimization according to the provided symbol resolutions using the
12// resolution-based LTO interface, and outputs one or more object files.
13//
14// This program is intended to eventually replace llvm-lto which uses the legacy
15// LTO interface.
16//
17//===----------------------------------------------------------------------===//
18
19#include "llvm/LTO/LTO.h"
20#include "llvm/Support/CommandLine.h"
21#include "llvm/Support/TargetSelect.h"
22
23using namespace llvm;
24using namespace lto;
25using namespace object;
26
27static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
28 cl::desc("<input bitcode files>"));
29
30static cl::opt<std::string> OutputFilename("o", cl::Required,
31 cl::desc("Output filename"),
32 cl::value_desc("filename"));
33
34static cl::opt<bool> SaveTemps("save-temps", cl::desc("Save temporary files"));
35
36static cl::list<std::string> SymbolResolutions(
37 "r",
38 cl::desc("Specify a symbol resolution: filename,symbolname,resolution\n"
39 "where \"resolution\" is a sequence (which may be empty) of the\n"
40 "following characters:\n"
41 " p - prevailing: the linker has chosen this definition of the\n"
42 " symbol\n"
43 " l - local: the definition of this symbol is unpreemptable at\n"
44 " runtime and is known to be in this linkage unit\n"
45 " x - externally visible: the definition of this symbol is\n"
46 " visible outside of the LTO unit\n"
47 "A resolution for each symbol must be specified."),
48 cl::ZeroOrMore);
49
50static void check(Error E, std::string Msg) {
51 if (!E)
52 return;
53 handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
54 errs() << "llvm-lto: " << Msg << ": " << EIB.message().c_str() << '\n';
55 });
56 exit(1);
57}
58
59template <typename T> static T check(Expected<T> E, std::string Msg) {
60 if (E)
61 return std::move(*E);
62 check(E.takeError(), Msg);
63 return T();
64}
65
66static void check(std::error_code EC, std::string Msg) {
67 check(errorCodeToError(EC), Msg);
68}
69
70template <typename T> static T check(ErrorOr<T> E, std::string Msg) {
71 if (E)
72 return std::move(*E);
73 check(E.getError(), Msg);
74 return T();
75}
76
Mehdi Amini970800e2016-08-17 06:23:09 +000077namespace {
78// Define the LTOOutput handling
79class LTOOutput : public lto::NativeObjectOutput {
Chandler Carruth5f6d73b2016-08-17 07:48:34 +000080 std::string Path;
Mehdi Amini970800e2016-08-17 06:23:09 +000081
82public:
Chandler Carruth5f6d73b2016-08-17 07:48:34 +000083 LTOOutput(std::string Path) : Path(std::move(Path)) {}
Mehdi Amini970800e2016-08-17 06:23:09 +000084 std::unique_ptr<raw_pwrite_stream> getStream() override {
85 std::error_code EC;
86 auto S = llvm::make_unique<raw_fd_ostream>(Path, EC, sys::fs::F_None);
87 check(EC, Path);
88 return std::move(S);
89 }
90};
91}
92
Teresa Johnson9ba95f92016-08-11 14:58:12 +000093int main(int argc, char **argv) {
94 InitializeAllTargets();
95 InitializeAllTargetMCs();
96 InitializeAllAsmPrinters();
97 InitializeAllAsmParsers();
98
99 cl::ParseCommandLineOptions(argc, argv, "Resolution-based LTO test harness");
100
101 std::map<std::pair<std::string, std::string>, SymbolResolution>
102 CommandLineResolutions;
103 for (std::string R : SymbolResolutions) {
104 StringRef Rest = R;
105 StringRef FileName, SymbolName;
106 std::tie(FileName, Rest) = Rest.split(',');
107 if (Rest.empty()) {
108 llvm::errs() << "invalid resolution: " << R << '\n';
109 return 1;
110 }
111 std::tie(SymbolName, Rest) = Rest.split(',');
112 SymbolResolution Res;
113 for (char C : Rest) {
114 if (C == 'p')
115 Res.Prevailing = true;
116 else if (C == 'l')
117 Res.FinalDefinitionInLinkageUnit = true;
118 else if (C == 'x')
119 Res.VisibleToRegularObj = true;
120 else
121 llvm::errs() << "invalid character " << C << " in resolution: " << R
122 << '\n';
123 }
124 CommandLineResolutions[{FileName, SymbolName}] = Res;
125 }
126
127 std::vector<std::unique_ptr<MemoryBuffer>> MBs;
128
129 Config Conf;
130 Conf.DiagHandler = [](const DiagnosticInfo &) {
131 exit(1);
132 };
133
134 if (SaveTemps)
135 check(Conf.addSaveTemps(OutputFilename), "Config::addSaveTemps failed");
136
137 LTO Lto(std::move(Conf));
138
139 bool HasErrors = false;
140 for (std::string F : InputFilenames) {
141 std::unique_ptr<MemoryBuffer> MB = check(MemoryBuffer::getFile(F), F);
142 std::unique_ptr<InputFile> Input =
143 check(InputFile::create(MB->getMemBufferRef()), F);
144
145 std::vector<SymbolResolution> Res;
146 for (const InputFile::Symbol &Sym : Input->symbols()) {
147 auto I = CommandLineResolutions.find({F, Sym.getName()});
148 if (I == CommandLineResolutions.end()) {
149 llvm::errs() << argv[0] << ": missing symbol resolution for " << F
150 << ',' << Sym.getName() << '\n';
151 HasErrors = true;
152 } else {
153 Res.push_back(I->second);
154 CommandLineResolutions.erase(I);
155 }
156 }
157
158 if (HasErrors)
159 continue;
160
161 MBs.push_back(std::move(MB));
162 check(Lto.add(std::move(Input), Res), F);
163 }
164
165 if (!CommandLineResolutions.empty()) {
166 HasErrors = true;
167 for (auto UnusedRes : CommandLineResolutions)
168 llvm::errs() << argv[0] << ": unused symbol resolution for "
169 << UnusedRes.first.first << ',' << UnusedRes.first.second
170 << '\n';
171 }
172 if (HasErrors)
173 return 1;
174
Mehdi Amini970800e2016-08-17 06:23:09 +0000175 auto AddOutput = [&](size_t Task) {
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000176 std::string Path = OutputFilename + "." + utostr(Task);
Chandler Carruth5f6d73b2016-08-17 07:48:34 +0000177 return llvm::make_unique<LTOOutput>(std::move(Path));
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000178 };
179
Mehdi Amini970800e2016-08-17 06:23:09 +0000180 check(Lto.run(AddOutput), "LTO::run failed");
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000181}