source.c (6379B)
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 /* Register a file slot from a pre-interned name Sym (skips the intern). Draws 95 * the next sequential file_id from sm->nfiles++ exactly like file_register, so 96 * the file_id sequence -- which is byte-observable through DWARF line tables and 97 * diagnostics -- is unchanged. */ 98 static KitStatus file_register_sym(SourceManager* sm, Sym sym, 99 SourceFileKind kind, int system_header, 100 u32* id_out) { 101 u32 id; 102 if (files_grow(sm, sm->nfiles + 1)) return KIT_NOMEM; 103 id = sm->nfiles++; 104 memset(&sm->files[id], 0, sizeof(sm->files[id])); 105 sm->files[id].info.id = id; 106 sm->files[id].info.name = sym; 107 sm->files[id].info.path = (kind == SRC_FILE_REAL) ? sym : 0; 108 sm->files[id].info.kind = (u8)kind; 109 sm->files[id].info.system_header = (u8)(system_header ? 1 : 0); 110 *id_out = id; 111 return KIT_OK; 112 } 113 114 static KitStatus file_register(SourceManager* sm, Slice name, 115 SourceFileKind kind, int system_header, 116 u32* id_out) { 117 Sym sym = pool_intern_slice(sm->c->global, name); 118 return file_register_sym(sm, sym, kind, system_header, id_out); 119 } 120 121 KitStatus source_add_file(SourceManager* sm, const char* path, 122 int system_header, u32* id_out) { 123 return file_register(sm, slice_from_cstr(path ? path : ""), SRC_FILE_REAL, 124 system_header, id_out); 125 } 126 127 KitStatus source_add_memory(SourceManager* sm, KitSlice name, u32* id_out) { 128 return file_register(sm, name, SRC_FILE_MEMORY, 0, id_out); 129 } 130 131 KitStatus source_add_memory_sym(SourceManager* sm, Sym name, u32* id_out) { 132 return file_register_sym(sm, name, SRC_FILE_MEMORY, 0, id_out); 133 } 134 135 KitStatus source_add_builtin(SourceManager* sm, KitSlice name, u32* id_out) { 136 return file_register(sm, name, SRC_FILE_BUILTIN, 0, id_out); 137 } 138 139 KitStatus source_add_include(SourceManager* sm, u32 includer_file_id, 140 u32 included_file_id, SrcLoc include_loc, 141 int system, int resolved_system) { 142 if (includes_grow(sm)) return KIT_NOMEM; 143 sm->includes[sm->nincludes].info.includer_file_id = includer_file_id; 144 sm->includes[sm->nincludes].info.included_file_id = included_file_id; 145 sm->includes[sm->nincludes].info.include_loc = include_loc; 146 sm->includes[sm->nincludes].info.system = (u8)(system ? 1 : 0); 147 sm->includes[sm->nincludes].info.resolved_system = 148 (u8)(resolved_system ? 1 : 0); 149 sm->nincludes++; 150 return KIT_OK; 151 } 152 153 KitStatus source_add_macro_expansion(SourceManager* sm, Sym macro_name, 154 SrcLoc spelling_loc, SrcLoc expansion_loc, 155 u32* id_out) { 156 (void)spelling_loc; 157 (void)expansion_loc; 158 if (files_grow(sm, sm->nfiles + 1)) return KIT_NOMEM; 159 { 160 u32 id = sm->nfiles++; 161 memset(&sm->files[id], 0, sizeof(sm->files[id])); 162 sm->files[id].info.id = id; 163 sm->files[id].info.name = macro_name; 164 sm->files[id].info.kind = SRC_FILE_MACRO; 165 *id_out = id; 166 } 167 return KIT_OK; 168 } 169 170 const SourceFile* source_file(SourceManager* sm, u32 file_id) { 171 if (file_id == 0 || file_id >= sm->nfiles) return NULL; 172 return &sm->files[file_id].info; 173 } 174 175 const SourceExpansion* source_expansion(SourceManager* sm, 176 u32 expansion_file_id) { 177 (void)sm; 178 (void)expansion_file_id; 179 return NULL; 180 } 181 182 SrcLoc source_spelling_loc(SourceManager* sm, SrcLoc loc) { 183 (void)sm; 184 return loc; 185 } 186 SrcLoc source_expansion_loc(SourceManager* sm, SrcLoc loc) { 187 (void)sm; 188 return loc; 189 } 190 191 SourceDepIter* source_depiter_new(SourceManager* sm) { 192 SourceDepIter* it = (SourceDepIter*)sm->heap->alloc(sm->heap, sizeof(*it), 193 _Alignof(SourceDepIter)); 194 if (!it) return NULL; 195 it->sm = sm; 196 it->idx = 0; 197 return it; 198 } 199 200 const SourceInclude* source_depiter_next(SourceDepIter* it) { 201 if (!it || it->idx >= it->sm->nincludes) return NULL; 202 return &it->sm->includes[it->idx++].info; 203 } 204 205 void source_depiter_free(SourceDepIter* it) { 206 if (!it) return; 207 it->sm->heap->free(it->sm->heap, it, sizeof(*it)); 208 }