Cthulhu  0.2.10
Cthulhu compiler collection
main.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-3.0-only
2 
3 #include "base/panic.h"
4 #include "setup/setup.h"
5 #include "setup/memory.h"
6 #include "format/colour.h"
7 #include "format/notify.h"
8 #include "base/log.h"
10 #include "cthulhu/broker/broker.h"
11 
12 #include "cthulhu/ssa/ssa.h"
13 #include "cthulhu/check/check.h"
14 
15 #include "io/console.h"
16 #include "notify/notify.h"
17 #include "scan/node.h"
18 #include "support/loader.h"
19 
20 #include "arena/arena.h"
21 
22 #include "std/map.h"
23 #include "std/str.h"
24 #include "std/vector.h"
25 
26 #include "core/macros.h"
27 
28 #include "fs/fs.h"
29 #include "io/io.h"
30 
31 #include "argparse/argparse.h"
32 #include "support/support.h"
33 
34 static const frontend_t kFrontendInfo = {
35  .info = {
36  .id = "frontend/example",
37  .name = "Example Frontend",
38  .version = {
39  .license = "GPLv3",
40  .desc = "Example compiler frontend",
41  .author = "Elliot Haisley",
42  .version = CT_NEW_VERSION(0, 0, 1),
43  }
44  }
45 };
46 
47 static int check_reports(logger_t *logger, report_config_t config, const char *title)
48 {
49  int err = text_report(logger_get_events(logger), config, title);
50  logger_reset(logger);
51 
52  if (err != CT_EXIT_OK)
53  {
54  return err;
55  }
56 
57  return 0;
58 }
59 
60 #define CHECK_LOG(logger, fmt) \
61  do \
62  { \
63  int err = check_reports(logger, report_config, fmt); \
64  if (err != CT_EXIT_OK) \
65  { \
66  return err; \
67  } \
68  } while (0)
69 
70 static io_t *make_file(logger_t *reports, const char *path, os_access_t flags, arena_t *arena)
71 {
72  io_t *io = io_file(path, flags, arena);
73  os_error_t err = io_error(io);
74  if (err != 0)
75  {
76  event_builder_t id = msg_notify(reports, &kEvent_FailedToOpenSourceFile, NULL, "failed to open `%s`", path);
77  msg_note(id, "%s", os_error_string(err, arena));
78  return NULL;
79  }
80 
81  return io;
82 }
83 
84 int main(int argc, const char **argv)
85 {
86  setup_default(NULL);
87 
88  ctu_log_update(true);
89  arena_t *arena = ctu_default_alloc();
90  node_t *node = node_builtin("example-frontend", arena);
91  broker_t *broker = broker_new(&kFrontendInfo, arena);
92  logger_t *logger = broker_get_logger(broker);
93 
94  loader_t *loader = loader_new(arena);
95  support_t *support = support_new(broker, loader, arena);
97 
98  io_t *con = io_stdout();
99 
100  text_config_t text_config = {
101  .config = {
102  .zeroth_line = false,
103  },
104  .colours = &kColourDefault,
105  .io = con,
106  };
107 
108  report_config_t report_config = {
110  .text_config = text_config,
111  };
112 
113  CHECK_LOG(logger, "adding languages");
114 
115  for (int i = 1; i < argc; i++)
116  {
117  const char *path = argv[i];
118 
119  // detect language by file extension
120  const char *ext = str_ext(path, arena);
121  language_runtime_t *lang = support_get_lang(support, ext);
122  if (lang == NULL)
123  {
124  io_printf(con, "no language found for file: %s\n", path);
125  }
126 
127  io_t *io = make_file(logger, path, eOsAccessRead, arena);
128  if (io != NULL)
129  {
130  broker_parse(lang, io);
131  }
132 
133  CHECK_LOG(logger, "parsing source");
134  }
135 
136  for (size_t pass = 0; pass < ePassCount; pass++)
137  {
138  broker_run_pass(broker, pass);
139 
140  char *msg = str_format(arena, "running compilation pass %s", broker_pass_name(pass));
141  CHECK_LOG(logger, msg);
142  }
143 
144  broker_resolve(broker);
145  CHECK_LOG(logger, "resolving symbols");
146 
147  vector_t *modmap = broker_get_modules(broker);
148 
149  check_tree(logger, modmap, arena);
150  CHECK_LOG(logger, "checking tree");
151 
152  ssa_result_t ssa = ssa_compile(modmap, arena);
153  CHECK_LOG(logger, "generating ssa");
154 
155  ssa_opt(logger, ssa, arena);
156  CHECK_LOG(logger, "optimizing ssa");
157 
158  fs_t *fs = fs_virtual("out", arena);
159 
160  target_emit_t emit = {
161  .layout = eFileLayoutFlat,
162  .fs = fs,
163  };
164 
165  target_runtime_t *debug = support_get_target(support, "debug");
166  target_runtime_t *cfamily = support_get_target(support, "cfamily");
167 
168  CTASSERT(debug != NULL);
169  CTASSERT(cfamily != NULL);
170 
171  target_emit_ssa(debug, &ssa, &emit);
172  CHECK_LOG(logger, "emitting debug ssa");
173 
174  emit_result_t cfamily_result = target_emit_ssa(cfamily, &ssa, &emit);
175  CHECK_LOG(logger, "emitting cfamily ssa");
176 
177  size_t len = vector_len(cfamily_result.files);
178  for (size_t i = 0; i < len; i++)
179  {
180  const char *path = vector_get(cfamily_result.files, i);
181  io_printf(con, "%s\n", path);
182  }
183 
184  fs_t *out = fs_physical("out", arena);
185  if (out == NULL)
186  {
187  msg_notify(logger, &kEvent_FailedToCreateOutputDirectory, node, "failed to create output directory");
188  }
189  CHECK_LOG(logger, "creating output directory");
190 
191  sync_result_t result = fs_sync(out, fs);
192  if (result.path != NULL)
193  {
194  msg_notify(logger, &kEvent_FailedToWriteOutputFile, node, "failed to sync %s", result.path);
195  }
196  CHECK_LOG(logger, "syncing output directory");
197 }
CT_NODISCARD STA_RET_STRING CT_OS_API char * os_error_string(os_error_t error, arena_t *arena)
convert an os error code to a string
Definition: os.c:56
os_access_t
file access mode
Definition: core.h:38
int main(int argc, const char **argv)
Definition: main.c:168
#define CHECK_LOG(logger, fmt)
Definition: main.c:60
CT_BROKER_API emit_result_t target_emit_ssa(target_runtime_t *runtime, const ssa_result_t *ssa, target_emit_t *emit)
Definition: broker.c:579
CT_BROKER_API void broker_parse(language_runtime_t *runtime, io_t *io)
Definition: broker.c:376
CT_BROKER_API void broker_run_pass(broker_t *broker, broker_pass_t pass)
Definition: broker.c:419
CT_BROKER_API void broker_resolve(broker_t *broker)
Definition: broker.c:450
CT_BROKER_API broker_t * broker_new(const frontend_t *frontend, arena_t *arena)
Definition: broker.c:130
CT_CONSTFN CT_BROKER_API const char * broker_pass_name(broker_pass_t pass)
extra stuff
Definition: broker.c:597
CT_BROKER_API vector_t * broker_get_modules(broker_t *broker)
get all the modules in the broker this does not include the root module
Definition: broker.c:362
CT_BROKER_API logger_t * broker_get_logger(broker_t *broker)
Definition: broker.c:325
@ ePassCount
Definition: broker.h:60
CT_BEGIN_API CT_CHECK_API void check_tree(logger_t *reports, vector_t *mods, arena_t *arena)
check the tree form IR all found errors are reported to the reports object
Definition: tree.c:1071
CT_FORMAT_API const colour_pallete_t kColourDefault
a colour pallete that applies ANSI VT100 colours
Definition: colour.c:24
#define CT_NEW_VERSION(major, minor, patch)
creates a new ctu_version_t from major, minor and patch
Definition: version_def.h:20
#define CT_EXIT_OK
no user errors or internal errors
Definition: macros.h:91
CT_NODISCARD CT_FS_API fs_t * fs_virtual(const char *name, arena_t *arena)
create a virtual filesystem interface
Definition: virtual.c:273
CT_NODISCARD CT_FS_API fs_t * fs_physical(const char *root, arena_t *arena)
create a filesystem interface to a physical location on disk
Definition: physical.c:215
CT_FS_API sync_result_t fs_sync(fs_t *dst, fs_t *src)
synchronize 2 filesystems copies all folders and files from src to dst
Definition: fs.c:511
CT_NODISCARD CT_IO_API io_t * io_file(const char *path, os_access_t mode, arena_t *arena)
create an IO object from a file
Definition: file.c:125
CT_NODISCARD CT_IO_API os_error_t io_error(const io_t *io)
get the last error from the io object
Definition: io.c:144
CT_IO_API io_t * io_stdout(void)
get the global stdout IO object
Definition: console.c:60
CT_IO_API size_t io_printf(io_t *io, STA_FORMAT_STRING const char *fmt,...)
printf to an io object
CT_SUPPORT_API language_runtime_t * support_get_lang(support_t *support, const char *ext)
Definition: support.c:176
CT_SUPPORT_API void support_load_default_modules(support_t *support)
load all default modules
Definition: support.c:139
CT_SUPPORT_API target_runtime_t * support_get_target(support_t *support, const char *name)
Definition: support.c:192
CT_SUPPORT_API support_t * support_new(broker_t *broker, loader_t *loader, arena_t *arena)
create a support instance from an existing loader and broker configures the broker with the modules i...
Definition: support.c:113
CT_NODISCARD CT_SCAN_API node_t * node_builtin(const char *name, arena_t *arena)
get the builtin node node used for drivers that declare builtin symbols
Definition: node.c:11
CT_BASE_API void ctu_log_update(bool enable)
update the verbosity of the logging system
Definition: log.c:15
CT_NOTIFY_API event_builder_t msg_notify(INOUT_NOTNULL logger_t *logs, const diagnostic_t *diagnostic, const node_t *node, STA_FORMAT_STRING const char *fmt,...)
notify the logger of a new message
CT_NOTIFY_API void logger_reset(logger_t *logs)
reset the loggers messages
Definition: notify.c:89
CT_NOTIFY_API void msg_note(event_builder_t builder, STA_FORMAT_STRING const char *fmt,...)
add a note to an existing message
CT_NODISCARD CT_NOTIFY_API typevec_t * logger_get_events(const logger_t *logs)
get the events from the logger
Definition: notify.c:36
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
CT_SETUP_API void setup_default(arena_t *arena)
initialise the runtime with default options
Definition: setup.c:188
CT_BEGIN_API CT_SETUP_API arena_t * ctu_default_alloc(void)
get the default allocator
Definition: memory.c:43
CT_SSA_API void ssa_opt(logger_t *reports, ssa_result_t mod, arena_t *arena)
Optimize a given module.
Definition: opt.c:359
CT_SSA_API ssa_result_t ssa_compile(vector_t *mods, arena_t *arena)
compile a set of trees into their ssa form
Definition: ssa.c:911
CT_NODISCARD CT_STD_API char * str_ext(const char *path, arena_t *arena)
get the last file extension from a path
Definition: str.c:173
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
Definition: vector.c:134
CT_NODISCARD CT_PUREFN CT_STD_API size_t vector_len(const vector_t *vector)
get the length of a vector
Definition: vector.c:152
CT_SUPPORT_API loader_t * loader_new(arena_t *arena)
Definition: loader.c:41
STA_DECL char * str_format(arena_t *arena, const char *fmt,...)
Definition: str.c:97
an allocator object
Definition: arena.h:86
vector_t * files
Definition: broker.h:224
an event builder handles adding additional information to an event
Definition: notify.h:68
bool zeroth_line
the zeroth line of a file is the first line
Definition: notify.h:51
the frontend running the mediator
Definition: broker.h:251
module_info_t info
information about the frontend
Definition: broker.h:253
Definition: common.h:72
io object implementation
Definition: impl.h:122
Definition: common.h:8
a logging sink
Definition: notify.c:14
const char * id
unique id for the module
Definition: broker.h:101
a position in a source file
Definition: node.h:23
text_format_t report_format
Definition: notify.h:92
the result of a fs_sync call this is here because we cant use Compiler message notification in the fs...
Definition: fs.h:116
const char * path
the file that failed to sync
Definition: fs.h:119
file_layout_t layout
Definition: broker.h:309
file_config_t config
Definition: notify.h:75
a generic vector of pointers
Definition: vector.c:16
CT_FORMAT_API int text_report(typevec_t *events, report_config_t config, const char *title)
Definition: common_extra.c:416
@ eTextSimple
simple text reporting
Definition: notify.h:63