1 /* Subroutines for the gcc driver.
2    Copyright (C) 2007-2020 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10 
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #define IN_TARGET_CODE 1
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "diagnostic.h"
27 #include "opts.h"
28 #include <stdlib.h>
29 
30 #ifdef _AIX
31 # include <sys/systemcfg.h>
32 #endif
33 
34 #ifdef __linux__
35 # include <link.h>
36 #endif
37 
38 #if defined (__APPLE__) || (__FreeBSD__)
39 # include <sys/types.h>
40 # include <sys/sysctl.h>
41 #endif
42 
43 #ifdef __linux__
44 /* Canonical GCC cpu name table.  */
45 static const char *rs6000_supported_cpu_names[] =
46 {
47 #define RS6000_CPU(NAME, CPU, FLAGS) NAME,
48 #include "rs6000-cpus.def"
49 #undef RS6000_CPU
50 };
51 
52 /* This table holds a list of cpus where their Linux AT_PLATFORM name differs
53    from their GCC canonical name.  The first column in a row contains the GCC
54    canonical cpu name and the other columns in that row contain AT_PLATFORM
55    names that should be mapped to the canonical name.  */
56 
57 static const char *linux_cpu_translation_table[][4] = {
58   { "403", "ppc403", NULL },
59   { "405", "ppc405", NULL },
60   { "440", "ppc440", "ppc440gp", NULL },
61   { "476", "ppc470", NULL },
62   { "601", "ppc601", NULL },
63   { "603", "ppc603", NULL },
64   { "604", "ppc604", NULL },
65   { "7400", "ppc7400", NULL },
66   { "7450", "ppc7450", NULL },
67   { "750", "ppc750", NULL },
68   { "823", "ppc823", NULL },
69   { "8540", "ppc8540", NULL },
70   { "8548", "ppc8548", NULL },
71   { "970", "ppc970", NULL },
72   { "cell", "ppc-cell-be", NULL },
73   { "e500mc", "ppce500mc", NULL },
74   { "e5500", "ppce5500", NULL },
75   { "e6500", "ppce6500", NULL },
76   { "power7", "power7+", NULL },
77   { NULL } /* End of table sentinel.  */
78 };
79 #endif
80 
81 const char *host_detect_local_cpu (int argc, const char **argv);
82 
83 #if GCC_VERSION >= 0
84 
85 /* Returns parameters that describe L1_ASSOC associative cache of size
86    L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB.  */
87 
88 static char *
describe_cache(unsigned l1_sizekb,unsigned l1_line,unsigned l1_assoc ATTRIBUTE_UNUSED,unsigned l2_sizekb)89 describe_cache (unsigned l1_sizekb, unsigned l1_line,
90 		unsigned l1_assoc ATTRIBUTE_UNUSED, unsigned l2_sizekb)
91 {
92   char l1size[1000], line[1000], l2size[1000];
93 
94   /* At the moment, gcc middle-end does not use the information about the
95      associativity of the cache.  */
96 
97   sprintf (l1size, "--param l1-cache-size=%u", l1_sizekb);
98   sprintf (line, "--param l1-cache-line-size=%u", l1_line);
99   sprintf (l2size, "--param l2-cache-size=%u", l2_sizekb);
100 
101   return concat (l1size, " ", line, " ", l2size, " ", NULL);
102 }
103 
104 #ifdef __APPLE__
105 
106 /* Returns the description of caches on Darwin.  */
107 
108 static char *
detect_caches_darwin(void)109 detect_caches_darwin (void)
110 {
111   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
112   size_t len = 4;
113   static int l1_size_name[2] = { CTL_HW, HW_L1DCACHESIZE };
114   static int l1_line_name[2] = { CTL_HW, HW_CACHELINE };
115   static int l2_size_name[2] = { CTL_HW, HW_L2CACHESIZE };
116 
117   sysctl (l1_size_name, 2, &l1_sizekb, &len, NULL, 0);
118   sysctl (l1_line_name, 2, &l1_line, &len, NULL, 0);
119   sysctl (l2_size_name, 2, &l2_sizekb, &len, NULL, 0);
120   l1_assoc = 0;
121 
122   return describe_cache (l1_sizekb / 1024, l1_line, l1_assoc,
123 			 l2_sizekb / 1024);
124 }
125 
126 static const char *
detect_processor_darwin(void)127 detect_processor_darwin (void)
128 {
129   unsigned int proc;
130   size_t len = 4;
131 
132   sysctlbyname ("hw.cpusubtype", &proc, &len, NULL, 0);
133 
134   if (len > 0)
135     switch (proc)
136       {
137       case 1:
138 	return "601";
139       case 2:
140 	return "602";
141       case 3:
142 	return "603";
143       case 4:
144       case 5:
145 	return "603e";
146       case 6:
147 	return "604";
148       case 7:
149 	return "604e";
150       case 8:
151 	return "620";
152       case 9:
153 	return "750";
154       case 10:
155 	return "7400";
156       case 11:
157 	return "7450";
158       case 100:
159 	return "970";
160       default:
161 	return "powerpc";
162       }
163 
164   return "powerpc";
165 }
166 
167 #endif /* __APPLE__ */
168 
169 #ifdef __FreeBSD__
170 
171 /* Returns the description of caches on FreeBSD PPC.  */
172 
173 static char *
detect_caches_freebsd(void)174 detect_caches_freebsd (void)
175 {
176   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
177   size_t len = 4;
178 
179   /* Currently, as of FreeBSD-7.0, there is only the cacheline_size
180      available via sysctl.  */
181   sysctlbyname ("machdep.cacheline_size", &l1_line, &len, NULL, 0);
182 
183   l1_sizekb = 32;
184   l1_assoc = 0;
185   l2_sizekb = 512;
186 
187   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
188 }
189 
190 /* Currently returns default powerpc.  */
191 static const char *
detect_processor_freebsd(void)192 detect_processor_freebsd (void)
193 {
194   return "powerpc";
195 }
196 
197 #endif /* __FreeBSD__  */
198 
199 #ifdef __linux__
200 
201 /* Returns the canonical AT_PLATFORM if present, otherwise NULL.  */
202 
203 static const char *
elf_platform(void)204 elf_platform (void)
205 {
206   /* Used to cache the result we determine below.  */
207   static const char *cpu = NULL;
208 
209   /* Use the cached AT_PLATFORM cpu name if we've already determined it.  */
210   if (cpu != NULL)
211     return cpu;
212 
213   int fd = open ("/proc/self/auxv", O_RDONLY);
214 
215   if (fd != -1)
216     {
217       char buf[1024];
218       ElfW(auxv_t) *av;
219       ssize_t n;
220 
221       n = read (fd, buf, sizeof (buf));
222       close (fd);
223 
224       if (n > 0)
225 	{
226 	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
227 	    if (av->a_type == AT_PLATFORM)
228 	      {
229 		/* Cache the result.  */
230 		cpu = (const char *) av->a_un.a_val;
231 		break;
232 	      }
233 	}
234 
235       /* Verify that CPU is either a valid -mcpu=<cpu> option name, or is a
236 	 valid alternative name.  If it is a valid alternative name, then use
237 	 the canonical name.  */
238       if (cpu != NULL)
239 	{
240 	  size_t i, j;
241 	  char *s;
242 
243 	  /* Check if AT_PLATFORM is a GCC canonical cpu name.  */
244 	  for (i = 0; i < ARRAY_SIZE (rs6000_supported_cpu_names); i++)
245 	    if (!strcmp (cpu, rs6000_supported_cpu_names[i]))
246 	      return cpu;
247 
248 	  /* Check if AT_PLATFORM can be translated to a canonical cpu name.  */
249 	  for (i = 0; linux_cpu_translation_table[i][0] != NULL; i++)
250 	    {
251 	      const char *canonical = linux_cpu_translation_table[i][0];
252 	      for (j = 1; linux_cpu_translation_table[i][j] != NULL; j++)
253 		if (!strcmp (cpu, linux_cpu_translation_table[i][j]))
254 		  {
255 		    /* Cache the result.  */
256 		    cpu = canonical;
257 		    return cpu;
258 		  }
259 	    }
260 
261 	  /* The kernel returned an AT_PLATFORM name we do not support.  */
262 	  auto_vec <const char *> candidates;
263 	  for (i = 0; i < ARRAY_SIZE (rs6000_supported_cpu_names); i++)
264 	    candidates.safe_push (rs6000_supported_cpu_names[i]);
265 	  candidates_list_and_hint (cpu, s, candidates);
266 	  error ("unsupported cpu name returned from kernel "
267 		 "for %<-mcpu=native%>: %s", cpu);
268 	  fatal_error (input_location, "please use an explicit cpu name; "
269 		       "valid cpu names are: %s", s);
270 	}
271     }
272   return NULL;
273 }
274 
275 /* Returns AT_DCACHEBSIZE if present, otherwise generic 32.  */
276 
277 static int
elf_dcachebsize(void)278 elf_dcachebsize (void)
279 {
280   int fd;
281 
282   fd = open ("/proc/self/auxv", O_RDONLY);
283 
284   if (fd != -1)
285     {
286       char buf[1024];
287       ElfW(auxv_t) *av;
288       ssize_t n;
289 
290       n = read (fd, buf, sizeof (buf));
291       close (fd);
292 
293       if (n > 0)
294 	{
295 	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
296 	    switch (av->a_type)
297 	      {
298 	      case AT_DCACHEBSIZE:
299 		return av->a_un.a_val;
300 
301 	      default:
302 		break;
303 	      }
304 	}
305     }
306   return 32;
307 }
308 
309 /* Returns the description of caches on Linux.  */
310 
311 static char *
detect_caches_linux(void)312 detect_caches_linux (void)
313 {
314   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
315   const char *platform;
316 
317   platform = elf_platform ();
318 
319   if (platform != NULL)
320     {
321       l1_line = 128;
322 
323       if (platform[5] == '6')
324 	/* POWER6 and POWER6x */
325 	l1_sizekb = 64;
326       else
327 	l1_sizekb = 32;
328     }
329   else
330     {
331       l1_line = elf_dcachebsize ();
332       l1_sizekb = 32;
333     }
334 
335   l1_assoc = 0;
336   l2_sizekb = 512;
337 
338   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
339 }
340 
341 static const char *
detect_processor_linux(void)342 detect_processor_linux (void)
343 {
344   const char *platform;
345 
346   platform = elf_platform ();
347 
348   if (platform != NULL)
349     return platform;
350   else
351     return "powerpc";
352 }
353 
354 #endif /* __linux__ */
355 
356 #ifdef _AIX
357 /* Returns the description of caches on AIX.  */
358 
359 static char *
detect_caches_aix(void)360 detect_caches_aix (void)
361 {
362   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
363 
364   l1_sizekb = _system_configuration.dcache_size / 1024;
365   l1_line = _system_configuration.dcache_line;
366   l1_assoc = _system_configuration.dcache_asc;
367   l2_sizekb = _system_configuration.L2_cache_size / 1024;
368 
369   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
370 }
371 
372 
373 /* Returns the processor implementation on AIX.  */
374 
375 static const char *
detect_processor_aix(void)376 detect_processor_aix (void)
377 {
378   switch (_system_configuration.implementation)
379     {
380     case 0x0008:
381       return "601";
382 
383     case 0x0020:
384       return "603";
385 
386     case 0x0010:
387       return "604";
388 
389     case 0x0040:
390       return "620";
391 
392     case 0x0080:
393       return "630";
394 
395     case 0x0100:
396     case 0x0200:
397     case 0x0400:
398       return "rs64";
399 
400     case 0x0800:
401       return "power4";
402 
403     case 0x2000:
404       if (_system_configuration.version == 0x0F0000)
405 	return "power5";
406       else
407 	return "power5+";
408 
409     case 0x4000:
410       return "power6";
411 
412     case 0x8000:
413       return "power7";
414 
415     case 0x10000:
416       return "power8";
417 
418     case 0x20000:
419       return "power9";
420 
421     default:
422       return "powerpc";
423     }
424 }
425 #endif /* _AIX */
426 
427 
428 /*
429  * Array to map -mcpu=native names to the switches passed to the assembler.
430  * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
431  * should be made there as well.
432  */
433 
434 struct asm_name {
435   const char *cpu;
436   const char *asm_sw;
437 };
438 
439 static const struct asm_name asm_names[] = {
440 #if defined (_AIX)
441   { "power3",	"-m620" },
442   { "power4",	"-mpwr4" },
443   { "power5",	"-mpwr5" },
444   { "power5+",	"-mpwr5x" },
445   { "power6",	"-mpwr6" },
446   { "power6x",	"-mpwr6" },
447   { "power7",	"-mpwr7" },
448   { "power8",	"-mpwr8" },
449   { "power9",	"-mpwr9" },
450   { "power10",	"-mpwr10" },
451   { "powerpc",	"-mppc" },
452   { "rs64",	"-mppc" },
453   { "603",	"-m603" },
454   { "603e",	"-m603" },
455   { "604",	"-m604" },
456   { "604e",	"-m604" },
457   { "620",	"-m620" },
458   { "630",	"-m620" },
459   { "970",	"-m970" },
460   { "G5",	"-m970" },
461   { NULL,	"\
462   %{mvsx: -mpwr6; \
463     maltivec: -m970; \
464     maix64|mpowerpc64: -mppc64; \
465     : %(asm_default)}" },
466 
467 #else
468   { "cell",	"-mcell" },
469   { "power3",	"-mppc64" },
470   { "power4",	"-mpower4" },
471   { "power5",	"-mpower5" },
472   { "power5+",	"-mpower5" },
473   { "power6",	"-mpower6 %{!mvsx:%{!maltivec:-maltivec}}" },
474   { "power6x",	"-mpower6 %{!mvsx:%{!maltivec:-maltivec}}" },
475   { "power7",	"-mpower7" },
476   { "power8",	"%{mpower9-vector:-mpower9;:-mpower8}" },
477   { "power9",	"-mpower9" },
478   { "power10",	"-mpower10" },
479   { "a2",	"-ma2" },
480   { "powerpc",	"-mppc" },
481   { "powerpc64", "-mppc64" },
482   { "powerpc64le", "%{mpower9-vector:-mpower9;:-mpower8}" },
483   { "rs64",	"-mppc64" },
484   { "401",	"-mppc" },
485   { "403",	"-m403" },
486   { "405",	"-m405" },
487   { "405fp",	"-m405" },
488   { "440",	"-m440" },
489   { "440fp",	"-m440" },
490   { "464",	"-m440" },
491   { "464fp",	"-m440" },
492   { "476",	"-m476" },
493   { "476fp",	"-m476" },
494   { "505",	"-mppc" },
495   { "601",	"-m601" },
496   { "602",	"-mppc" },
497   { "603",	"-mppc" },
498   { "603e",	"-mppc" },
499   { "ec603e",	"-mppc" },
500   { "604",	"-mppc" },
501   { "604e",	"-mppc" },
502   { "620",	"-mppc64" },
503   { "630",	"-mppc64" },
504   { "740",	"-mppc" },
505   { "750",	"-mppc" },
506   { "G3",	"-mppc" },
507   { "7400",	"-mppc %{!mvsx:%{!maltivec:-maltivec}}" },
508   { "7450",	"-mppc %{!mvsx:%{!maltivec:-maltivec}}" },
509   { "G4",	"-mppc %{!mvsx:%{!maltivec:-maltivec}}" },
510   { "801",	"-mppc" },
511   { "821",	"-mppc" },
512   { "823",	"-mppc" },
513   { "860",	"-mppc" },
514   { "970",	"-mpower4 %{!mvsx:%{!maltivec:-maltivec}}" },
515   { "G5",	"-mpower4 %{!mvsx:%{!maltivec:-maltivec}}" },
516   { "8540",	"-me500" },
517   { "8548",	"-me500" },
518   { "e300c2",	"-me300" },
519   { "e300c3",	"-me300" },
520   { "e500mc",	"-me500mc" },
521   { "e500mc64",	"-me500mc64" },
522   { "e5500",	"-me5500" },
523   { "e6500",	"-me6500" },
524   { "titan",	"-mtitan" },
525   { NULL,	"\
526 %{mpower9-vector: -mpower9; \
527   mpower8-vector|mcrypto|mdirect-move|mhtm: -mpower8; \
528   mvsx: -mpower7; \
529   mpowerpc64: -mppc64; \
530   : %(asm_default)}" },
531 #endif
532 };
533 
534 /* This will be called by the spec parser in gcc.c when it sees
535    a %:local_cpu_detect(args) construct.  Currently it will be called
536    with either "arch" or "tune" as argument depending on if -march=native
537    or -mtune=native is to be substituted.
538 
539    Additionally it will be called with "asm" to select the appropriate flags
540    for the assembler.
541 
542    It returns a string containing new command line parameters to be
543    put at the place of the above two options, depending on what CPU
544    this is executed.
545 
546    ARGC and ARGV are set depending on the actual arguments given
547    in the spec.  */
548 const char *
host_detect_local_cpu(int argc,const char ** argv)549 host_detect_local_cpu (int argc, const char **argv)
550 {
551   const char *cpu = NULL;
552   const char *cache = "";
553   const char *options = "";
554   bool arch;
555   bool assembler;
556   size_t i;
557 
558   if (argc < 1)
559     return NULL;
560 
561   arch = strcmp (argv[0], "cpu") == 0;
562   assembler = (!arch && strcmp (argv[0], "asm") == 0);
563   if (!arch && !assembler && strcmp (argv[0], "tune"))
564     return NULL;
565 
566   if (! assembler)
567     {
568 #if defined (_AIX)
569       cache = detect_caches_aix ();
570 #elif defined (__APPLE__)
571       cache = detect_caches_darwin ();
572 #elif defined (__FreeBSD__)
573       cache = detect_caches_freebsd ();
574       /* FreeBSD PPC does not provide any cache information yet.  */
575       cache = "";
576 #elif defined (__linux__)
577       cache = detect_caches_linux ();
578       /* PPC Linux does not provide any cache information yet.  */
579       cache = "";
580 #else
581       cache = "";
582 #endif
583     }
584 
585 #if defined (_AIX)
586   cpu = detect_processor_aix ();
587 #elif defined (__APPLE__)
588   cpu = detect_processor_darwin ();
589 #elif defined (__FreeBSD__)
590   cpu = detect_processor_freebsd ();
591 #elif defined (__linux__)
592   cpu = detect_processor_linux ();
593 #else
594   cpu = "powerpc";
595 #endif
596 
597   if (assembler)
598     {
599       for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++)
600 	{
601 	  if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu))
602 	    return asm_names[i].asm_sw;
603 	}
604 
605       return NULL;
606     }
607 
608   return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
609 }
610 
611 #else /* GCC_VERSION */
612 
613 /* If we aren't compiling with GCC we just provide a minimal
614    default value.  */
615 const char *
host_detect_local_cpu(int argc,const char ** argv)616 host_detect_local_cpu (int argc, const char **argv)
617 {
618   const char *cpu;
619   bool arch;
620 
621   if (argc < 1)
622     return NULL;
623 
624   arch = strcmp (argv[0], "cpu") == 0;
625   if (!arch && strcmp (argv[0], "tune"))
626     return NULL;
627 
628   if (arch)
629     cpu = "powerpc";
630 
631   return concat ("-m", argv[0], "=", cpu, NULL);
632 }
633 
634 #endif /* GCC_VERSION */
635 
636