File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/tools/llc/llc.cpp |
Warning: | line 670, column 13 Potential leak of memory pointed to by 'MMIWP' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This is the llc code generator driver. It provides a convenient | |||
10 | // command-line interface for generating native assembly-language code | |||
11 | // or C code, given LLVM bitcode. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "llvm/ADT/STLExtras.h" | |||
16 | #include "llvm/ADT/ScopeExit.h" | |||
17 | #include "llvm/ADT/Triple.h" | |||
18 | #include "llvm/Analysis/TargetLibraryInfo.h" | |||
19 | #include "llvm/CodeGen/CommandFlags.h" | |||
20 | #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" | |||
21 | #include "llvm/CodeGen/LinkAllCodegenComponents.h" | |||
22 | #include "llvm/CodeGen/MIRParser/MIRParser.h" | |||
23 | #include "llvm/CodeGen/MachineFunctionPass.h" | |||
24 | #include "llvm/CodeGen/MachineModuleInfo.h" | |||
25 | #include "llvm/CodeGen/TargetPassConfig.h" | |||
26 | #include "llvm/CodeGen/TargetSubtargetInfo.h" | |||
27 | #include "llvm/IR/AutoUpgrade.h" | |||
28 | #include "llvm/IR/DataLayout.h" | |||
29 | #include "llvm/IR/DiagnosticInfo.h" | |||
30 | #include "llvm/IR/DiagnosticPrinter.h" | |||
31 | #include "llvm/IR/IRPrintingPasses.h" | |||
32 | #include "llvm/IR/LLVMContext.h" | |||
33 | #include "llvm/IR/LLVMRemarkStreamer.h" | |||
34 | #include "llvm/IR/LegacyPassManager.h" | |||
35 | #include "llvm/IR/Module.h" | |||
36 | #include "llvm/IR/Verifier.h" | |||
37 | #include "llvm/IRReader/IRReader.h" | |||
38 | #include "llvm/InitializePasses.h" | |||
39 | #include "llvm/MC/MCTargetOptionsCommandFlags.h" | |||
40 | #include "llvm/MC/SubtargetFeature.h" | |||
41 | #include "llvm/MC/TargetRegistry.h" | |||
42 | #include "llvm/Pass.h" | |||
43 | #include "llvm/Remarks/HotnessThresholdParser.h" | |||
44 | #include "llvm/Support/CommandLine.h" | |||
45 | #include "llvm/Support/Debug.h" | |||
46 | #include "llvm/Support/FileSystem.h" | |||
47 | #include "llvm/Support/FormattedStream.h" | |||
48 | #include "llvm/Support/Host.h" | |||
49 | #include "llvm/Support/InitLLVM.h" | |||
50 | #include "llvm/Support/ManagedStatic.h" | |||
51 | #include "llvm/Support/PluginLoader.h" | |||
52 | #include "llvm/Support/SourceMgr.h" | |||
53 | #include "llvm/Support/TargetSelect.h" | |||
54 | #include "llvm/Support/TimeProfiler.h" | |||
55 | #include "llvm/Support/ToolOutputFile.h" | |||
56 | #include "llvm/Support/WithColor.h" | |||
57 | #include "llvm/Target/TargetLoweringObjectFile.h" | |||
58 | #include "llvm/Target/TargetMachine.h" | |||
59 | #include "llvm/Transforms/Utils/Cloning.h" | |||
60 | #include <memory> | |||
61 | using namespace llvm; | |||
62 | ||||
63 | static codegen::RegisterCodeGenFlags CGF; | |||
64 | ||||
65 | // General options for llc. Other pass-specific options are specified | |||
66 | // within the corresponding llc passes, and target-specific options | |||
67 | // and back-end code generation options are specified with the target machine. | |||
68 | // | |||
69 | static cl::opt<std::string> | |||
70 | InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-")); | |||
71 | ||||
72 | static cl::opt<std::string> | |||
73 | InputLanguage("x", cl::desc("Input language ('ir' or 'mir')")); | |||
74 | ||||
75 | static cl::opt<std::string> | |||
76 | OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); | |||
77 | ||||
78 | static cl::opt<std::string> | |||
79 | SplitDwarfOutputFile("split-dwarf-output", | |||
80 | cl::desc(".dwo output filename"), | |||
81 | cl::value_desc("filename")); | |||
82 | ||||
83 | static cl::opt<unsigned> | |||
84 | TimeCompilations("time-compilations", cl::Hidden, cl::init(1u), | |||
85 | cl::value_desc("N"), | |||
86 | cl::desc("Repeat compilation N times for timing")); | |||
87 | ||||
88 | static cl::opt<bool> TimeTrace("time-trace", cl::desc("Record time trace")); | |||
89 | ||||
90 | static cl::opt<unsigned> TimeTraceGranularity( | |||
91 | "time-trace-granularity", | |||
92 | cl::desc( | |||
93 | "Minimum time granularity (in microseconds) traced by time profiler"), | |||
94 | cl::init(500), cl::Hidden); | |||
95 | ||||
96 | static cl::opt<std::string> | |||
97 | TimeTraceFile("time-trace-file", | |||
98 | cl::desc("Specify time trace file destination"), | |||
99 | cl::value_desc("filename")); | |||
100 | ||||
101 | static cl::opt<std::string> | |||
102 | BinutilsVersion("binutils-version", cl::Hidden, | |||
103 | cl::desc("Produced object files can use all ELF features " | |||
104 | "supported by this binutils version and newer." | |||
105 | "If -no-integrated-as is specified, the generated " | |||
106 | "assembly will consider GNU as support." | |||
107 | "'none' means that all ELF features can be used, " | |||
108 | "regardless of binutils support")); | |||
109 | ||||
110 | static cl::opt<bool> | |||
111 | NoIntegratedAssembler("no-integrated-as", cl::Hidden, | |||
112 | cl::desc("Disable integrated assembler")); | |||
113 | ||||
114 | static cl::opt<bool> | |||
115 | PreserveComments("preserve-as-comments", cl::Hidden, | |||
116 | cl::desc("Preserve Comments in outputted assembly"), | |||
117 | cl::init(true)); | |||
118 | ||||
119 | // Determine optimization level. | |||
120 | static cl::opt<char> | |||
121 | OptLevel("O", | |||
122 | cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " | |||
123 | "(default = '-O2')"), | |||
124 | cl::Prefix, | |||
125 | cl::ZeroOrMore, | |||
126 | cl::init(' ')); | |||
127 | ||||
128 | static cl::opt<std::string> | |||
129 | TargetTriple("mtriple", cl::desc("Override target triple for module")); | |||
130 | ||||
131 | static cl::opt<std::string> SplitDwarfFile( | |||
132 | "split-dwarf-file", | |||
133 | cl::desc( | |||
134 | "Specify the name of the .dwo file to encode in the DWARF output")); | |||
135 | ||||
136 | static cl::opt<bool> NoVerify("disable-verify", cl::Hidden, | |||
137 | cl::desc("Do not verify input module")); | |||
138 | ||||
139 | static cl::opt<bool> DisableSimplifyLibCalls("disable-simplify-libcalls", | |||
140 | cl::desc("Disable simplify-libcalls")); | |||
141 | ||||
142 | static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden, | |||
143 | cl::desc("Show encoding in .s output")); | |||
144 | ||||
145 | static cl::opt<bool> | |||
146 | DwarfDirectory("dwarf-directory", cl::Hidden, | |||
147 | cl::desc("Use .file directives with an explicit directory"), | |||
148 | cl::init(true)); | |||
149 | ||||
150 | static cl::opt<bool> AsmVerbose("asm-verbose", | |||
151 | cl::desc("Add comments to directives."), | |||
152 | cl::init(true)); | |||
153 | ||||
154 | static cl::opt<bool> | |||
155 | CompileTwice("compile-twice", cl::Hidden, | |||
156 | cl::desc("Run everything twice, re-using the same pass " | |||
157 | "manager and verify the result is the same."), | |||
158 | cl::init(false)); | |||
159 | ||||
160 | static cl::opt<bool> DiscardValueNames( | |||
161 | "discard-value-names", | |||
162 | cl::desc("Discard names from Value (other than GlobalValue)."), | |||
163 | cl::init(false), cl::Hidden); | |||
164 | ||||
165 | static cl::list<std::string> IncludeDirs("I", cl::desc("include search path")); | |||
166 | ||||
167 | static cl::opt<bool> RemarksWithHotness( | |||
168 | "pass-remarks-with-hotness", | |||
169 | cl::desc("With PGO, include profile count in optimization remarks"), | |||
170 | cl::Hidden); | |||
171 | ||||
172 | static cl::opt<Optional<uint64_t>, false, remarks::HotnessThresholdParser> | |||
173 | RemarksHotnessThreshold( | |||
174 | "pass-remarks-hotness-threshold", | |||
175 | cl::desc("Minimum profile count required for " | |||
176 | "an optimization remark to be output. " | |||
177 | "Use 'auto' to apply the threshold from profile summary."), | |||
178 | cl::value_desc("N or 'auto'"), cl::init(0), cl::Hidden); | |||
179 | ||||
180 | static cl::opt<std::string> | |||
181 | RemarksFilename("pass-remarks-output", | |||
182 | cl::desc("Output filename for pass remarks"), | |||
183 | cl::value_desc("filename")); | |||
184 | ||||
185 | static cl::opt<std::string> | |||
186 | RemarksPasses("pass-remarks-filter", | |||
187 | cl::desc("Only record optimization remarks from passes whose " | |||
188 | "names match the given regular expression"), | |||
189 | cl::value_desc("regex")); | |||
190 | ||||
191 | static cl::opt<std::string> RemarksFormat( | |||
192 | "pass-remarks-format", | |||
193 | cl::desc("The format used for serializing remarks (default: YAML)"), | |||
194 | cl::value_desc("format"), cl::init("yaml")); | |||
195 | ||||
196 | namespace { | |||
197 | static ManagedStatic<std::vector<std::string>> RunPassNames; | |||
198 | ||||
199 | struct RunPassOption { | |||
200 | void operator=(const std::string &Val) const { | |||
201 | if (Val.empty()) | |||
202 | return; | |||
203 | SmallVector<StringRef, 8> PassNames; | |||
204 | StringRef(Val).split(PassNames, ',', -1, false); | |||
205 | for (auto PassName : PassNames) | |||
206 | RunPassNames->push_back(std::string(PassName)); | |||
207 | } | |||
208 | }; | |||
209 | } | |||
210 | ||||
211 | static RunPassOption RunPassOpt; | |||
212 | ||||
213 | static cl::opt<RunPassOption, true, cl::parser<std::string>> RunPass( | |||
214 | "run-pass", | |||
215 | cl::desc("Run compiler only for specified passes (comma separated list)"), | |||
216 | cl::value_desc("pass-name"), cl::ZeroOrMore, cl::location(RunPassOpt)); | |||
217 | ||||
218 | static int compileModule(char **, LLVMContext &); | |||
219 | ||||
220 | [[noreturn]] static void reportError(Twine Msg, StringRef Filename = "") { | |||
221 | SmallString<256> Prefix; | |||
222 | if (!Filename.empty()) { | |||
223 | if (Filename == "-") | |||
224 | Filename = "<stdin>"; | |||
225 | ("'" + Twine(Filename) + "': ").toStringRef(Prefix); | |||
226 | } | |||
227 | WithColor::error(errs(), "llc") << Prefix << Msg << "\n"; | |||
228 | exit(1); | |||
229 | } | |||
230 | ||||
231 | [[noreturn]] static void reportError(Error Err, StringRef Filename) { | |||
232 | assert(Err)(static_cast <bool> (Err) ? void (0) : __assert_fail ("Err" , "llvm/tools/llc/llc.cpp", 232, __extension__ __PRETTY_FUNCTION__ )); | |||
233 | handleAllErrors(createFileError(Filename, std::move(Err)), | |||
234 | [&](const ErrorInfoBase &EI) { reportError(EI.message()); }); | |||
235 | llvm_unreachable("reportError() should not return")::llvm::llvm_unreachable_internal("reportError() should not return" , "llvm/tools/llc/llc.cpp", 235); | |||
236 | } | |||
237 | ||||
238 | static std::unique_ptr<ToolOutputFile> GetOutputStream(const char *TargetName, | |||
239 | Triple::OSType OS, | |||
240 | const char *ProgName) { | |||
241 | // If we don't yet have an output filename, make one. | |||
242 | if (OutputFilename.empty()) { | |||
243 | if (InputFilename == "-") | |||
244 | OutputFilename = "-"; | |||
245 | else { | |||
246 | // If InputFilename ends in .bc or .ll, remove it. | |||
247 | StringRef IFN = InputFilename; | |||
248 | if (IFN.endswith(".bc") || IFN.endswith(".ll")) | |||
249 | OutputFilename = std::string(IFN.drop_back(3)); | |||
250 | else if (IFN.endswith(".mir")) | |||
251 | OutputFilename = std::string(IFN.drop_back(4)); | |||
252 | else | |||
253 | OutputFilename = std::string(IFN); | |||
254 | ||||
255 | switch (codegen::getFileType()) { | |||
256 | case CGFT_AssemblyFile: | |||
257 | if (TargetName[0] == 'c') { | |||
258 | if (TargetName[1] == 0) | |||
259 | OutputFilename += ".cbe.c"; | |||
260 | else if (TargetName[1] == 'p' && TargetName[2] == 'p') | |||
261 | OutputFilename += ".cpp"; | |||
262 | else | |||
263 | OutputFilename += ".s"; | |||
264 | } else | |||
265 | OutputFilename += ".s"; | |||
266 | break; | |||
267 | case CGFT_ObjectFile: | |||
268 | if (OS == Triple::Win32) | |||
269 | OutputFilename += ".obj"; | |||
270 | else | |||
271 | OutputFilename += ".o"; | |||
272 | break; | |||
273 | case CGFT_Null: | |||
274 | OutputFilename = "-"; | |||
275 | break; | |||
276 | } | |||
277 | } | |||
278 | } | |||
279 | ||||
280 | // Decide if we need "binary" output. | |||
281 | bool Binary = false; | |||
282 | switch (codegen::getFileType()) { | |||
283 | case CGFT_AssemblyFile: | |||
284 | break; | |||
285 | case CGFT_ObjectFile: | |||
286 | case CGFT_Null: | |||
287 | Binary = true; | |||
288 | break; | |||
289 | } | |||
290 | ||||
291 | // Open the file. | |||
292 | std::error_code EC; | |||
293 | sys::fs::OpenFlags OpenFlags = sys::fs::OF_None; | |||
294 | if (!Binary) | |||
295 | OpenFlags |= sys::fs::OF_TextWithCRLF; | |||
296 | auto FDOut = std::make_unique<ToolOutputFile>(OutputFilename, EC, OpenFlags); | |||
297 | if (EC) { | |||
298 | reportError(EC.message()); | |||
299 | return nullptr; | |||
300 | } | |||
301 | ||||
302 | return FDOut; | |||
303 | } | |||
304 | ||||
305 | struct LLCDiagnosticHandler : public DiagnosticHandler { | |||
306 | bool *HasError; | |||
307 | LLCDiagnosticHandler(bool *HasErrorPtr) : HasError(HasErrorPtr) {} | |||
308 | bool handleDiagnostics(const DiagnosticInfo &DI) override { | |||
309 | if (DI.getKind() == llvm::DK_SrcMgr) { | |||
310 | const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI); | |||
311 | const SMDiagnostic &SMD = DISM.getSMDiag(); | |||
312 | ||||
313 | if (SMD.getKind() == SourceMgr::DK_Error) | |||
314 | *HasError = true; | |||
315 | ||||
316 | SMD.print(nullptr, errs()); | |||
317 | ||||
318 | // For testing purposes, we print the LocCookie here. | |||
319 | if (DISM.isInlineAsmDiag() && DISM.getLocCookie()) | |||
320 | WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n"; | |||
321 | ||||
322 | return true; | |||
323 | } | |||
324 | ||||
325 | if (DI.getSeverity() == DS_Error) | |||
326 | *HasError = true; | |||
327 | ||||
328 | if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) | |||
329 | if (!Remark->isEnabled()) | |||
330 | return true; | |||
331 | ||||
332 | DiagnosticPrinterRawOStream DP(errs()); | |||
333 | errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; | |||
334 | DI.print(DP); | |||
335 | errs() << "\n"; | |||
336 | return true; | |||
337 | } | |||
338 | }; | |||
339 | ||||
340 | // main - Entry point for the llc compiler. | |||
341 | // | |||
342 | int main(int argc, char **argv) { | |||
343 | InitLLVM X(argc, argv); | |||
344 | ||||
345 | // Enable debug stream buffering. | |||
346 | EnableDebugBuffering = true; | |||
347 | ||||
348 | // Initialize targets first, so that --version shows registered targets. | |||
349 | InitializeAllTargets(); | |||
350 | InitializeAllTargetMCs(); | |||
351 | InitializeAllAsmPrinters(); | |||
352 | InitializeAllAsmParsers(); | |||
353 | ||||
354 | // Initialize codegen and IR passes used by llc so that the -print-after, | |||
355 | // -print-before, and -stop-after options work. | |||
356 | PassRegistry *Registry = PassRegistry::getPassRegistry(); | |||
357 | initializeCore(*Registry); | |||
358 | initializeCodeGen(*Registry); | |||
359 | initializeLoopStrengthReducePass(*Registry); | |||
360 | initializeLowerIntrinsicsPass(*Registry); | |||
361 | initializeEntryExitInstrumenterPass(*Registry); | |||
362 | initializePostInlineEntryExitInstrumenterPass(*Registry); | |||
363 | initializeUnreachableBlockElimLegacyPassPass(*Registry); | |||
364 | initializeConstantHoistingLegacyPassPass(*Registry); | |||
365 | initializeScalarOpts(*Registry); | |||
366 | initializeVectorization(*Registry); | |||
367 | initializeScalarizeMaskedMemIntrinLegacyPassPass(*Registry); | |||
368 | initializeExpandReductionsPass(*Registry); | |||
369 | initializeExpandVectorPredicationPass(*Registry); | |||
370 | initializeHardwareLoopsPass(*Registry); | |||
371 | initializeTransformUtils(*Registry); | |||
372 | initializeReplaceWithVeclibLegacyPass(*Registry); | |||
373 | initializeTLSVariableHoistLegacyPassPass(*Registry); | |||
374 | ||||
375 | // Initialize debugging passes. | |||
376 | initializeScavengerTestPass(*Registry); | |||
377 | ||||
378 | // Register the target printer for --version. | |||
379 | cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); | |||
380 | ||||
381 | cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); | |||
382 | ||||
383 | if (TimeTrace) | |||
384 | timeTraceProfilerInitialize(TimeTraceGranularity, argv[0]); | |||
385 | auto TimeTraceScopeExit = make_scope_exit([]() { | |||
386 | if (TimeTrace) { | |||
387 | if (auto E = timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) { | |||
388 | handleAllErrors(std::move(E), [&](const StringError &SE) { | |||
389 | errs() << SE.getMessage() << "\n"; | |||
390 | }); | |||
391 | return; | |||
392 | } | |||
393 | timeTraceProfilerCleanup(); | |||
394 | } | |||
395 | }); | |||
396 | ||||
397 | LLVMContext Context; | |||
398 | Context.setDiscardValueNames(DiscardValueNames); | |||
399 | ||||
400 | // Set a diagnostic handler that doesn't exit on the first error | |||
401 | bool HasError = false; | |||
402 | Context.setDiagnosticHandler( | |||
403 | std::make_unique<LLCDiagnosticHandler>(&HasError)); | |||
404 | ||||
405 | Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr = | |||
406 | setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses, | |||
407 | RemarksFormat, RemarksWithHotness, | |||
408 | RemarksHotnessThreshold); | |||
409 | if (Error E = RemarksFileOrErr.takeError()) | |||
410 | reportError(std::move(E), RemarksFilename); | |||
411 | std::unique_ptr<ToolOutputFile> RemarksFile = std::move(*RemarksFileOrErr); | |||
412 | ||||
413 | if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir") | |||
414 | reportError("input language must be '', 'IR' or 'MIR'"); | |||
415 | ||||
416 | // Compile the module TimeCompilations times to give better compile time | |||
417 | // metrics. | |||
418 | for (unsigned I = TimeCompilations; I; --I) | |||
419 | if (int RetVal = compileModule(argv, Context)) | |||
420 | return RetVal; | |||
421 | ||||
422 | if (RemarksFile) | |||
423 | RemarksFile->keep(); | |||
424 | return 0; | |||
425 | } | |||
426 | ||||
427 | static bool addPass(PassManagerBase &PM, const char *argv0, | |||
428 | StringRef PassName, TargetPassConfig &TPC) { | |||
429 | if (PassName == "none") | |||
430 | return false; | |||
431 | ||||
432 | const PassRegistry *PR = PassRegistry::getPassRegistry(); | |||
433 | const PassInfo *PI = PR->getPassInfo(PassName); | |||
434 | if (!PI) { | |||
435 | WithColor::error(errs(), argv0) | |||
436 | << "run-pass " << PassName << " is not registered.\n"; | |||
437 | return true; | |||
438 | } | |||
439 | ||||
440 | Pass *P; | |||
441 | if (PI->getNormalCtor()) | |||
442 | P = PI->getNormalCtor()(); | |||
443 | else { | |||
444 | WithColor::error(errs(), argv0) | |||
445 | << "cannot create pass: " << PI->getPassName() << "\n"; | |||
446 | return true; | |||
447 | } | |||
448 | std::string Banner = std::string("After ") + std::string(P->getPassName()); | |||
449 | TPC.addMachinePrePasses(); | |||
450 | PM.add(P); | |||
451 | TPC.addMachinePostPasses(Banner); | |||
452 | ||||
453 | return false; | |||
454 | } | |||
455 | ||||
456 | static int compileModule(char **argv, LLVMContext &Context) { | |||
457 | // Load the module to be compiled... | |||
458 | SMDiagnostic Err; | |||
459 | std::unique_ptr<Module> M; | |||
460 | std::unique_ptr<MIRParser> MIR; | |||
461 | Triple TheTriple; | |||
462 | std::string CPUStr = codegen::getCPUStr(), | |||
463 | FeaturesStr = codegen::getFeaturesStr(); | |||
464 | ||||
465 | // Set attributes on functions as loaded from MIR from command line arguments. | |||
466 | auto setMIRFunctionAttributes = [&CPUStr, &FeaturesStr](Function &F) { | |||
467 | codegen::setFunctionAttributes(CPUStr, FeaturesStr, F); | |||
468 | }; | |||
469 | ||||
470 | auto MAttrs = codegen::getMAttrs(); | |||
471 | bool SkipModule = codegen::getMCPU() == "help" || | |||
472 | (!MAttrs.empty() && MAttrs.front() == "help"); | |||
| ||||
473 | ||||
474 | CodeGenOpt::Level OLvl = CodeGenOpt::Default; | |||
475 | switch (OptLevel) { | |||
476 | default: | |||
477 | WithColor::error(errs(), argv[0]) << "invalid optimization level.\n"; | |||
478 | return 1; | |||
479 | case ' ': break; | |||
480 | case '0': OLvl = CodeGenOpt::None; break; | |||
481 | case '1': OLvl = CodeGenOpt::Less; break; | |||
482 | case '2': OLvl = CodeGenOpt::Default; break; | |||
483 | case '3': OLvl = CodeGenOpt::Aggressive; break; | |||
484 | } | |||
485 | ||||
486 | // Parse 'none' or '$major.$minor'. Disallow -binutils-version=0 because we | |||
487 | // use that to indicate the MC default. | |||
488 | if (!BinutilsVersion.empty() && BinutilsVersion != "none") { | |||
489 | StringRef V = BinutilsVersion.getValue(); | |||
490 | unsigned Num; | |||
491 | if (V.consumeInteger(10, Num) || Num == 0 || | |||
492 | !(V.empty() || | |||
493 | (V.consume_front(".") && !V.consumeInteger(10, Num) && V.empty()))) { | |||
494 | WithColor::error(errs(), argv[0]) | |||
495 | << "invalid -binutils-version, accepting 'none' or major.minor\n"; | |||
496 | return 1; | |||
497 | } | |||
498 | } | |||
499 | TargetOptions Options; | |||
500 | auto InitializeOptions = [&](const Triple &TheTriple) { | |||
501 | Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple); | |||
502 | Options.BinutilsVersion = | |||
503 | TargetMachine::parseBinutilsVersion(BinutilsVersion); | |||
504 | Options.DisableIntegratedAS = NoIntegratedAssembler; | |||
505 | Options.MCOptions.ShowMCEncoding = ShowMCEncoding; | |||
506 | Options.MCOptions.MCUseDwarfDirectory = DwarfDirectory; | |||
507 | Options.MCOptions.AsmVerbose = AsmVerbose; | |||
508 | Options.MCOptions.PreserveAsmComments = PreserveComments; | |||
509 | Options.MCOptions.IASSearchPaths = IncludeDirs; | |||
510 | Options.MCOptions.SplitDwarfFile = SplitDwarfFile; | |||
511 | }; | |||
512 | ||||
513 | Optional<Reloc::Model> RM = codegen::getExplicitRelocModel(); | |||
514 | ||||
515 | const Target *TheTarget = nullptr; | |||
516 | std::unique_ptr<TargetMachine> Target; | |||
517 | ||||
518 | // If user just wants to list available options, skip module loading | |||
519 | if (!SkipModule
| |||
520 | auto SetDataLayout = | |||
521 | [&](StringRef DataLayoutTargetTriple) -> Optional<std::string> { | |||
522 | // If we are supposed to override the target triple, do so now. | |||
523 | std::string IRTargetTriple = DataLayoutTargetTriple.str(); | |||
524 | if (!TargetTriple.empty()) | |||
525 | IRTargetTriple = Triple::normalize(TargetTriple); | |||
526 | TheTriple = Triple(IRTargetTriple); | |||
527 | if (TheTriple.getTriple().empty()) | |||
528 | TheTriple.setTriple(sys::getDefaultTargetTriple()); | |||
529 | ||||
530 | std::string Error; | |||
531 | TheTarget = | |||
532 | TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); | |||
533 | if (!TheTarget) { | |||
534 | WithColor::error(errs(), argv[0]) << Error; | |||
535 | exit(1); | |||
536 | } | |||
537 | ||||
538 | // On AIX, setting the relocation model to anything other than PIC is | |||
539 | // considered a user error. | |||
540 | if (TheTriple.isOSAIX() && RM.hasValue() && *RM != Reloc::PIC_) | |||
541 | reportError("invalid relocation model, AIX only supports PIC", | |||
542 | InputFilename); | |||
543 | ||||
544 | InitializeOptions(TheTriple); | |||
545 | Target = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine( | |||
546 | TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, | |||
547 | codegen::getExplicitCodeModel(), OLvl)); | |||
548 | assert(Target && "Could not allocate target machine!")(static_cast <bool> (Target && "Could not allocate target machine!" ) ? void (0) : __assert_fail ("Target && \"Could not allocate target machine!\"" , "llvm/tools/llc/llc.cpp", 548, __extension__ __PRETTY_FUNCTION__ )); | |||
549 | ||||
550 | return Target->createDataLayout().getStringRepresentation(); | |||
551 | }; | |||
552 | if (InputLanguage == "mir" || | |||
553 | (InputLanguage == "" && StringRef(InputFilename).endswith(".mir"))) { | |||
554 | MIR = createMIRParserFromFile(InputFilename, Err, Context, | |||
555 | setMIRFunctionAttributes); | |||
556 | if (MIR) | |||
557 | M = MIR->parseIRModule(SetDataLayout); | |||
558 | } else { | |||
559 | M = parseIRFile(InputFilename, Err, Context, SetDataLayout); | |||
560 | } | |||
561 | if (!M) { | |||
562 | Err.print(argv[0], WithColor::error(errs(), argv[0])); | |||
563 | return 1; | |||
564 | } | |||
565 | if (!TargetTriple.empty()) | |||
566 | M->setTargetTriple(Triple::normalize(TargetTriple)); | |||
567 | } else { | |||
568 | TheTriple = Triple(Triple::normalize(TargetTriple)); | |||
569 | if (TheTriple.getTriple().empty()) | |||
570 | TheTriple.setTriple(sys::getDefaultTargetTriple()); | |||
571 | ||||
572 | // Get the target specific parser. | |||
573 | std::string Error; | |||
574 | TheTarget = | |||
575 | TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); | |||
576 | if (!TheTarget) { | |||
577 | WithColor::error(errs(), argv[0]) << Error; | |||
578 | return 1; | |||
579 | } | |||
580 | ||||
581 | // On AIX, setting the relocation model to anything other than PIC is | |||
582 | // considered a user error. | |||
583 | if (TheTriple.isOSAIX() && RM.hasValue() && *RM != Reloc::PIC_) { | |||
584 | WithColor::error(errs(), argv[0]) | |||
585 | << "invalid relocation model, AIX only supports PIC.\n"; | |||
586 | return 1; | |||
587 | } | |||
588 | ||||
589 | InitializeOptions(TheTriple); | |||
590 | Target = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine( | |||
591 | TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, | |||
592 | codegen::getExplicitCodeModel(), OLvl)); | |||
593 | assert(Target && "Could not allocate target machine!")(static_cast <bool> (Target && "Could not allocate target machine!" ) ? void (0) : __assert_fail ("Target && \"Could not allocate target machine!\"" , "llvm/tools/llc/llc.cpp", 593, __extension__ __PRETTY_FUNCTION__ )); | |||
594 | ||||
595 | // If we don't have a module then just exit now. We do this down | |||
596 | // here since the CPU/Feature help is underneath the target machine | |||
597 | // creation. | |||
598 | return 0; | |||
599 | } | |||
600 | ||||
601 | assert(M && "Should have exited if we didn't have a module!")(static_cast <bool> (M && "Should have exited if we didn't have a module!" ) ? void (0) : __assert_fail ("M && \"Should have exited if we didn't have a module!\"" , "llvm/tools/llc/llc.cpp", 601, __extension__ __PRETTY_FUNCTION__ )); | |||
602 | if (codegen::getFloatABIForCalls() != FloatABI::Default) | |||
603 | Options.FloatABIType = codegen::getFloatABIForCalls(); | |||
604 | ||||
605 | // Figure out where we are going to send the output. | |||
606 | std::unique_ptr<ToolOutputFile> Out = | |||
607 | GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]); | |||
608 | if (!Out) return 1; | |||
609 | ||||
610 | // Ensure the filename is passed down to CodeViewDebug. | |||
611 | Target->Options.ObjectFilenameForDebug = Out->outputFilename(); | |||
612 | ||||
613 | std::unique_ptr<ToolOutputFile> DwoOut; | |||
614 | if (!SplitDwarfOutputFile.empty()) { | |||
615 | std::error_code EC; | |||
616 | DwoOut = std::make_unique<ToolOutputFile>(SplitDwarfOutputFile, EC, | |||
617 | sys::fs::OF_None); | |||
618 | if (EC) | |||
619 | reportError(EC.message(), SplitDwarfOutputFile); | |||
620 | } | |||
621 | ||||
622 | // Build up all of the passes that we want to do to the module. | |||
623 | legacy::PassManager PM; | |||
624 | ||||
625 | // Add an appropriate TargetLibraryInfo pass for the module's triple. | |||
626 | TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple())); | |||
627 | ||||
628 | // The -disable-simplify-libcalls flag actually disables all builtin optzns. | |||
629 | if (DisableSimplifyLibCalls) | |||
630 | TLII.disableAllFunctions(); | |||
631 | PM.add(new TargetLibraryInfoWrapperPass(TLII)); | |||
632 | ||||
633 | // Verify module immediately to catch problems before doInitialization() is | |||
634 | // called on any passes. | |||
635 | if (!NoVerify && verifyModule(*M, &errs())) | |||
636 | reportError("input module cannot be verified", InputFilename); | |||
637 | ||||
638 | // Override function attributes based on CPUStr, FeaturesStr, and command line | |||
639 | // flags. | |||
640 | codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M); | |||
641 | ||||
642 | if (mc::getExplicitRelaxAll() && codegen::getFileType() != CGFT_ObjectFile) | |||
643 | WithColor::warning(errs(), argv[0]) | |||
644 | << ": warning: ignoring -mc-relax-all because filetype != obj"; | |||
645 | ||||
646 | { | |||
647 | raw_pwrite_stream *OS = &Out->os(); | |||
648 | ||||
649 | // Manually do the buffering rather than using buffer_ostream, | |||
650 | // so we can memcmp the contents in CompileTwice mode | |||
651 | SmallVector<char, 0> Buffer; | |||
652 | std::unique_ptr<raw_svector_ostream> BOS; | |||
653 | if ((codegen::getFileType() != CGFT_AssemblyFile && | |||
654 | !Out->os().supportsSeeking()) || | |||
655 | CompileTwice) { | |||
656 | BOS = std::make_unique<raw_svector_ostream>(Buffer); | |||
657 | OS = BOS.get(); | |||
658 | } | |||
659 | ||||
660 | const char *argv0 = argv[0]; | |||
661 | LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target); | |||
662 | MachineModuleInfoWrapperPass *MMIWP = | |||
663 | new MachineModuleInfoWrapperPass(&LLVMTM); | |||
664 | ||||
665 | // Construct a custom pass pipeline that starts after instruction | |||
666 | // selection. | |||
667 | if (!RunPassNames->empty()) { | |||
668 | if (!MIR) { | |||
669 | WithColor::warning(errs(), argv[0]) | |||
670 | << "run-pass is for .mir file only.\n"; | |||
| ||||
671 | return 1; | |||
672 | } | |||
673 | TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM); | |||
674 | if (TPC.hasLimitedCodeGenPipeline()) { | |||
675 | WithColor::warning(errs(), argv[0]) | |||
676 | << "run-pass cannot be used with " | |||
677 | << TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n"; | |||
678 | return 1; | |||
679 | } | |||
680 | ||||
681 | TPC.setDisableVerify(NoVerify); | |||
682 | PM.add(&TPC); | |||
683 | PM.add(MMIWP); | |||
684 | TPC.printAndVerify(""); | |||
685 | for (const std::string &RunPassName : *RunPassNames) { | |||
686 | if (addPass(PM, argv0, RunPassName, TPC)) | |||
687 | return 1; | |||
688 | } | |||
689 | TPC.setInitialized(); | |||
690 | PM.add(createPrintMIRPass(*OS)); | |||
691 | PM.add(createFreeMachineFunctionPass()); | |||
692 | } else if (Target->addPassesToEmitFile( | |||
693 | PM, *OS, DwoOut ? &DwoOut->os() : nullptr, | |||
694 | codegen::getFileType(), NoVerify, MMIWP)) { | |||
695 | reportError("target does not support generation of this file type"); | |||
696 | } | |||
697 | ||||
698 | const_cast<TargetLoweringObjectFile *>(LLVMTM.getObjFileLowering()) | |||
699 | ->Initialize(MMIWP->getMMI().getContext(), *Target); | |||
700 | if (MIR) { | |||
701 | assert(MMIWP && "Forgot to create MMIWP?")(static_cast <bool> (MMIWP && "Forgot to create MMIWP?" ) ? void (0) : __assert_fail ("MMIWP && \"Forgot to create MMIWP?\"" , "llvm/tools/llc/llc.cpp", 701, __extension__ __PRETTY_FUNCTION__ )); | |||
702 | if (MIR->parseMachineFunctions(*M, MMIWP->getMMI())) | |||
703 | return 1; | |||
704 | } | |||
705 | ||||
706 | // Before executing passes, print the final values of the LLVM options. | |||
707 | cl::PrintOptionValues(); | |||
708 | ||||
709 | // If requested, run the pass manager over the same module again, | |||
710 | // to catch any bugs due to persistent state in the passes. Note that | |||
711 | // opt has the same functionality, so it may be worth abstracting this out | |||
712 | // in the future. | |||
713 | SmallVector<char, 0> CompileTwiceBuffer; | |||
714 | if (CompileTwice) { | |||
715 | std::unique_ptr<Module> M2(llvm::CloneModule(*M)); | |||
716 | PM.run(*M2); | |||
717 | CompileTwiceBuffer = Buffer; | |||
718 | Buffer.clear(); | |||
719 | } | |||
720 | ||||
721 | PM.run(*M); | |||
722 | ||||
723 | auto HasError = | |||
724 | ((const LLCDiagnosticHandler *)(Context.getDiagHandlerPtr()))->HasError; | |||
725 | if (*HasError) | |||
726 | return 1; | |||
727 | ||||
728 | // Compare the two outputs and make sure they're the same | |||
729 | if (CompileTwice) { | |||
730 | if (Buffer.size() != CompileTwiceBuffer.size() || | |||
731 | (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) != | |||
732 | 0)) { | |||
733 | errs() | |||
734 | << "Running the pass manager twice changed the output.\n" | |||
735 | "Writing the result of the second run to the specified output\n" | |||
736 | "To generate the one-run comparison binary, just run without\n" | |||
737 | "the compile-twice option\n"; | |||
738 | Out->os() << Buffer; | |||
739 | Out->keep(); | |||
740 | return 1; | |||
741 | } | |||
742 | } | |||
743 | ||||
744 | if (BOS) { | |||
745 | Out->os() << Buffer; | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | // Declare success. | |||
750 | Out->keep(); | |||
751 | if (DwoOut) | |||
752 | DwoOut->keep(); | |||
753 | ||||
754 | return 0; | |||
755 | } |