Cthulhu  0.2.10
Cthulhu compiler collection
support.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "support/support.h"
4 
5 #include "arena/arena.h"
6 #include "base/panic.h"
7 
9 
10 #include "cthulhu/events/events.h"
11 #include "notify/notify.h"
12 #include "std/str.h"
13 #include "std/typed/vector.h"
14 #include "std/map.h"
15 #include "std/set.h"
16 #include <stdio.h>
17 
18 typedef struct support_t
19 {
23 
25 
27 
28  // map of extensions to the associated language runtime
29  // map_t<const char*, language_runtime_t*>
31 
32  // map_t<const char*, plugin_runtime_t*>
34 
35  // map_t<const char*, target_runtime_t*>
37 } support_t;
38 
39 static void add_loaded_module(support_t *support, loaded_module_t mod)
40 {
41  typevec_push(support->modules, &mod);
42 
43  logger_t *logger = broker_get_logger(support->broker);
44  const node_t *node = broker_get_node(support->broker);
45  if (mod.type & eModLanguage)
46  {
47  const language_t *lang = mod.lang;
48  CTASSERTF(lang != NULL, "language module is NULL");
49  const module_info_t *info = &lang->info;
50  CTASSERTF(info != NULL, "language info is NULL");
51  CTASSERTF_ALWAYS(str_startswith(info->id, "lang/"), "language id `%s` must start with `lang/`", info->id);
52 
53  const char *id = info->id + sizeof("lang/") - 1;
54 
55  if (map_contains(support->languages, id))
56  {
57  msg_notify(logger, &kEvent_LanguageDriverConflict, node, "%s already loaded", info->id);
58  }
59 
60  language_runtime_t *runtime = broker_add_language(support->broker, lang);
61  map_set(support->languages, id, runtime);
62 
63  for (size_t i = 0; lang->exts[i]; i++)
64  {
65  const char *ext = lang->exts[i];
66  const language_runtime_t *old = map_get(support->extmap, ext);
67  if (old != NULL)
68  {
69  const language_t *ol = old->info;
70  const module_info_t *prev = &ol->info;
71  msg_notify(logger, &kEvent_ExtensionConflict, node, "extension %s already associated with %s", ext, prev->id);
72  }
73  map_set(support->extmap, ext, runtime);
74  }
75  }
76 
77  if (mod.type & eModPlugin)
78  {
79  const plugin_t *plugin = mod.plugin;
80  const module_info_t *info = &plugin->info;
81  CTASSERTF_ALWAYS(str_startswith(info->id, "plugin/"), "plugin id `%s` must start with `plugin/`", info->id);
82 
83  const char *id = info->id + sizeof("plugin/") - 1;
84 
85  if (map_contains(support->plugins, id))
86  {
87  msg_notify(logger, &kEvent_PluginConflict, node, "%s already loaded", info->id);
88  }
89 
90  plugin_runtime_t *runtime = broker_add_plugin(support->broker, plugin);
91  map_set(support->plugins, id, runtime);
92  }
93 
94  if (mod.type & eModTarget)
95  {
96  const target_t *target = mod.target;
97  const module_info_t *info = &target->info;
98  CTASSERTF_ALWAYS(str_startswith(info->id, "target/"), "target id `%s` must start with `target/`", info->id);
99 
100  const char *id = info->id + sizeof("target/") - 1;
101 
102  if (map_contains(support->targets, id))
103  {
104  msg_notify(logger, &kEvent_TargetConflict, node, "%s already loaded", info->id);
105  }
106 
107  target_runtime_t *runtime = broker_add_target(support->broker, target);
108  map_set(support->targets, id, runtime);
109  }
110 }
111 
112 STA_DECL
113 support_t *support_new(broker_t *broker, loader_t *loader, arena_t *arena)
114 {
115  CTASSERT(broker != NULL);
116  CTASSERT(loader != NULL);
117 
118  support_t *support = ARENA_MALLOC(sizeof(support_t), "support", NULL, arena);
119  support->arena = arena;
120  support->broker = broker;
121  support->loader = loader;
122 
123  support->modules = typevec_new(sizeof(loaded_module_t), 16, arena);
124  support->languages = map_new(16, kTypeInfoString, arena);
125  support->extmap = map_new(16, kTypeInfoString, arena);
126  support->plugins = map_new(16, kTypeInfoString, arena);
127  support->targets = map_new(16, kTypeInfoString, arena);
128 
129  ARENA_IDENTIFY(support->modules, "modules", support, arena);
130  ARENA_IDENTIFY(support->languages, "languages", support, arena);
131  ARENA_IDENTIFY(support->extmap, "extmap", support, arena);
132  ARENA_IDENTIFY(support->plugins, "plugins", support, arena);
133  ARENA_IDENTIFY(support->targets, "targets", support, arena);
134 
135  return support;
136 }
137 
138 STA_DECL
140 {
141  CTASSERT(support != NULL);
142 
143  typevec_t *mods = load_default_modules(support->loader);
144  size_t len = typevec_len(mods);
145  for (size_t i = 0; i < len; i++)
146  {
147  loaded_module_t *mod = typevec_offset(mods, i);
148  add_loaded_module(support, *mod);
149  }
150 }
151 
152 STA_DECL
153 bool support_load_module(support_t *support, module_type_t mask, const char *name, loaded_module_t *out)
154 {
155  CTASSERT(support != NULL);
156  CTASSERT(name != NULL);
157  CTASSERT(out != NULL);
158 
159  loaded_module_t mod = load_module(support->loader, mask, name);
160  add_loaded_module(support, mod);
161 
162  *out = mod;
163 
164  return mod.type != eModNone;
165 }
166 
167 STA_DECL
169 {
170  CTASSERT(support != NULL);
171 
172  return support->modules;
173 }
174 
175 STA_DECL
176 language_runtime_t *support_get_lang(support_t *support, const char *ext)
177 {
178  CTASSERT(support != NULL);
179 
180  return map_get(support->extmap, ext);
181 }
182 
183 STA_DECL
184 plugin_runtime_t *support_get_plugin(support_t *support, const char *name)
185 {
186  CTASSERT(support != NULL);
187 
188  return map_get(support->plugins, name);
189 }
190 
191 STA_DECL
192 target_runtime_t *support_get_target(support_t *support, const char *name)
193 {
194  CTASSERT(support != NULL);
195 
196  return map_get(support->targets, name);
197 }
#define STA_DECL
sal2 annotation on function implementations to copy annotations from the declaration
CT_BROKER_API const node_t * broker_get_node(broker_t *broker)
Definition: broker.c:333
CT_BROKER_API language_runtime_t * broker_add_language(broker_t *broker, const language_t *lang)
Definition: broker.c:175
CT_BROKER_API target_runtime_t * broker_add_target(broker_t *broker, const target_t *target)
Definition: broker.c:241
CT_BROKER_API plugin_runtime_t * broker_add_plugin(broker_t *broker, const plugin_t *plugin)
Definition: broker.c:220
CT_BROKER_API logger_t * broker_get_logger(broker_t *broker)
Definition: broker.c:325
CT_STD_API void map_set(map_t *map, const void *key, void *value)
set a key-value pair in a map
Definition: map.c:294
CT_NODISCARD CT_STD_API map_t * map_new(size_t size, hash_info_t info, arena_t *arena)
create a new map on the heap
Definition: map.c:113
CT_NODISCARD CT_PUREFN CT_STD_API bool map_contains(const map_t *map, const void *key)
check if a map contains a key
Definition: map.c:351
CT_NODISCARD CT_PUREFN CT_STD_API void * map_get(const map_t *map, const void *key)
get a value from a map
Definition: map.c:324
typedefCT_BEGIN_API struct support_t support_t
Definition: support.h:27
#define ARENA_IDENTIFY(ptr, name, parent, arena)
rename and reparent a pointer in a custom allocator
Definition: arena.h:409
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
Definition: arena.h:392
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
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:116
#define CTASSERTF_ALWAYS(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:85
CT_NODISCARD CT_PUREFN CT_STD_API bool str_startswith(const char *str, const char *prefix)
see if a string starts with a prefix
Definition: str.c:233
CT_STD_API const hash_info_t kTypeInfoString
type information for a c style string
Definition: typeinfo.c:35
CT_STD_API void * typevec_push(typevec_t *vec, const void *src)
push a value onto the vector
Definition: vector.c:156
CT_NODISCARD CT_PUREFN CT_STD_API size_t typevec_len(const typevec_t *vec)
get the length of a vector
Definition: vector.c:120
CT_NODISCARD CT_STD_API typevec_t * typevec_new(size_t width, size_t len, arena_t *arena)
create a new typed vector on the heap
Definition: vector.c:77
CT_NODISCARD CT_PUREFN CT_STD_API void * typevec_offset(const typevec_t *vec, size_t index)
get a pointer to the value at the given index
Definition: vector.c:191
CT_SUPPORT_API loaded_module_t load_module(loader_t *loader, module_type_t mask, const char *name)
Definition: loader.c:104
CT_SUPPORT_API typevec_t * load_default_modules(loader_t *loader)
Definition: loader.c:52
module_type_t
Definition: loader.h:32
an allocator object
Definition: arena.h:86
const language_t * info
Definition: broker.h:262
a language driver support capabilities
Definition: broker.h:143
const char *const * exts
the default file extensions this language should be used for
Definition: broker.h:155
module_info_t info
common information about the language
Definition: broker.h:145
const plugin_t * plugin
Definition: loader.h:52
module_type_t type
Definition: loader.h:49
const target_t * target
Definition: loader.h:53
const language_t * lang
Definition: loader.h:51
Definition: common.h:8
a logging sink
Definition: notify.c:14
an unordered hash map
Definition: map.h:38
common information about anything the broker supports
Definition: broker.h:99
const char * id
unique id for the module
Definition: broker.h:101
a position in a source file
Definition: node.h:23
plugin support capabilities
Definition: broker.h:202
module_info_t info
information about the plugin
Definition: broker.h:204
typevec_t * modules
Definition: support.c:24
loader_t * loader
Definition: support.c:22
map_t * languages
Definition: support.c:26
map_t * plugins
Definition: support.c:33
map_t * extmap
Definition: support.c:30
broker_t * broker
Definition: support.c:21
arena_t * arena
Definition: support.c:20
map_t * targets
Definition: support.c:36
a codegen target backend
Definition: broker.h:232
module_info_t info
information about the target
Definition: broker.h:234
A vector with a fixed type size.
Definition: vector.h:24
STA_DECL 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
STA_DECL plugin_runtime_t * support_get_plugin(support_t *support, const char *name)
Definition: support.c:184
STA_DECL void support_load_default_modules(support_t *support)
load all default modules
Definition: support.c:139
STA_DECL target_runtime_t * support_get_target(support_t *support, const char *name)
Definition: support.c:192
STA_DECL bool support_load_module(support_t *support, module_type_t mask, const char *name, loaded_module_t *out)
Definition: support.c:153
STA_DECL language_runtime_t * support_get_lang(support_t *support, const char *ext)
Definition: support.c:176
STA_DECL typevec_t * support_get_modules(support_t *support)
Definition: support.c:168