2 Copyright © 1995-2018, 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 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
)
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 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");
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 "#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"
107 banner
, cfg
->includenameupper
, cfg
->includenameupper
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
134 for (linelistit
= cfg
->stubprivatelines
; linelistit
!=NULL
; linelistit
= linelistit
->next
)
135 fprintf(out
, "%s\n", linelistit
->s
);
137 if (!(cfg
->options
& OPTION_NOINCLUDES
))
140 fprintf(out
, "#define __%s_RELLIBBASE__\n", cfg
->includenameupper
);
141 fprintf(out
, "#include <proto/%s.h>\n", cfg
->includename
);
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
);
155 "%s__aros_getbase_%s(void);\n"
157 cfg
->libbasetypeptrextern
, cfg
->libbase
164 "#include <stddef.h>\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"
174 static void writefuncstub(struct config
*cfg
, int is_rel
, FILE *out
, struct functionhead
*funclistit
)
176 struct stringlist
*aliasesit
;
177 struct functionarg
*arglistit
;
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;
189 funclistit
->type
, funclistit
->name
191 for (arglistit
= funclistit
->arguments
;
193 arglistit
= arglistit
->next
196 if (arglistit
!= funclistit
->arguments
)
198 fprintf(out
, "%s", arglistit
->arg
);
199 if (strchr(arglistit
->reg
, '/')) {
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
;
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
234 else /* nquad != 0 */
238 " %sAROS_LCQUAD%d%s(%s, %s, \\\n",
239 (isvoid
) ? "" : "return ",
240 funclistit
->argcount
, (isvoid
) ? "NR" : "",
241 funclistit
->type
, funclistit
->name
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
;
256 arglistit
= arglistit
->next
259 char *quad2
= strchr(arglistit
->reg
, '/');
261 type
= getargtype(arglistit
);
262 name
= getargname(arglistit
);
263 assert(type
!= NULL
&& name
!= NULL
);
268 " AROS_LCAQUAD(%s, %s, %s, %s), \\\n",
269 type
, name
, arglistit
->reg
, quad2
+1
276 " AROS_LCA(%s, %s, %s), \\\n",
277 type
, name
, arglistit
->reg
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
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",
303 funclistit
->name
, cfg
->libbase
, funclistit
->lvo
307 for (aliasesit
= funclistit
->aliases
;
309 aliasesit
= aliasesit
->next
312 fprintf(out
, "AROS_GM_LIBFUNCALIAS(%s, %s)\n",
313 funclistit
->name
, aliasesit
->s