2 Copyright © 1995-2016, 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
->libgendir
, 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
->libgendir
, 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
->includenameupper
, cfg
->includenameupper
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
122 for (linelistit
= cfg
->stubprivatelines
; linelistit
!=NULL
; linelistit
= linelistit
->next
)
123 fprintf(out
, "%s\n", linelistit
->s
);
125 if (!(cfg
->options
& OPTION_NOINCLUDES
))
128 fprintf(out
, "#define __%s_RELLIBBASE__\n", cfg
->includenameupper
);
129 fprintf(out
, "#include <proto/%s.h>\n", cfg
->includename
);
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
);
143 "%s__aros_getbase_%s(void);\n"
145 cfg
->libbasetypeptrextern
, cfg
->libbase
152 "#include <stddef.h>\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"
162 static void writefuncstub(struct config
*cfg
, int is_rel
, FILE *out
, struct functionhead
*funclistit
)
164 struct stringlist
*aliasesit
;
165 struct functionarg
*arglistit
;
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;
177 funclistit
->type
, funclistit
->name
179 for (arglistit
= funclistit
->arguments
;
181 arglistit
= arglistit
->next
184 if (arglistit
!= funclistit
->arguments
)
186 fprintf(out
, "%s", arglistit
->arg
);
187 if (strchr(arglistit
->reg
, '/')) {
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
;
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
222 else /* nquad != 0 */
226 " %sAROS_LCQUAD%d%s(%s, %s, \\\n",
227 (isvoid
) ? "" : "return ",
228 funclistit
->argcount
, (isvoid
) ? "NR" : "",
229 funclistit
->type
, funclistit
->name
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
;
244 arglistit
= arglistit
->next
247 char *quad2
= strchr(arglistit
->reg
, '/');
249 type
= getargtype(arglistit
);
250 name
= getargname(arglistit
);
251 assert(type
!= NULL
&& name
!= NULL
);
256 " AROS_LCAQUAD(%s, %s, %s, %s), \\\n",
257 type
, name
, arglistit
->reg
, quad2
+1
264 " AROS_LCA(%s, %s, %s), \\\n",
265 type
, name
, arglistit
->reg
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
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",
291 funclistit
->name
, cfg
->libbase
, funclistit
->lvo
295 for (aliasesit
= funclistit
->aliases
;
297 aliasesit
= aliasesit
->next
300 fprintf(out
, "AROS_GM_LIBFUNCALIAS(%s, %s)\n",
301 funclistit
->name
, aliasesit
->s