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 namespace logging::debug {
23 inline const DebugStream CodeGen("codegen");
24 } // namespace logging::debug
25 
26 class Node;
27 class Unit;
28 
29 namespace detail {
30 
31 namespace codegen {
32 enum class TypeUsage { Storage, CopyParameter, InParameter, InOutParameter, FunctionResult, Ctor, None };
33 
34 struct CxxTypes {
35  std::optional<cxx::Type> base_type;
36  std::optional<cxx::Type> storage;
37  std::optional<cxx::Type> result;
38  std::optional<cxx::Type> param_copy;
39  std::optional<cxx::Type> param_in;
40  std::optional<cxx::Type> param_inout;
41  std::optional<cxx::Type> ctor;
42  std::optional<cxx::Expression> default_;
43 };
44 
46 struct CxxTypeInfo {
47  bool predefined;
50  std::optional<cxx::declaration::Constant> forward;
51  std::optional<cxx::declaration::Constant> declaration;
52 };
53 
54 } // namespace codegen
55 
60 class CodeGen {
61 public:
62  CodeGen(const std::shared_ptr<Context>& context) : _context(context) {}
63 
65  Result<cxx::Unit> compileModule(Node& root, hilti::Unit* hilti_unit,
66  bool include_implementation); // NOLINT(google-runtime-references)
67 
69  Result<cxx::Unit> linkUnits(const std::vector<cxx::linker::MetaData>& mds);
70 
71  std::shared_ptr<Context> context() const { return _context.lock(); }
72  const Options& options() const { return context()->options(); }
73 
74  // These must be called only while a module is being compiled.
75  std::optional<cxx::declaration::Type> typeDeclaration(const hilti::Type& t);
76  std::list<cxx::declaration::Type> typeDependencies(const hilti::Type& t);
77  cxx::Type compile(const hilti::Type& t, codegen::TypeUsage usage);
78  cxx::Expression compile(const hilti::Expression& e, bool lhs = false);
79  cxx::Expression compile(const hilti::Ctor& c, bool lhs = false);
80  cxx::Expression compile(const hilti::expression::ResolvedOperator& o, bool lhs = false);
81  cxx::Block compile(const hilti::Statement& s, cxx::Block* b = nullptr);
82  cxx::declaration::Function compile(const ID& id, type::Function ft, declaration::Linkage linkage,
83  function::CallingConvention cc = function::CallingConvention::Standard,
84  const std::optional<AttributeSet>& fattrs = {},
85  std::optional<cxx::ID> namespace_ = {});
86  std::vector<cxx::Expression> compileCallArguments(const hilti::node::Range<Expression>& args,
88  std::vector<cxx::Expression> compileCallArguments(const hilti::node::Range<Expression>& args,
90  std::optional<cxx::Expression> typeDefaultValue(const hilti::Type& t);
91  codegen::TypeUsage parameterKindToTypeUsage(declaration::parameter::Kind);
92 
93  cxx::Expression typeInfo(const hilti::Type& t);
94  void addTypeInfoDefinition(const hilti::Type& t);
95 
96  cxx::Expression coerce(const cxx::Expression& e, const Type& src, const Type& dst); // only for supported coercions
97  cxx::Expression pack(const Expression& data, const std::vector<Expression>& args);
98  cxx::Expression pack(const hilti::Type& t, const cxx::Expression& data, const std::vector<cxx::Expression>& args);
99  cxx::Expression unpack(const hilti::Type& t, const Expression& data, const std::vector<Expression>& args,
100  bool throw_on_error);
101  cxx::Expression unpack(const hilti::Type& t, const cxx::Expression& data, const std::vector<cxx::Expression>& args,
102  bool throw_on_error);
103  void addDeclarationFor(const hilti::Type& t) { _need_decls.push_back(t); }
104 
105  cxx::Expression addTmp(const std::string& prefix, const cxx::Type& t);
106  cxx::Expression addTmp(const std::string& prefix, const cxx::Expression& init);
107 
116  cxx::ID uniqueID(const std::string& prefix, const Node& n);
117 
118  cxx::Expression self() const { return _self.back(); }
119  cxx::Expression dollardollar() const {
120  return {"__dd", cxx::Side::LHS};
121  } // TODO(robin): We hardcode the currently; need a stack, too?
122  void pushSelf(detail::cxx::Expression e) { _self.push_back(std::move(e)); }
123  void popSelf() { _self.pop_back(); }
124 
125  auto cxxBlock() const { return ! _cxx_blocks.empty() ? _cxx_blocks.back() : nullptr; }
126  void pushCxxBlock(cxx::Block* b) { _cxx_blocks.push_back(b); }
127  void popCxxBlock() { _cxx_blocks.pop_back(); }
128 
129  void enablePrioritizeTypes() { ++_prioritize_types; }
130  void disablePrioritizeTypes() { --_prioritize_types; }
131  bool prioritizeTypes() const { return _prioritize_types > 0; }
132 
133  cxx::Unit* unit() const; // will abort if not compiling a module.
134  hilti::Unit* hiltiUnit() const; // will abort if not compiling a module.
135 
136 private:
137  const codegen::CxxTypeInfo& _getOrCreateTypeInfo(const hilti::Type& t);
138 
139  // Adapt expression so that it can be used as a LHS. If expr is already a
140  // LHS, it's returned directly. Otherwise it assigns it over into a
141  // temporary, which is then returned.
142  cxx::Expression _makeLhs(cxx::Expression expr, const Type& type);
143 
144  std::unique_ptr<cxx::Unit> _cxx_unit;
145  hilti::Unit* _hilti_unit = nullptr;
146  std::weak_ptr<Context> _context;
147  std::vector<detail::cxx::Expression> _self = {{"__self", cxx::Side::LHS}};
148  std::vector<detail::cxx::Block*> _cxx_blocks;
149  std::vector<detail::cxx::declaration::Local> _tmps;
150  std::map<std::string, int> _tmp_counters;
151  std::vector<hilti::Type> _need_decls;
154  hilti::util::Cache<cxx::ID, cxx::declaration::Type> _cache_types_declarations;
155  int _prioritize_types = 0;
156 };
157 
158 } // namespace detail
159 } // namespace hilti
Definition: function.h:71
Definition: codegen.h:34
Definition: elements.h:223
Definition: node.h:37
Definition: context.h:33
bool predefined
Definition: codegen.h:47
std::optional< cxx::declaration::Constant > declaration
Definition: codegen.h:51
cxx::Expression reference
Definition: codegen.h:49
Definition: unit.h:65
Definition: codegen.h:46
Definition: type.h:160
Definition: node.h:40
Definition: cache.h:15
Definition: unit.h:49
Definition: elements.h:69
std::optional< cxx::declaration::Constant > forward
Definition: codegen.h:50
Definition: elements.h:91
Definition: node.h:111
Definition: codegen.h:60
Definition: id.h:18
Definition: result.h:67