let genmodule store a modules generated linklib files (e.g. stubs) in a different...
[AROS.git] / tools / genmodule / writestubs.c
blob58eacc62c979d76045199f97fb5f2686326999d0
1 /*
2 Copyright © 1995-2016, 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->libgendir, 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->libgendir, 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->includenameupper, cfg->includenameupper
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->includenameupper
120 freeBanner(banner);
122 for (linelistit = cfg->stubprivatelines; linelistit!=NULL; linelistit = linelistit->next)
123 fprintf(out, "%s\n", linelistit->s);
125 if (!(cfg->options & OPTION_NOINCLUDES))
127 if (is_rel)
128 fprintf(out, "#define __%s_RELLIBBASE__\n", cfg->includenameupper);
129 fprintf(out, "#include <proto/%s.h>\n", cfg->includename);
131 else
133 fprintf(out,
134 "#include <exec/types.h>\n"
135 "#include <aros/system.h>\n\n"
138 for (linelistit = cfg->cdefprivatelines; linelistit!=NULL; linelistit = linelistit->next)
139 fprintf(out, "%s\n", linelistit->s);
141 fprintf(out,
142 "\n"
143 "%s__aros_getbase_%s(void);\n"
144 "\n",
145 cfg->libbasetypeptrextern, cfg->libbase
149 fprintf
151 out,
152 "#include <stddef.h>\n"
153 "\n"
154 "#include <aros/cpu.h>\n"
155 "#include <aros/genmodule.h>\n"
156 "#include <aros/libcall.h>\n"
157 "#include <aros/symbolsets.h>\n"
158 "\n"
162 static void writefuncstub(struct config *cfg, int is_rel, FILE *out, struct functionhead *funclistit)
164 struct stringlist *aliasesit;
165 struct functionarg *arglistit;
166 char *type, *name;
168 if (funclistit->libcall != STACK)
170 int nargs = 0, nquad = 0;
171 int isvoid = strcmp(funclistit->type, "void") == 0
172 || strcmp(funclistit->type, "VOID") == 0;
174 fprintf(out,
175 "\n"
176 "%s %s(",
177 funclistit->type, funclistit->name
179 for (arglistit = funclistit->arguments;
180 arglistit!=NULL;
181 arglistit = arglistit->next
184 if (arglistit != funclistit->arguments)
185 fprintf(out, ", ");
186 fprintf(out, "%s", arglistit->arg);
187 if (strchr(arglistit->reg, '/')) {
188 nquad++;
189 } else {
190 nargs++;
194 fprintf(out,
195 ")\n"
196 "{\n"
198 if (nquad == 0) {
199 fprintf(out,
200 " %sAROS_LC%d%s(%s, %s,\n",
201 (isvoid) ? "" : "return ",
202 funclistit->argcount, (isvoid) ? "NR" : "",
203 funclistit->type, funclistit->name
206 for (arglistit = funclistit->arguments;
207 arglistit!=NULL;
208 arglistit = arglistit->next
211 type = getargtype(arglistit);
212 name = getargname(arglistit);
213 assert(type != NULL && name != NULL);
215 fprintf(out, " AROS_LCA(%s,%s,%s),\n",
216 type, name, arglistit->reg
218 free(type);
219 free(name);
222 else /* nquad != 0 */
224 if (nargs == 0) {
225 fprintf(out,
226 " %sAROS_LCQUAD%d%s(%s, %s, \\\n",
227 (isvoid) ? "" : "return ",
228 funclistit->argcount, (isvoid) ? "NR" : "",
229 funclistit->type, funclistit->name
232 else
234 fprintf(out,
235 " %sAROS_LC%dQUAD%d%s(%s, %s, \\\n",
236 (isvoid) ? "" : "return ",
237 nargs, nquad, (isvoid) ? "NR" : "",
238 funclistit->type, funclistit->name
242 for (arglistit = funclistit->arguments;
243 arglistit != NULL;
244 arglistit = arglistit->next
247 char *quad2 = strchr(arglistit->reg, '/');
249 type = getargtype(arglistit);
250 name = getargname(arglistit);
251 assert(type != NULL && name != NULL);
253 if (quad2) {
254 *quad2 = 0;
255 fprintf(out,
256 " AROS_LCAQUAD(%s, %s, %s, %s), \\\n",
257 type, name, arglistit->reg, quad2+1
259 *quad2 = '/';
261 else
263 fprintf(out,
264 " AROS_LCA(%s, %s, %s), \\\n",
265 type, name, arglistit->reg
268 free(type);
269 free(name);
273 fprintf(out, " %s, __aros_getbase_%s(), %u, %s);\n}\n",
274 cfg->libbasetypeptrextern, cfg->libbase, funclistit->lvo, cfg->basename
277 else /* libcall==STACK */
279 /* Library version requirement added only for stack call functions
280 * since each function is in separate compilation unit. Reg call
281 * functions are all in one compilation unit. In such case highest
282 * version would alway be required even if function for that version
283 * is not used.
285 fprintf(out, "void __%s_%s_libreq(){ AROS_LIBREQ(%s,%d); }\n",
286 funclistit->name, cfg->libbase, cfg->libbase, funclistit->version
289 fprintf(out, "AROS_GM_%sLIBFUNCSTUB(%s, %s, %d)\n",
290 is_rel ? "REL" : "",
291 funclistit->name, cfg->libbase, funclistit->lvo
295 for (aliasesit = funclistit->aliases;
296 aliasesit != NULL;
297 aliasesit = aliasesit->next
300 fprintf(out, "AROS_GM_LIBFUNCALIAS(%s, %s)\n",
301 funclistit->name, aliasesit->s