#include "as_analyzer.h" #include #include const char * compose_section_label(struct allocator * alct, const char * section, const char * name) { size_t section_len = strlen(section); size_t name_len = strlen(name); size_t sz = section_len + name_len; char * buf = allocate(alct, sz + 1); memcpy(buf, section, section_len); memcpy(buf + section_len, name, name_len); buf[sz] = '\0'; return buf; } void process_section_label(struct allocator * alct, struct prog * prog) { const char * section = ""; struct stmt ** stmts = prog->stmts->stmts; for (size_t i = 0; ; i++) { if (stmts[i] == NULL) break; if (stmts[i]->label == NULL) continue; const char* name = stmts[i]->label->name; if (name[0] == '.') { stmts[i]->label->name = compose_section_label(alct, section, name); } else { section = name; continue; } } } size_t instr_size(struct instr * instr) { return op_size(instr->op); } struct sym_table new_sym_table(struct allocator * alct) { struct sym_table tbl; tbl.cap = 16; tbl.size = 0; tbl.buf = allocate(alct, sizeof(struct sym_table_entry) * 16); return tbl; } void sym_table_add(struct allocator * alct, struct sym_table* tbl, const char* name, int pos) { if (tbl->cap == tbl->size) { void *old_buf = tbl->buf; tbl->buf = allocate(alct, sizeof(struct sym_table_entry) * tbl->cap * 2); memcpy(tbl->buf, old_buf, sizeof(struct sym_table_entry) * tbl->cap); tbl->cap = tbl->cap * 2; } tbl->buf[tbl->size] = (struct sym_table_entry){.name = name, .offset = pos,}; tbl->size += 1; } int sym_table_lookup(sym_table* tbl, const char* name) { for (int i = 0; i < tbl->size; i++) { if (strcmp(name, tbl->buf[i].name) == 0) { return tbl->buf[i].offset; } } return -1; } struct sym_table analyze_prog(struct allocator * alct, struct prog * prog) { process_section_label(alct, prog); struct stmt * * stmts = prog->stmts->stmts; struct sym_table tbl = new_sym_table(alct); size_t cur_pos = 0; for (int i = 0; ; i++) { if (stmts[i] == NULL) break; struct stmt * stmt = stmts[i]; if (stmt->label) { sym_table_add(alct, &tbl, stmt->label->name, cur_pos); } if (stmt->instr) { cur_pos += instr_size(stmt->instr); } } return tbl; }