diff options
Diffstat (limited to 'libinterp/loader.c')
| -rw-r--r-- | libinterp/loader.c | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/libinterp/loader.c b/libinterp/loader.c new file mode 100644 index 00000000..3de66c7e --- /dev/null +++ b/libinterp/loader.c @@ -0,0 +1,444 @@ +#include "lib9.h" +#include "isa.h" +#include "interp.h" +#include "runt.h" +#include "loadermod.h" +#include "raise.h" +#include <kernel.h> + +static uchar Instmap[] = Loader_Inst_map; +static Type* Tinst; +static uchar Tdescmap[] = Loader_Typedesc_map; +static Type* Tdesc; +static uchar Tlinkmap[] = Loader_Link_map; +static Type* Tlink; + +void +loadermodinit(void) +{ + sysinit(); + builtinmod("$Loader", Loadermodtab, Loadermodlen); + Tinst = dtype(freeheap, sizeof(Loader_Inst), Instmap, sizeof(Instmap)); + Tdesc = dtype(freeheap, sizeof(Loader_Typedesc), Tdescmap, sizeof(Tdescmap)); + Tlink = dtype(freeheap, sizeof(Loader_Link), Tlinkmap, sizeof(Tlinkmap)); +} + +static void +brunpatch(Loader_Inst *ip, Module *m) +{ + switch(ip->op) { + case ICALL: + case IJMP: + case IBEQW: + case IBNEW: + case IBLTW: + case IBLEW: + case IBGTW: + case IBGEW: + case IBEQB: + case IBNEB: + case IBLTB: + case IBLEB: + case IBGTB: + case IBGEB: + case IBEQF: + case IBNEF: + case IBLTF: + case IBLEF: + case IBGTF: + case IBGEF: + case IBEQC: + case IBNEC: + case IBLTC: + case IBLEC: + case IBGTC: + case IBGEC: + case IBEQL: + case IBNEL: + case IBLTL: + case IBLEL: + case IBGTL: + case IBGEL: + case ISPAWN: + ip->dst = (Inst*)ip->dst - m->prog; + break; + } +} + +void +Loader_ifetch(void *a) +{ + Heap *h; + Array *ar; + Module *m; + Inst *i, *ie; + Loader_Inst *li; + F_Loader_ifetch *f; + + f = a; + destroy(*f->ret); + *f->ret = H; + + if(f->mp == H) + return; + m = f->mp->m; + if(m == H) + return; + if(m->compiled) { + kwerrstr("compiled module"); + return; + } + + h = nheap(sizeof(Array)+m->nprog*sizeof(Loader_Inst)); + h->t = &Tarray; + h->t->ref++; + ar = H2D(Array*, h); + ar->t = Tinst; + Tinst->ref++; + ar->len = m->nprog; + ar->root = H; + ar->data = (uchar*)ar+sizeof(Array); + + li = (Loader_Inst*)ar->data; + i = m->prog; + ie = i + m->nprog; + while(i < ie) { + li->op = i->op; + li->addr = i->add; + li->src = i->s.imm; + li->dst = i->d.imm; + li->mid = i->reg; + if(UDST(i->add) == AIMM) + brunpatch(li, m); + li++; + i++; + } + + *f->ret = ar; +} + +void +Loader_link(void *a) +{ + Link *p; + Heap *h; + Type **t; + int nlink; + Module *m; + Array *ar; + Loader_Link *ll; + F_Loader_link *f; + + f = a; + destroy(*f->ret); + *f->ret = H; + + if(f->mp == H) + return; + m = f->mp->m; + if(m == H) + return; + + nlink = 0; + for(p = m->ext; p->name; p++) + nlink++; + + h = nheap(sizeof(Array)+nlink*sizeof(Loader_Link)); + h->t = &Tarray; + h->t->ref++; + ar = H2D(Array*, h); + ar->t = Tlink; + Tlink->ref++; + ar->len = nlink; + ar->root = H; + ar->data = (uchar*)ar+sizeof(Array); + + ll = (Loader_Link*)ar->data + nlink; + for(p = m->ext; p->name; p++) { + ll--; + ll->name = c2string(p->name, strlen(p->name)); + ll->sig = p->sig; + if(m->prog == nil) { + ll->pc = -1; + ll->tdesc = -1; + } else { + ll->pc = p->u.pc - m->prog; + ll->tdesc = 0; + for(t = m->type; *t != p->frame; t++) + ll->tdesc++; + } + } + + *f->ret = ar; +} + +void +Loader_tdesc(void *a) +{ + int i; + Heap *h; + Type *t; + Array *ar; + Module *m; + F_Loader_tdesc *f; + Loader_Typedesc *lt; + + f = a; + destroy(*f->ret); + *f->ret = H; + + if(f->mp == H) + return; + m = f->mp->m; + if(m == H) + return; + + h = nheap(sizeof(Array)+m->ntype*sizeof(Loader_Typedesc)); + h->t = &Tarray; + h->t->ref++; + ar = H2D(Array*, h); + ar->t = Tdesc; + Tdesc->ref++; + ar->len = m->ntype; + ar->root = H; + ar->data = (uchar*)ar+sizeof(Array); + + lt = (Loader_Typedesc*)ar->data; + for(i = 0; i < m->ntype; i++) { + t = m->type[i]; + lt->size = t->size; + lt->map = H; + if(t->np != 0) + lt->map = mem2array(t->map, t->np); + lt++; + } + + *f->ret = ar; +} + +void +Loader_newmod(void *a) +{ + Heap *h; + Module *m; + Array *ia; + Modlink *ml; + Inst *i, *ie; + Loader_Inst *li; + F_Loader_newmod *f; + + f = a; + destroy(*f->ret); + *f->ret = H; + + if(f->inst == H || f->data == H) { + kwerrstr("nil parameters"); + return; + } + if(f->nlink < 0) { + kwerrstr("bad nlink"); + return; + } + + m = malloc(sizeof(Module)); + if(m == nil) { + kwerrstr(exNomem); + return; + } + m->origmp = H; + m->ref = 1; + m->ss = f->ss; + m->name = strdup(string2c(f->name)); + m->path = strdup(m->name); + m->ntype = 1; + m->type = malloc(sizeof(Type*)); + if(m->name == nil || m->path == nil || m->type == nil) { + kwerrstr(exNomem); + goto bad; + } + m->origmp = (uchar*)f->data; + h = D2H(f->data); + h->ref++; + Setmark(h); + m->type[0] = h->t; + h->t->ref++; + + ia = f->inst; + m->nprog = ia->len; + m->prog = malloc(m->nprog*sizeof(Inst)); + if(m->prog == nil) + goto bad; + i = m->prog; + ie = i + m->nprog; + li = (Loader_Inst*)ia->data; + while(i < ie) { + i->op = li->op; + i->add = li->addr; + i->reg = li->mid; + i->s.imm = li->src; + i->d.imm = li->dst; + if(brpatch(i, m) == 0) { + kwerrstr("bad branch addr"); + goto bad; + } + i++; + li++; + } + m->entryt = nil; + m->entry = m->prog; + + ml = mklinkmod(m, f->nlink); + ml->MP = m->origmp; + m->origmp = H; + m->pctab = nil; + *f->ret = ml; + return; +bad: + destroy(m->origmp); + freemod(m); +} + +void +Loader_tnew(void *a) +{ + int mem; + Module *m; + Type *t, **nt; + Array *ar, az; + F_Loader_tnew *f; + + f = a; + *f->ret = -1; + if(f->mp == H) + return; + m = f->mp->m; + if(m == H) + return; + if(m->origmp != H){ + kwerrstr("need newmod"); + return; + } + + ar = f->map; + if(ar == H) { + ar = &az; + ar->len = 0; + ar->data = nil; + } + + t = dtype(freeheap, f->size, ar->data, ar->len); + if(t == nil) + return; + + mem = (m->ntype+1)*sizeof(Type*); + if(msize(m->type) > mem) { + *f->ret = m->ntype; + m->type[m->ntype++] = t; + return; + } + nt = realloc(m->type, mem); + if(nt == nil) { + kwerrstr(exNomem); + return; + } + m->type = nt; + f->mp->type = nt; + *f->ret = m->ntype; + m->type[m->ntype++] = t; +} + +void +Loader_ext(void *a) +{ + Modl *l; + Module *m; + Modlink *ml; + F_Loader_ext *f; + + f = a; + *f->ret = -1; + if(f->mp == H) { + kwerrstr("nil mp"); + return; + } + ml = f->mp; + m = ml->m; + if(f->tdesc < 0 || f->tdesc >= m->ntype) { + kwerrstr("bad tdesc"); + return; + } + if(f->pc < 0 || f->pc >= m->nprog) { + kwerrstr("bad pc"); + return; + } + if(f->idx < 0 || f->idx >= ml->nlinks) { + kwerrstr("bad idx"); + return; + } + l = &ml->links[f->idx]; + l->u.pc = m->prog + f->pc; + l->frame = m->type[f->tdesc]; + *f->ret = 0; +} + +void +Loader_dnew(void *a) +{ + F_Loader_dnew *f; + Heap *h; + Array *ar, az; + Type *t; + + f = a; + *f->ret = H; + if(f->map == H) + return; + ar = f->map; + if(ar == H) { + ar = &az; + ar->len = 0; + ar->data = nil; + } + t = dtype(freeheap, f->size, ar->data, ar->len); + if(t == nil) { + kwerrstr(exNomem); + return; + } + + h=heapz(t); + if(h == nil) { + freetype(t); + kwerrstr(exNomem); + return; + } + + *f->ret=H2D(Loader_Niladt*, h); +} + +void +Loader_compile(void *a) +{ + Module *m; + F_Loader_compile *f; + + f = a; + *f->ret = -1; + if(f->mp == H) { + kwerrstr("nil mp"); + return; + } + m = f->mp->m; + if(m->compiled) { + kwerrstr("compiled module"); + return; + } + *f->ret = 0; + m->origmp = f->mp->MP; + if(cflag || f->flag) + if(compile(m, m->nprog, f->mp)) { + f->mp->prog = m->prog; + f->mp->compiled = 1; + } else + *f->ret = -1; + m->origmp = H; +} |
