Mostly changes ported from ABIv0 branch:
[AROS.git] / tools / genmodule / writestubs.c
blob8c99ab7248b4a0bc75b6596dbd1681c3bdf8662e
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Function to write module stubs. Part of genmodule.
7 Stubs are agregated differently into objects files based on STACK vs REG
8 convention.
10 Linker will always put a whole object file from archive into
11 executable. If all stubs are in one object file, all stubs are present
12 in executable, inflating its size, even if they are not used.
14 In majority of cases REG call function stubs will be handled be inlines
15 or defines while STACK call function stubs will be linked from linklib.
17 Based on above paragraphs, putting stubs of STACK functions into separate
18 object files will allow for linker to only include required function stubs.
21 #include "genmodule.h"
23 static void writeheader(struct config *cfg, int is_rel, FILE *out);
24 static void writefuncstub(struct config *cfg, int is_rel, FILE *out, struct functionhead *funclistit);
26 void writestubs(struct config *cfg, int is_rel)
28 FILE *out;
29 char line[256];
30 struct functionhead *funclistit;
32 /* Build STACKCALL - each stub in separate object file */
33 for (funclistit = cfg->funclist;
34 funclistit!=NULL;
35 funclistit = funclistit->next
38 if (funclistit->lvo >= cfg->firstlvo && funclistit->libcall == STACK)
41 snprintf(line, 255, "%s/%s_%s_%sstub.c", cfg->gendir, cfg->modulename, funclistit->name, is_rel ? "rel" : "");
42 out = fopen(line, "w");
44 if (out == NULL)
46 perror(line);
47 exit(20);
50 writeheader(cfg, is_rel, out);
51 writefuncstub(cfg, is_rel, out, funclistit);
53 fclose(out);
57 /* Build REGCALL - all stusb in one object file */
58 snprintf(line, 255, "%s/%s_regcall_%sstubs.c", cfg->gendir, cfg->modulename, is_rel ? "rel" : "");
59 out = fopen(line, "w");
61 if (out == NULL)
63 perror(line);
64 exit(20);
67 writeheader(cfg, is_rel, out);
69 for (funclistit = cfg->funclist;
70 funclistit!=NULL;
71 funclistit = funclistit->next
74 if (funclistit->lvo >= cfg->firstlvo && funclistit->libcall != STACK)
76 writefuncstub(cfg, is_rel, out, funclistit);
79 fclose(out);
83 static void writeheader(struct config *cfg, int is_rel, FILE *out)
85 struct stringlist *linelistit;
86 char *banner;
88 banner = getBanner(cfg);
89 if (is_rel) {
90 fprintf
92 out,
93 "%s"
94 "#undef NOLIBINLINE\n"
95 "#undef NOLIBDEFINES\n"
96 "#define NOLIBINLINE\n"
97 "#define NOLIBDEFINES\n"
98 "char *__aros_getoffsettable(void);\n"
99 "#ifndef __%s_NOLIBBASE__\n"
100 "/* Do not include the libbase */\n"
101 "#define __%s_NOLIBBASE__\n"
102 "#endif\n",
103 banner, cfg->modulenameupper, cfg->modulenameupper
105 } else {
106 fprintf
108 out,
109 "%s"
110 "#undef NOLIBINLINE\n"
111 "#undef NOLIBDEFINES\n"
112 "#define NOLIBINLINE\n"
113 "#define NOLIBDEFINES\n"
114 "/* Be sure that the libbases are included in the stubs file */\n"
115 "#undef __NOLIBBASE__\n"
116 "#undef __%s_NOLIBBASE__\n",
117 banner, cfg->modulenameupper
120 freeBanner(banner);
122 if (!(cfg->options & OPTION_NOINCLUDES))
124 if (is_rel)
125 fprintf(out, "#define __%s_RELLIBBASE__\n", cfg->modulenameupper);
126 fprintf(out, "#include <proto/%s.h>\n", cfg->modulename);
128 else
130 fprintf(out,
131 "#include <exec/types.h>\n"
132 "#include <aros/system.h>\n\n"
135 for (linelistit = cfg->cdefprivatelines; linelistit!=NULL; linelistit = linelistit->next)
136 fprintf(out, "%s\n", linelistit->s);
138 fprintf(out,
139 "\n"
140 "%s__aros_getbase_%s(void);\n"
141 "\n",
142 cfg->libbasetypeptrextern, cfg->libbase
146 fprintf
148 out,
149 "#include <stddef.h>\n"
150 "\n"
151 "#include <aros/cpu.h>\n"
152 "#include <aros/genmodule.h>\n"
153 "#include <aros/libcall.h>\n"
154 "\n"
158 static void writefuncstub(struct config *cfg, int is_rel, FILE *out, struct functionhead *funclistit)
160 struct stringlist *aliasesit;
161 struct functionarg *arglistit;
162 char *type, *name;
164 if (funclistit->libcall != STACK)
166 int nargs = 0, nquad = 0;
167 int isvoid = strcmp(funclistit->type, "void") == 0
168 || strcmp(funclistit->type, "VOID") == 0;
170 fprintf(out,
171 "\n"
172 "%s %s(",
173 funclistit->type, funclistit->name
175 for (arglistit = funclistit->arguments;
176 arglistit!=NULL;
177 arglistit = arglistit->next
180 if (arglistit != funclistit->arguments)
181 fprintf(out, ", ");
182 fprintf(out, "%s", arglistit->arg);
183 if (strchr(arglistit->reg, '/')) {
184 nquad++;
185 } else {
186 nargs++;
190 fprintf(out,
191 ")\n"
192 "{\n"
194 if (nquad == 0) {
195 fprintf(out,
196 " %sAROS_LC%d%s(%s, %s,\n",
197 (isvoid) ? "" : "return ",
198 funclistit->argcount, (isvoid) ? "NR" : "",
199 funclistit->type, funclistit->name
202 for (arglistit = funclistit->arguments;
203 arglistit!=NULL;
204 arglistit = arglistit->next
207 type = getargtype(arglistit);
208 name = getargname(arglistit);
209 assert(type != NULL && name != NULL);
211 fprintf(out, " AROS_LCA(%s,%s,%s),\n",
212 type, name, arglistit->reg
214 free(type);
215 free(name);
218 else /* nquad != 0 */
220 if (nargs == 0) {
221 fprintf(out,
222 " %sAROS_LCQUAD%d%s(%s, %s, \\\n",
223 (isvoid) ? "" : "return ",
224 funclistit->argcount, (isvoid) ? "NR" : "",
225 funclistit->type, funclistit->name
228 else
230 fprintf(out,
231 " %sAROS_LC%dQUAD%d%s(%s, %s, \\\n",
232 (isvoid) ? "" : "return ",
233 nargs, nquad, (isvoid) ? "NR" : "",
234 funclistit->type, funclistit->name
238 for (arglistit = funclistit->arguments;
239 arglistit != NULL;
240 arglistit = arglistit->next
243 char *quad2 = strchr(arglistit->reg, '/');
245 type = getargtype(arglistit);
246 name = getargname(arglistit);
247 assert(type != NULL && name != NULL);
249 if (quad2) {
250 *quad2 = 0;
251 fprintf(out,
252 " AROS_LCAQUAD(%s, %s, %s, %s), \\\n",
253 type, name, arglistit->reg, quad2+1
255 *quad2 = '/';
257 else
259 fprintf(out,
260 " AROS_LCA(%s, %s, %s), \\\n",
261 type, name, arglistit->reg
264 free(type);
265 free(name);
269 fprintf(out, " %s, __aros_getbase_%s(), %u, %s);\n}\n",
270 cfg->libbasetypeptrextern, cfg->libbase, funclistit->lvo, cfg->basename
273 else /* libcall==STACK */
275 fprintf(out, "AROS_GM_%sLIBFUNCSTUB(%s, %s, %d)\n",
276 is_rel ? "REL" : "",
277 funclistit->name, cfg->libbase, funclistit->lvo
281 for (aliasesit = funclistit->aliases;
282 aliasesit != NULL;
283 aliasesit = aliasesit->next
286 fprintf(out, "AROS_GM_LIBFUNCALIAS(%s, %s)\n",
287 funclistit->name, aliasesit->s