Spicy
driver.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <fstream>
6 #include <iostream>
7 #include <memory>
8 #include <set>
9 #include <string>
10 #include <string_view>
11 #include <unordered_map>
12 #include <utility>
13 #include <vector>
14 
15 #include <hilti/rt/filesystem.h>
16 
17 #include <hilti/base/logger.h>
18 #include <hilti/base/result.h>
19 #include <hilti/base/timing.h>
20 #include <hilti/compiler/context.h>
21 #include <hilti/compiler/unit.h>
22 
23 namespace hilti {
24 
25 class JIT;
26 struct Options;
27 
28 namespace driver {
29 
31 enum class Dependencies {
32  None,
33  All,
34  Code
35 };
36 
42 struct Options {
43  bool include_linker = false;
44  bool output_hilti = false;
45  bool output_prototypes = false;
46  bool output_cxx = false;
47  std::string output_cxx_prefix;
48  bool output_linker = false;
49  Dependencies output_dependencies = Dependencies::None;
50  bool execute_code = false;
51  bool show_backtraces = false;
52  bool abort_on_exceptions = false;
53  bool keep_tmps = false;
54  bool skip_dependencies = false;
55  bool report_resource_usage = false;
56  bool report_times = false;
57  bool dump_code = false;
58  bool global_optimizations = true;
59  std::vector<hilti::rt::filesystem::path>
61  hilti::rt::filesystem::path output_path;
62  std::unique_ptr<Logger>
65  Options() { logger = std::make_unique<Logger>(); }
66 };
67 
68 } // namespace driver
69 
82 class Driver {
83 public:
88  explicit Driver(std::string name);
89 
97  Driver(std::string name, const hilti::rt::filesystem::path& argv0);
98 
99  virtual ~Driver();
100 
101  Driver() = delete;
102  Driver(const Driver&) = delete;
103  Driver(Driver&&) noexcept = delete;
104  Driver& operator=(const Driver&) = delete;
105  Driver& operator=(Driver&&) noexcept = delete;
106 
117  Result<Nothing> parseOptions(int argc, char** argv);
118 
131  Result<Nothing> addInput(hilti::Module&& m, const hilti::rt::filesystem::path& path = "");
132 
145  Result<Nothing> addInput(const hilti::rt::filesystem::path& path);
146 
148  bool hasInputs() const {
149  return ! (_pending_units.empty() && _processed_units.empty() && _processed_paths.empty() &&
150  _libraries.empty() && _external_cxxs.empty());
151  }
152 
154  const auto& driverOptions() const { return _driver_options; }
155 
157  const auto& hiltiOptions() const { return _compiler_options; }
158 
164  void setDriverOptions(driver::Options options);
165 
171  void setCompilerOptions(hilti::Options options);
172 
179  Result<Nothing> initialize();
180 
188  Result<Nothing> compile();
189 
193  Result<Nothing> transformUnits();
194 
199  auto context() const { return _ctx; }
200 
210  Result<Nothing> initRuntime();
211 
218  Result<Nothing> executeMain();
219 
226  Result<Nothing> finishRuntime();
227 
236  Result<Nothing> run();
237 
238 protected:
243  void usage();
244 
250  Result<Nothing> compileUnits();
251 
259  Result<Nothing> codegenUnits();
260 
266  Result<Nothing> linkUnits();
267 
273  Result<Nothing> outputUnits();
274 
280  Result<Nothing> jitUnits();
281 
290  result::Error error(std::string_view msg, const hilti::rt::filesystem::path& p = "");
291 
300  result::Error augmentError(const result::Error& err, const hilti::rt::filesystem::path& p = "");
301 
310  Result<std::ofstream> openOutput(const hilti::rt::filesystem::path& p, bool binary = false, bool append = false);
311 
319  Result<Nothing> openInput(std::ifstream& in, const hilti::rt::filesystem::path& p);
320 
328  Result<Nothing> writeOutput(std::ifstream& in, const hilti::rt::filesystem::path& p);
329 
336  Result<std::stringstream> readInput(const hilti::rt::filesystem::path& p);
337 
346  Result<hilti::rt::filesystem::path> writeToTemp(std::ifstream& in, const std::string& name_hint,
347  const std::string& extension = "tmp");
348 
350  void dumpUnit(const Unit& unit);
351 
357  void printHiltiException(const hilti::rt::Exception& e);
358 
363  virtual std::string hookAddCommandLineOptions() { return ""; }
364 
366  virtual bool hookProcessCommandLineOption(char opt, const char* optarg) { return false; }
367 
372  virtual std::string hookAugmentUsage() { return ""; }
373 
378  virtual void hookAddInput(const hilti::rt::filesystem::path& path) {}
379 
384  virtual void hookAddInput(const hilti::Module& m, const hilti::rt::filesystem::path& path) {}
385 
391  virtual void hookNewASTPreCompilation(const ID& name, const std::optional<hilti::rt::filesystem::path>& path,
392  const Node& root) {}
393 
399  virtual void hookNewASTPostCompilation(const ID& name, const std::optional<hilti::rt::filesystem::path>& path,
400  const Node& root) {}
401 
411 
416  virtual void hookInitRuntime() {}
417 
422  virtual void hookFinishRuntime() {}
423 
424 private:
425  // Tracking the state of the compilation pipeline to catch out of order
426  // operation.
427  enum Stage { UNINITIALIZED, INITIALIZED, COMPILED, CODEGENED, LINKED, JITTED } _stage = UNINITIALIZED;
428 
429  void _addUnit(Unit unit);
430  Result<Nothing> _compileUnit(Unit unit);
431 
438  static Result<void*> _symbol(const std::string& symbol);
439 
440  std::string _name;
441  driver::Options _driver_options;
442  hilti::Options _compiler_options;
443 
444  std::vector<Unit> _pending_units;
445 
446  std::set<hilti::ID> _processed_units;
447  std::set<hilti::rt::filesystem::path> _processed_paths;
448 
449  std::shared_ptr<Context> _ctx; // driver's compiler context
450  std::unique_ptr<hilti::JIT> _jit; // driver's JIT instance
451  std::shared_ptr<const hilti::rt::Library> _library; // Compiled code
452 
453  std::vector<CxxCode> _generated_cxxs;
454  std::unordered_map<std::string, Library> _libraries;
455  std::vector<hilti::rt::filesystem::path> _external_cxxs;
456  std::vector<linker::MetaData> _mds;
457  std::vector<Unit> _hlts;
458 
459  bool _runtime_initialized = false; // true once initRuntime() has succeeded
460  std::set<std::string> _tmp_files; // all tmp files created, so that we can clean them up.
461 };
462 
463 } // namespace hilti
virtual void hookAddInput(const hilti::rt::filesystem::path &path)
Definition: driver.h:378
std::unique_ptr< Logger > logger
Definition: driver.h:63
Definition: result.h:18
Definition: context.h:32
const auto & driverOptions() const
Definition: driver.h:154
virtual std::string hookAugmentUsage()
Definition: driver.h:372
virtual void hookNewASTPreCompilation(const ID &name, const std::optional< hilti::rt::filesystem::path > &path, const Node &root)
Definition: driver.h:391
virtual Result< Nothing > hookCompilationFinished()
Definition: driver.h:410
virtual void hookInitRuntime()
Definition: driver.h:416
virtual bool hookProcessCommandLineOption(char opt, const char *optarg)
Definition: driver.h:366
bool hasInputs() const
Definition: driver.h:148
auto context() const
Definition: driver.h:199
virtual void hookAddInput(const hilti::Module &m, const hilti::rt::filesystem::path &path)
Definition: driver.h:384
virtual void hookFinishRuntime()
Definition: driver.h:422
hilti::rt::filesystem::path output_path
Definition: driver.h:61
Definition: driver.h:82
virtual std::string hookAddCommandLineOptions()
Definition: driver.h:363
Definition: unit.h:43
Definition: module.h:20
Definition: node.h:97
const auto & hiltiOptions() const
Definition: driver.h:157
Definition: exception.h:21
Definition: result.h:57
std::string output_cxx_prefix
Definition: driver.h:47
Definition: id.h:18
Definition: result.h:67
virtual void hookNewASTPostCompilation(const ID &name, const std::optional< hilti::rt::filesystem::path > &path, const Node &root)
Definition: driver.h:399
Definition: driver.h:42
std::vector< hilti::rt::filesystem::path > inputs
Definition: driver.h:60