mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-02 23:18:44 +00:00
338 lines
12 KiB
C
338 lines
12 KiB
C
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||
|
│ │
|
||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||
|
│ │
|
||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||
|
#include "libc/bits/safemacros.h"
|
||
|
#include "libc/calls/calls.h"
|
||
|
#include "libc/calls/sigbits.h"
|
||
|
#include "libc/calls/struct/sigset.h"
|
||
|
#include "libc/errno.h"
|
||
|
#include "libc/fmt/conv.h"
|
||
|
#include "libc/log/log.h"
|
||
|
#include "libc/mem/mem.h"
|
||
|
#include "libc/runtime/runtime.h"
|
||
|
#include "libc/str/str.h"
|
||
|
#include "libc/sysv/consts/sig.h"
|
||
|
#include "libc/x/x.h"
|
||
|
|
||
|
#define MANUAL \
|
||
|
"\
|
||
|
OVERVIEW\n\
|
||
|
\n\
|
||
|
GNU/LLVM Compiler Collection Frontend Frontend\n\
|
||
|
\n\
|
||
|
DESCRIPTION\n\
|
||
|
\n\
|
||
|
This launches gcc or clang while filtering out\n\
|
||
|
flags they whine about.\n\
|
||
|
\n\
|
||
|
EXAMPLE\n\
|
||
|
\n\
|
||
|
compile.com gcc -o program program.c\n\
|
||
|
\n"
|
||
|
|
||
|
struct Flags {
|
||
|
size_t n;
|
||
|
char **p;
|
||
|
};
|
||
|
|
||
|
struct Command {
|
||
|
size_t n;
|
||
|
char *p;
|
||
|
};
|
||
|
|
||
|
bool iscc;
|
||
|
bool isclang;
|
||
|
bool isgcc;
|
||
|
bool wantasan;
|
||
|
bool wantfentry;
|
||
|
bool wantframe;
|
||
|
bool wantnop;
|
||
|
bool wantnopg;
|
||
|
bool wantpg;
|
||
|
bool wantrecord;
|
||
|
bool wantubsan;
|
||
|
|
||
|
char *cc;
|
||
|
char *colorflag;
|
||
|
char *outdir;
|
||
|
char *outpath;
|
||
|
char ccpath[PATH_MAX];
|
||
|
int ccversion;
|
||
|
|
||
|
struct Flags flags;
|
||
|
struct Command command;
|
||
|
|
||
|
void AddFlag(char *s) {
|
||
|
size_t n;
|
||
|
flags.p = realloc(flags.p, ++flags.n * sizeof(*flags.p));
|
||
|
flags.p[flags.n - 1] = s;
|
||
|
if (s) {
|
||
|
n = strlen(s);
|
||
|
if (command.n) {
|
||
|
command.p = realloc(command.p, command.n + 1 + n);
|
||
|
command.p[command.n] = ' ';
|
||
|
memcpy(command.p + command.n + 1, s, n);
|
||
|
command.n += 1 + n;
|
||
|
} else {
|
||
|
command.p = realloc(command.p, command.n + n);
|
||
|
memcpy(command.p + command.n, s, n);
|
||
|
command.n += n;
|
||
|
}
|
||
|
} else {
|
||
|
command.p = realloc(command.p, command.n + 1);
|
||
|
command.p[command.n] = '\n';
|
||
|
command.n += 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[]) {
|
||
|
int i, ws, pid;
|
||
|
sigset_t mask, savemask;
|
||
|
|
||
|
if (argc == 1) {
|
||
|
write(2, MANUAL, sizeof(MANUAL) - 1);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if (argc == 2 && !strcmp(argv[1], "--do-nothing")) {
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
if (!isdirectory("o/third_party/gcc")) {
|
||
|
system("third_party/gcc/unbundle.sh");
|
||
|
}
|
||
|
|
||
|
cc = argv[1];
|
||
|
if (!strchr(cc, '/')) {
|
||
|
if (!(cc = commandv(argv[1], ccpath))) exit(127);
|
||
|
}
|
||
|
|
||
|
ccversion = atoi(firstnonnull(emptytonull(getenv("CCVERSION")), "4"));
|
||
|
isgcc = strstr(basename(cc), "gcc");
|
||
|
isclang = strstr(basename(cc), "clang");
|
||
|
iscc = isgcc | isclang;
|
||
|
|
||
|
for (i = 1; i < argc; ++i) {
|
||
|
if (argv[i][0] != '-') {
|
||
|
AddFlag(argv[i]);
|
||
|
continue;
|
||
|
}
|
||
|
if (!strcmp(argv[i], "-o")) {
|
||
|
AddFlag(argv[i]);
|
||
|
AddFlag((outpath = argv[++i]));
|
||
|
continue;
|
||
|
}
|
||
|
if (iscc) {
|
||
|
AddFlag(argv[i]);
|
||
|
continue;
|
||
|
}
|
||
|
if (!strcmp(argv[i], "-w")) {
|
||
|
AddFlag(argv[i]);
|
||
|
AddFlag("-D__W__");
|
||
|
} else if (!strcmp(argv[i], "-Oz")) {
|
||
|
if (isclang) {
|
||
|
AddFlag(argv[i]);
|
||
|
} else {
|
||
|
AddFlag("-Os");
|
||
|
}
|
||
|
} else if (!strcmp(argv[i], "-pg")) {
|
||
|
wantpg = true;
|
||
|
} else if (!strcmp(argv[i], "-x-no-pg")) {
|
||
|
wantnopg = true;
|
||
|
} else if (!strcmp(argv[i], "-mfentry")) {
|
||
|
wantfentry = true;
|
||
|
} else if (!strcmp(argv[i], "-mnop-mcount")) {
|
||
|
wantnop = true;
|
||
|
} else if (!strcmp(argv[i], "-mrecord-mcount")) {
|
||
|
wantrecord = true;
|
||
|
} else if (!strcmp(argv[i], "-fno-omit-frame-pointer")) {
|
||
|
wantframe = true;
|
||
|
} else if (!strcmp(argv[i], "-fomit-frame-pointer")) {
|
||
|
wantframe = false;
|
||
|
} else if (!strcmp(argv[i], "-mno-vzeroupper")) {
|
||
|
if (isgcc) {
|
||
|
AddFlag("-Wa,-msse2avx");
|
||
|
AddFlag("-D__MNO_VZEROUPPER__");
|
||
|
} else if (isclang) {
|
||
|
AddFlag("-mllvm");
|
||
|
AddFlag("-x86-use-vzeroupper=0");
|
||
|
}
|
||
|
} else if (!strcmp(argv[i], "-msse2avx")) {
|
||
|
if (isgcc) {
|
||
|
AddFlag(argv[i]);
|
||
|
} else if (isclang) {
|
||
|
AddFlag("-Wa,-msse2avx");
|
||
|
}
|
||
|
} else if (!strcmp(argv[i], "-fsanitize=address")) {
|
||
|
if (isgcc && ccversion >= 6) wantasan = true;
|
||
|
} else if (!strcmp(argv[i], "-fsanitize=undefined")) {
|
||
|
if (isgcc && ccversion >= 6) wantubsan = true;
|
||
|
} else if (!strcmp(argv[i], "-fno-sanitize=address")) {
|
||
|
wantasan = false;
|
||
|
} else if (!strcmp(argv[i], "-fno-sanitize=undefined")) {
|
||
|
wantubsan = false;
|
||
|
} else if (!strcmp(argv[i], "-fno-sanitize=all")) {
|
||
|
wantasan = false;
|
||
|
wantubsan = false;
|
||
|
} else if (startswith(argv[i], "-fsanitize=implicit") &&
|
||
|
strstr(argv[i], "integer")) {
|
||
|
if (isgcc) AddFlag(argv[i]);
|
||
|
} else if (startswith(argv[i], "-fvect-cost") ||
|
||
|
startswith(argv[i], "-mstringop") ||
|
||
|
startswith(argv[i], "-gz") ||
|
||
|
strstr(argv[i], "stack-protector") ||
|
||
|
strstr(argv[i], "sanitize") ||
|
||
|
startswith(argv[i], "-fvect-cost") ||
|
||
|
startswith(argv[i], "-fvect-cost")) {
|
||
|
if (isgcc && ccversion >= 6) {
|
||
|
AddFlag(argv[i]);
|
||
|
}
|
||
|
} else if (startswith(argv[i], "-fdiagnostic-color=")) {
|
||
|
colorflag = argv[i];
|
||
|
} else if (startswith(argv[i], "-R") ||
|
||
|
!strcmp(argv[i], "-fsave-optimization-record")) {
|
||
|
if (isclang) AddFlag(argv[i]);
|
||
|
} else if (isclang &&
|
||
|
(!strcmp(argv[i], "-gstabs") || !strcmp(argv[i], "-ftrapv") ||
|
||
|
!strcmp(argv[i], "-fsignaling-nans") ||
|
||
|
!strcmp(argv[i], "-fcx-limited-range") ||
|
||
|
!strcmp(argv[i], "-fno-fp-int-builtin-inexact") ||
|
||
|
!strcmp(argv[i], "-Wno-unused-but-set-variable") ||
|
||
|
!strcmp(argv[i], "-Wunsafe-loop-optimizations") ||
|
||
|
!strcmp(argv[i], "-mdispatch-scheduler") ||
|
||
|
!strcmp(argv[i], "-ftracer") ||
|
||
|
!strcmp(argv[i], "-frounding-math") ||
|
||
|
!strcmp(argv[i], "-fmerge-constants") ||
|
||
|
!strcmp(argv[i], "-fmodulo-sched") ||
|
||
|
!strcmp(argv[i], "-fopt-info-vec") ||
|
||
|
!strcmp(argv[i], "-fopt-info-vec-missed") ||
|
||
|
!strcmp(argv[i], "-fmodulo-sched-allow-regmoves") ||
|
||
|
!strcmp(argv[i], "-freschedule-modulo-scheduled-loops") ||
|
||
|
!strcmp(argv[i], "-fipa-pta") ||
|
||
|
!strcmp(argv[i], "-fsched2-use-superblocks") ||
|
||
|
!strcmp(argv[i], "-fbranch-target-load-optimize") ||
|
||
|
!strcmp(argv[i], "-fdelete-dead-exceptions") ||
|
||
|
!strcmp(argv[i], "-funsafe-loop-optimizations") ||
|
||
|
!strcmp(argv[i], "-mmitigate-rop") ||
|
||
|
!strcmp(argv[i], "-fno-align-jumps") ||
|
||
|
!strcmp(argv[i], "-fno-align-labels") ||
|
||
|
!strcmp(argv[i], "-fno-align-loops") ||
|
||
|
!strcmp(argv[i], "-fivopts") ||
|
||
|
!strcmp(argv[i], "-fschedule-insns") ||
|
||
|
!strcmp(argv[i], "-fno-semantic-interposition") ||
|
||
|
!strcmp(argv[i], "-mno-fentry") ||
|
||
|
!strcmp(argv[i], "-fversion-loops-for-strides") ||
|
||
|
!strcmp(argv[i], "-femit-struct-debug-baseonly") ||
|
||
|
!strcmp(argv[i], "-ftree-loop-vectorize") ||
|
||
|
!strcmp(argv[i], "-gdescribe-dies") ||
|
||
|
!strcmp(argv[i], "-flimit-function-alignment") ||
|
||
|
!strcmp(argv[i], "-ftree-loop-im") ||
|
||
|
!strcmp(argv[i], "-fno-instrument-functions") ||
|
||
|
!strcmp(argv[i], "-fstack-clash-protection") ||
|
||
|
!strcmp(argv[i], "-mfpmath=sse+387") ||
|
||
|
!strcmp(argv[i], "-Wa,--noexecstack") ||
|
||
|
!strcmp(argv[i], "-freg-struct-return") ||
|
||
|
!strcmp(argv[i], "-mcall-ms2sysv-xlogues") ||
|
||
|
startswith(argv[i], "-ffixed-") ||
|
||
|
startswith(argv[i], "-fcall-saved") ||
|
||
|
startswith(argv[i], "-fcall-used") ||
|
||
|
startswith(argv[i], "-fgcse-") ||
|
||
|
strstr(argv[i], "shrink-wrap") ||
|
||
|
strstr(argv[i], "schedule-insns2") ||
|
||
|
startswith(argv[i], "-fvect-cost-model=") ||
|
||
|
startswith(argv[i], "-fsimd-cost-model=") ||
|
||
|
startswith(argv[i], "-fopt-info") ||
|
||
|
startswith(argv[i], "-mstringop-strategy=") ||
|
||
|
startswith(argv[i], "-mpreferred-stack-boundary=") ||
|
||
|
strstr(argv[i], "gnu-unique") ||
|
||
|
startswith(argv[i], "-Wframe-larger-than=") ||
|
||
|
strstr(argv[i], "whole-program") ||
|
||
|
startswith(argv[i], "-Wa,--size-check=") ||
|
||
|
startswith(argv[i], "-Wa,--listing"))) {
|
||
|
/* ignore flag so clang won't whine */
|
||
|
} else {
|
||
|
AddFlag(argv[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (iscc) {
|
||
|
if (isclang) {
|
||
|
AddFlag("-fno-integrated-as");
|
||
|
AddFlag("-Wno-unused-command-line-argument");
|
||
|
AddFlag("-Wno-incompatible-pointer-types-discards-qualifiers");
|
||
|
}
|
||
|
AddFlag("-no-canonical-prefixes");
|
||
|
if (!IsTerminalInarticulate()) {
|
||
|
AddFlag(firstnonnull(colorflag, "-fdiagnostics-color=always"));
|
||
|
}
|
||
|
if (wantpg && !wantnopg) {
|
||
|
AddFlag("-pg");
|
||
|
AddFlag("-D__PG__");
|
||
|
if (wantnop && !isclang) {
|
||
|
AddFlag("-mnop-mcount");
|
||
|
AddFlag("-D__MNOP_MCOUNT__");
|
||
|
}
|
||
|
if (wantrecord) {
|
||
|
AddFlag("-mrecord-mcount");
|
||
|
AddFlag("-D__MRECORD_MCOUNT__");
|
||
|
}
|
||
|
if (wantfentry) {
|
||
|
AddFlag("-mfentry");
|
||
|
AddFlag("-D__MFENTRY__");
|
||
|
}
|
||
|
}
|
||
|
if (wantasan) {
|
||
|
AddFlag("-fsanitize=address");
|
||
|
AddFlag("-D__FSANITIZE_ADDRESS__");
|
||
|
}
|
||
|
if (wantubsan) {
|
||
|
AddFlag("-fsanitize=undefined");
|
||
|
AddFlag("-fno-data-sections");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AddFlag(NULL);
|
||
|
|
||
|
if (outpath) {
|
||
|
outdir = xdirname(outpath);
|
||
|
if (!isdirectory(outdir)) {
|
||
|
makedirs(outdir, 0755);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
write(2, command.p, command.n);
|
||
|
|
||
|
sigfillset(&mask);
|
||
|
sigprocmask(SIG_BLOCK, &mask, &savemask);
|
||
|
if ((pid = vfork()) == -1) exit(errno);
|
||
|
if (!pid) {
|
||
|
sigprocmask(SIG_SETMASK, &savemask, NULL);
|
||
|
execv(cc, flags.p);
|
||
|
_exit(127);
|
||
|
}
|
||
|
while (waitpid(pid, &ws, 0) == -1) {
|
||
|
if (errno != EINTR) exit(errno);
|
||
|
}
|
||
|
|
||
|
if (WIFEXITED(ws)) {
|
||
|
return WEXITSTATUS(ws);
|
||
|
} else {
|
||
|
return 128 + WTERMSIG(ws);
|
||
|
}
|
||
|
}
|