#include "header.h" static u32_t text_addr = 0; #define FOREACH_PROGS(progs) for (rv32_prog_t **pprog = progs, *prog = *progs; \ *pprog != NULL; prog = *(++pprog)) int append(const void *key, void *value, void *context) { symtab_asm_t* symtab = (symtab_asm_t*) context; symasm_entry_t* entry = (symasm_entry_t*) key; u32_t* addr = (u32_t*) value; *addr += text_addr; // size to index salloc_alloc(16); if (entry->attr == GLOBAL) { symtab_asm_put(symtab, entry, *addr); } return 1; } rv32_prog_t* link_rv32_prog(rv32_prog_t* progs[]) { symtab_asm_t symtab; init_symtab_asm(&symtab); rv32_prog_t* exe = salloc_alloc(sizeof(rv32_prog_t)); init_rv32_prog(exe, NULL); FOREACH_PROGS(progs) { prog->text_base_address = text_addr; text_addr += prog->text.size; } exe->text.data = salloc_alloc(text_addr * sizeof(u32_t)); exe->text.cap = text_addr; exe->text.size = text_addr; text_addr = 0; FOREACH_PROGS(progs) { rt_memcpy(exe->text.data + text_addr, prog->text.data, prog->text.size * sizeof(u32_t)); // FIXME hashtable_foreach(&prog->symtab.symtab, append, &symtab); text_addr += prog->text.size; } // find by self FOREACH_PROGS(progs) { for (int i = 0; i < prog->rinstrs.size; i++) { u32_t* paddr; u32_t addr; paddr = symtab_asm_get(&prog->symtab, &prog->rinstrs.data[i].target); if (paddr == NULL) { paddr = symtab_asm_get(&symtab, &prog->rinstrs.data[i].target); if (paddr == NULL) { LOG_FATAL("linker: %s not found", prog->rinstrs.data[i].target.name); } addr = *paddr; } else { addr = *paddr; // addr += prog->text_base_address; } // FIXME int cur_idx = prog->text_base_address + prog->rinstrs.data[i].address; prog->rinstrs.data[i].instr.imm += (addr - cur_idx) * sizeof(u32_t); emit_rv32_instr(exe, &prog->rinstrs.data[i].instr, cur_idx, NULL); // symtab_get(&prog->symtab, &prog->rinstrs.data[i].target); } } return exe; }