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