cw.c revision 02e56f3f1bfc8d9977bafb8cb5202f576dcded27
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Wrapper for the GNU C compiler to make it accept the Sun C compiler
* arguments where possible.
*
* Since the translation is inexact, this is something of a work-in-progress.
*/
/*
* -# Verbose mode
* -### Show compiler commands built by driver, no compilation
* -A<name[(tokens)]> Preprocessor predicate assertion
* -B<[static|dynamic]> Specify dynamic or static binding
* -C Prevent preprocessor from removing comments
* -c Compile only - produce .o files, suppress linking
* -cg92 Alias for -xtarget=ss1000
* -D<name[=token]> Associate name with token as if by #define
* -d[y|n] dynamic [-dy] or static [-dn] option to linker
* -E Compile source through preprocessor only, output to stdout
* -erroff=<t> Suppress warnings specified by tags t(%none, %all, <tag list>)
* -errtags=<a> Display messages with tags a(no, yes)
* -errwarn=<t> Treats warnings specified by tags t(%none, %all, <tag list>)
* as errors
* -fast Optimize using a selection of options
* -fd Report old-style function definitions and declarations
* -flags Show this summary of compiler options
* -fnonstd Initialize floating-point hardware to non-standard preferences
* -fns[=<yes|no>] Select non-standard floating point mode
* -fprecision=<p> Set FP rounding precision mode p(single, double, extended)
* -fround=<r> Select the IEEE rounding mode in effect at startup
* -fsimple[=<n>] Select floating-point optimization preferences <n>
* -fsingle Use single-precision arithmetic (-Xt and -Xs modes only)
* -ftrap=<t> Select floating-point trapping mode in effect at startup
* -fstore force floating pt. values to target precision on assignment
* -G Build a dynamic shared library
* -g Compile for debugging
* -H Print path name of each file included during compilation
* -h <name> Assign <name> to generated dynamic shared library
* -I<dir> Add <dir> to preprocessor #include file search path
* -i Passed to linker to ignore any LD_LIBRARY_PATH setting
* -keeptmp Keep temporary files created during compilation
* -KPIC Compile position independent code with 32-bit addresses
* -Kpic Compile position independent code
* -L<dir> Pass to linker to add <dir> to the library search path
* -l<name> Link with library lib<name>.a or lib<name>.so
* -mc Remove duplicate strings from .comment section of output files
* -mr Remove all strings from .comment section of output files
* -mr,"string" Remove all strings and append "string" to .comment section
* -mt Specify options needed when compiling multi-threaded code
* -native Find available processor, generate code accordingly
* -nofstore Do not force floating pt. values to target precision
* on assignment
* -nolib Same as -xnolib
* -noqueue Disable queuing of compiler license requests
* -norunpath Do not build in a runtime path for shared libraries
* -O Use default optimization level (-xO2 or -xO3. Check man page.)
* -o <outputfile> Set name of output file to <outputfile>
* -P Compile source through preprocessor only, output to .i file
* -PIC Alias for -KPIC or -xcode=pic32
* -p Compile for profiling with prof
* -pic Alias for -Kpic or -xcode=pic13
* -qp Compile for profiling with prof
* -R<dir[:dir]> Build runtime search path list into executable
* -S Compile and only generate assembly code (.s)
* -s Strip symbol table from the executable file
* -t Turn off duplicate symbol warnings when linking
* -U<name> Delete initial definition of preprocessor symbol <name>
* -V Report version number of each compilation phase
* -v Do stricter semantic checking
* -W<c>,<arg> Pass <arg> to specified component <c> (a,l,m,p,0,2,h,i,u)
* -w Suppress compiler warning messages
* -Xa Compile assuming ANSI C conformance, allow K & R extensions
* (default mode)
* -Xc Compile assuming strict ANSI C conformance
* -Xs Compile assuming (pre-ANSI) K & R C style code
* -Xt Compile assuming K & R conformance, allow ANSI C
* -x386 Generate code for the 80386 processor
* -x486 Generate code for the 80486 processor
* -xarch=<a> Specify target architecture instruction set
* -xbuiltin[=<b>] When profitable inline, or substitute intrinisic functions
* for system functions, b={%all,%none}
* -xCC Accept C++ style comments
* -xchar_byte_order=<o> Specify multi-char byte order <o> (default, high, low)
* -xchip=<c> Specify the target processor for use by the optimizer
* -xcode=<c> Generate different code for forming addresses
* -xcrossfile[=<n>] Enable optimization and inlining across source files,
* n={0|1}
* -xF Compile for later mapfile reordering
* -xhelp=<f> Display on-line help information f(flags, readme, errors)
* -xildoff Cancel -xildon
* -xildon Enable use of the incremental linker, ild
* -xinline=[<a>,...,<a>] Attempt inlining of specified user routines,
* <a>={%auto,func,no%func}
* -xlibmieee Force IEEE 754 return values for math routines in
* exceptional cases
* -xlibmil Inline selected libm math routines for optimization
* -xlic_lib=sunperf Link in the Sun supplied performance libraries
* -xlicinfo Show license server information
* -xM Generate makefile dependencies
* -xmaxopt=[off,1,2,3,4,5] maximum optimization level allowed on #pragma opt
* -xnolib Do not link with default system libraries
* -xnolibmil Cancel -xlibmil on command line
* -xO<n> Generate optimized code (n={1|2|3|4|5})
* -xP Print prototypes for function definitions
* -xpentium Generate code for the pentium processor
* -xpg Compile for profiling with gprof
* -xprofile=<p> Collect data for a profile or use a profile to optimize
* <p>={{collect,use}[:<path>],tcov}
* -xregs=<r> Control register allocation
* -xs Allow debugging without object (.o) files
* -xsb Compile for use with the WorkShop source browser
* -xsbfast Generate only WorkShop source browser info, no compilation
* -xsfpconst Represent unsuffixed floating point constants as single
* precision
* -xspace Do not do optimizations that increase code size
* -xstrconst Place string literals into read-only data segment
* -xtarget=<t> Specify target system for optimization
* -xtemp=<dir> Set directory for temporary files to <dir>
* -xtime Report the execution time for each compilation phase
* -xtransition Emit warnings for differences between K&R C and ANSI C
* -xtrigraphs[=<yes|no>] Enable|disable trigraph translation
* -xunroll=n Enable unrolling loops n times where possible
* -Y<c>,<dir> Specify <dir> for location of component <c> (a,l,m,p,0,h,i,u)
* -YA,<dir> Change default directory searched for components
* -YI,<dir> Change default directory searched for include files
* -YP,<dir> Change default directory for finding libraries files
* -YS,<dir> Change default directory for startup object files
*/
/*
* Translation table:
*/
/*
* -# -v
* -### error
* -A<name[(tokens)]> pass-thru
* -B<[static|dynamic]> pass-thru (syntax error for anything else)
* -C pass-thru
* -c pass-thru
* -cg92 -m32 -mcpu=v8 -mtune=supersparc (SPARC only)
* -D<name[=token]> pass-thru
* -dy or -dn -Wl,-dy or -Wl,-dn
* -E pass-thru
* -erroff=E_EMPTY_TRANSLATION_UNIT ignore
* -errtags=%all -Wall
* -errwarn=%all -Werror else -Wno-error
* -fast error
* -fd error
* -flags --help
* -fnonstd error
* -fns[=<yes|no>] error
* -fprecision=<p> error
* -fround=<r> error
* -fsimple[=<n>] error
* -fsingle[=<n>] error
* -ftrap=<t> error
* -fstore error
* -G pass-thru
* -g pass-thru
* -H pass-thru
* -h <name> pass-thru
* -I<dir> pass-thru
* -i pass-thru
* -keeptmp -save-temps
* -KPIC -fPIC
* -Kpic -fpic
* -L<dir> pass-thru
* -l<name> pass-thru
* -mc error
* -mr error
* -mr,"string" error
* -mt -D_REENTRANT
* -native error
* -nofstore error
* -nolib -nodefaultlibs
* -noqueue ignore
* -norunpath ignore
* -O -O1 (Check the man page to be certain)
* -o <outputfile> pass-thru
* -P -E -o filename.i (or error)
* -PIC -fPIC (C++ only)
* -p pass-thru
* -pic -fpic (C++ only)
* -Q[y|n] error
* -qp -p
* -R<dir[:dir]> pass-thru
* -S pass-thru
* -s -Wl,-s
* -t -Wl,-t
* -U<name> pass-thru
* -V --version
* -v -Wall
* -Wa,<arg> pass-thru
* -Wp,<arg> pass-thru except -xc99=<a>
* -Wl,<arg> pass-thru
* -Wu,-xmodel=kernel -ffreestanding -mcmodel=kernel -mno-red-zone
* -Wu,-save_args -msave-args
* -w pass-thru
* -Xa -std=iso9899:199409 or -ansi
* -Xc -ansi -pedantic
* -Xt error
* -Xs -traditional -std=c89
* -x386 -march=i386 (x86 only)
* -x486 -march=i486 (x86 only)
* -xarch=<a> table
* -xbuiltin[=<b>] -fbuiltin (-fno-builtin otherwise)
* -xCC ignore
* -xchar_byte_order=<o> error
* -xchip=<c> table
* -xcode=<c> table
* -xdebugformat=<format> ignore (always use dwarf-2 for gcc)
* -xcrossfile[=<n>] ignore
* -xe error
* -xF error
* -xhelp=<f> error
* -xildoff ignore
* -xildon ignore
* -xinline ignore
* -xlibmieee error
* -xlibmil error
* -xlic_lib=sunperf error
* -xM -M
* -xM1 -MM
* -xmaxopt=[...] error
* -xnolib -nodefaultlibs
* -xnolibmil error
* -xO<n> -O<n>
* -xP error
* -xpentium -march=pentium (x86 only)
* -xpg error
* -xprofile=<p> error
* -xregs=<r> table
* -xs error
* -xsb error
* -xsbfast error
* -xsfpconst error
* -xspace ignore (-not -Os)
* -xstrconst ignore
* -xtarget=<t> table
* -xtemp=<dir> error
* -xtime error
* -xtransition -Wtransition
* -xtrigraphs=<yes|no> -trigraphs -notrigraphs
* -xunroll=n error
* -W0,-xdbggen=no%usedonly -fno-eliminate-unused-debug-symbols
* -fno-eliminate-unused-debug-types
* -Y<c>,<dir> error
* -YA,<dir> error
* -YI,<dir> -nostdinc -I<dir>
* -YP,<dir> error
* -YS,<dir> error
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/isa_defs.h>
static int echo = 1;
static int newargc;
static const char *progname;
static char *default_cc_dir;
static char *default_gcc_dir;
static char *default_cplusplus_dir;
static char *default_gplusplus_dir;
static const char *xarch_tbl[] = {
#if defined(__x86)
"generic", NULL,
#endif
};
static const char *xchip_tbl[] = {
#if defined(__x86)
#endif
};
static const char *xcode_tbl[] = {
#if defined(__sparc)
#endif
};
static const char *xtarget_tbl[] = {
#if defined(__x86)
#endif /* __x86 */
};
static const char *xregs_tbl[] = {
#if defined(__sparc)
#endif /* __sparc */
};
struct aelist {
struct ae {
char *ae_arg;
};
static struct aelist *
newael(void)
{
}
static void
{
else
newargc++;
}
static void
{
exit(2);
}
/*
* Add the current favourite set of warnings to the gcc invocation.
*/
static void
{
static int warningsonce;
if (warningsonce++)
return;
newae(h, "-Wall");
newae(h, "-Wno-unknown-pragmas");
newae(h, "-Wno-missing-braces");
newae(h, "-Wno-sign-compare");
newae(h, "-Wno-parentheses");
newae(h, "-Wno-uninitialized");
newae(h, "-Wno-implicit-function-declaration");
newae(h, "-Wno-unused");
newae(h, "-Wno-trigraphs");
newae(h, "-Wno-char-subscripts");
newae(h, "-Wno-switch");
}
static void
{
if (level >= 2) {
newae(h, "-fno-strict-aliasing");
newae(h, "-fno-unit-at-a-time");
newae(h, "-fno-optimize-sibling-calls");
}
}
/* ARGSUSED */
static void
{
}
static void
{
static int xconce;
if (xconce++)
return;
newae(h, "-ansi");
newae(h, "-pedantic-errors");
}
static void
{
static int xsonce;
if (xsonce++)
return;
newae(h, "-traditional");
newae(h, "-traditional-cpp");
}
static void
usage()
{
"usage: %s { -_cc | -_gcc | -_CC | -_g++ } [ -_compiler | ... ]\n",
progname);
exit(2);
}
static void
{
table++;
table++;
}
table++;
table++;
}
}
static void
{
int c;
int pic = 0;
int nolibc = 0;
char *program;
/*
* Basic defaults for ON compilation
*/
newae(h, "-fident");
newae(h, "-finline");
newae(h, "-fno-inline-functions");
newae(h, "-fno-builtin");
newae(h, "-fno-asm");
newae(h, "-nodefaultlibs");
#if defined(__sparc)
/*
* The SPARC ldd and std instructions require 8-byte alignment of
* their address operand. gcc correctly uses them only when the
* ABI requires 8-byte alignment; unfortunately we have a number of
* pieces of buggy code that doesn't conform to the ABI. This
* flag makes gcc work more like Studio with -xmemalign=4.
*/
newae(h, "-mno-integer-ldd-std");
#endif
/*
* This is needed because 'u' is defined
* under a conditional on 'sun'. Should
* probably just remove the conditional,
* or make it be dependent on '__sun'.
*
* -Dunix is also missing in enhanced ANSI mode
*/
newae(h, "-D__sun");
/*
* Walk the argument list, translating as we go ..
*/
while (--argc > 0) {
if (*arg == '-')
arglen--;
else {
/*
* Discard inline files that gcc doesn't grok
*/
if (arglen > 3 &&
continue;
/*
* Otherwise, filenames, and partial arguments
* are simply passed through for gcc to chew on.
*/
continue;
}
if (cplusplus) {
/* discard -compat=4 and -compat=5 */
continue;
}
/* discard -Qoption and its two arguments */
if (argc < 3)
argc -= 2;
argv += 2;
continue;
}
/* turn warnings into errors */
/* newae(h, "-Werror"); */
continue;
}
/* no exceptions */
newae(h, "-fno-exceptions");
/* no run time type descriptor information */
newae(h, "-fno-rtti");
continue;
}
newae(h, "-fpic");
pic = 1;
continue;
}
newae(h, "-fPIC");
pic = 1;
continue;
}
/* gcc has no corresponding option */
continue;
}
/* -nodefaultlibs is on by default */
nolibc = 1;
continue;
}
#if defined(__sparc)
continue;
}
#endif /* __sparc */
}
switch ((c = arg[1])) {
case '_':
echo = 0;
/* EMPTY */;
exit(0);
} else
break;
case '#':
if (arglen == 1) {
newae(h, "-v");
break;
}
break;
case 'g':
newae(h, "-gdwarf-2");
break;
case 'E':
if (arglen == 1) {
newae(h, "-xc");
nolibc = 1;
break;
}
break;
case 'c':
case 'S':
if (arglen == 1)
nolibc = 1;
/* FALLTHROUGH */
case 'C':
case 'H':
case 'p':
if (arglen == 1) {
break;
}
break;
case 'A':
case 'h':
case 'I':
case 'i':
case 'L':
case 'l':
case 'o':
case 'R':
case 'U':
case 'u':
case 'w':
break;
case 'D':
/*
* XXX Clearly a hack ... do we need _KADB too?
*/
newae(h, "-ffreestanding");
break;
case 'd':
if (arglen == 2) {
newae(h, "-Wl,-dy");
break;
}
newae(h, "-Wl,-dn");
break;
}
}
/*
* -dalign forces alignment in some cases;
* gcc does not need any flag to do this.
*/
break;
}
break;
case 'e':
"-erroff=E_EMPTY_TRANSLATION_UNIT") == 0) {
/*
* Accept but ignore this -- gcc doesn't
* seem to complain about empty translation
* units
*/
break;
}
/* XX64 -- ignore all -erroff= options, for now */
break;
warnings(h);
break;
}
newae(h, "-Werror");
break;
}
break;
case 'f':
newae(h, "--help");
break;
}
break;
case 'G':
newae(h, "-shared");
nolibc = 1;
break;
case 'k':
newae(h, "-save-temps");
break;
}
break;
case 'K':
if (arglen == 1) {
error("-K");
argc--;
} else {
arg += 2;
}
newae(h, "-fpic");
pic = 1;
break;
}
newae(h, "-fPIC");
pic = 1;
break;
}
error("-K");
break;
case 'm':
newae(h, "-D_REENTRANT");
break;
}
break;
case 'B': /* linker options */
case 'M':
case 'z':
{
char *opt;
char *s;
if (arglen == 1) {
argc--;
} else {
}
newae(h, s);
free(s);
}
break;
case 'n':
/*
* Horrid license server stuff - n/a
*/
break;
}
break;
case 'O':
if (arglen == 1) {
newae(h, "-O");
break;
}
break;
case 'P':
/*
* We could do '-E -o filename.i', but that's hard,
* and we don't need it for the case that's triggering
* this addition. We'll require the user to specify
* -o in the Makefile. If they don't they'll find out
* in a hurry.
*/
newae(h, "-E");
nolibc = 1;
break;
case 'q':
newae(h, "-p");
break;
}
break;
case 's':
if (arglen == 1) {
newae(h, "-Wl,-s");
break;
}
break;
case 't':
if (arglen == 1) {
newae(h, "-Wl,-t");
break;
}
break;
case 'V':
if (arglen == 1) {
echo = 0;
newae(h, "--version");
break;
}
break;
case 'v':
if (arglen == 1) {
warnings(h);
break;
}
break;
case 'W':
/*
* gcc's preprocessor will accept c99
* regardless, so accept and ignore.
*/
break;
}
break;
}
/* (undocumented) enables _Pragma */
break;
}
/*
* This is a polite way of saying
* "no c99 constructs allowed!"
* For now, just accept and ignore this.
*/
break;
}
/*
* gcc doesn't prefix local symbols
* in debug mode, so this is not needed.
*/
break;
}
/*
* Generate tests at the top of loops.
* There is no direct gcc equivalent, ignore.
*/
break;
}
newae(h, "-fno-eliminate-unused-debug-symbols");
newae(h, "-fno-eliminate-unused-debug-types");
break;
}
/*
* Elimination and expansion of conditionals;
* gcc has no direct equivalent.
*/
break;
}
/*
* Prevents optimizing away checks for
* unbound weak symbol addresses. gcc does
* not do this, so it's not needed.
*/
break;
}
pic = 1;
break;
}
/*
* Prevents insertion of register symbols.
* gcc doesn't do this, so ignore it.
*/
break;
}
#if defined(__x86)
newae(h, "-fno-jump-tables");
newae(h, "-fno-constant-pools");
break;
}
newae(h, "-ffreestanding");
newae(h, "-mno-red-zone");
model = "-mcmodel=kernel";
nolibc = 1;
break;
}
newae(h, "-msave-args");
break;
}
#endif /* __x86 */
break;
case 'X':
Xamode(h);
break;
}
Xcmode(h);
break;
}
Xsmode(h);
break;
}
break;
case 'x':
if (arglen == 1)
switch (arg[2]) {
#if defined(__x86)
case '3':
newae(h, "-march=i386");
break;
}
break;
case '4':
newae(h, "-march=i486");
break;
}
break;
#endif /* __x86 */
case 'a':
break;
}
break;
case 'b':
newae(h, "-fbuiltin");
break;
}
break;
case 'C':
/* Accept C++ style comments -- ignore */
break;
break;
case 'c':
newae(h, "-std=gnu99");
break;
}
newae(h, "-std=gnu89");
break;
}
break;
}
pic = 1;
break;
}
break;
break;
break;
case 'd':
break;
break;
break;
case 'F':
/* compile for mapfile reordering -- ignore */
break;
break;
case 'i':
/* No inlining; ignore */
break;
/* No incremental linking; ignore */
break;
break;
case 'M':
newae(h, "-M");
break;
}
newae(h, "-MM");
break;
}
break;
case 'n':
nolibc = 1;
break;
}
break;
case 'O':
int c = *(arg + 3);
int level;
if (level > 5)
if (level >= 2) {
/*
* For gcc-3.4.x at -O2 we
* need to disable optimizations
* that break ON.
*/
optim_disable(h, level);
/*
* limit -xO3 to -O2 as well.
*/
level = 2;
}
newae(h, s);
free(s);
break;
}
break;
case 'p':
newae(h, "-march=pentium");
break;
}
newae(h, "-pg");
break;
}
break;
case 'r':
break;
}
break;
case 's':
break;
break;
case 't':
newae(h, "-Wtransition");
break;
}
newae(h, "-trigraphs");
break;
}
newae(h, "-notrigraphs");
break;
}
break;
}
break;
case 'e':
case 'h':
case 'l':
default:
break;
}
break;
case 'Y':
if (arglen == 1) {
error("-Y");
argc--;
} else {
arg += 2;
}
/* Just ignore -YS,... for now */
break;
s[0] = '-';
s[1] = 'B';
newae(h, s);
free(s);
break;
}
s[0] = '-';
s[1] = 'I';
newae(h, "-nostdinc");
newae(h, s);
free(s);
break;
}
break;
case 'Q':
/*
* We could map -Qy into -Wl,-Qy etc.
*/
default:
break;
}
}
if (!nolibc)
newae(h, "-lc");
}
/* ARGSUSED4 */
static void
{
char *program;
/*
* This is pretty simple.
* We just have to recognize -V, -_noecho, -_compiler, -_cc= and -_gcc=
*/
while (--argc > 0) {
if (*arg != '-') {
echo = 0;
echo = 0;
exit(0);
exit(2);
}
}
}
int
{
const char *dir;
int ac;
char **newargv;
struct ae *a;
else
progname++;
/*
* Figure out where to get our tools from. This depends on
* the environment variables set at run time.
*/
}
default_cc_dir = (char *)cc_buf;
default_gcc_dir = (char *)gcc_buf;
}
/*
* The first argument must be one of "-_cc", "-_gcc", "-_CC", or "-_g++"
*/
if (argc == 1)
usage();
argc--;
argv++;
} else {
/* assume "-_gcc" by default */
argc++;
argv--;
}
if (echo)
(void) printf("+ ");
if (echo)
if (a == h->ael_tail)
break;
}
if (echo) {
(void) printf("\n");
}
/*
* Here goes ..
*/
/*
* execvp() returns only on error.
*/
perror("execvp");
return (4);
}