diff options
Diffstat (limited to 'dseg.c')
| -rw-r--r-- | dseg.c | 95 |
1 files changed, 23 insertions, 72 deletions
@@ -8,35 +8,9 @@ static integral_t string_counter = 0; -void dseg_init(struct dseg* dseg) { - dseg->entries = ccc_alloc(DEFAULT_SIZE * sizeof(struct dseg_entry*)); - dseg->cap = DEFAULT_SIZE; -} - -static void dseg_entry_destroy(struct dseg_entry* entry) { - free(entry->symbol); -} - -void dseg_destroy(struct dseg* dseg) { - for (integral_t i = 0; i < dseg->cap; i++) { - if (dseg->entries[i] == NULL) continue; - dseg_entry_destroy(dseg->entries[i]); - free(dseg->entries[i]); - } - free(dseg->entries); -} - -static inline integral_t advance_hash( - integral_t hash, - integral_t val, - integral_t cap -) { - return ((hash << 5) - hash + val) % cap;; -} - static integral_t hash_string(const char* str, integral_t cap) { integral_t hash = 0, i = 0; - while (str[i] != 0) hash = advance_hash(hash, str[i++], cap); + while (str[i] != 0) ADVANCE_HASH(hash, str[i++], cap); return hash; } @@ -57,6 +31,22 @@ static bool ent_eq(const struct dseg_entry* a, const struct dseg_entry* b) { DSEG_PANIC("equality function not defined for entry type"); } +static void ent_destroy(struct dseg_entry* entry) { + free(entry->symbol); +} + +void dseg_init(struct hash_map* dseg) { + hm_init( + dseg, + (hm_hash_fn) hash_ent, + (hm_eq_fn) ent_eq, + (hm_destroy_fn) ent_destroy); +} + +void dseg_destroy(struct hash_map* dseg) { + hm_destroy(dseg); +} + static void ent_assign_key(struct dseg_entry* ent) { switch (ent->type) { case ENT_STRING: @@ -70,47 +60,8 @@ static void ent_assign_key(struct dseg_entry* ent) { } } -static struct dseg_entry** dseg_cell( - const struct dseg* dseg, - const struct dseg_entry* ent -) { - integral_t orig_idx = hash_ent(ent, dseg->cap); - integral_t idx = orig_idx; - - do { - if (dseg->entries[idx] == NULL || ent_eq(dseg->entries[idx], ent)) - return &dseg->entries[idx]; - } while ((idx = (idx + 1) % dseg->cap) != orig_idx); - return NULL; -} - -static void rehash_dseg(struct dseg* dseg) { - struct dseg_entry** old_ents = dseg->entries; - integral_t old_cap = dseg->cap; - - dseg->cap = (dseg->cap + 1) << 1; - dseg->entries = ccc_alloc(dseg->cap * sizeof(struct dseg_entry*)); - - for (integral_t i = 0; i < old_cap; i++) { - if (old_ents[i] == NULL) continue; - struct dseg_entry** cell = dseg_cell(dseg, old_ents[i]); - if (cell == NULL) { - fprintf(stderr, "ccc: data segment rehash failed, likely a bug\n"); - exit(1); - } - *cell = old_ents[i]; - } - - free(old_ents); -} - -const char* dseg_put(struct dseg* dseg, struct dseg_entry entry) { - struct dseg_entry** cell = dseg_cell(dseg, &entry); - while (cell == NULL) { - rehash_dseg(dseg); - cell = dseg_cell(dseg, &entry); - } - +const char* dseg_put(struct hash_map* dseg, struct dseg_entry entry) { + struct dseg_entry** cell = (struct dseg_entry**) hm_cell_w(dseg, &entry); if (*cell != NULL) return (*cell)->symbol; struct dseg_entry* new_ent = ccc_alloc(sizeof(struct dseg_entry)); *cell = new_ent; @@ -123,7 +74,7 @@ static inline bool is_printable(char c) { return ' ' <= c && c <= '~'; } -void emit_string(FILE* outfile, const struct dseg_entry* ent) { +void emit_string_data(FILE* outfile, const struct dseg_entry* ent) { const char* str = ent->key.string; fprintf(outfile, "db "); for (integral_t i = 0; str[i] != 0;) { @@ -138,16 +89,16 @@ void emit_string(FILE* outfile, const struct dseg_entry* ent) { fprintf(outfile, "0x0"); } -void emit_dseg(FILE* outfile, const struct dseg* dseg) { +void emit_dseg(FILE* outfile, const struct hash_map* dseg) { fprintf(outfile, "section .data\n"); for (integral_t i = 0; i < dseg->cap; i++) { const struct dseg_entry* ent = dseg->entries[i]; - if (dseg->entries[i] == NULL) continue; + if (ent == NULL) continue; fprintf(outfile, "\t%s ", ent->symbol); switch (ent->type) { case ENT_STRING: - emit_string(outfile, ent); + emit_string_data(outfile, ent); break; } fprintf(outfile, "\n"); |
