Spicy
codegen.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <algorithm>
6 #include <list>
7 #include <map>
8 #include <memory>
9 #include <optional>
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 #include <hilti/ast/function.h>
15 #include <hilti/base/cache.h>
16 #include <hilti/compiler/context.h>
17 #include <hilti/compiler/detail/cxx/elements.h>
18 #include <hilti/compiler/detail/cxx/unit.h>
19 
20 namespace hilti {
21 
22 class Node;
23 class Unit;
24 
25 namespace detail {
26 
27 namespace codegen {
28 enum class TypeUsage { Storage, CopyParameter, InParameter, InOutParameter, FunctionResult, Ctor, None };
29 
30 struct CxxTypes {
31  std::optional<cxx::Type> base_type;
32  std::optional<cxx::Type> storage;
33  std::optional<cxx::Type> result;
34  std::optional<cxx::Type> param_copy;
35  std::optional<cxx::Type> param_in;
36  std::optional<cxx::Type> param_inout;
37  std::optional<cxx::Type> ctor;
38  std::optional<cxx::Expression> default_;
39 };
40 
42 struct CxxTypeInfo {
43  bool predefined;
46  std::optional<cxx::declaration::Constant> forward;
47  std::optional<cxx::declaration::Constant> declaration;
48 };
49 
50 } // namespace codegen
51 
56 class CodeGen {
57 public:
58  CodeGen(std::shared_ptr<Context> context) : _context(std::move(context)) {}
59 
61  Result<cxx::Unit> compileModule(Node& root, hilti::Unit* hilti_unit,
62  bool include_implementation); // NOLINT(google-runtime-references)
63 
65  Result<cxx::Unit> linkUnits(const std::vector<cxx::linker::MetaData>& mds);
66 
67  std::shared_ptr<Context> context() const { return _context.lock(); }
68  const Options& options() const { return context()->options(); }
69 
70  // These must be called only while a module is being compiled.
71  std::optional<cxx::declaration::Type> typeDeclaration(const hilti::Type& t);
72  std::list<cxx::declaration::Type> typeDependencies(const hilti::Type& t);
73  cxx::Type compile(const hilti::Type& t, codegen::TypeUsage usage);
74  cxx::Expression compile(const hilti::Expression& e, bool lhs = false);
75  cxx::Expression compile(const hilti::Ctor& c);
76  cxx::Expression compile(const hilti::expression::ResolvedOperator& o, bool lhs = false);
77  cxx::Block compile(const hilti::Statement& s, cxx::Block* b = nullptr);
78  cxx::declaration::Function compile(const ID& id, type::Function ft, declaration::Linkage linkage,
79  function::CallingConvention cc = function::CallingConvention::Standard,
80  const std::optional<AttributeSet>& fattrs = {},
81  std::optional<cxx::ID> namespace_ = {});
82  std::vector<cxx::Expression> compileCallArguments(const hilti::node::Range<Expression>& args,
84  std::vector<cxx::Expression> compileCallArguments(const hilti::node::Range<Expression>& args,
86  std::optional<cxx::Expression> typeDefaultValue(const hilti::Type& t);
87 
88  cxx::Expression typeInfo(const hilti::Type& t);
89  void addTypeInfoDefinition(const hilti::Type& t);
90 
91  cxx::Expression coerce(const cxx::Expression& e, const Type& src, const Type& dst); // only for supported coercions
92  cxx::Expression unpack(const hilti::Type& t, const Expression& data, const std::vector<Expression>& args);
93  cxx::Expression unpack(const hilti::Type& t, const cxx::Expression& data, const std::vector<cxx::Expression>& args);
94  void addDeclarationFor(const hilti::Type& t) { _need_decls.push_back(t); }
95 
96  cxx::Expression addTmp(const std::string& prefix, const cxx::Type& t);
97  cxx::Expression addTmp(const std::string& prefix, const cxx::Expression& init);
98 
107  cxx::ID uniqueID(const std::string& prefix, const Node& n);
108 
109  cxx::Expression self() const { return _selfs.back(); }
110  cxx::Expression dollardollar() const {
111  return "__dd";
112  } // TODO(robin): We hardcode the currently; need a stack, too?
113  void pushSelf(detail::cxx::Expression e) { _selfs.push_back(std::move(e)); }
114  void popSelf() { _selfs.pop_back(); }
115 
116  auto cxxBlock() const { return ! _cxx_blocks.empty() ? _cxx_blocks.back() : nullptr; }
117  void pushCxxBlock(cxx::Block* b) { _cxx_blocks.push_back(b); }
118  void popCxxBlock() { _cxx_blocks.pop_back(); }
119 
120  void enablePrioritizeTypes() { ++_prioritize_types; }
121  void disablePrioritizeTypes() { --_prioritize_types; }
122  bool prioritizeTypes() const { return _prioritize_types > 0; }
123 
124  cxx::Unit* unit() const; // will abort if not compiling a module.
125  hilti::Unit* hiltiUnit() const; // will abort if not compiling a module.
126 
127 private:
128  const codegen::CxxTypeInfo& _getOrCreateTypeInfo(const hilti::Type& t);
129 
130  std::unique_ptr<cxx::Unit> _cxx_unit;
131  hilti::Unit* _hilti_unit = nullptr;
132  std::weak_ptr<Context> _context;
133  std::vector<detail::cxx::Expression> _selfs = {"__self"};
134  std::vector<detail::cxx::Block*> _cxx_blocks;
135  std::vector<detail::cxx::declaration::Local> _tmps;
136  std::map<std::string, int> _tmp_counters;
137  std::vector<hilti::Type> _need_decls;
140  hilti::util::Cache<cxx::ID, cxx::declaration::Type> _cache_types_declarations;
141  int _prioritize_types = 0;
142 };
143 
144 } // namespace detail
145 } // namespace hilti
Definition: function.h:71
Definition: codegen.h:30
Definition: elements.h:177
Definition: elements.h:28
Definition: node.h:39
Definition: context.h:33
bool predefined
Definition: codegen.h:43
std::optional< cxx::declaration::Constant > declaration
Definition: codegen.h:47
cxx::Expression reference
Definition: codegen.h:45
Definition: unit.h:68
Definition: codegen.h:42
Definition: type.h:159
Definition: node.h:42
Definition: cache.h:15
Definition: unit.h:47
std::optional< cxx::declaration::Constant > forward
Definition: codegen.h:46
Definition: elements.h:66
Definition: node.h:113
Definition: codegen.h:56
Definition: id.h:18
Definition: result.h:67