Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
bootstrap.cpp
Go to the documentation of this file.
2
3#include <ranges>
4#include <sstream>
5
6#include "thorin/axiom.h"
7#include "thorin/driver.h"
8
9namespace thorin {
10
11void bootstrap(Driver& driver, Sym plugin, std::ostream& h) {
12 Tab tab;
13 tab.print(h, "#pragma once\n\n");
14 tab.print(h, "#include <thorin/axiom.h>\n"
15 "#include <thorin/plugin.h>\n\n");
16
17 tab.print(h, "/// @namespace thorin::plug::{} @ref {} \n", plugin, plugin);
18 tab.print(h, "namespace thorin {{\n");
19 tab.print(h, "namespace plug::{} {{\n\n", plugin);
20
21 plugin_t plugin_id = *Annex::mangle(plugin);
22 std::vector<std::ostringstream> normalizers, outer_namespace;
23
24 tab.print(h << std::hex, "static constexpr plugin_t Plugin_Id = 0x{};\n\n", plugin_id);
25
26 const auto& unordered = driver.plugin2annxes(plugin);
27 std::deque<std::pair<Sym, Annex>> infos(unordered.begin(), unordered.end());
28 std::ranges::sort(infos, [&](const auto& p1, const auto& p2) { return p1.second.tag_id < p2.second.tag_id; });
29
30 // clang-format off
31 for (const auto& [key, ax] : infos) {
32 if (ax.plugin != plugin) continue; // this is from an import
33
34 tab.print(h, "/// @name %%{}.{}\n///@{{\n", plugin, ax.tag);
35 tab.print(h, "#ifdef DOXYGEN // see https://github.com/doxygen/doxygen/issues/9668\n");
36 tab.print(h, "enum {} : flags_t {{\n", ax.tag);
37 tab.print(h, "#else\n");
38 tab.print(h, "enum class {} : flags_t {{\n", ax.tag);
39 tab.print(h, "#endif\n");
40 ++tab;
41 flags_t ax_id = plugin_id | (ax.tag_id << 8u);
42
43 auto& os = outer_namespace.emplace_back();
44 print(os << std::hex, "template<> constexpr flags_t Annex::Base<plug::{}::{}> = 0x{};\n", plugin, ax.tag, ax_id);
45
46 if (auto& subs = ax.subs; !subs.empty()) {
47 for (const auto& aliases : subs) {
48 const auto& sub = aliases.front();
49 tab.print(h, "{} = 0x{},\n", sub, ax_id++);
50 for (size_t i = 1; i < aliases.size(); ++i) tab.print(h, "{} = {},\n", aliases[i], sub);
51
52 if (ax.normalizer)
53 print(normalizers.emplace_back(), "normalizers[flags_t({}::{})] = &{}<{}::{}>;", ax.tag, sub,
54 ax.normalizer, ax.tag, sub);
55 }
56 } else {
57 if (ax.normalizer)
58 print(normalizers.emplace_back(), "normalizers[flags_t(Annex::Base<{}>)] = &{};", ax.tag, ax.normalizer);
59 }
60 --tab;
61 tab.print(h, "}};\n\n");
62
63 if (!ax.subs.empty()) tab.print(h, "THORIN_ENUM_OPERATORS({})\n", ax.tag);
64 print(outer_namespace.emplace_back(), "template<> constexpr size_t Annex::Num<plug::{}::{}> = {};\n", plugin, ax.tag, ax.subs.size());
65
66 if (ax.normalizer) {
67 if (auto& subs = ax.subs; !subs.empty()) {
68 tab.print(h, "template<{}>\nRef {}(Ref, Ref, Ref);\n\n", ax.tag, ax.normalizer);
69 } else {
70 tab.print(h, "Ref {}(Ref, Ref, Ref);\n", ax.normalizer);
71 }
72 }
73 tab.print(h, "///@}}\n\n");
74 }
75 // clang-format on
76
77 if (!normalizers.empty()) {
78 tab.print(h, "void register_normalizers(Normalizers& normalizers);\n\n");
79 tab.print(h, "#define THORIN_{}_NORMALIZER_IMPL \\\n", plugin);
80 ++tab;
81 tab.print(h, "void register_normalizers(Normalizers& normalizers) {{\\\n");
82 ++tab;
83 for (const auto& normalizer : normalizers) tab.print(h, "{} \\\n", normalizer.str());
84 --tab;
85 tab.print(h, "}}\n");
86 --tab;
87 }
88
89 tab.print(h, "}} // namespace plug::{}\n\n", plugin);
90
91 tab.print(h, "#ifndef DOXYGEN // don't include in Doxygen documentation\n");
92 for (const auto& line : outer_namespace) tab.print(h, "{}", line.str());
93 tab.print(h, "\n");
94
95 // emit helpers for non-function axiom
96 for (const auto& [tag, ax] : infos) {
97 if (ax.pi || ax.plugin != plugin) continue; // from function or other plugin?
98 tab.print(h, "template<> struct Axiom::Match<plug::{}::{}> {{ using type = Axiom; }};\n", ax.plugin, ax.tag);
99 }
100
101 tab.print(h, "#endif\n");
102 tab.print(h, "}} // namespace thorin\n");
103}
104
105} // namespace thorin
Some "global" variables needed all over the place.
Definition driver.h:17
const auto & plugin2annxes(Sym plugin)
Definition driver.h:81
Keeps track of indentation level.
Definition print.h:184
std::ostream & print(std::ostream &os, const char *s, Args &&... args)
Definition print.h:200
Definition cfg.h:11
std::ostream & print(std::ostream &os, const char *s)
Base case.
Definition print.cpp:5
void bootstrap(Driver &, Sym, std::ostream &)
Definition bootstrap.cpp:11
u64 plugin_t
Definition types.h:47
u64 flags_t
Definition types.h:46
static std::optional< plugin_t > mangle(Sym s)
Mangles s into a dense 48-bit representation.
Definition plugin.cpp:9