Added support for a new config option, "includename". This value defaults
[AROS.git] / tools / genmodule / writestubs.c
blob59696e6722549f6e8935d7edb1c44ca81d3e7f8a
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->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 if (!(cfg->options & OPTION_NOINCLUDES))
124 if (is_rel)
125 fprintf(out, "#define __%s_RELLIBBASE__\n", cfg->includenameupper);
126 fprintf(out, "#include <proto/%s.h>\n", cfg->includename);
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 "#include <aros/symbolsets.h>\n"
155 "\n"
159 static void writefuncstub(struct config *cfg, int is_rel, FILE *out, struct functionhead *funclistit)
161 struct stringlist *aliasesit;
162 struct functionarg *arglistit;
163 char *type, *name;
165 if (funclistit->libcall != STACK)
167 int nargs = 0, nquad = 0;
168 int isvoid = strcmp(funclistit->type, "void") == 0
169 || strcmp(funclistit->type, "VOID") == 0;
171 fprintf(out,
172 "\n"
173 "%s %s(",
174 funclistit->type, funclistit->name
176 for (arglistit = funclistit->arguments;
177 arglistit!=NULL;
178 arglistit = arglistit->next
181 if (arglistit != funclistit->arguments)
182 fprintf(out, ", ");
183 fprintf(out, "%s", arglistit->arg);
184 if (strchr(arglistit->reg, '/')) {
185 nquad++;
186 } else {
187 nargs++;
191 fprintf(out,
192 ")\n"
193 "{\n"
195 if (nquad == 0) {
196 fprintf(out,
197 " %sAROS_LC%d%s(%s, %s,\n",
198 (isvoid) ? "" : "return ",
199 funclistit->argcount, (isvoid) ? "NR" : "",
200 funclistit->type, funclistit->name
203 for (arglistit = funclistit->arguments;
204 arglistit!=NULL;
205 arglistit = arglistit->next
208 type = getargtype(arglistit);
209 name = getargname(arglistit);
210 assert(type != NULL && name != NULL);
212 fprintf(out, " AROS_LCA(%s,%s,%s),\n",
213 type, name, arglistit->reg
215 free(type);
216 free(name);
219 else /* nquad != 0 */
221 if (nargs == 0) {
222 fprintf(out,
223 " %sAROS_LCQUAD%d%s(%s, %s, \\\n",
224 (isvoid) ? "" : "return ",
225 funclistit->argcount, (isvoid) ? "NR" : "",
226 funclistit->type, funclistit->name
229 else
231 fprintf(out,
232 " %sAROS_LC%dQUAD%d%s(%s, %s, \\\n",
233 (isvoid) ? "" : "return ",
234 nargs, nquad, (isvoid) ? "NR" : "",
235 funclistit->type, funclistit->name
239 for (arglistit = funclistit->arguments;
240 arglistit != NULL;
241 arglistit = arglistit->next
244 char *quad2 = strchr(arglistit->reg, '/');
246 type = getargtype(arglistit);
247 name = getargname(arglistit);
248 assert(type != NULL && name != NULL);
250 if (quad2) {
251 *quad2 = 0;
252 fprintf(out,
253 " AROS_LCAQUAD(%s, %s, %s, %s), \\\n",
254 type, name, arglistit->reg, quad2+1
256 *quad2 = '/';
258 else
260 fprintf(out,
261 " AROS_LCA(%s, %s, %s), \\\n",
262 type, name, arglistit->reg
265 free(type);
266 free(name);
270 fprintf(out, " %s, __aros_getbase_%s(), %u, %s);\n}\n",
271 cfg->libbasetypeptrextern, cfg->libbase, funclistit->lvo, cfg->basename
274 else /* libcall==STACK */
276 /* Library version requirement added only for stack call functions
277 * since each function is in separate compilation unit. Reg call
278 * functions are all in one compilation unit. In such case highest
279 * version would alway be required even if function for that version
280 * is not used.
282 fprintf(out, "void __%s_%s_libreq(){ AROS_LIBREQ(%s,%d); }\n",
283 funclistit->name, cfg->libbase, cfg->libbase, funclistit->version
286 fprintf(out, "AROS_GM_%sLIBFUNCSTUB(%s, %s, %d)\n",
287 is_rel ? "REL" : "",
288 funclistit->name, cfg->libbase, funclistit->lvo
292 for (aliasesit = funclistit->aliases;
293 aliasesit != NULL;
294 aliasesit = aliasesit->next
297 fprintf(out, "AROS_GM_LIBFUNCALIAS(%s, %s)\n",
298 funclistit->name, aliasesit->s