xref: /netbsd-src/external/bsd/pcc/dist/pcc/cc/driver/platform.c (revision 3862d4bab153103b9c3d09043872889458100388)
1 /*	Id: platform.c,v 1.5 2012/08/09 11:41:28 ragge Exp 	*/
2 /*	$NetBSD: platform.c,v 1.1.1.2 2014/07/24 19:25:08 plunky Exp $	*/
3 
4 /*-
5  * Copyright (c) 2011 Joerg Sonnenberger <joerg@NetBSD.org>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <string.h>
34 
35 #include "driver.h"
36 #include "config.h"
37 
38 #include "ccconfig.h"
39 
40 #ifndef NEW_DRIVER_CFG
41 #define	USE_OLD_DRIVER_CFG
42 #endif
43 
44 #define _MKS(x)		#x
45 #define MKS(x)		_MKS(x)
46 
47 #ifndef PREPROCESSOR
48 #define PREPROCESSOR	"cpp"
49 #endif
50 
51 #ifndef COMPILER
52 #define COMPILER	"ccom"
53 #endif
54 
55 #ifndef ASSEMBLER
56 #define ASSEMBLER	"as"
57 #endif
58 
59 #ifndef LINKER
60 #define LINKER		"ld"
61 #endif
62 
63 enum architecture {
64 	ARCH_ANY,
65 	ARCH_I386,
66 	ARCH_X86_64
67 };
68 
69 static const struct {
70 	enum architecture arch;
71 	const char *name;
72 } arch_mapping[] = {
73 #ifdef USE_OLD_DRIVER_CFG
74 	{ ARCH_ANY, TARGMACH },
75 #else
76 	{ ARCH_I386, "i386" },
77 	{ ARCH_X86_64, "x86_64" } ,
78 #endif
79 };
80 
81 enum os {
82 	OS_ANY,
83 	OS_NETBSD,
84 	OS_LINUX
85 };
86 
87 static const struct {
88 	enum os os;
89 	const char *name;
90 } os_mapping[] = {
91 #ifdef USE_OLD_DRIVER_CFG
92 	{ OS_ANY, TARGOS },
93 #else
94 	{ OS_NETBSD, "netbsd" },
95 	{ OS_LINUX, "linux" },
96 #endif
97 };
98 
99 struct platform_specific {
100 	enum architecture arch;
101 	enum os os;
102 	const char * const *values;
103 };
104 
105 #ifndef USE_OLD_DRIVER_CFG
106 static const char * const early_program_csu_values0[] = { "crt0.o", NULL };
107 static const char * const early_program_csu_values1[] = { "crt1.o", NULL };
108 #else
109 static const char * const early_program_csu_values2[] = {
110 	CRT0FILE, NULL
111 };
112 #endif
113 
114 static const struct platform_specific early_program_csu[] = {
115 #ifdef USE_OLD_DRIVER_CFG
116 	{ ARCH_ANY, OS_ANY, early_program_csu_values2 },
117 #else
118 	{ ARCH_ANY, OS_NETBSD, early_program_csu_values0 },
119 	{ ARCH_ANY, OS_LINUX, early_program_csu_values1 },
120 #endif
121 };
122 
123 static const char * const late_program_csu_values0[] = {
124     "crtend.o", "crtn.o", NULL
125 };
126 static const struct platform_specific late_program_csu[] = {
127     { ARCH_ANY, OS_ANY, late_program_csu_values0 },
128 };
129 
130 static const char * const early_dso_csu_values0[] = {
131     "crtio", "crtbeginS.o", NULL
132 };
133 static const struct platform_specific early_dso_csu[] = {
134     { ARCH_ANY, OS_ANY, early_dso_csu_values0 },
135 };
136 
137 static const char * const late_dso_csu_values0[] = {
138     "crtendS.o", "crtn.o", NULL
139 };
140 static const struct platform_specific late_dso_csu[] = {
141     { ARCH_ANY, OS_ANY, late_dso_csu_values0 },
142 };
143 
144 static const char * const predefined_macros_values0[] = {
145     "-D__x86_64__", "-D__x86_64", "-D__amd64__", "-D__amd64", NULL
146 };
147 static const char * const predefined_macros_values1[] = {
148     "-D__NetBSD__", "-D__ELF__", NULL
149 };
150 static const char * const predefined_macros_values2[] = {
151     "-D__linux__", "-D__ELF__", NULL
152 };
153 static const char * const predefined_macros_values3[] = {
154     "-D__i386__", NULL
155 };
156 static const char * const predefined_macros_values4[] = {
157     "-D__PCC__=" MKS(PCC_MAJOR),
158     "-D__PCC_MINOR__=" MKS(PCC_MINOR),
159     "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR),
160     "-D__VERSION__=" MKS(VERSSTR),
161     "-D__STDC_ISO_10646__=200009L",
162     NULL
163 };
164 static const char * const predefined_macros_values5[] = {
165     "-D__GNUC__=4",
166     "-D__GNUC_MINOR__=3",
167     "-D__GNUC_PATCHLEVEL__=1",
168     "-D__GNUC_STDC_INLINE__=1",
169     NULL
170 };
171 static const struct platform_specific predefined_macros[] = {
172     { ARCH_X86_64, OS_ANY, predefined_macros_values0 },
173     { ARCH_ANY, OS_NETBSD, predefined_macros_values1 },
174     { ARCH_ANY, OS_LINUX, predefined_macros_values2 },
175     { ARCH_I386, OS_ANY, predefined_macros_values3 },
176     { ARCH_ANY, OS_ANY, predefined_macros_values4 },
177     { ARCH_ANY, OS_ANY, predefined_macros_values5 },
178 };
179 
180 static const char * const early_linker_values0[] = {
181     "-dynamic-linker", "/libexec/ld.elf_so", NULL
182 };
183 static const char * const early_linker_values1[] = {
184     "-m", "elf_i386", NULL
185 };
186 static const char * const early_linker_values2[] = {
187     "-m", "elf_x86_64", NULL
188 };
189 static const char * const early_linker_values3[] = {
190     "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", NULL
191 };
192 static const char * const early_linker_values4[] = {
193     "-m", "elf_i386", NULL
194 };
195 static const char * const early_linker_values5[] = {
196     "-m", "elf_x86_64", NULL
197 };
198 static const struct platform_specific early_linker[] = {
199     { ARCH_ANY, OS_NETBSD, early_linker_values0 },
200     { ARCH_I386, OS_NETBSD, early_linker_values1 },
201     { ARCH_X86_64, OS_NETBSD, early_linker_values2 },
202     { ARCH_ANY, OS_LINUX, early_linker_values3 },
203     { ARCH_I386, OS_LINUX, early_linker_values4 },
204     { ARCH_X86_64, OS_LINUX, early_linker_values5 },
205 };
206 
207 static const char * const sysincdir_list_values0[] = {
208     "=/usr/include", NULL
209 };
210 static const char * const sysincdir_list_values1[] = {
211     /* XXX fix up for libpcc? */
212     "=/usr/lib/gcc/x86_64-linux-gnu/4.4/include", NULL
213 };
214 static const struct platform_specific sysincdir_list[] = {
215     { ARCH_ANY, OS_ANY, sysincdir_list_values0 },
216     { ARCH_X86_64, OS_LINUX, sysincdir_list_values1 },
217 };
218 
219 static const char * const crtdir_list_values0[] = {
220     "=/usr/lib/i386", "=/usr/lib", NULL
221 };
222 static const char * const crtdir_list_values1[] = {
223     "=/usr/lib", NULL
224 };
225 static const char * const crtdir_list_values2[] = {
226     "=/usr/lib64", "=/usr/lib/gcc/x86_64-linux-gnu/4.4", NULL
227 };
228 static const struct platform_specific crtdir_list[] = {
229     { ARCH_I386, OS_NETBSD, crtdir_list_values0 },
230     { ARCH_X86_64, OS_NETBSD, crtdir_list_values1 },
231     { ARCH_X86_64, OS_LINUX, crtdir_list_values2 },
232 };
233 
234 static const char * const stdlib_list_values0[] = {
235     "-L/usr/lib/gcc/x86_64-linux-gnu/4.4", NULL
236 };
237 static const char * const stdlib_list_values1[] = {
238     "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed",
239     "-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", NULL
240 };
241 static const struct platform_specific stdlib_list[] = {
242     { ARCH_X86_64, OS_LINUX, stdlib_list_values0 },
243     { ARCH_ANY, OS_ANY, stdlib_list_values1 },
244 };
245 
246 static const char * const program_dirs_values0[] = {
247     LIBEXECDIR, NULL
248 };
249 static const struct platform_specific program_dirs[] = {
250     { ARCH_ANY, OS_ANY, program_dirs_values0 },
251 };
252 
253 #define	ARRAYLEN(a)	(sizeof(a) / sizeof((a)[0]))
254 #define	ARRAYPAIR(a)	a, ARRAYLEN(a)
255 
256 static const struct {
257 	const struct platform_specific *initializer;
258 	size_t len;
259 	struct strlist *list;
260 } platform_specific_inits[] = {
261     { ARRAYPAIR(early_program_csu), &early_program_csu_files },
262     { ARRAYPAIR(late_program_csu), &late_program_csu_files },
263     { ARRAYPAIR(early_dso_csu), &early_dso_csu_files },
264     { ARRAYPAIR(late_dso_csu), &late_dso_csu_files },
265     { ARRAYPAIR(predefined_macros), &preprocessor_flags },
266     { ARRAYPAIR(early_linker), &early_linker_flags },
267     { ARRAYPAIR(sysincdir_list), &sysincdirs },
268     { ARRAYPAIR(crtdir_list), &crtdirs },
269     { ARRAYPAIR(stdlib_list), &stdlib_flags },
270     { ARRAYPAIR(program_dirs), &progdirs },
271 };
272 
273 void
init_platform_specific(const char * os_name,const char * arch_name)274 init_platform_specific(const char *os_name, const char *arch_name)
275 {
276 	enum os os;
277 	enum architecture arch;
278 	size_t i, j, len;
279 	const struct platform_specific *initializer;
280 	struct strlist *l;
281 
282 	os = OS_ANY;
283 	for (i = 0; i < ARRAYLEN(os_mapping); ++i) {
284 		if (strcmp(os_mapping[i].name, os_name) == 0) {
285 			os = os_mapping[i].os;
286 			break;
287 		}
288 	}
289 	if (os == OS_ANY)
290 		error("unknown Operating System: %s", os_name);
291 
292 	arch = ARCH_ANY;
293 	for (i = 0; i < ARRAYLEN(arch_mapping); ++i) {
294 		if (strcmp(arch_mapping[i].name, arch_name) == 0) {
295 			arch = arch_mapping[i].arch;
296 			break;
297 		}
298 	}
299 	if (arch == ARCH_ANY)
300 		error("unknown architecture: %s", arch_name);
301 
302 	for (i = 0; i < ARRAYLEN(platform_specific_inits); ++i) {
303 		initializer = platform_specific_inits[i].initializer;
304 		len = platform_specific_inits[i].len;
305 		l = platform_specific_inits[i].list;
306 		for (j = 0; j < len; ++j) {
307 			if (initializer[j].arch != arch &&
308 			    initializer[j].arch != ARCH_ANY)
309 				continue;
310 			if (initializer[j].os != os &&
311 			    initializer[j].os != OS_ANY)
312 				continue;
313 			strlist_append_array(l, initializer[j].values);
314 		}
315 	}
316 
317 	preprocessor = PREPROCESSOR;
318 	compiler = COMPILER;
319 	assembler = ASSEMBLER;
320 	linker = LINKER;
321 }
322