xref: /inferno-os/libinterp/link.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "raise.h"
5 #include <kernel.h>
6 
7 static void
8 newlink(Link *l, char *fn, int sig, Type *t)
9 {
10 	l->name = malloc(strlen(fn)+1);
11 	if(l->name == nil)
12 		error(exNomem);
13 	strcpy(l->name, fn);
14 	l->sig = sig;
15 	l->frame = t;
16 }
17 
18 void
19 runtime(Module *m, Link *l, char *fn, int sig, void (*runt)(void*), Type *t)
20 {
21 	USED(m);
22 	newlink(l, fn, sig, t);
23 	l->u.runt = runt;
24 }
25 
26 void
27 mlink(Module *m, Link* l, uchar *fn, int sig, int pc, Type *t)
28 {
29 	newlink(l, (char*)fn, sig, t);
30 	l->u.pc = m->prog+pc;
31 }
32 
33 static int
34 linkm(Module *m, Modlink *ml, int i, Import *ldt)
35 {
36 	Link *l;
37 	int sig;
38 	char e[ERRMAX];
39 
40 	sig = ldt->sig;
41 	for(l = m->ext; l->name; l++)
42 		if(strcmp(ldt->name, l->name) == 0)
43 			break;
44 
45 	if(l == nil) {
46 		snprint(e, sizeof(e), "link failed fn %s->%s() not implemented", m->name, ldt->name);
47 		goto bad;
48 	}
49 	if(l->sig != sig) {
50 		snprint(e, sizeof(e), "link typecheck %s->%s() %ux/%ux",
51 							m->name, ldt->name, l->sig, sig);
52 		goto bad;
53 	}
54 
55 	ml->links[i].u = l->u;
56 	ml->links[i].frame = l->frame;
57 	return 0;
58 bad:
59 	kwerrstr(e);
60 	print("%s\n", e);
61 	return -1;
62 }
63 
64 Modlink*
65 mklinkmod(Module *m, int n)
66 {
67 	Heap *h;
68 	Modlink *ml;
69 
70 	h = nheap(sizeof(Modlink)+(n-1)*sizeof(ml->links[0]));
71 	h->t = &Tmodlink;
72 	Tmodlink.ref++;
73 	ml = H2D(Modlink*, h);
74 	ml->nlinks = n;
75 	ml->m = m;
76 	ml->prog = m->prog;
77 	ml->type = m->type;
78 	ml->compiled = m->compiled;
79 	ml->MP = H;
80 	ml->data = nil;
81 
82 	return ml;
83 }
84 
85 Modlink*
86 linkmod(Module *m, Import *ldt, int mkmp)
87 {
88 	Type *t;
89 	Heap *h;
90 	int i;
91 	Modlink *ml;
92 	Import *l;
93 
94 	if(m == nil)
95 		return H;
96 
97 	for(i = 0, l = ldt; l->name != nil; i++, l++)
98 		;
99 	ml = mklinkmod(m, i);
100 
101 	if(mkmp){
102 		if(m->rt == DYNMOD)
103 			newdyndata(ml);
104 		else if(mkmp && m->origmp != H && m->ntype > 0) {
105 			t = m->type[0];
106 			h = nheap(t->size);
107 			h->t = t;
108 			t->ref++;
109 			ml->MP = H2D(uchar*, h);
110 			newmp(ml->MP, m->origmp, t);
111 		}
112 	}
113 
114 	for(i = 0, l = ldt; l->name != nil; i++, l++) {
115 		if(linkm(m, ml, i, l) < 0){
116 			destroy(ml);
117 			return H;
118 		}
119 	}
120 
121 	return ml;
122 }
123 
124 void
125 destroylinks(Module *m)
126 {
127 	Link *l;
128 
129 	for(l = m->ext; l->name; l++)
130 		free(l->name);
131 	free(m->ext);
132 }
133