2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
5 Function to write module stubs. Part of genmodule.
7 Stubs are agregated differently into objects files based on STACK vs REG
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
)
30 struct functionhead
*funclistit
;
32 /* Build STACKCALL - each stub in separate object file */
33 for (funclistit
= cfg
->funclist
;
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");
50 writeheader(cfg
, is_rel
, out
);
51 writefuncstub(cfg
, is_rel
, out
, funclistit
);
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");
67 writeheader(cfg
, is_rel
, out
);
69 for (funclistit
= cfg
->funclist
;
71 funclistit
= funclistit
->next
74 if (funclistit
->lvo
>= cfg
->firstlvo
&& funclistit
->libcall
!= STACK
)
76 writefuncstub(cfg
, is_rel
, out
, funclistit
);
83 static void writeheader(struct config
*cfg
, int is_rel
, FILE *out
)
85 struct stringlist
*linelistit
;
88 banner
= getBanner(cfg
);
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"
103 banner
, cfg
->modulenameupper
, cfg
->modulenameupper
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
122 if (!(cfg
->options
& OPTION_NOINCLUDES
))
125 fprintf(out
, "#define __%s_RELLIBBASE__\n", cfg
->modulenameupper
);
126 fprintf(out
, "#include <proto/%s.h>\n", cfg
->modulename
);
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
);
140 "%s__aros_getbase_%s(void);\n"
142 cfg
->libbasetypeptrextern
, cfg
->libbase
149 "#include <stddef.h>\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"
159 static void writefuncstub(struct config
*cfg
, int is_rel
, FILE *out
, struct functionhead
*funclistit
)
161 struct stringlist
*aliasesit
;
162 struct functionarg
*arglistit
;
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;
174 funclistit
->type
, funclistit
->name
176 for (arglistit
= funclistit
->arguments
;
178 arglistit
= arglistit
->next
181 if (arglistit
!= funclistit
->arguments
)
183 fprintf(out
, "%s", arglistit
->arg
);
184 if (strchr(arglistit
->reg
, '/')) {
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
;
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
219 else /* nquad != 0 */
223 " %sAROS_LCQUAD%d%s(%s, %s, \\\n",
224 (isvoid
) ? "" : "return ",
225 funclistit
->argcount
, (isvoid
) ? "NR" : "",
226 funclistit
->type
, funclistit
->name
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
;
241 arglistit
= arglistit
->next
244 char *quad2
= strchr(arglistit
->reg
, '/');
246 type
= getargtype(arglistit
);
247 name
= getargname(arglistit
);
248 assert(type
!= NULL
&& name
!= NULL
);
253 " AROS_LCAQUAD(%s, %s, %s, %s), \\\n",
254 type
, name
, arglistit
->reg
, quad2
+1
261 " AROS_LCA(%s, %s, %s), \\\n",
262 type
, name
, arglistit
->reg
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
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",
288 funclistit
->name
, cfg
->libbase
, funclistit
->lvo
292 for (aliasesit
= funclistit
->aliases
;
294 aliasesit
= aliasesit
->next
297 fprintf(out
, "AROS_GM_LIBFUNCALIAS(%s, %s)\n",
298 funclistit
->name
, aliasesit
->s