Enhance chibicc

main
Justine Tunney 2020-12-09 04:00:48 -08:00
parent 8da931a7f6
commit 9df2cef4c4
52 changed files with 2606 additions and 2004 deletions

View File

@ -104,7 +104,7 @@ CONFIG_COPTS += \
-ftrapv
TARGET_ARCH ?= \
-march=k8-sse3
-msse3
OVERRIDE_CCFLAGS += \
-fno-pie
@ -177,6 +177,6 @@ ifeq ($(MODE), ansi)
CONFIG_CFLAGS += -std=c11
#CONFIG_CPPFLAGS += -ansi
CONFIG_CXXFLAGS += -std=c++11
TARGET_ARCH ?= -march=k8-sse3
TARGET_ARCH ?= -msse3
endif

View File

@ -22,6 +22,11 @@ set -e
SPECIAL_TEXT=$(
$1 --version |
sed -n '
/chibicc/ {
i\
chibicc
q
}
/Free Software/ {
i\
gcc

View File

@ -229,12 +229,12 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
* @see Intel Six-Thousand Page Manual Manual V.3A §8.2.3.1
* @see atomic_load()
*/
#define atomic_store(MEM, VAL) \
({ \
autotype(VAL) Val = (VAL); \
typeof(&Val) Mem = (MEM); \
asm("mov%z1\t%1,%0" : "=m,m"(*Mem) : "i,r"(Val)); \
Val; \
#define atomic_store(MEM, VAL) \
({ \
autotype(VAL) Val = (VAL); \
typeof(&Val) Mem = (MEM); \
asm("mov%z1\t%1,%0" : "=m"(*Mem) : "r"(Val)); \
Val; \
})
#define bts(MEM, BIT) __BitOp("bts", BIT, MEM) /** bit test and set */

View File

@ -39,9 +39,6 @@ $(LIBC_BITS_A).pkg: \
$(LIBC_BITS_A_OBJS) \
$(foreach x,$(LIBC_BITS_A_DIRECTDEPS),$($(x)_A).pkg)
#o/$(MODE)/libc/bits/bsf.o: CC = clang-10
#o/$(MODE)/libc/bits/bsf.o: CC = /opt/cross9cc/bin/x86_64-linux-musl-cc
LIBC_BITS_LIBS = $(foreach x,$(LIBC_BITS_ARTIFACTS),$($(x)))
LIBC_BITS_SRCS = $(foreach x,$(LIBC_BITS_ARTIFACTS),$($(x)_SRCS))
LIBC_BITS_HDRS = $(foreach x,$(LIBC_BITS_ARTIFACTS),$($(x)_HDRS))

View File

@ -1,7 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_FMT_BING_H_
#define COSMOPOLITAN_LIBC_FMT_BING_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#ifndef __cplusplus
int bing(int, int) nosideeffect;
int unbing(int) nosideeffect;
@ -9,8 +8,6 @@ void *unbingbuf(void *, size_t, const char16_t *, int);
void *unbingstr(const char16_t *) paramsnonnull() mallocesque;
void *unhexbuf(void *, size_t, const char *);
void *unhexstr(const char *) mallocesque;
short *bingblit(int ys, int xs, unsigned char[ys][xs], int, int);
#endif /* __cplusplus */
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_FMT_BING_H_ */

View File

@ -2,7 +2,7 @@
#define COSMOPOLITAN_LIBC_FMT_PFLINK_H_
#include "libc/dce.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#if !defined(__STRICT_ANSI__) && !defined(__chibicc__)
#ifndef __STRICT_ANSI__
/**
* @fileoverview builtin+preprocessor+linker tricks for printf/scanf.

View File

@ -10,7 +10,7 @@
#define COSMOPOLITAN_CXX_USING_
#endif
#if defined(__STRICT_ANSI__) && __STDC_VERSION__ + 0 < 201112
#ifdef __STRICT_ANSI__
#define asm __asm__
#endif
@ -773,8 +773,9 @@ typedef uint64_t uintmax_t;
*/
#if __cplusplus + 0 >= 201103L
#define autotype(x) auto
#elif (__has_builtin(auto_type) || defined(__llvm__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
#elif ((__has_builtin(auto_type) || defined(__llvm__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409) && \
!defined(__chibicc__))
#define autotype(x) __auto_type
#else
#define autotype(x) typeof(x)

View File

@ -7,7 +7,7 @@ COSMOPOLITAN_C_START_
void palignr(void *, const void *, const void *, unsigned long);
#ifndef __STRICT_ANSI__
#if !defined(__STRICT_ANSI__) && !defined(__chibicc__)
__intrin_xmm_t __palignrs(__intrin_xmm_t, __intrin_xmm_t);
#define palignr(C, B, A, I) \
do { \

View File

@ -20,7 +20,7 @@
#include "libc/intrin/pand.h"
/**
* Nands 128-bit integers.
* Ands 128-bit integers.
*
* @param 𝑎 [w/o] receives result
* @param 𝑏 [r/o] supplies first input vector

View File

@ -59,10 +59,7 @@ cescapec:
#ifdef __STRICT_ANSI__
.LQM: mov $'?',%ah
ret
.LESC:
#elif defined(__GNUC__)
.LESC: mov $'e',%ah
ret
#else
.LQM:
#endif
1: mov %edi,%eax
@ -91,9 +88,7 @@ cescapectab.ro:
.byte 1,.LVT-.Lanchorpoint
.byte 1,.LFF-.Lanchorpoint
.byte 1,.LCR-.Lanchorpoint
.byte 0x1b-'\r-1,1b-.Lanchorpoint
.byte 1,.LESC-.Lanchorpoint
.byte '\"-0x1b-1,1b-.Lanchorpoint
.byte '\"-'\r-1,1b-.Lanchorpoint
.byte 1,.LDQ-.Lanchorpoint
.byte '\'-'\"-1,1b-.Lanchorpoint
.byte 1,.LSQ-.Lanchorpoint

View File

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_STR_STRCMP8TO16I_H_
#define COSMOPOLITAN_LIBC_STR_STRCMP8TO16I_H_
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/str/oldutf16.internal.h"
#include "libc/str/str.h"
#include "libc/str/tpdecode.internal.h"
@ -12,9 +13,12 @@ forceinline int strcmp8to16i(const char *s1, const char16_t *s2, size_t n,
int res = 0;
if (n) {
do {
unsigned i, j;
wint_t wc1, wc2;
s1 += abs(tpdecode(s1, &wc1));
s2 += abs(getutf16(s2, &wc2));
i = tpdecode(s1, &wc1);
j = getutf16(s2, &wc2);
s1 += ABS(i);
s2 += ABS(j);
if ((res = xlat(wc1) - xlat(wc2)) || !wc1) break;
} while (n == -1ul || --n);
}

View File

@ -32,6 +32,8 @@
#include "libc/x/x.h"
#include "tool/viz/lib/formatstringtable-testlib.h"
short *bingblit(int ys, int xs, unsigned char[ys][xs], int, int);
TEST(magikarp, testConvolve) {
signed char K[8] = {-1, -3, 3, 17, 17, 3, -3, -1};
EXPECT_BINEQ(

View File

@ -32,6 +32,8 @@
#include "libc/x/x.h"
#include "tool/viz/lib/formatstringtable-testlib.h"
short *bingblit(int ys, int xs, unsigned char[ys][xs], int, int);
void *AbsoluteDifference(int yn, int xn, unsigned char C[yn][xn], int ays,
int axs, const unsigned char A[ays][axs], int bys,
int bxs, const unsigned char B[bys][bxs]) {

View File

@ -17,9 +17,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/runtime/runtime.h"
#include "libc/calls/calls.h"
#include "libc/sysv/consts/ok.h"
#include "libc/testlib/testlib.h"
@ -29,7 +29,9 @@ textstartup static void init(void) {
}
const void *const ctors[] initarray = {init};
TEST(access, readDirectory) { ASSERT_EQ(0, access("test/libc/", F_OK)); }
TEST(access, readDirectory) {
ASSERT_EQ(0, access("test/libc/", F_OK));
}
TEST(access, readThisCode) {
ASSERT_EQ(0, access("test/libc/access_test.c", R_OK));

View File

@ -26,6 +26,7 @@ TEST(cescapec, test) {
EXPECT_EQ('\\' | 'r' << 8, cescapec('\r'));
EXPECT_EQ('\\' | 'n' << 8, cescapec('\n'));
EXPECT_EQ('\\' | '0' << 8 | '0' << 16 | '0' << 24, cescapec(0));
EXPECT_EQ('\\' | '0' << 8 | '3' << 16 | '3' << 24, cescapec('\e'));
EXPECT_EQ('\\' | '1' << 8 | '7' << 16 | '7' << 24, cescapec(0x7F));
EXPECT_EQ('\\' | '3' << 8 | '7' << 16 | '7' << 24, cescapec(0xFF));
EXPECT_EQ('\\' | '3' << 8 | '7' << 16 | '7' << 24, cescapec(0xFFFF));

View File

@ -17,13 +17,14 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/struct/timespec.h"
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/clock.h"
#include "libc/testlib/testlib.h"
#include "libc/time/time.h"
#include "libc/calls/struct/timespec.h"
#include "libc/x/x.h"
TEST(clock_gettime, testClockRealtime) {
@ -31,5 +32,5 @@ TEST(clock_gettime, testClockRealtime) {
struct timespec ts;
EXPECT_NE(-1, gettimeofday(&tv, NULL));
EXPECT_NE(-1, clock_gettime(CLOCK_REALTIME, &ts));
EXPECT_LT((unsigned)abs(ts.tv_sec - tv.tv_sec), 5u);
EXPECT_LT((unsigned)ABS(ts.tv_sec - tv.tv_sec), 5u);
}

View File

@ -6,21 +6,30 @@ which is great, considering it's a 220kb αcτµαlly pδrταblε εxεcµταb
local enhancements
- support __asm__
- support dce
- support gnu asm
- support __int128
- support _Static_assert
- support __vector_size__
- support __builtin_memcpy
- support __builtin_add_overflow, etc.
- support __builtin_memcpy, strlen, strpbrk, etc.
- support __builtin_constant_p, __builtin_likely, etc.
- support __builtin_isunordered, __builtin_islessgreater, etc.
- support __builtin_ctz, __builtin_bswap, __builtin_popcount, etc.
- support __constructor__, __destructor__, __section__, __cold__, etc.
- support __constructor__, __section__, __cold__, -ffunction-sections, etc.
- support building -x assembler-with-cpp a.k.a. .S files
- support profiling w/ -mcount / -mfentry / -mnop-mcount
- improve error messages to trace macro expansions
- reduce #lines of generated assembly by a third
- reduce #bytes of generated binary by a third
local bug fixes
- allow casted values to be lvalues
- permit parentheses around string-initializer
- fix 64-bit bug in generated code for struct bitfields
- fix bug where last statement in statement expression couldn't have label
- print_tokens (chibicc -E) now works in the case of adjacent string literals
local changes

View File

@ -40,7 +40,7 @@ static void DecodeAsmConstraints(AsmOperand *op) {
switch ((c = op->str[i++])) {
case '\0':
case ',': // alternative group
return;
return; // todo: read combos
case '0':
case '1':
case '2':
@ -180,13 +180,17 @@ static bool IsLvalue(AsmOperand *op) {
}
}
static bool CanUseReg(Node *n) {
return is_integer(n->ty) || n->ty->kind == TY_PTR;
static bool CanUseReg(Node **n) {
if ((*n)->ty->kind == TY_ARRAY) {
*n = new_cast(*n, pointer_to((*n)->ty->base));
return true;
}
return is_integer((*n)->ty) || (*n)->ty->kind == TY_PTR;
}
static bool CanUseXmm(Node *n) {
return n->ty->kind == TY_FLOAT || n->ty->kind == TY_DOUBLE ||
n->ty->kind == TY_PTR ||
return n->ty->vector_size == 16 || n->ty->kind == TY_FLOAT ||
n->ty->kind == TY_DOUBLE || n->ty->kind == TY_PTR ||
(n->ty->kind == TY_ARRAY && n->ty->size == 16);
}
@ -201,7 +205,7 @@ static int PickAsmReferenceType(AsmOperand *op, AsmOperand *ref) {
case kAsmMem:
error_tok(op->tok, "bad reference");
case kAsmReg:
if (!CanUseReg(op->node)) {
if (!CanUseReg(&op->node)) {
error_tok(op->tok, "expected integral expression");
}
op->regmask = 0;
@ -235,7 +239,7 @@ static int PickAsmOperandType(Asm *a, AsmOperand *op) {
if ((op->type & kAsmFpu) && op->node->ty->kind == TY_LDOUBLE) return kAsmFpu;
if ((op->type & kAsmXmm) && CanUseXmm(op->node)) return kAsmXmm;
if ((op->type & kAsmMmx) && CanUseMmx(op->node)) return kAsmMmx;
if ((op->type & kAsmReg) && CanUseReg(op->node)) return kAsmReg;
if ((op->type & kAsmReg) && CanUseReg(&op->node)) return kAsmReg;
if (op->type & kAsmFlag) return kAsmFlag;
if (op->type & kAsmRaw) return kAsmRaw;
error_tok(op->tok, "constraint mismatch");
@ -245,7 +249,7 @@ static Token *ParseAsmOperand(Asm *a, AsmOperand *op, Token *tok) {
int i;
op->tok = tok;
op->str = ConsumeStringLiteral(&tok, tok);
tok = skip(tok, "(");
tok = skip(tok, '(');
op->node = expr(&tok, tok);
add_type(op->node);
DecodeAsmConstraints(op);
@ -255,7 +259,7 @@ static Token *ParseAsmOperand(Asm *a, AsmOperand *op, Token *tok) {
} else {
op->type = PickAsmOperandType(a, op);
}
return skip(tok, ")");
return skip(tok, ')');
}
static Token *ParseAsmOperands(Asm *a, Token *tok) {
@ -267,7 +271,7 @@ static Token *ParseAsmOperands(Asm *a, Token *tok) {
tok = ParseAsmOperand(a, &a->ops[a->n], tok);
++a->n;
if (!EQUAL(tok, ",")) break;
tok = skip(tok, ",");
tok = skip(tok, ',');
}
return tok;
}
@ -315,10 +319,6 @@ static void PickAsmRegisters(Asm *a) {
}
}
}
for (i = 0; i < a->n; ++i) {
assert(!a->ops[i].regmask);
assert(!a->ops[i].x87mask);
}
}
static void MarkUsedAsmOperands(Asm *a) {
@ -378,11 +378,13 @@ static Token *ParseAsmClobbers(Asm *a, Token *tok) {
i = s[3] - '0';
i &= 7;
a->x87clob |= 1 << i;
} else if (!strcmp(s, "memory")) {
/* do nothing */
} else {
error_tok(stok, "unknown clobber register");
}
if (!EQUAL(tok, ",")) break;
tok = skip(tok, ",");
tok = skip(tok, ',');
}
return tok;
}
@ -402,25 +404,25 @@ Asm *asm_stmt(Token **rest, Token *tok) {
Asm *a = calloc(1, sizeof(Asm));
tok = tok->next;
while (EQUAL(tok, "volatile") || EQUAL(tok, "inline")) tok = tok->next;
tok = skip(tok, "(");
tok = skip(tok, '(');
a->tok = tok;
a->str = ConsumeStringLiteral(&tok, tok);
if (!EQUAL(tok, ")")) {
a->isgnu = true;
tok = skip(tok, ":");
tok = skip(tok, ':');
tok = ParseAsmOperands(a, tok);
if (!EQUAL(tok, ")")) {
tok = skip(tok, ":");
tok = skip(tok, ':');
tok = ParseAsmOperands(a, tok);
if (!EQUAL(tok, ")")) {
tok = skip(tok, ":");
tok = skip(tok, ':');
tok = ParseAsmClobbers(a, tok);
}
}
}
PickAsmRegisters(a);
MarkUsedAsmOperands(a);
*rest = skip(tok, ")");
*rest = skip(tok, ')');
return a;
}
@ -541,24 +543,26 @@ static char *HandleAsmSpecifier(Asm *a, char *p) {
static void EmitAsmText(Asm *a) {
char c, *p;
if (a->isgnu) {
flushln();
fprintf(output_stream, "\t");
for (p = a->str;;) {
switch ((c = *p++)) {
case '\0':
fputc('\n', output_stream);
return;
case '%':
p = HandleAsmSpecifier(a, p);
break;
default:
fputc(c, output_stream);
break;
if (*a->str) {
if (a->isgnu) {
flushln();
fprintf(output_stream, "\t");
for (p = a->str;;) {
switch ((c = *p++)) {
case '\0':
fputc('\n', output_stream);
return;
case '%':
p = HandleAsmSpecifier(a, p);
break;
default:
fputc(c, output_stream);
break;
}
}
} else {
println("\t%s", a->str);
}
} else {
println("\t%s", a->str);
}
}
@ -668,9 +672,9 @@ static void StoreAsmOutputs(Asm *a) {
println("\tset%s\t(%%rax)", a->ops[i].str + a->ops[i].predicate);
break;
case kAsmReg:
z = bsr(a->ops[i].node->ty->size);
if (a->ops[i].reg) {
gen_addr(a->ops[i].node);
z = bsr(a->ops[i].node->ty->size);
if (z > 3) error_tok(a->tok, "bad asm out size");
println("\tmov\t%%%s,(%%rax)", kGreg[z][a->ops[i].reg]);
} else {
@ -678,7 +682,7 @@ static void StoreAsmOutputs(Asm *a) {
push();
pop("%rbx");
gen_addr(a->ops[i].node);
println("\tmov\t%%rbx,(%%rax)");
println("\tmov\t%%%s,(%%rax)", kGreg[z][3]);
println("\tpop\t%%rbx");
}
break;

View File

@ -150,8 +150,9 @@ static int getTypeId(Type *ty) {
return F64;
case TY_LDOUBLE:
return F80;
default:
return U64;
}
return U64;
}
void gen_cast(Type *from, Type *to) {

View File

@ -16,15 +16,21 @@ typedef enum {
FILE_DSO,
} FileType;
bool opt_fcommon = true;
bool opt_fpic;
bool opt_verbose;
bool opt_mpopcnt;
bool opt_common = true;
bool opt_data_sections;
bool opt_fentry;
bool opt_function_sections;
bool opt_no_builtin;
bool opt_nop_mcount;
bool opt_pg;
bool opt_mfentry;
bool opt_mnop_mcount;
bool opt_mrecord_mcount;
bool opt_pic;
bool opt_popcnt;
bool opt_record_mcount;
bool opt_sse3;
bool opt_sse4;
bool opt_verbose;
static bool opt_A;
static bool opt_E;
static bool opt_M;
static bool opt_MD;
@ -56,6 +62,14 @@ static void usage(int status) {
exit(status);
}
static void version(void) {
printf("\
chibicc (cosmopolitan) 9.0.0\n\
copyright 2019 rui ueyama\n\
copyright 2020 justine alexandra roberts tunney\n");
exit(0);
}
static bool take_arg(char *arg) {
char *x[] = {"-o", "-I", "-idirafter", "-include",
"-x", "-MF", "-MT", "-Xlinker"};
@ -130,231 +144,171 @@ static void PrintMemoryUsage(void) {
fprintf(stderr, "allocated %,ld bytes of memory\n", mi.arena);
}
static void strarray_push_comma(StringArray *a, char *s) {
char *p;
for (; *s++ == ','; s = p) {
p = strchrnul(s, ',');
strarray_push(a, strndup(s, p - s));
}
}
static void parse_args(int argc, char **argv) {
// Make sure that all command line options that take an argument
// have an argument.
for (int i = 1; i < argc; i++)
if (take_arg(argv[i]))
if (!argv[++i]) usage(1);
for (int i = 1; i < argc; i++) {
if (take_arg(argv[i])) {
if (!argv[++i]) {
usage(1);
}
}
}
StringArray idirafter = {};
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-###")) {
opt_hash_hash_hash = true;
continue;
}
if (!strcmp(argv[i], "-cc1")) {
} else if (!strcmp(argv[i], "-cc1")) {
opt_cc1 = true;
continue;
}
if (!strcmp(argv[i], "--help")) usage(0);
if (!strcmp(argv[i], "-v")) {
} else if (!strcmp(argv[i], "--help")) {
usage(0);
} else if (!strcmp(argv[i], "--version")) {
version();
} else if (!strcmp(argv[i], "-v")) {
opt_verbose = true;
atexit(PrintMemoryUsage);
continue;
}
if (!strcmp(argv[i], "-o")) {
} else if (!strcmp(argv[i], "-o")) {
opt_o = argv[++i];
continue;
}
if (!strncmp(argv[i], "-o", 2)) {
} else if (startswith(argv[i], "-o")) {
opt_o = argv[i] + 2;
continue;
}
if (!strcmp(argv[i], "-S")) {
} else if (!strcmp(argv[i], "-S")) {
opt_S = true;
continue;
}
if (!strcmp(argv[i], "-fcommon")) {
opt_fcommon = true;
continue;
}
if (!strcmp(argv[i], "-fno-common")) {
opt_fcommon = false;
continue;
}
if (!strcmp(argv[i], "-c")) {
} else if (!strcmp(argv[i], "-fcommon")) {
opt_common = true;
} else if (!strcmp(argv[i], "-fno-common")) {
opt_common = false;
} else if (!strcmp(argv[i], "-fno-builtin")) {
opt_no_builtin = true;
} else if (!strcmp(argv[i], "-c")) {
opt_c = true;
continue;
}
if (!strcmp(argv[i], "-E")) {
} else if (!strcmp(argv[i], "-E")) {
opt_E = true;
continue;
}
if (!strncmp(argv[i], "-I", 2)) {
} else if (!strcmp(argv[i], "-A")) {
opt_A = true;
} else if (!strcmp(argv[i], "-I")) {
strarray_push(&include_paths, argv[++i]);
} else if (startswith(argv[i], "-I")) {
strarray_push(&include_paths, argv[i] + 2);
continue;
}
if (!strcmp(argv[i], "-D")) {
} else if (!strcmp(argv[i], "-iquote")) {
strarray_push(&include_paths, argv[++i]);
} else if (startswith(argv[i], "-iquote")) {
strarray_push(&include_paths, argv[i] + strlen("-iquote"));
} else if (!strcmp(argv[i], "-isystem")) {
strarray_push(&include_paths, argv[++i]);
} else if (startswith(argv[i], "-isystem")) {
strarray_push(&include_paths, argv[i] + strlen("-isystem"));
} else if (!strcmp(argv[i], "-D")) {
define(argv[++i]);
continue;
}
if (!strncmp(argv[i], "-D", 2)) {
} else if (startswith(argv[i], "-D")) {
define(argv[i] + 2);
continue;
}
if (!strcmp(argv[i], "-U")) {
} else if (!strcmp(argv[i], "-U")) {
undef_macro(argv[++i]);
continue;
}
if (!strncmp(argv[i], "-U", 2)) {
} else if (!strncmp(argv[i], "-U", 2)) {
undef_macro(argv[i] + 2);
continue;
}
if (!strcmp(argv[i], "-include")) {
} else if (!strcmp(argv[i], "-include")) {
strarray_push(&opt_include, argv[++i]);
continue;
}
if (!strcmp(argv[i], "-x")) {
} else if (!strcmp(argv[i], "-x")) {
opt_x = parse_opt_x(argv[++i]);
continue;
}
if (!strncmp(argv[i], "-x", 2)) {
} else if (!strncmp(argv[i], "-x", 2)) {
opt_x = parse_opt_x(argv[i] + 2);
continue;
}
if (!strncmp(argv[i], "-l", 2) || !strncmp(argv[i], "-Wl,", 4)) {
strarray_push(&input_paths, argv[i]);
continue;
}
if (!strcmp(argv[i], "-Xassembler")) {
} else if (startswith(argv[i], "-Wa")) {
strarray_push_comma(&as_extra_args, argv[i]);
} else if (startswith(argv[i], "-Wl")) {
strarray_push_comma(&ld_extra_args, argv[i]);
} else if (!strcmp(argv[i], "-Xassembler")) {
strarray_push(&as_extra_args, argv[++i]);
continue;
}
if (!strcmp(argv[i], "-Xlinker")) {
} else if (!strcmp(argv[i], "-Xlinker")) {
strarray_push(&ld_extra_args, argv[++i]);
continue;
}
if (!strcmp(argv[i], "-s")) {
} else if (!strncmp(argv[i], "-l", 2) || !strncmp(argv[i], "-Wl,", 4)) {
strarray_push(&input_paths, argv[i]);
} else if (!strcmp(argv[i], "-s")) {
strarray_push(&ld_extra_args, "-s");
continue;
}
if (!strcmp(argv[i], "-M")) {
} else if (!strcmp(argv[i], "-M")) {
opt_M = true;
continue;
}
if (!strcmp(argv[i], "-MF")) {
} else if (!strcmp(argv[i], "-MF")) {
opt_MF = argv[++i];
continue;
}
if (!strcmp(argv[i], "-MP")) {
} else if (!strcmp(argv[i], "-MP")) {
opt_MP = true;
continue;
}
if (!strcmp(argv[i], "-MT")) {
if (opt_MT == NULL)
} else if (!strcmp(argv[i], "-MT")) {
if (!opt_MT) {
opt_MT = argv[++i];
else
} else {
opt_MT = xasprintf("%s %s", opt_MT, argv[++i]);
continue;
}
if (!strcmp(argv[i], "-MD")) {
}
} else if (!strcmp(argv[i], "-MD")) {
opt_MD = true;
continue;
}
if (!strcmp(argv[i], "-MQ")) {
if (opt_MT == NULL)
} else if (!strcmp(argv[i], "-MQ")) {
if (!opt_MT) {
opt_MT = quote_makefile(argv[++i]);
else
} else {
opt_MT = xasprintf("%s %s", opt_MT, quote_makefile(argv[++i]));
continue;
}
if (!strcmp(argv[i], "-MMD")) {
}
} else if (!strcmp(argv[i], "-MMD")) {
opt_MD = opt_MMD = true;
continue;
}
if (!strcmp(argv[i], "-fpie") || !strcmp(argv[i], "-fpic") ||
!strcmp(argv[i], "-fPIC")) {
opt_fpic = true;
continue;
}
if (!strcmp(argv[i], "-pg")) {
} else if (!strcmp(argv[i], "-fpie") || !strcmp(argv[i], "-fpic") ||
!strcmp(argv[i], "-fPIC")) {
opt_pic = true;
} else if (!strcmp(argv[i], "-pg")) {
opt_pg = true;
continue;
}
if (!strcmp(argv[i], "-mfentry")) {
opt_mfentry = true;
continue;
}
if (!strcmp(argv[i], "-mrecord-mcount")) {
opt_mrecord_mcount = true;
continue;
}
if (!strcmp(argv[i], "-mnop-mcount")) {
opt_mnop_mcount = true;
continue;
}
if (!strcmp(argv[i], "-mpopcnt")) {
opt_mpopcnt = true;
continue;
}
if (!strcmp(argv[i], "-cc1-input")) {
} else if (!strcmp(argv[i], "-mfentry")) {
opt_fentry = true;
} else if (!strcmp(argv[i], "-ffunction-sections")) {
opt_function_sections = true;
} else if (!strcmp(argv[i], "-fdata-sections")) {
opt_data_sections = true;
} else if (!strcmp(argv[i], "-mrecord-mcount")) {
opt_record_mcount = true;
} else if (!strcmp(argv[i], "-mnop-mcount")) {
opt_nop_mcount = true;
} else if (!strcmp(argv[i], "-msse3")) {
opt_sse3 = true;
} else if (!strcmp(argv[i], "-msse4") || !strcmp(argv[i], "-msse4.2") ||
!strcmp(argv[i], "-msse4.1")) {
opt_sse4 = true;
} else if (!strcmp(argv[i], "-mpopcnt")) {
opt_popcnt = true;
} else if (!strcmp(argv[i], "-cc1-input")) {
base_file = argv[++i];
continue;
}
if (!strcmp(argv[i], "-cc1-output")) {
} else if (!strcmp(argv[i], "-cc1-output")) {
output_file = argv[++i];
continue;
}
if (!strcmp(argv[i], "-idirafter")) {
} else if (!strcmp(argv[i], "-idirafter")) {
strarray_push(&idirafter, argv[i++]);
continue;
}
if (!strcmp(argv[i], "-static")) {
} else if (!strcmp(argv[i], "-static")) {
opt_static = true;
strarray_push(&ld_extra_args, "-static");
continue;
}
if (!strcmp(argv[i], "-shared")) {
fprintf(stderr, "error: -shared not supported\n");
exit(1);
}
if (!strcmp(argv[i], "-L")) {
} else if (!strcmp(argv[i], "-shared")) {
error("-shared not supported");
} else if (!strcmp(argv[i], "-L")) {
strarray_push(&ld_extra_args, "-L");
strarray_push(&ld_extra_args, argv[++i]);
continue;
}
if (!strncmp(argv[i], "-L", 2)) {
} else if (startswith(argv[i], "-L")) {
strarray_push(&ld_extra_args, "-L");
strarray_push(&ld_extra_args, argv[i] + 2);
continue;
} else {
if (argv[i][0] == '-' && argv[i][1]) {
/* compiler should not whine about the flags race */
if (opt_verbose) {
fprintf(stderr, "unknown argument: %s\n", argv[i]);
}
} else {
strarray_push(&input_paths, argv[i]);
}
}
#if 0
if (!strcmp(argv[i], "-hashmap-test")) {
hashmap_test();
exit(0);
}
#endif
// These options are ignored for now.
if (startswith(argv[i], "-O") || startswith(argv[i], "-W") ||
startswith(argv[i], "-g") || startswith(argv[i], "-std=") ||
startswith(argv[i], "-fno-") || startswith(argv[i], "-mno-") ||
startswith(argv[i], "-fsanitize") ||
startswith(argv[i], "-fdebug-prefix-map") ||
!strcmp(argv[i], "-fwrapv") || !strcmp(argv[i], "-nostdlib") ||
!strcmp(argv[i], "-nostdinc") || !strcmp(argv[i], "-ffreestanding") ||
!strcmp(argv[i], "-fstrict-aliasing") ||
!strcmp(argv[i], "-fstrict-overflow") ||
!strcmp(argv[i], "-frecord-gcc-switches") ||
!strcmp(argv[i], "-fsignaling-nans") ||
!strcmp(argv[i], "-frounding-math") ||
!strcmp(argv[i], "-fcx-limited-range") ||
!strcmp(argv[i], "-fmodulo-sched") ||
!strcmp(argv[i], "-fmerge-constants") ||
!strcmp(argv[i], "-fmerge-all-constants") ||
!strcmp(argv[i], "-fno-builtin") ||
!strcmp(argv[i], "-fno-omit-frame-pointer") ||
!strcmp(argv[i], "-fno-stack-protector") ||
!strcmp(argv[i], "-fno-strict-aliasing") || !strcmp(argv[i], "-m64") ||
!strcmp(argv[i], "-mno-red-zone") || !strcmp(argv[i], "-w")) {
continue;
}
if (argv[i][0] == '-' && argv[i][1] != '\0')
error("unknown argument: %s", argv[i]);
strarray_push(&input_paths, argv[i]);
}
for (int i = 0; i < idirafter.len; i++)
for (int i = 0; i < idirafter.len; i++) {
strarray_push(&include_paths, idirafter.data[i]);
if (input_paths.len == 0) error("no input files");
}
if (!input_paths.len) {
error("no input files");
}
// -E implies that the input is the C macro language.
if (opt_E) opt_x = FILE_C;
}
@ -439,13 +393,36 @@ static void run_cc1(int argc, char **argv, char *input, char *output) {
run_subprocess(args);
}
static void print_token(FILE *out, Token *tok) {
switch (tok->kind) {
case TK_STR:
switch (tok->ty->base->size) {
case 1:
fprintf(out, "%`'.*s", tok->ty->array_len - 1, tok->str);
break;
case 2:
fprintf(out, "%`'.*hs", tok->ty->array_len - 1, tok->str);
break;
case 4:
fprintf(out, "%`'.*ls", tok->ty->array_len - 1, tok->str);
break;
default:
UNREACHABLE();
}
break;
default:
fprintf(out, "%.*s", tok->len, tok->loc);
break;
}
}
static void print_tokens(Token *tok) {
FILE *out = open_file(opt_o ? opt_o : "-");
int line = 1;
for (; tok->kind != TK_EOF; tok = tok->next) {
if (line > 1 && tok->at_bol) fprintf(out, "\n");
if (tok->has_space && !tok->at_bol) fprintf(out, " ");
fprintf(out, "%.*s", tok->len, tok->loc);
print_token(out, tok);
line++;
}
fprintf(out, "\n");
@ -547,7 +524,10 @@ static void cc1(void) {
return;
}
Obj *prog = parse(tok);
// Traverse the AST to emit assembly.
if (opt_A) {
print_ast(stdout, prog);
return;
}
FILE *out = open_file(output_file);
codegen(prog, out);
fclose(out);
@ -582,7 +562,7 @@ static void run_linker(StringArray *inputs, char *output) {
strarray_push(&arr, "elf_x86_64");
strarray_push(&arr, "-z");
strarray_push(&arr, "max-page-size=0x1000");
strarray_push(&arr, "-mnostdlib");
strarray_push(&arr, "-nostdlib");
strarray_push(&arr, "--gc-sections");
strarray_push(&arr, "--build-id=none");
strarray_push(&arr, "--no-dynamic-linker");
@ -611,8 +591,9 @@ int main(int argc, char **argv) {
cc1();
return 0;
}
if (input_paths.len > 1 && opt_o && (opt_c || opt_S | opt_E))
if (input_paths.len > 1 && opt_o && (opt_c || opt_S | opt_E)) {
error("cannot specify '-o' with '-c,' '-S' or '-E' with multiple files");
}
StringArray ld_args = {};
for (int i = 0; i < input_paths.len; i++) {
char *input = input_paths.data[i];
@ -650,7 +631,7 @@ int main(int argc, char **argv) {
}
continue;
}
assert(type == FILE_C);
assert(type == FILE_C || type == FILE_ASM_CPP);
// Just preprocess
if (opt_E || opt_M) {
run_cc1(argc, argv, input, NULL);

View File

@ -114,7 +114,7 @@ void warn_tok(Token *, char *, ...)
File **get_input_files(void);
File *new_file(char *, int, char *);
Token *skip(Token *, char *);
Token *skip(Token *, char);
Token *tokenize(File *);
Token *tokenize_file(char *);
Token *tokenize_string_literal(Token *, Type *);
@ -269,10 +269,10 @@ typedef enum {
ND_MUL, // *
ND_DIV, // /
ND_NEG, // unary -
ND_MOD, // %
ND_BITAND, // &
ND_BITOR, // |
ND_BITXOR, // ^
ND_REM, // %
ND_BINAND, // &
ND_BINOR, // |
ND_BINXOR, // ^
ND_SHL, // <<
ND_SHR, // >>
ND_EQ, // ==
@ -329,61 +329,44 @@ struct Node {
Node *inc;
// Block or statement expression
Node *body;
union {
struct {
// Function call
Type *func_ty;
Node *args;
bool pass_by_stack;
Obj *ret_buffer;
};
struct {
// Switch
Node *case_next;
Node *default_case;
// Goto or labeled statement, or labels-as-values
char *label;
char *unique_label;
Node *goto_next;
// "break" and "continue" labels
char *brk_label;
char *cont_label;
// Case
long begin;
long end;
};
struct {
// Struct member access
Member *member;
};
struct {
// Assembly
Asm *azm;
};
struct {
// Atomic compare-and-swap
Node *cas_addr;
Node *cas_old;
Node *cas_new;
};
struct {
// Atomic op= operators
Obj *atomic_addr;
Node *atomic_expr;
};
struct {
// Variable
Obj *var;
};
struct {
// Numeric literal
int64_t val;
long double fval;
};
struct {
FpClassify *fpc;
};
};
// Function call
Type *func_ty;
Node *args;
Obj *ret_buffer;
bool pass_by_stack;
bool realign_stack;
// Switch
Node *case_next;
Node *default_case;
// Goto or labeled statement, or labels-as-values
char *label;
char *unique_label;
Node *goto_next;
// "break" and "continue" labels
char *brk_label;
char *cont_label;
// Case
long begin;
long end;
// Struct member access
Member *member;
// Assembly
Asm *azm;
// Atomic compare-and-swap
Node *cas_addr;
Node *cas_old;
Node *cas_new;
// Atomic op= operators
Obj *atomic_addr;
Node *atomic_expr;
// Variable
Obj *var;
// Arithmetic
Node *overflow;
// Numeric literal
int64_t val;
long double fval;
FpClassify *fpc;
};
Node *expr(Token **, Token *);
@ -396,6 +379,12 @@ int64_t const_expr(Token **, Token *);
int64_t eval(Node *);
int64_t eval2(Node *, char ***);
//
// debug.c
//
void print_ast(FILE *, Obj *);
//
// type.c
//
@ -560,15 +549,20 @@ void hashmap_test(void);
//
extern StringArray include_paths;
extern bool opt_fcommon;
extern bool opt_fpic;
extern bool opt_verbose;
extern bool opt_mpopcnt;
extern char *base_file;
extern bool opt_common;
extern bool opt_data_sections;
extern bool opt_fentry;
extern bool opt_function_sections;
extern bool opt_no_builtin;
extern bool opt_nop_mcount;
extern bool opt_pg;
extern bool opt_mfentry;
extern bool opt_mnop_mcount;
extern bool opt_mrecord_mcount;
extern bool opt_pic;
extern bool opt_popcnt;
extern bool opt_record_mcount;
extern bool opt_sse3;
extern bool opt_sse4;
extern bool opt_verbose;
extern char *base_file;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -55,6 +55,7 @@ THIRD_PARTY_CHIBICC_A_DIRECTDEPS = \
LIBC_TIME \
LIBC_UNICODE \
LIBC_X \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_GDTOA
@ -73,10 +74,10 @@ $(THIRD_PARTY_CHIBICC_A).pkg: \
o/$(MODE)/third_party/chibicc/chibicc.com.dbg: \
$(THIRD_PARTY_CHIBICC_A_DEPS) \
$(THIRD_PARTY_CHIBICC_A) \
o/$(MODE)/third_party/chibicc/chibicc.o \
$(THIRD_PARTY_CHIBICC_A).pkg \
$(APE) \
$(CRT) \
$(APE)
o/$(MODE)/third_party/chibicc/chibicc.o \
$(THIRD_PARTY_CHIBICC_A).pkg
@$(APELINK)
o/$(MODE)/third_party/chibicc/chibicc2.com.dbg: \
@ -93,16 +94,16 @@ o/$(MODE)/third_party/chibicc/chibicc.o: \
-DAPE=\"o/$(MODE)/ape/ape.o\" \
-DLDS=\"o/$(MODE)/ape/ape.lds\"
o/$(MODE)/third_party/chibicc/chibicc.chibicc.s: \
o/$(MODE)/third_party/chibicc/chibicc.chibicc.o: \
CHIBICC_FLAGS += \
-DCRT=\"$(CRT)\" \
-DAPE=\"o/$(MODE)/ape/ape.o\" \
-DLDS=\"o/$(MODE)/ape/ape.lds\"
o/$(MODE)/%.chibicc.s: %.c o/$(MODE)/third_party/chibicc/chibicc.com.dbg
@ACTION=CHIBICC TARGET=$@ build/do $(CHIBICC) $(CHIBICC_FLAGS) -S -o $@ $<
o/$(MODE)/%.chibicc2.s: %.c o/$(MODE)/third_party/chibicc/chibicc2.com.dbg
@ACTION=CHIBICC2 TARGET=$@ build/do $(CHIBICC2) $(CHIBICC_FLAGS) -S -o $@ $<
o/$(MODE)/%.chibicc.o: %.c o/$(MODE)/third_party/chibicc/chibicc.com.dbg
@ACTION=CHIBICC TARGET=$@ build/do $(CHIBICC) $(CHIBICC_FLAGS) -c -o $@ $<
o/$(MODE)/%.chibicc2.o: %.c o/$(MODE)/third_party/chibicc/chibicc2.com.dbg
@ACTION=CHIBICC2 TARGET=$@ build/do $(CHIBICC2) $(CHIBICC_FLAGS) -c -o $@ $<
THIRD_PARTY_CHIBICC_LIBS = $(foreach x,$(THIRD_PARTY_CHIBICC_ARTIFACTS),$($(x)))
THIRD_PARTY_CHIBICC_SRCS = $(foreach x,$(THIRD_PARTY_CHIBICC_ARTIFACTS),$($(x)_SRCS))
@ -115,5 +116,4 @@ $(THIRD_PARTY_CHIBICC_OBJS): $(BUILD_FILES) third_party/chibicc/chibicc.mk
o/$(MODE)/third_party/chibicc: \
o/$(MODE)/third_party/chibicc/test \
$(THIRD_PARTY_CHIBICC_BINS) \
$(THIRD_PARTY_CHIBICC_CHECKS) \
$(THIRD_PARTY_CHIBICC_A_SRCS:%.c=o/$(MODE)/%.chibicc.s)
$(THIRD_PARTY_CHIBICC_CHECKS)

File diff suppressed because it is too large Load Diff

View File