llvm.org GIT mirror llvm / 608d7b4
Modernize the C++ APIs for creating LTO modules. This is a continuation of r253367. These functions return is owned by the caller, so they return std::unique_ptr now. The call can fail, so the return is wrapped in ErrorOr. They have a context where to report diagnostics, so they don't need to take a string out parameter. With this there are no call to getGlobalContext in lib/LTO. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254721 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 3 years ago
4 changed file(s) with 179 addition(s) and 141 deletion(s). Raw diff Collapse all Expand all
9090 /// InitializeAllTargetMCs();
9191 /// InitializeAllAsmPrinters();
9292 /// InitializeAllAsmParsers();
93 static LTOModule *createFromFile(const char *path, TargetOptions options,
94 std::string &errMsg);
95 static LTOModule *createFromOpenFile(int fd, const char *path, size_t size,
96 TargetOptions options,
97 std::string &errMsg);
98 static LTOModule *createFromOpenFileSlice(int fd, const char *path,
99 size_t map_size, off_t offset,
100 TargetOptions options,
101 std::string &errMsg);
102 static LTOModule *createFromBuffer(const void *mem, size_t length,
103 TargetOptions options, std::string &errMsg,
104 StringRef path = "");
105
106 static LTOModule *createInLocalContext(const void *mem, size_t length,
107 TargetOptions options,
108 std::string &errMsg, StringRef path);
109 static LTOModule *createInContext(const void *mem, size_t length,
110 TargetOptions options, std::string &errMsg,
111 StringRef path, LLVMContext *Context);
93 static ErrorOr>
94 createFromFile(LLVMContext &Context, const char *path, TargetOptions options);
95 static ErrorOr>
96 createFromOpenFile(LLVMContext &Context, int fd, const char *path,
97 size_t size, TargetOptions options);
98 static ErrorOr>
99 createFromOpenFileSlice(LLVMContext &Context, int fd, const char *path,
100 size_t map_size, off_t offset, TargetOptions options);
101 static ErrorOr>
102 createFromBuffer(LLVMContext &Context, const void *mem, size_t length,
103 TargetOptions options, StringRef path = "");
104
105 static ErrorOr>
106 createInLocalContext(const void *mem, size_t length, TargetOptions options,
107 StringRef path);
108 static ErrorOr>
109 createInContext(const void *mem, size_t length, TargetOptions options,
110 StringRef path, LLVMContext *Context);
112111
113112 const Module &getModule() const {
114113 return const_cast(this)->getModule();
206205 bool objcClassNameFromExpression(const Constant *c, std::string &name);
207206
208207 /// Create an LTOModule (private version).
209 static LTOModule *makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
210 std::string &errMsg, LLVMContext *Context);
208 static ErrorOr>
209 makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
210 LLVMContext *Context);
211211 };
212212 }
213213 #endif
9999 return getBitcodeProducerString(*BCOrErr, Context);
100100 }
101101
102 LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options,
103 std::string &errMsg) {
102 ErrorOr>
103 LTOModule::createFromFile(LLVMContext &Context, const char *path,
104 TargetOptions options) {
104105 ErrorOr> BufferOrErr =
105106 MemoryBuffer::getFile(path);
106 if (std::error_code EC = BufferOrErr.getError()) {
107 errMsg = EC.message();
108 return nullptr;
109 }
107 if (std::error_code EC = BufferOrErr.getError())
108 return EC;
110109 std::unique_ptr Buffer = std::move(BufferOrErr.get());
111 return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg,
112 &getGlobalContext());
113 }
114
115 LTOModule *LTOModule::createFromOpenFile(int fd, const char *path, size_t size,
116 TargetOptions options,
117 std::string &errMsg) {
118 return createFromOpenFileSlice(fd, path, size, 0, options, errMsg);
119 }
120
121 LTOModule *LTOModule::createFromOpenFileSlice(int fd, const char *path,
122 size_t map_size, off_t offset,
123 TargetOptions options,
124 std::string &errMsg) {
110 return makeLTOModule(Buffer->getMemBufferRef(), options, &Context);
111 }
112
113 ErrorOr>
114 LTOModule::createFromOpenFile(LLVMContext &Context, int fd, const char *path,
115 size_t size, TargetOptions options) {
116 return createFromOpenFileSlice(Context, fd, path, size, 0, options);
117 }
118
119 ErrorOr>
120 LTOModule::createFromOpenFileSlice(LLVMContext &Context, int fd,
121 const char *path, size_t map_size,
122 off_t offset, TargetOptions options) {
125123 ErrorOr> BufferOrErr =
126124 MemoryBuffer::getOpenFileSlice(fd, path, map_size, offset);
127 if (std::error_code EC = BufferOrErr.getError()) {
128 errMsg = EC.message();
129 return nullptr;
130 }
125 if (std::error_code EC = BufferOrErr.getError())
126 return EC;
131127 std::unique_ptr Buffer = std::move(BufferOrErr.get());
132 return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg,
133 &getGlobalContext());
134 }
135
136 LTOModule *LTOModule::createFromBuffer(const void *mem, size_t length,
137 TargetOptions options,
138 std::string &errMsg, StringRef path) {
139 return createInContext(mem, length, options, errMsg, path,
140 &getGlobalContext());
141 }
142
143 LTOModule *LTOModule::createInLocalContext(const void *mem, size_t length,
144 TargetOptions options,
145 std::string &errMsg,
146 StringRef path) {
147 return createInContext(mem, length, options, errMsg, path, nullptr);
148 }
149
150 LTOModule *LTOModule::createInContext(const void *mem, size_t length,
151 TargetOptions options,
152 std::string &errMsg, StringRef path,
153 LLVMContext *Context) {
128 return makeLTOModule(Buffer->getMemBufferRef(), options, &Context);
129 }
130
131 ErrorOr>
132 LTOModule::createFromBuffer(LLVMContext &Context, const void *mem,
133 size_t length, TargetOptions options,
134 StringRef path) {
135 return createInContext(mem, length, options, path, &Context);
136 }
137
138 ErrorOr>
139 LTOModule::createInLocalContext(const void *mem, size_t length,
140 TargetOptions options, StringRef path) {
141 return createInContext(mem, length, options, path, nullptr);
142 }
143
144 ErrorOr>
145 LTOModule::createInContext(const void *mem, size_t length,
146 TargetOptions options, StringRef path,
147 LLVMContext *Context) {
154148 StringRef Data((const char *)mem, length);
155149 MemoryBufferRef Buffer(Data, path);
156 return makeLTOModule(Buffer, options, errMsg, Context);
157 }
158
159 static std::unique_ptr parseBitcodeFileImpl(MemoryBufferRef Buffer,
160 LLVMContext &Context,
161 bool ShouldBeLazy,
162 std::string &ErrMsg) {
150 return makeLTOModule(Buffer, options, Context);
151 }
152
153 static ErrorOr>
154 parseBitcodeFileImpl(MemoryBufferRef Buffer, LLVMContext &Context,
155 bool ShouldBeLazy) {
163156
164157 // Find the buffer.
165158 ErrorOr MBOrErr =
166159 IRObjectFile::findBitcodeInMemBuffer(Buffer);
167 if (std::error_code EC = MBOrErr.getError()) {
168 ErrMsg = EC.message();
169 return nullptr;
170 }
171
172 std::function DiagnosticHandler =
173 [&ErrMsg](const DiagnosticInfo &DI) {
174 raw_string_ostream Stream(ErrMsg);
175 DiagnosticPrinterRawOStream DP(Stream);
176 DI.print(DP);
177 };
160 if (std::error_code EC = MBOrErr.getError())
161 return EC;
178162
179163 if (!ShouldBeLazy) {
180164 // Parse the full file.
181 ErrorOr> M =
182 parseBitcodeFile(*MBOrErr, Context, DiagnosticHandler);
183 if (!M)
184 return nullptr;
165 ErrorOr> M = parseBitcodeFile(*MBOrErr, Context);
166 if (std::error_code EC = M.getError())
167 return EC;
185168 return std::move(*M);
186169 }
187170
189172 std::unique_ptr LightweightBuf =
190173 MemoryBuffer::getMemBuffer(*MBOrErr, false);
191174 ErrorOr> M =
192 getLazyBitcodeModule(std::move(LightweightBuf), Context,
193 DiagnosticHandler, true /*ShouldLazyLoadMetadata*/);
194 if (!M)
195 return nullptr;
175 getLazyBitcodeModule(std::move(LightweightBuf), Context, nullptr,
176 true /*ShouldLazyLoadMetadata*/);
177 if (std::error_code EC = M.getError())
178 return EC;
196179 return std::move(*M);
197180 }
198181
199 LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer,
200 TargetOptions options, std::string &errMsg,
201 LLVMContext *Context) {
182 ErrorOr>
183 LTOModule::makeLTOModule(MemoryBufferRef Buffer, TargetOptions options,
184 LLVMContext *Context) {
202185 std::unique_ptr OwnedContext;
203186 if (!Context) {
204187 OwnedContext = llvm::make_unique();
207190
208191 // If we own a context, we know this is being used only for symbol
209192 // extraction, not linking. Be lazy in that case.
210 std::unique_ptr M = parseBitcodeFileImpl(
211 Buffer, *Context,
212 /* ShouldBeLazy */ static_cast(OwnedContext), errMsg);
213 if (!M)
214 return nullptr;
193 ErrorOr> MOrErr =
194 parseBitcodeFileImpl(Buffer, *Context,
195 /* ShouldBeLazy */ static_cast(OwnedContext));
196 if (std::error_code EC = MOrErr.getError())
197 return EC;
198 std::unique_ptr &M = *MOrErr;
215199
216200 std::string TripleStr = M->getTargetTriple();
217201 if (TripleStr.empty())
219203 llvm::Triple Triple(TripleStr);
220204
221205 // find machine architecture for this module
206 std::string errMsg;
222207 const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
223208 if (!march)
224 return nullptr;
209 return std::unique_ptr(nullptr);
225210
226211 // construct LTOModule, hand over ownership of module and target
227212 SubtargetFeatures Features;
245230 std::unique_ptr IRObj(
246231 new object::IRObjectFile(Buffer, std::move(M)));
247232
248 LTOModule *Ret;
233 std::unique_ptr Ret;
249234 if (OwnedContext)
250 Ret = new LTOModule(std::move(IRObj), target, std::move(OwnedContext));
235 Ret.reset(new LTOModule(std::move(IRObj), target, std::move(OwnedContext)));
251236 else
252 Ret = new LTOModule(std::move(IRObj), target);
237 Ret.reset(new LTOModule(std::move(IRObj), target));
253238
254239 Ret->parseSymbols();
255240 Ret->parseMetadata();
256241
257 return Ret;
242 return std::move(Ret);
258243 }
259244
260245 /// Create a MemoryBuffer from a memory range with an optional name.
123123 errs() << Msg << "\n";
124124 }
125125
126 static std::string CurrentActivity;
126127 static void diagnosticHandler(const DiagnosticInfo &DI) {
127128 raw_ostream &OS = errs();
128129 OS << "llvm-lto: ";
129130 switch (DI.getSeverity()) {
130131 case DS_Error:
131 OS << "error: ";
132 OS << "error";
132133 break;
133134 case DS_Warning:
134 OS << "warning: ";
135 OS << "warning";
135136 break;
136137 case DS_Remark:
137 OS << "remark: ";
138 OS << "remark";
138139 break;
139140 case DS_Note:
140 OS << "note: ";
141 break;
142 }
141 OS << "note";
142 break;
143 }
144 if (!CurrentActivity.empty())
145 OS << ' ' << CurrentActivity;
146 OS << ": ";
143147
144148 DiagnosticPrinterRawOStream DP(OS);
145149 DI.print(DP);
147151
148152 if (DI.getSeverity() == DS_Error)
149153 exit(1);
154 }
155
156 static void diagnosticHandlerWithContenxt(const DiagnosticInfo &DI,
157 void *Context) {
158 diagnosticHandler(DI);
150159 }
151160
152161 static void error(const Twine &Msg) {
171180 MemoryBuffer::getFile(Path);
172181 error(BufferOrErr, "error loading file '" + Path + "'");
173182 Buffer = std::move(BufferOrErr.get());
174 std::string Error;
175 std::unique_ptr Ret(LTOModule::createInLocalContext(
176 Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Error, Path));
177 if (!Error.empty())
178 error("error loading file '" + Path + "' " + Error);
179 return Ret;
183 CurrentActivity = ("loading file '" + Path + "'").str();
184 ErrorOr> Ret = LTOModule::createInLocalContext(
185 Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Path);
186 CurrentActivity = "";
187 return std::move(*Ret);
180188 }
181189
182190 /// \brief List symbols in each IR file.
206214 FunctionInfoIndex CombinedIndex;
207215 uint64_t NextModuleId = 0;
208216 for (auto &Filename : InputFilenames) {
217 CurrentActivity = "loading file '" + Filename + "'";
209218 ErrorOr> IndexOrErr =
210219 llvm::getFunctionIndexForFile(Filename, diagnosticHandler);
211 error(IndexOrErr, "error loading file '" + Filename + "'");
212220 std::unique_ptr Index = std::move(IndexOrErr.get());
221 CurrentActivity = "";
213222 // Skip files without a function summary.
214223 if (!Index)
215224 continue;
256265
257266 unsigned BaseArg = 0;
258267
259 LTOCodeGenerator CodeGen(getGlobalContext());
268 LLVMContext Context;
269 Context.setDiagnosticHandler(diagnosticHandlerWithContenxt, nullptr, true);
270
271 LTOCodeGenerator CodeGen(Context);
260272
261273 if (UseDiagnosticHandler)
262274 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
273285 std::vector KeptDSOSyms;
274286
275287 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
276 std::string error;
277 std::unique_ptr Module(
278 LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error));
279 if (!error.empty()) {
280 errs() << argv[0] << ": error loading file '" << InputFilenames[i]
281 << "': " << error << "\n";
282 return 1;
283 }
288 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
289 ErrorOr> ModuleOrErr =
290 LTOModule::createFromFile(Context, InputFilenames[i].c_str(), Options);
291 std::unique_ptr &Module = *ModuleOrErr;
292 CurrentActivity = "";
284293
285294 unsigned NumSyms = Module->getSymbolCount();
286295 for (unsigned I = 0; I < NumSyms; ++I) {
1414 #include "llvm-c/lto.h"
1515 #include "llvm/ADT/STLExtras.h"
1616 #include "llvm/CodeGen/CommandFlags.h"
17 #include "llvm/IR/DiagnosticInfo.h"
18 #include "llvm/IR/DiagnosticPrinter.h"
1719 #include "llvm/IR/LLVMContext.h"
1820 #include "llvm/LTO/LTOCodeGenerator.h"
1921 #include "llvm/LTO/LTOModule.h"
6365 // Holds the command-line option parsing state of the LTO module.
6466 static bool parsedOptions = false;
6567
68 static LLVMContext *LTOContext = nullptr;
69
70 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
71 if (DI.getSeverity() != DS_Error) {
72 DiagnosticPrinterRawOStream DP(errs());
73 DI.print(DP);
74 errs() << '\n';
75 return;
76 }
77 sLastErrorString = "";
78 {
79 raw_string_ostream Stream(sLastErrorString);
80 DiagnosticPrinterRawOStream DP(Stream);
81 DI.print(DP);
82 }
83 sLastErrorString += '\n';
84 }
85
6686 // Initialize the configured targets if they have not been initialized.
6787 static void lto_initialize() {
6888 if (!initialized) {
7898 InitializeAllAsmParsers();
7999 InitializeAllAsmPrinters();
80100 InitializeAllDisassemblers();
101
102 LTOContext = &getGlobalContext();
103 LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true);
81104 initialized = true;
82105 }
83106 }
94117 // libLTO API semantics, which require that the code generator owns the object
95118 // file.
96119 struct LibLTOCodeGenerator : LTOCodeGenerator {
97 LibLTOCodeGenerator() : LTOCodeGenerator(getGlobalContext()) {
120 LibLTOCodeGenerator() : LTOCodeGenerator(*LTOContext) {
98121 setDiagnosticHandler(handleLibLTODiagnostic, nullptr); }
99122 LibLTOCodeGenerator(std::unique_ptr Context)
100123 : LTOCodeGenerator(*Context), OwnedContext(std::move(Context)) {
165188 lto_module_t lto_module_create(const char* path) {
166189 lto_initialize();
167190 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
168 return wrap(LTOModule::createFromFile(path, Options, sLastErrorString));
191 ErrorOr> M =
192 LTOModule::createFromFile(*LTOContext, path, Options);
193 if (!M)
194 return nullptr;
195 return wrap(M->release());
169196 }
170197
171198 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
172199 lto_initialize();
173200 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
174 return wrap(
175 LTOModule::createFromOpenFile(fd, path, size, Options, sLastErrorString));
201 ErrorOr> M =
202 LTOModule::createFromOpenFile(*LTOContext, fd, path, size, Options);
203 if (!M)
204 return nullptr;
205 return wrap(M->release());
176206 }
177207
178208 lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
181211 off_t offset) {
182212 lto_initialize();
183213 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
184 return wrap(LTOModule::createFromOpenFileSlice(fd, path, map_size, offset,
185 Options, sLastErrorString));
214 ErrorOr> M = LTOModule::createFromOpenFileSlice(
215 *LTOContext, fd, path, map_size, offset, Options);
216 if (!M)
217 return nullptr;
218 return wrap(M->release());
186219 }
187220
188221 lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
189222 lto_initialize();
190223 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
191 return wrap(LTOModule::createFromBuffer(mem, length, Options, sLastErrorString));
224 ErrorOr> M =
225 LTOModule::createFromBuffer(*LTOContext, mem, length, Options);
226 if (!M)
227 return nullptr;
228 return wrap(M->release());
192229 }
193230
194231 lto_module_t lto_module_create_from_memory_with_path(const void* mem,
196233 const char *path) {
197234 lto_initialize();
198235 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
199 return wrap(
200 LTOModule::createFromBuffer(mem, length, Options, sLastErrorString, path));
236 ErrorOr> M =
237 LTOModule::createFromBuffer(*LTOContext, mem, length, Options, path);
238 if (!M)
239 return nullptr;
240 return wrap(M->release());
201241 }
202242
203243 lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
204244 const char *path) {
205245 lto_initialize();
206246 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
207 return wrap(LTOModule::createInLocalContext(mem, length, Options,
208 sLastErrorString, path));
247 ErrorOr> M =
248 LTOModule::createInLocalContext(mem, length, Options, path);
249 if (!M)
250 return nullptr;
251 return wrap(M->release());
209252 }
210253
211254 lto_module_t lto_module_create_in_codegen_context(const void *mem,
214257 lto_code_gen_t cg) {
215258 lto_initialize();
216259 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
217 return wrap(LTOModule::createInContext(mem, length, Options, sLastErrorString,
218 path, &unwrap(cg)->getContext()));
260 ErrorOr> M = LTOModule::createInContext(
261 mem, length, Options, path, &unwrap(cg)->getContext());
262 return wrap(M->release());
219263 }
220264
221265 void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }