source.c (5597B)
1 /* SourceManager — file-id authority for diagnostics, dependency output, 2 * and DWARF. */ 3 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include "core/core.h" 8 #include "core/heap.h" 9 #include "core/pool.h" 10 #include "core/slice.h" 11 12 typedef struct SrcMgrFile { 13 SourceFile info; 14 } SrcMgrFile; 15 16 typedef struct SrcMgrInclude { 17 SourceInclude info; 18 } SrcMgrInclude; 19 20 struct SourceManager { 21 Compiler* c; 22 Heap* heap; 23 24 SrcMgrFile* files; 25 u32 nfiles; 26 u32 files_cap; 27 28 SrcMgrInclude* includes; 29 u32 nincludes; 30 u32 includes_cap; 31 }; 32 33 struct SourceDepIter { 34 SourceManager* sm; 35 u32 idx; 36 }; 37 38 static int files_grow(SourceManager* sm, u32 want) { 39 u32 new_cap; 40 SrcMgrFile* nf; 41 if (want <= sm->files_cap) return 0; 42 new_cap = sm->files_cap ? sm->files_cap * 2 : 16; 43 while (new_cap < want) new_cap *= 2; 44 nf = (SrcMgrFile*)sm->heap->realloc( 45 sm->heap, sm->files, sizeof(*sm->files) * sm->files_cap, 46 sizeof(*sm->files) * new_cap, _Alignof(SrcMgrFile)); 47 if (!nf) return 1; 48 sm->files = nf; 49 sm->files_cap = new_cap; 50 return 0; 51 } 52 53 static int includes_grow(SourceManager* sm) { 54 u32 new_cap; 55 SrcMgrInclude* ni; 56 if (sm->nincludes < sm->includes_cap) return 0; 57 new_cap = sm->includes_cap ? sm->includes_cap * 2 : 16; 58 ni = (SrcMgrInclude*)sm->heap->realloc( 59 sm->heap, sm->includes, sizeof(*sm->includes) * sm->includes_cap, 60 sizeof(*sm->includes) * new_cap, _Alignof(SrcMgrInclude)); 61 if (!ni) return 1; 62 sm->includes = ni; 63 sm->includes_cap = new_cap; 64 return 0; 65 } 66 67 SourceManager* source_new(Compiler* c) { 68 Heap* h = c->ctx->heap; 69 SourceManager* sm = 70 (SourceManager*)h->alloc(h, sizeof(*sm), _Alignof(SourceManager)); 71 if (!sm) return NULL; 72 memset(sm, 0, sizeof(*sm)); 73 sm->c = c; 74 sm->heap = h; 75 if (files_grow(sm, 1)) { 76 h->free(h, sm, sizeof(*sm)); 77 return NULL; 78 } 79 memset(&sm->files[0], 0, sizeof(sm->files[0])); 80 sm->nfiles = 1; 81 return sm; 82 } 83 84 void source_free(SourceManager* sm) { 85 if (!sm) return; 86 if (sm->files) 87 sm->heap->free(sm->heap, sm->files, sizeof(*sm->files) * sm->files_cap); 88 if (sm->includes) 89 sm->heap->free(sm->heap, sm->includes, 90 sizeof(*sm->includes) * sm->includes_cap); 91 sm->heap->free(sm->heap, sm, sizeof(*sm)); 92 } 93 94 static KitStatus file_register(SourceManager* sm, Slice name, 95 SourceFileKind kind, int system_header, 96 u32* id_out) { 97 Sym sym; 98 u32 id; 99 if (files_grow(sm, sm->nfiles + 1)) return KIT_NOMEM; 100 sym = pool_intern_slice(sm->c->global, name); 101 id = sm->nfiles++; 102 memset(&sm->files[id], 0, sizeof(sm->files[id])); 103 sm->files[id].info.id = id; 104 sm->files[id].info.name = sym; 105 sm->files[id].info.path = (kind == SRC_FILE_REAL) ? sym : 0; 106 sm->files[id].info.kind = (u8)kind; 107 sm->files[id].info.system_header = (u8)(system_header ? 1 : 0); 108 *id_out = id; 109 return KIT_OK; 110 } 111 112 KitStatus source_add_file(SourceManager* sm, const char* path, 113 int system_header, u32* id_out) { 114 return file_register(sm, slice_from_cstr(path ? path : ""), SRC_FILE_REAL, 115 system_header, id_out); 116 } 117 118 KitStatus source_add_memory(SourceManager* sm, KitSlice name, u32* id_out) { 119 return file_register(sm, name, SRC_FILE_MEMORY, 0, id_out); 120 } 121 122 KitStatus source_add_builtin(SourceManager* sm, KitSlice name, u32* id_out) { 123 return file_register(sm, name, SRC_FILE_BUILTIN, 0, id_out); 124 } 125 126 KitStatus source_add_include(SourceManager* sm, u32 includer_file_id, 127 u32 included_file_id, SrcLoc include_loc, 128 int system) { 129 if (includes_grow(sm)) return KIT_NOMEM; 130 sm->includes[sm->nincludes].info.includer_file_id = includer_file_id; 131 sm->includes[sm->nincludes].info.included_file_id = included_file_id; 132 sm->includes[sm->nincludes].info.include_loc = include_loc; 133 sm->includes[sm->nincludes].info.system = (u8)(system ? 1 : 0); 134 sm->nincludes++; 135 return KIT_OK; 136 } 137 138 KitStatus source_add_macro_expansion(SourceManager* sm, Sym macro_name, 139 SrcLoc spelling_loc, SrcLoc expansion_loc, 140 u32* id_out) { 141 (void)spelling_loc; 142 (void)expansion_loc; 143 if (files_grow(sm, sm->nfiles + 1)) return KIT_NOMEM; 144 { 145 u32 id = sm->nfiles++; 146 memset(&sm->files[id], 0, sizeof(sm->files[id])); 147 sm->files[id].info.id = id; 148 sm->files[id].info.name = macro_name; 149 sm->files[id].info.kind = SRC_FILE_MACRO; 150 *id_out = id; 151 } 152 return KIT_OK; 153 } 154 155 const SourceFile* source_file(SourceManager* sm, u32 file_id) { 156 if (file_id == 0 || file_id >= sm->nfiles) return NULL; 157 return &sm->files[file_id].info; 158 } 159 160 const SourceExpansion* source_expansion(SourceManager* sm, 161 u32 expansion_file_id) { 162 (void)sm; 163 (void)expansion_file_id; 164 return NULL; 165 } 166 167 SrcLoc source_spelling_loc(SourceManager* sm, SrcLoc loc) { 168 (void)sm; 169 return loc; 170 } 171 SrcLoc source_expansion_loc(SourceManager* sm, SrcLoc loc) { 172 (void)sm; 173 return loc; 174 } 175 176 SourceDepIter* source_depiter_new(SourceManager* sm) { 177 SourceDepIter* it = (SourceDepIter*)sm->heap->alloc(sm->heap, sizeof(*it), 178 _Alignof(SourceDepIter)); 179 if (!it) return NULL; 180 it->sm = sm; 181 it->idx = 0; 182 return it; 183 } 184 185 const SourceInclude* source_depiter_next(SourceDepIter* it) { 186 if (!it || it->idx >= it->sm->nincludes) return NULL; 187 return &it->sm->includes[it->idx++].info; 188 } 189 190 void source_depiter_free(SourceDepIter* it) { 191 if (!it) return; 192 it->sm->heap->free(it->sm->heap, it, sizeof(*it)); 193 }