smcc/linker/riscv32_linker.c
2025-04-01 00:13:21 +08:00

66 lines
2.2 KiB
C

#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;
}