Spicy
unit.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <iostream>
6 #include <list>
7 #include <map>
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <tuple>
12 #include <utility>
13 #include <vector>
14 
15 #include <hilti/rt/filesystem.h>
16 #include <hilti/rt/json-fwd.h>
17 #include <hilti/rt/types/reference.h>
18 
19 #include <hilti/ast/ctor.h>
20 #include <hilti/ast/expression.h>
21 #include <hilti/ast/module.h>
22 #include <hilti/ast/operator.h>
23 #include <hilti/ast/statement.h>
24 #include <hilti/ast/type.h>
25 #include <hilti/ast/types/function.h>
26 #include <hilti/base/result.h>
27 #include <hilti/compiler/context.h>
28 #include <hilti/compiler/detail/cxx/elements.h>
29 #include <hilti/compiler/detail/cxx/formatter.h>
30 
31 namespace hilti::detail::cxx {
32 
33 class Linker;
34 
35 namespace linker {
36 
38 
45 struct Join {
48  std::list<cxx::declaration::Type>
50  int64_t priority =
51  0;
52  bool declare_only = false;
54  bool operator<(const Join& other) const {
55  return std::make_tuple(id, priority, callee.id) < std::make_tuple(other.id, other.priority, other.callee.id);
56  }
57 };
58 
59 extern void to_json(nlohmann::json& j, const Join& x); // NOLINT
60 extern void from_json(const nlohmann::json& j, Join& x); // NOLINT
61 
62 } // namespace linker
63 
65 class Unit {
66 public:
67  Unit(const std::shared_ptr<Context>& context);
68 
69  void setModule(const hilti::Module& m, const hilti::Unit& hilti_unit);
70  cxx::ID moduleID() const { return _module_id; }
71 
72  void setUsesGlobals() { _uses_globals = true; }
73 
74  void add(const declaration::IncludeFile& i, const Meta& m = Meta());
75  void add(const declaration::Global& g, const Meta& m = Meta());
76  void add(const declaration::Constant& c, const Meta& m = Meta());
77  void add(const declaration::Type& t, const Meta& m = Meta());
78  void add(const declaration::Function& f, const Meta& m = Meta());
79  void add(const Function& f, const Meta& m = Meta());
80  void add(const std::string& stmt, const Meta& m = Meta()); // add generic top-level item
81  void add(const linker::Join& f);
82 
83  // Prioritize type with given ID to be written out so that others
84  // depending on it will have it available.
85  void prioritizeType(const cxx::ID& id) {
86  if ( std::find(_types_in_order.begin(), _types_in_order.end(), id) == _types_in_order.end() )
87  _types_in_order.push_back(id);
88  }
89 
90  bool hasDeclarationFor(const cxx::ID& id);
91  std::optional<cxx::declaration::Type> lookupType(const cxx::ID& id) const;
92 
93  void addComment(const std::string& comment);
94  void addInitialization(cxx::Block block) { _init_module.appendFromBlock(std::move(block)); }
95  void addPreInitialization(cxx::Block block) { _preinit_module.appendFromBlock(std::move(block)); }
96 
97  Result<Nothing> finalize();
98 
99  Result<Nothing> print(std::ostream& out) const; // only after finalize
100  Result<Nothing> createPrototypes(std::ostream& out); // only after finalize
101  void importDeclarations(const Unit& other); // only after finalize
102  Result<linker::MetaData> linkerMetaData() const; // only after finalize
103  cxx::ID cxxNamespace() const;
104 
105  std::shared_ptr<Context> context() const { return _context.lock(); }
106 
107  static std::pair<bool, std::optional<linker::MetaData>> readLinkerMetaData(std::istream& input);
108 
109 protected:
110  friend class Linker;
111  Unit(const std::shared_ptr<Context>& context, cxx::ID module_id);
112  Unit(const std::shared_ptr<Context>& context, cxx::ID module_id, const std::string& cxx_code);
113 
114 private:
115  void _generateCode(Formatter& f, bool prototypes_only);
116  void _addHeader(Formatter& f);
117  void _addModuleInitFunction();
118 
119  std::weak_ptr<Context> _context;
120 
121  cxx::ID _module_id;
122  hilti::rt::filesystem::path _module_path;
123  bool _no_linker_meta_data = false;
124  bool _uses_globals = false;
125 
126  std::optional<std::string> _cxx_code;
127 
128  std::vector<std::string> _comments;
129  std::set<declaration::IncludeFile> _includes;
130  std::map<ID, declaration::Type> _types;
131  std::vector<ID> _types_in_order;
132  std::map<ID, declaration::Type> _types_forward;
133  std::map<ID, declaration::Global> _globals;
134  std::map<ID, declaration::Constant> _constants;
135  std::map<ID, declaration::Constant> _constants_forward;
136  std::multimap<ID, declaration::Function> _function_declarations;
137  std::multimap<ID, Function> _function_implementations;
138  std::vector<std::string> _statements;
139  std::set<linker::Join> _linker_joins; // set to keep sorted.
140  std::set<std::string> _namespaces; // set to keep sorted.
141  std::set<ID> _ids;
142 
143  cxx::Block _init_module;
144  cxx::Block _preinit_module;
145  cxx::Block _init_globals;
146 };
147 
148 } // namespace hilti::detail::cxx
Definition: formatter.h:16
Definition: elements.h:198
std::list< cxx::declaration::Type > aux_types
Definition: unit.h:49
Definition: elements.h:121
Definition: unit.h:65
Definition: meta.h:19
Definition: elements.h:18
cxx::ID id
Definition: unit.h:46
cxx::declaration::Function callee
Definition: unit.h:47
Definition: reference.h:47
Definition: unit.h:49
Definition: linker.h:28
Definition: elements.h:66
Definition: module.h:21
bool declare_only
Definition: unit.h:52
Definition: elements.h:274
Definition: elements.h:154
int64_t priority
Definition: unit.h:50
Definition: result.h:67