This commit is contained in:
ZZY
2025-04-01 00:13:21 +08:00
parent 2b4857001c
commit 74f43a1ab7
79 changed files with 2271 additions and 2861 deletions

21
linker/Makefile Normal file
View File

@ -0,0 +1,21 @@
CC = gcc
CFLAGS = -g -Wall -I..
# CLFAGS += -fsanitize=address
all: smcc
smcc: cc asm lib
$(CC) $(CFLAGS) riscv32_crt.c riscv32_linker.c test_main.c -L../assembler/riscv32 -lasm -L../ccompiler -lcc -L../lib -lcore -o smcc
lib:
make -C ../lib
asm:
make -C ../assembler/riscv32
cc:
make -C ../ccompiler
clean:
make -C ../lib clean
make -C ../assembler/riscv32 clean
make -C ../ccompiler clean

6
linker/header.h Normal file
View File

@ -0,0 +1,6 @@
#include <assembler/riscv32/riscv32.h>
#include <assembler/riscv32/riscv32_instr.h>
#include <lib/core.h>
rv32_prog_t* gen_rv32_crt();
rv32_prog_t* link_rv32_prog(rv32_prog_t* progs[]);

21
linker/riscv32_crt.c Normal file
View File

@ -0,0 +1,21 @@
#include "header.h"
// #include <assembler/riscv32/riscv32.c>
rv32_prog_t* gen_rv32_crt() {
rv32_prog_t* crt = (rv32_prog_t*)salloc_alloc(sizeof(rv32_prog_t));
init_rv32_prog(crt, NULL);
rv32_li(crt, REG_SP, 0x1000);
rv32_li(crt, REG_RA, 0x0);
// call main
symasm_entry_t entry = {
.name = "main",
.attr = GLOBAL
};
rv32_call_l(crt, &entry);
// ecall exit2
rv32_li(crt, REG_A7, 93);
rv32_ecall(crt);
return crt;
}

65
linker/riscv32_linker.c Normal file
View File

@ -0,0 +1,65 @@
#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;
}

58
linker/test_main.c Normal file
View File

@ -0,0 +1,58 @@
#include "header.h"
#include <ccompiler/ccompiler.h>
#include <stdio.h>
int main(int argc, char** argv) {
// gcc rv32ima_codegen.c -o rv32gen.exe
init_lib_core();
log_set_level(NULL, LOG_LEVEL_ERROR | LOG_LEVEL_WARN | LOG_LEVEL_FATAL);
const char* infilename = "test.c";
const char* outfilename = "flat.bin";
if (argc >= 2) {
infilename = argv[1];
}
if (argc >= 3) {
outfilename = argv[2];
}
FILE* in = fopen(infilename, "r");
FILE* out = fopen(outfilename, "wb");
if (in == NULL || out == NULL) {
printf("Failed to open file\n");
return 1;
}
smcc_cc_t cc = {
.file = infilename,
.sread = (sread_fn)fread,
.stream = in,
};
asm_prog_t *prog = smcc_cc(&cc);
// gen_rv32_instr(&prog->rv32);
rv32_prog_t* rv32_crt = gen_rv32_crt();
rv32_prog_t* rv32_progs[3] = {
rv32_crt,
&prog->rv32,
NULL,
};
// rv32_progs[0] = rv32_crt;
// rv32_progs[1] = &prog->rv32;
// rv32_progs[2] = NULL;
rv32_prog_t* code = link_rv32_prog(rv32_progs);
// for (int i = 0; i < code->instrs.size; i++) {
// fwrite(&code->instrs.data[i].instr, 4, 1, out);
// fflush(out);
// }
// Flatbin fmt
fwrite(code->text.data, sizeof(u32_t), code->text.size, out);
// fwrite(code->data.data, sizeof(u8_t)code->text.size, 1, out);
fclose(in);
fclose(out);
return 0;
}