typo..
[AROS.git] / tools / genmodule / writestubs.c
blob8ba6c15591561438565e67b8f1f464433356c84b
1 /*
2 Copyright © 1995-2018, 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 by 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 stubs 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 "#ifdef NOLIBINLINE\n"
95 "#undef NOLIBINLINE\n"
96 "#endif /* NOLIBINLINE */\n"
97 "#ifdef NOLIBDEFINES\n"
98 "#undef NOLIBDEFINES\n"
99 "#endif /* NOLIBDEFINES */\n"
100 "#define NOLIBINLINE\n"
101 "#define NOLIBDEFINES\n"
102 "char *__aros_getoffsettable(void);\n"
103 "#ifndef __%s_NOLIBBASE__\n"
104 "/* Do not include the libbase */\n"
105 "#define __%s_NOLIBBASE__\n"
106 "#endif\n",
107 banner, cfg->includenameupper, cfg->includenameupper
109 } else {
110 fprintf
112 out,
113 "%s"
114 "#ifdef NOLIBINLINE\n"
115 "#undef NOLIBINLINE\n"
116 "#endif /* NOLIBINLINE */\n"
117 "#ifdef NOLIBDEFINES\n"
118 "#undef NOLIBDEFINES\n"
119 "#endif /* NOLIBDEFINES */\n"
120 "#define NOLIBINLINE\n"
121 "#define NOLIBDEFINES\n"
122 "/* Be sure that the libbases are included in the stubs file */\n"
123 "#ifdef __NOLIBBASE__\n"
124 "#undef __NOLIBBASE__\n"
125 "#endif /* __NOLIBBASE__ */\n"
126 "#ifdef __%s_NOLIBBASE__\n"
127 "#undef __%s_NOLIBBASE__\n"
128 "#endif /* __%s_NOLIBBASE__ */\n",
129 banner, cfg->includenameupper, cfg->includenameupper, cfg->includenameupper
132 freeBanner(banner);
134 for (linelistit = cfg->stubprivatelines; linelistit!=NULL; linelistit = linelistit->next)
135 fprintf(out, "%s\n", linelistit->s);
137 if (!(cfg->options & OPTION_NOINCLUDES))
139 if (is_rel)
140 fprintf(out, "#define __%s_RELLIBBASE__\n", cfg->includenameupper);
141 fprintf(out, "#include <proto/%s.h>\n", cfg->includename);
143 else
145 fprintf(out,
146 "#include <exec/types.h>\n"
147 "#include <aros/system.h>\n\n"
150 for (linelistit = cfg->cdefprivatelines; linelistit!=NULL; linelistit = linelistit->next)
151 fprintf(out, "%s\n", linelistit->s);
153 fprintf(out,
154 "\n"
155 "%s__aros_getbase_%s(void);\n"
156 "\n",
157 cfg->libbasetypeptrextern, cfg->libbase
161 fprintf
163 out,
164 "#include <stddef.h>\n"
165 "\n"
166 "#include <aros/cpu.h>\n"
167 "#include <aros/genmodule.h>\n"
168 "#include <aros/libcall.h>\n"
169 "#include <aros/symbolsets.h>\n"
170 "\n"
174 static void writefuncstub(struct config *cfg, int is_rel, FILE *out, struct functionhead *funclistit)
176 struct stringlist *aliasesit;
177 struct functionarg *arglistit;
178 char *type, *name;
180 if (funclistit->libcall != STACK)
182 int nargs = 0, nquad = 0;
183 int isvoid = strcmp(funclistit->type, "void") == 0
184 || strcmp(funclistit->type, "VOID") == 0;
186 fprintf(out,
187 "\n"
188 "%s %s(",
189 funclistit->type, funclistit->name
191 for (arglistit = funclistit->arguments;
192 arglistit!=NULL;
193 arglistit = arglistit->next
196 if (arglistit != funclistit->arguments)
197 fprintf(out, ", ");
198 fprintf(out, "%s", arglistit->arg);
199 if (strchr(arglistit->reg, '/')) {
200 nquad++;
201 } else {
202 nargs++;
206 fprintf(out,
207 ")\n"
208 "{\n"
210 if (nquad == 0) {
211 fprintf(out,
212 " %sAROS_LC%d%s(%s, %s,\n",
213 (isvoid) ? "" : "return ",
214 funclistit->argcount, (isvoid) ? "NR" : "",
215 funclistit->type, funclistit->name
218 for (arglistit = funclistit->arguments;
219 arglistit!=NULL;
220 arglistit = arglistit->next
223 type = getargtype(arglistit);
224 name = getargname(arglistit);
225 assert(type != NULL && name != NULL);
227 fprintf(out, " AROS_LCA(%s,%s,%s),\n",
228 type, name, arglistit->reg
230 free(type);
231 free(name);
234 else /* nquad != 0 */
236 if (nargs == 0) {
237 fprintf(out,
238 " %sAROS_LCQUAD%d%s(%s, %s, \\\n",
239 (isvoid) ? "" : "return ",
240 funclistit->argcount, (isvoid) ? "NR" : "",
241 funclistit->type, funclistit->name
244 else
246 fprintf(out,
247 " %sAROS_LC%dQUAD%d%s(%s, %s, \\\n",
248 (isvoid) ? "" : "return ",
249 nargs, nquad, (isvoid) ? "NR" : "",
250 funclistit->type, funclistit->name
254 for (arglistit = funclistit->arguments;
255 arglistit != NULL;
256 arglistit = arglistit->next
259 char *quad2 = strchr(arglistit->reg, '/');
261 type = getargtype(arglistit);
262 name = getargname(arglistit);
263 assert(type != NULL && name != NULL);
265 if (quad2) {
266 *quad2 = 0;
267 fprintf(out,
268 " AROS_LCAQUAD(%s, %s, %s, %s), \\\n",
269 type, name, arglistit->reg, quad2+1
271 *quad2 = '/';
273 else
275 fprintf(out,
276 " AROS_LCA(%s, %s, %s), \\\n",
277 type, name, arglistit->reg
280 free(type);
281 free(name);
285 fprintf(out, " %s, __aros_getbase_%s(), %u, %s);\n}\n",
286 cfg->libbasetypeptrextern, cfg->libbase, funclistit->lvo, cfg->basename
289 else /* libcall==STACK */
291 /* Library version requirement added only for stack call functions
292 * since each function is in separate compilation unit. Reg call
293 * functions are all in one compilation unit. In such case highest
294 * version would always be required even if function for that version
295 * is not used.
297 fprintf(out, "void __%s_%s_libreq(){ AROS_LIBREQ(%s,%d); }\n",
298 funclistit->name, cfg->libbase, cfg->libbase, funclistit->version
301 fprintf(out, "AROS_GM_%sLIBFUNCSTUB(%s, %s, %d)\n",
302 is_rel ? "REL" : "",
303 funclistit->name, cfg->libbase, funclistit->lvo
307 for (aliasesit = funclistit->aliases;
308 aliasesit != NULL;
309 aliasesit = aliasesit->next
312 fprintf(out, "AROS_GM_LIBFUNCALIAS(%s, %s)\n",
313 funclistit->name, aliasesit->s