PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/sil-opt/SILOpt.cpp

https://gitlab.com/yenny.prathivi/swift
C++ | 359 lines | 263 code | 60 blank | 36 comment | 42 complexity | 0ded106dae788dd7e022294cb8398355 MD5 | raw file
  1. //===-- SILOpt.cpp - SIL Optimization Driver ------------------------------===//
  2. //
  3. // This source file is part of the Swift.org open source project
  4. //
  5. // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See http://swift.org/LICENSE.txt for license information
  9. // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  10. //
  11. //===----------------------------------------------------------------------===//
  12. //
  13. // This is a tool for reading sil files and running sil passes on them. The
  14. // targeted usecase is debugging and testing SIL passes.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #include "swift/Strings.h"
  18. #include "swift/Subsystems.h"
  19. #include "swift/AST/DiagnosticsFrontend.h"
  20. #include "swift/AST/SILOptions.h"
  21. #include "swift/Basic/LLVMInitialize.h"
  22. #include "swift/Frontend/DiagnosticVerifier.h"
  23. #include "swift/Frontend/Frontend.h"
  24. #include "swift/Frontend/PrintingDiagnosticConsumer.h"
  25. #include "swift/SILAnalysis/Analysis.h"
  26. #include "swift/SILPasses/Passes.h"
  27. #include "swift/SILPasses/PassManager.h"
  28. #include "swift/Serialization/SerializedModuleLoader.h"
  29. #include "swift/Serialization/SerializedSILLoader.h"
  30. #include "swift/Serialization/SerializationOptions.h"
  31. #include "llvm/ADT/Statistic.h"
  32. #include "llvm/Support/CommandLine.h"
  33. #include "llvm/Support/FileSystem.h"
  34. #include "llvm/Support/ManagedStatic.h"
  35. #include "llvm/Support/MemoryBuffer.h"
  36. #include "llvm/Support/Path.h"
  37. #include "llvm/Support/Signals.h"
  38. #include "llvm/Support/TargetSelect.h"
  39. using namespace swift;
  40. namespace {
  41. enum class OptGroup {
  42. Unknown, Diagnostics, Performance
  43. };
  44. } // end anonymous namespace
  45. static llvm::cl::opt<std::string>
  46. InputFilename(llvm::cl::desc("input file"), llvm::cl::init("-"),
  47. llvm::cl::Positional);
  48. static llvm::cl::opt<std::string>
  49. OutputFilename("o", llvm::cl::desc("output filename"));
  50. static llvm::cl::list<std::string>
  51. ImportPaths("I", llvm::cl::desc("add a directory to the import search path"));
  52. static llvm::cl::list<std::string>
  53. FrameworkPaths("F", llvm::cl::desc("add a directory to the framework search path"));
  54. static llvm::cl::opt<std::string>
  55. ModuleName("module-name", llvm::cl::desc("The name of the module if processing"
  56. " a module. Necessary for processing "
  57. "stdin."));
  58. static llvm::cl::opt<std::string>
  59. ResourceDir("resource-dir",
  60. llvm::cl::desc("The directory that holds the compiler resource files"));
  61. static llvm::cl::opt<std::string>
  62. SDKPath("sdk", llvm::cl::desc("The path to the SDK for use with the clang "
  63. "importer."),
  64. llvm::cl::init(""));
  65. static llvm::cl::opt<std::string>
  66. Target("target", llvm::cl::desc("target triple"));
  67. static llvm::cl::opt<OptGroup> OptimizationGroup(
  68. llvm::cl::desc("Predefined optimization groups:"),
  69. llvm::cl::values(clEnumValN(OptGroup::Diagnostics, "diagnostics",
  70. "Run diagnostic passes"),
  71. clEnumValN(OptGroup::Performance, "O",
  72. "Run performance passes"),
  73. clEnumValEnd),
  74. llvm::cl::init(OptGroup::Unknown));
  75. static llvm::cl::list<PassKind>
  76. Passes(llvm::cl::desc("Passes:"),
  77. llvm::cl::values(
  78. #define PASS(ID, NAME, DESCRIPTION) clEnumValN(PassKind::ID, NAME, DESCRIPTION),
  79. #include "swift/SILPasses/Passes.def"
  80. clEnumValEnd));
  81. static llvm::cl::opt<bool>
  82. PrintStats("print-stats", llvm::cl::desc("Print various statistics"));
  83. static llvm::cl::opt<bool>
  84. VerifyMode("verify",
  85. llvm::cl::desc("verify diagnostics against expected-"
  86. "{error|warning|note} annotations"));
  87. static llvm::cl::opt<unsigned>
  88. AssertConfId("assert-conf-id", llvm::cl::Hidden,
  89. llvm::cl::init(0));
  90. static llvm::cl::opt<int>
  91. SILInlineThreshold("sil-inline-threshold", llvm::cl::Hidden,
  92. llvm::cl::init(-1));
  93. static llvm::cl::opt<bool>
  94. EnableSILVerifyAll("enable-sil-verify-all",
  95. llvm::cl::Hidden,
  96. llvm::cl::init(true),
  97. llvm::cl::desc("Run sil verifications after every pass."));
  98. static llvm::cl::opt<bool>
  99. RemoveRuntimeAsserts("remove-runtime-asserts",
  100. llvm::cl::Hidden,
  101. llvm::cl::init(false),
  102. llvm::cl::desc("Remove runtime assertions (cond_fail)."));
  103. static llvm::cl::opt<bool>
  104. EmitVerboseSIL("emit-verbose-sil",
  105. llvm::cl::desc("Emit locations during sil emission."));
  106. static llvm::cl::opt<bool>
  107. EmitSIB("emit-sib", llvm::cl::desc("Emit serialized AST + SIL file(s)"));
  108. static llvm::cl::opt<std::string>
  109. ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path"));
  110. static llvm::cl::opt<bool>
  111. EnableSILSortOutput("sil-sort-output", llvm::cl::Hidden,
  112. llvm::cl::init(false),
  113. llvm::cl::desc("Sort Functions, VTables, Globals, "
  114. "WitnessTables by name to ease diffing."));
  115. static llvm::cl::opt<bool>
  116. DisableASTDump("sil-disable-ast-dump", llvm::cl::Hidden,
  117. llvm::cl::init(false),
  118. llvm::cl::desc("Do not dump AST."));
  119. static llvm::cl::opt<unsigned>
  120. ASTVerifierProcessCount("ast-verifier-process-count", llvm::cl::Hidden,
  121. llvm::cl::init(1));
  122. static llvm::cl::opt<unsigned>
  123. ASTVerifierProcessId("ast-verifier-process-id", llvm::cl::Hidden,
  124. llvm::cl::init(1));
  125. static llvm::cl::opt<bool>
  126. PerformWMO("wmo", llvm::cl::desc("Enable whole-module optimizations"));
  127. static void runCommandLineSelectedPasses(SILModule *Module) {
  128. SILPassManager PM(Module);
  129. for (auto Pass : Passes) {
  130. PM.addPass(Pass);
  131. }
  132. PM.run();
  133. }
  134. // This function isn't referenced outside its translation unit, but it
  135. // can't use the "static" keyword because its address is used for
  136. // getMainExecutable (since some platforms don't support taking the
  137. // address of main, and some platforms can't implement getMainExecutable
  138. // without being given the address of a function in the main executable).
  139. void anchorForGetMainExecutable() {}
  140. int main(int argc, char **argv) {
  141. INITIALIZE_LLVM(argc, argv);
  142. llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL optimizer\n");
  143. if (PrintStats)
  144. llvm::EnableStatistics();
  145. CompilerInvocation Invocation;
  146. Invocation.setMainExecutablePath(
  147. llvm::sys::fs::getMainExecutable(argv[0],
  148. reinterpret_cast<void *>(&anchorForGetMainExecutable)));
  149. // Give the context the list of search paths to use for modules.
  150. Invocation.setImportSearchPaths(ImportPaths);
  151. Invocation.setFrameworkSearchPaths(FrameworkPaths);
  152. // Set the SDK path and target if given.
  153. if (SDKPath.getNumOccurrences() == 0) {
  154. const char *SDKROOT = getenv("SDKROOT");
  155. if (SDKROOT)
  156. SDKPath = SDKROOT;
  157. }
  158. if (!SDKPath.empty())
  159. Invocation.setSDKPath(SDKPath);
  160. if (!Target.empty())
  161. Invocation.setTargetTriple(Target);
  162. if (!ResourceDir.empty())
  163. Invocation.setRuntimeResourcePath(ResourceDir);
  164. // Set the module cache path. If not passed in we use the default swift module
  165. // cache.
  166. Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath;
  167. Invocation.setParseStdlib();
  168. Invocation.getLangOptions().EnableAccessControl = false;
  169. Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
  170. Invocation.getLangOptions().ASTVerifierProcessCount =
  171. ASTVerifierProcessCount;
  172. Invocation.getLangOptions().ASTVerifierProcessId =
  173. ASTVerifierProcessId;
  174. // Setup the SIL Options.
  175. SILOptions &SILOpts = Invocation.getSILOptions();
  176. SILOpts.InlineThreshold = SILInlineThreshold;
  177. SILOpts.VerifyAll = EnableSILVerifyAll;
  178. SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts;
  179. SILOpts.AssertConfig = AssertConfId;
  180. if (OptimizationGroup != OptGroup::Diagnostics)
  181. SILOpts.Optimization = SILOptions::SILOptMode::Optimize;
  182. // Load the input file.
  183. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
  184. llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
  185. if (!FileBufOrErr) {
  186. fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
  187. exit(-1);
  188. }
  189. // If it looks like we have an AST, set the source file kind to SIL and the
  190. // name of the module to the file's name.
  191. Invocation.addInputBuffer(FileBufOrErr.get().get());
  192. serialization::ExtendedValidationInfo extendedInfo;
  193. auto result = serialization::validateSerializedAST(
  194. FileBufOrErr.get()->getBuffer(), &extendedInfo);
  195. bool HasSerializedAST = result.status == serialization::Status::Valid;
  196. if (HasSerializedAST) {
  197. const StringRef Stem = ModuleName.size() ?
  198. StringRef(ModuleName) :
  199. llvm::sys::path::stem(InputFilename);
  200. Invocation.setModuleName(Stem);
  201. Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
  202. } else {
  203. const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
  204. Invocation.setModuleName(Name);
  205. Invocation.setInputKind(InputFileKind::IFK_SIL);
  206. }
  207. CompilerInstance CI;
  208. PrintingDiagnosticConsumer PrintDiags;
  209. CI.addDiagnosticConsumer(&PrintDiags);
  210. if (!PerformWMO) {
  211. auto &FrontendOpts = Invocation.getFrontendOptions();
  212. if (!InputFilename.empty() && InputFilename != "-") {
  213. FrontendOpts.PrimaryInput = SelectedInput(
  214. FrontendOpts.InputFilenames.size());
  215. } else {
  216. FrontendOpts.PrimaryInput = SelectedInput(
  217. FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer);
  218. }
  219. }
  220. if (CI.setup(Invocation))
  221. return 1;
  222. CI.performSema();
  223. // If parsing produced an error, don't run any passes.
  224. if (CI.getASTContext().hadError())
  225. return 1;
  226. // Load the SIL if we have a module. We have to do this after SILParse
  227. // creating the unfortunate double if statement.
  228. if (HasSerializedAST) {
  229. assert(!CI.hasSILModule() &&
  230. "performSema() should not create a SILModule.");
  231. CI.setSILModule(SILModule::createEmptyModule(CI.getMainModule(),
  232. CI.getSILOptions()));
  233. std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create(
  234. CI.getASTContext(), CI.getSILModule(), nullptr);
  235. if (extendedInfo.isSIB())
  236. SL->getAllForModule(CI.getMainModule()->getName(), nullptr);
  237. else
  238. SL->getAll();
  239. }
  240. // If we're in verify mode, install a custom diagnostic handling for
  241. // SourceMgr.
  242. if (VerifyMode)
  243. enableDiagnosticVerifier(CI.getSourceMgr());
  244. if (OptimizationGroup == OptGroup::Diagnostics) {
  245. runSILDiagnosticPasses(*CI.getSILModule());
  246. } else if (OptimizationGroup == OptGroup::Performance) {
  247. runSILOptimizationPasses(*CI.getSILModule());
  248. } else {
  249. runCommandLineSelectedPasses(CI.getSILModule());
  250. }
  251. if (EmitSIB) {
  252. llvm::SmallString<128> OutputFile;
  253. if (OutputFilename.size()) {
  254. OutputFile = OutputFilename;
  255. } else if (ModuleName.size()) {
  256. OutputFile = ModuleName;
  257. llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION);
  258. } else {
  259. OutputFile = CI.getMainModule()->getName().str();
  260. llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION);
  261. }
  262. SerializationOptions serializationOpts;
  263. serializationOpts.OutputPath = OutputFile.c_str();
  264. serializationOpts.SerializeAllSIL = true;
  265. serializationOpts.IsSIB = true;
  266. serialize(CI.getMainModule(), serializationOpts, CI.getSILModule());
  267. } else {
  268. const StringRef OutputFile = OutputFilename.size() ?
  269. StringRef(OutputFilename) : "-";
  270. if (OutputFile == "-") {
  271. CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(),
  272. EnableSILSortOutput, !DisableASTDump);
  273. } else {
  274. std::error_code EC;
  275. llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None);
  276. if (EC) {
  277. llvm::errs() << "while opening '" << OutputFile << "': "
  278. << EC.message() << '\n';
  279. return 1;
  280. }
  281. CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(),
  282. EnableSILSortOutput, !DisableASTDump);
  283. }
  284. }
  285. bool HadError = CI.getASTContext().hadError();
  286. // If we're in -verify mode, we've buffered up all of the generated
  287. // diagnostics. Check now to ensure that they meet our expectations.
  288. if (VerifyMode) {
  289. HadError = verifyDiagnostics(CI.getSourceMgr(), CI.getInputBufferIDs());
  290. DiagnosticEngine &diags = CI.getDiags();
  291. if (diags.hasFatalErrorOccurred() &&
  292. !Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) {
  293. diags.resetHadAnyError();
  294. diags.diagnose(SourceLoc(), diag::verify_encountered_fatal);
  295. HadError = true;
  296. }
  297. }
  298. return HadError;
  299. }