Spicy
driver.h
1 // Copyright (c) 2020-now by the Zeek Project. See LICENSE for details.
2 // p
3 
4 #pragma once
5 
6 #include <fstream>
7 #include <iostream>
8 #include <map>
9 #include <memory>
10 #include <set>
11 #include <string>
12 #include <string_view>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <utility>
16 #include <vector>
17 
18 #include <hilti/rt/filesystem.h>
19 
20 #include <hilti/base/logger.h>
21 #include <hilti/base/result.h>
22 #include <hilti/base/timing.h>
23 #include <hilti/compiler/context.h>
24 #include <hilti/compiler/unit.h>
25 
26 namespace hilti {
27 
28 class JIT;
29 struct Options;
30 
31 namespace driver {
32 
34 enum class Dependencies {
35  None,
36  All,
37  Code
38 };
39 
45 struct Options {
46  bool include_linker = false;
47  bool output_hilti = false;
48  bool output_prototypes = false;
49  bool output_cxx = false;
50  std::string output_cxx_prefix;
51  bool output_linker = false;
52  Dependencies output_dependencies = Dependencies::None;
53  bool execute_code = false;
54  bool show_backtraces = false;
55  bool abort_on_exceptions = false;
56  bool keep_tmps = false;
57  bool skip_dependencies = false;
58  bool report_resource_usage = false;
59  bool report_times = false;
60  bool dump_code = false;
61  bool enable_profiling = false;
62  std::vector<hilti::rt::filesystem::path>
64  hilti::rt::filesystem::path output_path;
65  std::unique_ptr<Logger>
68  Options() { logger = std::make_unique<Logger>(); }
69 };
70 
71 } // namespace driver
72 
85 class Driver {
86 public:
91  explicit Driver(std::string name);
92 
100  Driver(std::string name, const hilti::rt::filesystem::path& argv0);
101 
102  virtual ~Driver();
103 
104  Driver() = delete;
105  Driver(const Driver&) = delete;
106  Driver(Driver&&) noexcept = delete;
107  Driver& operator=(const Driver&) = delete;
108  Driver& operator=(Driver&&) noexcept = delete;
109 
120  Result<Nothing> parseOptions(int argc, char** argv);
121 
128  void registerUnit(const std::shared_ptr<Unit>& unit) { _addUnit(unit); }
129 
137  auto i = _units.find(uid);
138  return i != _units.end() ? i->second.get() : nullptr;
139  }
140 
151  void updateProcessExtension(const declaration::module::UID& uid, const hilti::rt::filesystem::path& ext);
152 
165  Result<Nothing> addInput(const hilti::rt::filesystem::path& path);
166 
178 
180  bool hasInputs() const { return ! (_units.empty() && _libraries.empty() && _external_cxxs.empty()); }
181 
183  const auto& driverOptions() const { return _driver_options; }
184 
186  const auto& hiltiOptions() const { return _compiler_options; }
187 
194 
201 
209 
218 
223  const auto& context() const { return _ctx; }
224 
229  auto* builder() const { return _builder.get(); }
230 
232  const auto& options() const { return _ctx->options(); }
233 
244 
252 
260 
266  void fatalError(const std::string& msg);
267 
274 
284 
285 protected:
286  friend class ASTContext;
287 
292  void usage();
293 
300 
309 
316 
323 
330 
339  result::Error error(std::string_view msg, const hilti::rt::filesystem::path& p = "");
340 
349  result::Error augmentError(const result::Error& err, const hilti::rt::filesystem::path& p = "");
350 
359  Result<std::ofstream> openOutput(const hilti::rt::filesystem::path& p, bool binary = false, bool append = false);
360 
368  Result<Nothing> openInput(std::ifstream& in, const hilti::rt::filesystem::path& p);
369 
377  Result<Nothing> writeOutput(std::ifstream& in, const hilti::rt::filesystem::path& p);
378 
385  Result<std::stringstream> readInput(const hilti::rt::filesystem::path& p);
386 
395  Result<hilti::rt::filesystem::path> writeToTemp(std::ifstream& in, const std::string& name_hint,
396  const std::string& extension = "tmp");
397 
399  void dumpUnit(const Unit& unit);
400 
407 
416  virtual std::unique_ptr<Builder> createBuilder(ASTContext* ctx) const;
417 
422  virtual std::string hookAddCommandLineOptions() { return ""; }
423 
425  virtual bool hookProcessCommandLineOption(int opt, const char* optarg) { return false; }
426 
431  virtual std::string hookAugmentUsage() { return ""; }
432 
437  virtual void hookAddInput(std::shared_ptr<Unit> unit) {} // NOLINT(performance-unnecessary-value-param)
438 
443  virtual void hookAddInput(const hilti::rt::filesystem::path& path) {}
444 
450  virtual void hookNewASTPreCompilation(const Plugin& plugin, ASTRoot* root) {}
451 
467  virtual bool hookNewASTPostCompilation(const Plugin& plugin, ASTRoot* root) { return false; }
468 
474 
479  virtual void hookInitRuntime() {}
480 
485  virtual void hookFinishRuntime() {}
486 
487 private:
488  // Tracking the state of the compilation pipeline to catch out of order
489  // operation.
490  enum Stage { UNINITIALIZED, INITIALIZED, COMPILED, CODEGENED, LINKED, JITTED } _stage = UNINITIALIZED;
491 
492  // Backend for adding a new unit.
493  void _addUnit(const std::shared_ptr<Unit>& unit);
494 
495  // Run a specific plugin's AST passes on all units with the corresponding extension.
496  Result<Nothing> _resolveUnitsWithPlugin(const Plugin& plugin, std::vector<std::shared_ptr<Unit>> units, int& round);
497 
498  // Runs a specific plugin's transform step on a given set of units.
499  Result<Nothing> _transformUnitsWithPlugin(const Plugin& plugin, const std::vector<std::shared_ptr<Unit>>& units);
500 
501  // Run all plugins on current units, iterating until finished.
502  Result<Nothing> _resolveUnits();
503 
504  // Turns all HILTI units into C++.
505  Result<Nothing> _codegenUnits();
506 
507  // Performs global transformations on the generated code.
508  Result<Nothing> _optimizeUnits();
509 
510  // Sends a debug dump of a unit's AST to the global logger.
511  void _dumpAST(const std::shared_ptr<Unit>& unit, const logging::DebugStream& stream, const Plugin& plugin,
512  const std::string& prefix, int round);
513 
514  // Sends a debug dump of a unit's AST to the global logger.
515  void _dumpAST(const std::shared_ptr<Unit>& unit, const logging::DebugStream& stream, const std::string& prefix);
516 
517  // Sends a debug dump of a unit's AST to an output stream.
518  void _dumpAST(const std::shared_ptr<Unit>& unit, std::ostream& stream, const Plugin& plugin,
519  const std::string& prefix, int round);
520 
521  // Records a reduced debug dump of a unit's AST limited to just declarations.
522  void _dumpDeclarations(const std::shared_ptr<Unit>& unit, const Plugin& plugin);
523 
524  // Records a debug dump of a unit's AST to disk.
525  void _saveIterationAST(const std::shared_ptr<Unit>& unit, const Plugin& plugin, const std::string& prefix,
526  int round);
527 
528  // Records a debug dump of a unit's AST to disk.
529  void _saveIterationAST(const std::shared_ptr<Unit>& unit, const Plugin& plugin, const std::string& prefix,
530  const std::string& tag);
531 
532  // Sets the C++ namespaces for generated code from -x/-P prefix options.
533  Result<Nothing> _setCxxNamespacesFromPrefix(const char* prefix);
534 
541  static Result<void*> _symbol(const std::string& symbol);
542 
543  std::string _name;
544  driver::Options _driver_options;
545  hilti::Options _compiler_options;
546 
547  std::shared_ptr<Context> _ctx; // driver's compiler context
548  std::unique_ptr<hilti::Builder> _builder; // driver builder tied to its context
549  std::unique_ptr<hilti::JIT> _jit; // driver's JIT instance
550  std::shared_ptr<const hilti::rt::Library> _library; // Compiled code
551 
552  std::map<declaration::module::UID, std::shared_ptr<Unit>> _units;
553  std::vector<CxxCode> _generated_cxxs;
554  std::unordered_map<std::string, Library> _libraries;
555  std::vector<hilti::rt::filesystem::path> _external_cxxs;
556  std::vector<linker::MetaData> _mds;
557 
558  std::unordered_set<std::string> _processed_paths;
559 
560  bool _runtime_initialized = false; // true once initRuntime() has succeeded
561  std::set<std::string> _tmp_files; // all tmp files created, so that we can clean them up.
562 };
563 
564 } // namespace hilti
Definition: ast-context.h:121
Definition: ast-context.h:494
Definition: driver.h:85
Result< Nothing > compileUnits()
Definition: driver.cc:685
result::Error error(std::string_view msg, const hilti::rt::filesystem::path &p="")
Definition: driver.cc:144
Result< Nothing > linkUnits()
Definition: driver.cc:805
result::Error augmentError(const result::Error &err, const hilti::rt::filesystem::path &p="")
Definition: driver.cc:153
virtual std::string hookAugmentUsage()
Definition: driver.h:431
virtual void hookNewASTPreCompilation(const Plugin &plugin, ASTRoot *root)
Definition: driver.h:450
void printHiltiException(const hilti::rt::Exception &e)
Definition: driver.cc:936
Result< std::stringstream > readInput(const hilti::rt::filesystem::path &p)
Definition: driver.cc:185
const auto & driverOptions() const
Definition: driver.h:183
bool hasInputs() const
Definition: driver.h:180
virtual void hookAddInput(std::shared_ptr< Unit > unit)
Definition: driver.h:437
virtual bool hookProcessCommandLineOption(int opt, const char *optarg)
Definition: driver.h:425
virtual Result< Nothing > hookCompilationFinished(ASTRoot *root)
Definition: driver.h:473
Result< Nothing > finishRuntime()
Definition: driver.cc:1019
Result< Nothing > codegenUnits()
Result< Nothing > outputUnits()
Definition: driver.cc:844
const auto & options() const
Definition: driver.h:232
const auto & hiltiOptions() const
Definition: driver.h:186
Result< Nothing > jitUnits()
Definition: driver.cc:902
Result< Nothing > compile()
Definition: driver.cc:760
Result< Nothing > executeMain()
Definition: driver.cc:990
void dumpUnit(const Unit &unit)
Definition: driver.cc:230
void fatalError(const std::string &msg)
Definition: driver.cc:1035
Result< std::ofstream > openOutput(const hilti::rt::filesystem::path &p, bool binary=false, bool append=false)
Definition: driver.cc:157
void usage()
Definition: driver.cc:88
virtual void hookAddInput(const hilti::rt::filesystem::path &path)
Definition: driver.h:443
void updateProcessExtension(const declaration::module::UID &uid, const hilti::rt::filesystem::path &ext)
Definition: driver.cc:511
virtual void hookInitRuntime()
Definition: driver.h:479
const auto & context() const
Definition: driver.h:223
virtual std::unique_ptr< Builder > createBuilder(ASTContext *ctx) const
Definition: driver.cc:955
Result< Nothing > run()
Definition: driver.cc:723
Result< Nothing > addInput(const hilti::rt::filesystem::path &path)
Definition: driver.cc:564
Result< Nothing > openInput(std::ifstream &in, const hilti::rt::filesystem::path &p)
Definition: driver.cc:176
virtual std::string hookAddCommandLineOptions()
Definition: driver.h:422
Unit * lookupUnit(const declaration::module::UID &uid) const
Definition: driver.h:136
auto * builder() const
Definition: driver.h:229
void setDriverOptions(driver::Options options)
Definition: driver.cc:504
Result< hilti::rt::filesystem::path > writeToTemp(std::ifstream &in, const std::string &name_hint, const std::string &extension="tmp")
Definition: driver.cc:210
Result< Nothing > initialize()
Definition: driver.cc:474
void setCompilerOptions(hilti::Options options)
Definition: driver.cc:497
Result< Nothing > writeOutput(std::ifstream &in, const hilti::rt::filesystem::path &p)
Definition: driver.cc:198
Result< Nothing > parseOptions(int argc, char **argv)
Definition: driver.cc:271
virtual bool hookNewASTPostCompilation(const Plugin &plugin, ASTRoot *root)
Definition: driver.h:467
void registerUnit(const std::shared_ptr< Unit > &unit)
Definition: driver.h:128
Result< Nothing > initRuntime()
Definition: driver.cc:957
virtual void hookFinishRuntime()
Definition: driver.h:485
Definition: unit.h:47
Definition: exception.h:22
Definition: result.h:71
Definition: result.h:18
Definition: context.h:33
Definition: plugin.h:52
Definition: module-uid.h:20
Definition: driver.h:45
bool enable_profiling
Definition: driver.h:61
bool report_resource_usage
Definition: driver.h:58
bool report_times
Definition: driver.h:59
bool execute_code
Definition: driver.h:53
bool output_linker
Definition: driver.h:51
bool output_cxx
Definition: driver.h:49
std::vector< hilti::rt::filesystem::path > inputs
Definition: driver.h:63
bool show_backtraces
Definition: driver.h:54
hilti::rt::filesystem::path output_path
Definition: driver.h:64
bool output_hilti
Definition: driver.h:47
bool dump_code
Definition: driver.h:60
std::unique_ptr< Logger > logger
Definition: driver.h:66
bool keep_tmps
Definition: driver.h:56
std::string output_cxx_prefix
Definition: driver.h:50
bool include_linker
Definition: driver.h:46
bool abort_on_exceptions
Definition: driver.h:55
Dependencies output_dependencies
Definition: driver.h:52
bool output_prototypes
Definition: driver.h:48
bool skip_dependencies
Definition: driver.h:57
Definition: result.h:57