mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 15:28:30 +00:00
Enhance chibicc
This commit is contained in:
parent
8da931a7f6
commit
9df2cef4c4
52 changed files with 2606 additions and 2004 deletions
15
third_party/chibicc/README.cosmo
vendored
15
third_party/chibicc/README.cosmo
vendored
|
@ -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
|
||||
|
||||
|
|
80
third_party/chibicc/asm.c
vendored
80
third_party/chibicc/asm.c
vendored
|
@ -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;
|
||||
|
|
3
third_party/chibicc/cast.c
vendored
3
third_party/chibicc/cast.c
vendored
|
@ -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) {
|
||||
|
|
359
third_party/chibicc/chibicc.c
vendored
359
third_party/chibicc/chibicc.c
vendored
|
@ -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);
|
||||
|
|
130
third_party/chibicc/chibicc.h
vendored
130
third_party/chibicc/chibicc.h
vendored
|
@ -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) */
|
||||
|
|
20
third_party/chibicc/chibicc.mk
vendored
20
third_party/chibicc/chibicc.mk
vendored
|
@ -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)
|
||||
|
|
1121
third_party/chibicc/codegen.c
vendored
1121
third_party/chibicc/codegen.c
vendored
File diff suppressed because it is too large
Load diff
36
third_party/chibicc/hashmap.c
vendored
36
third_party/chibicc/hashmap.c
vendored
|
@ -18,8 +18,11 @@ static uint64_t fnv_hash(char *s, int len) {
|
|||
static void rehash(HashMap *map) {
|
||||
// Compute the size of the new hashmap.
|
||||
int nkeys = 0;
|
||||
for (int i = 0; i < map->capacity; i++)
|
||||
if (map->buckets[i].key && map->buckets[i].key != TOMBSTONE) nkeys++;
|
||||
for (int i = 0; i < map->capacity; i++) {
|
||||
if (map->buckets[i].key && map->buckets[i].key != TOMBSTONE) {
|
||||
nkeys++;
|
||||
}
|
||||
}
|
||||
size_t cap = map->capacity;
|
||||
while ((nkeys * 100) / cap >= 50) cap = cap * 2;
|
||||
// Create a new hashmap and copy all key-values.
|
||||
|
@ -101,32 +104,3 @@ void hashmap_delete2(HashMap *map, char *key, int keylen) {
|
|||
HashEntry *ent = get_entry(map, key, keylen);
|
||||
if (ent) ent->key = TOMBSTONE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void hashmap_test(void) {
|
||||
HashMap *map = calloc(1, sizeof(HashMap));
|
||||
for (int i = 0; i < 5000; i++)
|
||||
hashmap_put(map, xasprintf("key %d", i), (void *)(size_t)i);
|
||||
for (int i = 1000; i < 2000; i++) hashmap_delete(map, xasprintf("key %d", i));
|
||||
for (int i = 1500; i < 1600; i++)
|
||||
hashmap_put(map, xasprintf("key %d", i), (void *)(size_t)i);
|
||||
for (int i = 6000; i < 7000; i++)
|
||||
hashmap_put(map, xasprintf("key %d", i), (void *)(size_t)i);
|
||||
for (int i = 0; i < 1000; i++)
|
||||
assert((size_t)hashmap_get(map, xasprintf("key %d", i)) == i);
|
||||
for (int i = 1000; i < 1500; i++)
|
||||
assert(hashmap_get(map, "no such key") == NULL);
|
||||
for (int i = 1500; i < 1600; i++)
|
||||
assert((size_t)hashmap_get(map, xasprintf("key %d", i)) == i);
|
||||
for (int i = 1600; i < 2000; i++)
|
||||
assert(hashmap_get(map, "no such key") == NULL);
|
||||
for (int i = 2000; i < 5000; i++)
|
||||
assert((size_t)hashmap_get(map, xasprintf("key %d", i)) == i);
|
||||
for (int i = 5000; i < 6000; i++)
|
||||
assert(hashmap_get(map, "no such key") == NULL);
|
||||
for (int i = 6000; i < 7000; i++)
|
||||
hashmap_put(map, xasprintf("key %d", i), (void *)(size_t)i);
|
||||
assert(hashmap_get(map, "no such key") == NULL);
|
||||
printf("OK\n");
|
||||
}
|
||||
#endif
|
||||
|
|
854
third_party/chibicc/parse.c
vendored
854
third_party/chibicc/parse.c
vendored
File diff suppressed because it is too large
Load diff
47
third_party/chibicc/preprocess.c
vendored
47
third_party/chibicc/preprocess.c
vendored
|
@ -253,7 +253,7 @@ static Token *read_const_expr(Token **rest, Token *tok) {
|
|||
error_tok(start, "macro name must be an identifier");
|
||||
Macro *m = find_macro(tok);
|
||||
tok = tok->next;
|
||||
if (has_paren) tok = skip(tok, ")");
|
||||
if (has_paren) tok = skip(tok, ')');
|
||||
cur = cur->next = new_num_token(m ? 1 : 0, start);
|
||||
continue;
|
||||
}
|
||||
|
@ -318,16 +318,16 @@ static MacroParam *read_macro_params(Token **rest, Token *tok,
|
|||
MacroParam head = {};
|
||||
MacroParam *cur = &head;
|
||||
while (!EQUAL(tok, ")")) {
|
||||
if (cur != &head) tok = skip(tok, ",");
|
||||
if (cur != &head) tok = skip(tok, ',');
|
||||
if (EQUAL(tok, "...")) {
|
||||
*va_args_name = "__VA_ARGS__";
|
||||
*rest = skip(tok->next, ")");
|
||||
*rest = skip(tok->next, ')');
|
||||
return head.next;
|
||||
}
|
||||
if (tok->kind != TK_IDENT) error_tok(tok, "expected an identifier");
|
||||
if (EQUAL(tok->next, "...")) {
|
||||
*va_args_name = strndup(tok->loc, tok->len);
|
||||
*rest = skip(tok->next->next, ")");
|
||||
*rest = skip(tok->next->next, ')');
|
||||
return head.next;
|
||||
}
|
||||
MacroParam *m = calloc(1, sizeof(MacroParam));
|
||||
|
@ -386,7 +386,7 @@ static MacroArg *read_macro_args(Token **rest, Token *tok, MacroParam *params,
|
|||
MacroArg *cur = &head;
|
||||
MacroParam *pp = params;
|
||||
for (; pp; pp = pp->next) {
|
||||
if (cur != &head) tok = skip(tok, ",");
|
||||
if (cur != &head) tok = skip(tok, ',');
|
||||
cur = cur->next = read_macro_arg_one(&tok, tok, false);
|
||||
cur->name = pp->name;
|
||||
}
|
||||
|
@ -396,25 +396,27 @@ static MacroArg *read_macro_args(Token **rest, Token *tok, MacroParam *params,
|
|||
arg = calloc(1, sizeof(MacroArg));
|
||||
arg->tok = new_eof(tok);
|
||||
} else {
|
||||
if (pp != params) tok = skip(tok, ",");
|
||||
if (pp != params) tok = skip(tok, ',');
|
||||
arg = read_macro_arg_one(&tok, tok, true);
|
||||
}
|
||||
arg->name = va_args_name;
|
||||
;
|
||||
arg->is_va_args = true;
|
||||
cur = cur->next = arg;
|
||||
} else if (pp) {
|
||||
error_tok(start, "too many arguments");
|
||||
}
|
||||
skip(tok, ")");
|
||||
skip(tok, ')');
|
||||
*rest = tok;
|
||||
return head.next;
|
||||
}
|
||||
|
||||
static MacroArg *find_arg(MacroArg *args, Token *tok) {
|
||||
for (MacroArg *ap = args; ap; ap = ap->next)
|
||||
if (tok->len == strlen(ap->name) && !strncmp(tok->loc, ap->name, tok->len))
|
||||
for (MacroArg *ap = args; ap; ap = ap->next) {
|
||||
if (tok->len == strlen(ap->name) &&
|
||||
!strncmp(tok->loc, ap->name, tok->len)) {
|
||||
return ap;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -543,7 +545,7 @@ static Token *subst(Token *tok, MacroArg *args) {
|
|||
if (has_varargs(args))
|
||||
for (Token *t = arg->tok; t->kind != TK_EOF; t = t->next)
|
||||
cur = cur->next = t;
|
||||
tok = skip(tok, ")");
|
||||
tok = skip(tok, ')');
|
||||
continue;
|
||||
}
|
||||
// Handle a macro token. Macro arguments are completely macro-expanded
|
||||
|
@ -932,11 +934,11 @@ __chibicc__\000\
|
|||
__cosmopolitan__\000\
|
||||
1\000\
|
||||
__GNUC__\000\
|
||||
6\000\
|
||||
9\000\
|
||||
__GNUC_MINOR__\000\
|
||||
6\000\
|
||||
0\000\
|
||||
__GNUC_PATCHLEVEL__\000\
|
||||
6\000\
|
||||
0\000\
|
||||
__NO_INLINE__\000\
|
||||
16\000\
|
||||
__BIGGEST_ALIGNMENT__\000\
|
||||
|
@ -1289,9 +1291,13 @@ static void join_adjacent_string_literals(Token *tok) {
|
|||
"unsupported non-standard concatenation of string literals");
|
||||
}
|
||||
}
|
||||
if (basety->size > 1)
|
||||
for (Token *t = tok1; t->kind == TK_STR; t = t->next)
|
||||
if (t->ty->base->size == 1) *t = *tokenize_string_literal(t, basety);
|
||||
if (basety->size > 1) {
|
||||
for (Token *t = tok1; t->kind == TK_STR; t = t->next) {
|
||||
if (t->ty->base->size == 1) {
|
||||
*t = *tokenize_string_literal(t, basety);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (tok1->kind == TK_STR) tok1 = tok1->next;
|
||||
}
|
||||
// Second pass: concatenate adjacent string literals.
|
||||
|
@ -1307,10 +1313,9 @@ static void join_adjacent_string_literals(Token *tok) {
|
|||
array_of(tok1->ty->base, tok1->ty->array_len + tok2->ty->array_len - 1);
|
||||
t->str = calloc(1, t->ty->size);
|
||||
t->next = tok2->next;
|
||||
int i = 0;
|
||||
for (int j = 0; j < tok1->ty->size - tok1->ty->base->size; i++, j++)
|
||||
t->str[i] = tok1->str[j];
|
||||
for (int j = 0; j < tok2->ty->size; i++, j++) t->str[i] = tok2->str[j];
|
||||
memcpy(mempcpy(t->str, tok1->str, tok1->ty->size - tok1->ty->base->size),
|
||||
tok2->str, tok2->ty->size);
|
||||
t->len = strlen(t->loc);
|
||||
*tok1 = *t;
|
||||
}
|
||||
}
|
||||
|
|
249
third_party/chibicc/printast.c
vendored
Normal file
249
third_party/chibicc/printast.c
vendored
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*-*- 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 2020 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/alg/arraylist2.internal.h"
|
||||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
static const char kBoolStr[2][6] = {"false", "true"};
|
||||
|
||||
static const char kTypeKindStr[17][8] = {
|
||||
"VOID", "BOOL", "CHAR", "SHORT", "INT", "LONG",
|
||||
"INT128", "FLOAT", "DOUBLE", "LDOUBLE", "ENUM", "PTR",
|
||||
"FUNC", "ARRAY", "VLA", "STRUCT", "UNION",
|
||||
};
|
||||
|
||||
static const char kNodeKindStr[50][11] = {
|
||||
"NULL_EXPR", "ADD", "SUB", "MUL", "DIV", "NEG",
|
||||
"REM", "BINAND", "BINOR", "BINXOR", "SHL", "SHR",
|
||||
"EQ", "NE", "LT", "LE", "ASSIGN", "COND",
|
||||
"COMMA", "MEMBER", "ADDR", "DEREF", "NOT", "BITNOT",
|
||||
"LOGAND", "LOGOR", "RETURN", "IF", "FOR", "DO",
|
||||
"SWITCH", "CASE", "BLOCK", "GOTO", "GOTO_EXPR", "LABEL",
|
||||
"LABEL_VAL", "FUNCALL", "EXPR_STMT", "STMT_EXPR", "VAR", "VLA_PTR",
|
||||
"NUM", "CAST", "MEMZERO", "ASM", "CAS", "EXCH",
|
||||
"FPCLASSIFY",
|
||||
};
|
||||
|
||||
static struct Visited {
|
||||
size_t i, n;
|
||||
intptr_t *p;
|
||||
} g_visited;
|
||||
|
||||
static void PrintObj(FILE *, int, const char *, Obj *);
|
||||
static void PrintNode(FILE *, int, const char *, Node *);
|
||||
static void PrintType(FILE *, int, const char *, Type *);
|
||||
|
||||
static bool Visit(void *ptr) {
|
||||
size_t i;
|
||||
intptr_t addr = (intptr_t)ptr;
|
||||
for (i = 0; i < g_visited.i; ++i) {
|
||||
if (addr == g_visited.p[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
APPEND(&g_visited.p, &g_visited.i, &g_visited.n, &addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void PrintLine(FILE *f, int l, char *fmt, ...) {
|
||||
int i;
|
||||
va_list ap;
|
||||
for (i = 0; i < l; ++i) fputc(' ', f);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(f, fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
static void PrintBool(FILE *f, int l, const char *s, bool b) {
|
||||
if (!b) return;
|
||||
PrintLine(f, l, "%s%s", s, kBoolStr[b]);
|
||||
}
|
||||
|
||||
static void PrintInt(FILE *f, int l, const char *s, long x) {
|
||||
if (!x) return;
|
||||
PrintLine(f, l, "%s%ld", s, x);
|
||||
}
|
||||
|
||||
static void PrintStr(FILE *f, int l, const char *s, const char *t) {
|
||||
if (!t || !*t) return;
|
||||
PrintLine(f, l, "%s%`'s", s, t);
|
||||
}
|
||||
|
||||
static void PrintTokStr(FILE *f, int l, const char *s, Token *t) {
|
||||
if (!t) return;
|
||||
PrintLine(f, l, "%s%`'.*s", s, t->len, t->loc);
|
||||
}
|
||||
|
||||
static void PrintMember(FILE *f, int l, const char *s, Member *m) {
|
||||
if (!m) return;
|
||||
PrintLine(f, l, "%sMember { # %p", s, m);
|
||||
PrintTokStr(f, l + 2, "name: ", m->name);
|
||||
PrintInt(f, l + 2, "idx: ", m->idx);
|
||||
PrintInt(f, l + 2, "align: ", m->align);
|
||||
PrintInt(f, l + 2, "offset: ", m->offset);
|
||||
PrintBool(f, l + 2, "is_bitfield: ", m->is_bitfield);
|
||||
PrintInt(f, l + 2, "bit_offset: ", m->bit_offset);
|
||||
PrintInt(f, l + 2, "bit_width: ", m->bit_width);
|
||||
PrintType(f, l + 2, "ty: ", m->ty);
|
||||
PrintLine(f, l, "}");
|
||||
}
|
||||
|
||||
static void PrintMembers(FILE *f, int l, const char *s, Member *m) {
|
||||
for (; m; m = m->next) {
|
||||
PrintMember(f, l, s, m);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintType(FILE *f, int l, const char *s, Type *t) {
|
||||
for (; t; t = t->next) {
|
||||
if (Visit(t)) {
|
||||
PrintLine(f, l, "%sType { # %p", s, t);
|
||||
PrintLine(f, l + 2, "kind: TY_%s", kTypeKindStr[t->kind]);
|
||||
PrintInt(f, l + 2, "size: ", t->size);
|
||||
PrintInt(f, l + 2, "align: ", t->align);
|
||||
PrintBool(f, l + 2, "is_unsigned: ", t->is_unsigned);
|
||||
PrintBool(f, l + 2, "is_atomic: ", t->is_atomic);
|
||||
PrintType(f, l + 2, "origin: ", t->origin);
|
||||
PrintType(f, l + 2, "base: ", t->base);
|
||||
PrintTokStr(f, l + 2, "name: ", t->name);
|
||||
PrintTokStr(f, l + 2, "name_pos: ", t->name_pos);
|
||||
PrintInt(f, l + 2, "array_len: ", t->array_len);
|
||||
PrintInt(f, l + 2, "vector_size: ", t->vector_size);
|
||||
PrintNode(f, l + 2, "vla_len: ", t->vla_len);
|
||||
PrintObj(f, l + 2, "vla_size: ", t->vla_size);
|
||||
PrintMembers(f, l + 2, "members: ", t->members);
|
||||
PrintBool(f, l + 2, "is_flexible: ", t->is_flexible);
|
||||
PrintBool(f, l + 2, "is_packed: ", t->is_packed);
|
||||
PrintBool(f, l + 2, "is_aligned: ", t->is_aligned);
|
||||
PrintType(f, l + 2, "return_ty: ", t->return_ty);
|
||||
PrintType(f, l + 2, "params: ", t->params);
|
||||
PrintBool(f, l + 2, "is_variadic: ", t->is_variadic);
|
||||
PrintLine(f, l, "}");
|
||||
} else if (t->name) {
|
||||
PrintLine(f, l, "%sTY_%s %.*s # %p", s, kTypeKindStr[t->kind],
|
||||
t->name->len, t->name->loc, t);
|
||||
} else {
|
||||
PrintLine(f, l, "%sTY_%s # %p", s, kTypeKindStr[t->kind], t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintAsm(FILE *f, int l, const char *s, Asm *a) {
|
||||
int i;
|
||||
if (!a) return;
|
||||
PrintLine(f, l, "%sAsm { # %p", s, a);
|
||||
PrintStr(f, l + 2, "str: ", a->str);
|
||||
for (i = 0; i < a->n; ++i) {
|
||||
PrintLine(f, l + 2, "ops: AsmOperand {");
|
||||
PrintStr(f, l + 4, "str: ", a->ops[i].str);
|
||||
PrintNode(f, l + 4, "node: ", a->ops[i].node);
|
||||
PrintLine(f, l + 2, "}");
|
||||
}
|
||||
PrintLine(f, l, "}");
|
||||
}
|
||||
|
||||
static void PrintNode(FILE *f, int l, const char *s, Node *n) {
|
||||
for (; n; n = n->next) {
|
||||
PrintLine(f, l, "%sNode { # %p", s, n);
|
||||
PrintLine(f, l + 2, "kind: ND_%s", kNodeKindStr[n->kind]);
|
||||
PrintType(f, l + 2, "ty: ", n->ty);
|
||||
PrintNode(f, l + 2, "lhs: ", n->lhs);
|
||||
PrintNode(f, l + 2, "rhs: ", n->rhs);
|
||||
PrintNode(f, l + 2, "cond: ", n->cond);
|
||||
PrintNode(f, l + 2, "then: ", n->then);
|
||||
PrintNode(f, l + 2, "els: ", n->els);
|
||||
PrintNode(f, l + 2, "init: ", n->init);
|
||||
PrintNode(f, l + 2, "inc: ", n->inc);
|
||||
PrintNode(f, l + 2, "body: ", n->body);
|
||||
PrintType(f, l + 2, "func_ty: ", n->func_ty);
|
||||
PrintNode(f, l + 2, "args: ", n->args);
|
||||
PrintObj(f, l + 2, "ret_buffer: ", n->ret_buffer);
|
||||
PrintBool(f, l + 2, "pass_by_stack: ", n->pass_by_stack);
|
||||
PrintBool(f, l + 2, "realign_stack: ", n->realign_stack);
|
||||
PrintNode(f, l + 2, "case_next: ", n->case_next);
|
||||
PrintNode(f, l + 2, "default_case: ", n->default_case);
|
||||
PrintStr(f, l + 2, "label: ", n->label);
|
||||
PrintStr(f, l + 2, "unique_label: ", n->unique_label);
|
||||
PrintNode(f, l + 2, "goto_next: ", n->goto_next);
|
||||
PrintStr(f, l + 2, "brk_label: ", n->brk_label);
|
||||
PrintStr(f, l + 2, "cont_label: ", n->cont_label);
|
||||
PrintInt(f, l + 2, "begin: ", n->begin);
|
||||
PrintAsm(f, l + 2, "azm: ", n->azm);
|
||||
PrintInt(f, l + 2, "end: ", n->end);
|
||||
PrintMember(f, l + 2, "member: ", n->member);
|
||||
PrintObj(f, l + 2, "var: ", n->var);
|
||||
PrintNode(f, l + 2, "overflow: ", n->overflow);
|
||||
PrintInt(f, l + 2, "val: ", n->val);
|
||||
if (n->fval) PrintLine(f, l + 2, "fval: %Lf", n->fval);
|
||||
PrintLine(f, l, "}");
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintRelo(FILE *f, int l, const char *s, Relocation *r) {
|
||||
for (; r; r = r->next) {
|
||||
PrintLine(f, l, "%sRelocation { # %p", s, r);
|
||||
PrintInt(f, l + 2, "offset: ", r->offset);
|
||||
if (r->label) PrintStr(f, l + 2, "label: ", *r->label);
|
||||
PrintInt(f, l + 2, "addend: ", r->addend);
|
||||
PrintLine(f, l, "}");
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintObj(FILE *f, int l, const char *s, Obj *o) {
|
||||
if (!o) return;
|
||||
PrintLine(f, l, "%sObj { # %p", s, o);
|
||||
PrintStr(f, l + 2, "name: ", o->name);
|
||||
PrintType(f, l + 2, "ty: ", o->ty);
|
||||
PrintBool(f, l + 2, "is_local: ", o->is_local);
|
||||
PrintInt(f, l + 2, "align: ", o->align);
|
||||
PrintInt(f, l + 2, "offset: ", o->offset);
|
||||
PrintBool(f, l + 2, "is_function: ", o->is_function);
|
||||
PrintBool(f, l + 2, "is_definition: ", o->is_definition);
|
||||
PrintBool(f, l + 2, "is_static: ", o->is_static);
|
||||
PrintBool(f, l + 2, "is_weak: ", o->is_weak);
|
||||
PrintBool(f, l + 2, "is_externally_visible: ", o->is_externally_visible);
|
||||
PrintStr(f, l + 2, "asmname: ", o->asmname);
|
||||
PrintStr(f, l + 2, "section: ", o->section);
|
||||
PrintStr(f, l + 2, "visibility: ", o->visibility);
|
||||
PrintBool(f, l + 2, "is_tentative: ", o->is_tentative);
|
||||
PrintBool(f, l + 2, "is_string_literal: ", o->is_string_literal);
|
||||
PrintBool(f, l + 2, "is_tls: ", o->is_tls);
|
||||
PrintStr(f, l + 2, "init_data: ", o->init_data);
|
||||
PrintRelo(f, l + 2, "rel: ", o->rel);
|
||||
PrintBool(f, l + 2, "is_inline: ", o->is_inline);
|
||||
PrintBool(f, l + 2, "is_aligned: ", o->is_aligned);
|
||||
PrintBool(f, l + 2, "is_noreturn: ", o->is_noreturn);
|
||||
PrintBool(f, l + 2, "is_destructor: ", o->is_destructor);
|
||||
PrintBool(f, l + 2, "is_constructor: ", o->is_constructor);
|
||||
PrintInt(f, l + 2, "stack_size: ", o->stack_size);
|
||||
PrintObj(f, l + 2, "params: ", o->params);
|
||||
PrintNode(f, l + 2, "body: ", o->body);
|
||||
PrintObj(f, l + 2, "locals: ", o->locals);
|
||||
PrintObj(f, l + 2, "va_area: ", o->va_area);
|
||||
PrintObj(f, l + 2, "alloca_bottom: ", o->alloca_bottom);
|
||||
PrintBool(f, l + 2, "is_live: ", o->is_live);
|
||||
PrintBool(f, l + 2, "is_root: ", o->is_root);
|
||||
PrintLine(f, l, "}");
|
||||
}
|
||||
|
||||
void print_ast(FILE *f, Obj *o) {
|
||||
for (; o; o = o->next) {
|
||||
PrintObj(f, 0, "", o);
|
||||
}
|
||||
}
|
2
third_party/chibicc/test/alloca_test.c
vendored
2
third_party/chibicc/test/alloca_test.c
vendored
|
@ -11,7 +11,7 @@ int main() {
|
|||
char *p2 = alloca(16);
|
||||
char *p3 = 1 + (char *)alloca(3) + 1;
|
||||
p3 -= 2;
|
||||
char *p4 = fn(1, alloca(16), 3);
|
||||
char *p4 = fn(1, __builtin_alloca(16), 3);
|
||||
|
||||
ASSERT(16, p1 - p2);
|
||||
ASSERT(16, p2 - p3);
|
||||
|
|
6
third_party/chibicc/test/asm_test.c
vendored
6
third_party/chibicc/test/asm_test.c
vendored
|
@ -128,5 +128,11 @@ int main() {
|
|||
ASSERT(9, v1[6]);
|
||||
ASSERT(10, v1[7]);
|
||||
|
||||
{
|
||||
char *p;
|
||||
asm("mov\t%1,%0" : "=r"(p) : "r"("hello"));
|
||||
ASSERT(1, !strcmp(p, "hello"));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
8
third_party/chibicc/test/assert_test.c
vendored
Normal file
8
third_party/chibicc/test/assert_test.c
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
_Static_assert(1);
|
||||
_Static_assert(1, "hey");
|
||||
|
||||
main() {
|
||||
_Static_assert(sizeof(int) == 4, "wut");
|
||||
}
|
15
third_party/chibicc/test/attribute_test.c
vendored
15
third_party/chibicc/test/attribute_test.c
vendored
|
@ -1,6 +1,21 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
void doge() __attribute__((__nonnull__));
|
||||
void cate(char *) __attribute__((__nonnull__(1)));
|
||||
int var __attribute__((__section__(".data.var")));
|
||||
int ar[4] __attribute__((__section__(".data.var")));
|
||||
typedef int int2[2] __attribute__((__aligned__(64)));
|
||||
typedef int int4[4] __attribute__((__warn_if_not_aligned__(16)));
|
||||
|
||||
__attribute__((__nonnull__)) void doge2();
|
||||
__attribute__((__nonnull__(1))) void cate2(char *);
|
||||
__attribute__((__section__(".data.var"))) int var2;
|
||||
__attribute__((__section__(".data.var"))) int ar2[4];
|
||||
|
||||
int main() {
|
||||
int2 a;
|
||||
ASSERT(64, _Alignof(int2));
|
||||
ASSERT(64, _Alignof(a));
|
||||
ASSERT(5, ({
|
||||
struct {
|
||||
char a;
|
||||
|
|
242
third_party/chibicc/test/builtin_test.c
vendored
242
third_party/chibicc/test/builtin_test.c
vendored
|
@ -8,10 +8,87 @@
|
|||
#define FPCLASSIFY(x) \
|
||||
__builtin_fpclassify(FPNAN, FPINFINITE, FPNORMAL, FPSUBNORMAL, FPZERO, x)
|
||||
|
||||
#define conceal(x) \
|
||||
({ \
|
||||
typeof(x) cloak = x; \
|
||||
asm("" : "+r"(cloak)); \
|
||||
cloak; \
|
||||
})
|
||||
|
||||
struct frame {
|
||||
struct frame *next;
|
||||
intptr_t addr;
|
||||
};
|
||||
|
||||
struct frame *frame(void) {
|
||||
struct frame *myframe = __builtin_frame_address(0);
|
||||
struct frame *parentframe = myframe->next;
|
||||
return parentframe;
|
||||
}
|
||||
|
||||
void test_frame_address(void) {
|
||||
ASSERT(1, __builtin_frame_address(0) == frame());
|
||||
}
|
||||
|
||||
void test_constant(void) {
|
||||
ASSERT(1, __builtin_constant_p(1));
|
||||
ASSERT(0, __builtin_constant_p(conceal(1)));
|
||||
ASSERT(0, __builtin_constant_p(stdin));
|
||||
ASSERT(1, __builtin_constant_p(__builtin_popcount(0b10111011)));
|
||||
ASSERT(1, __builtin_constant_p(__builtin_popcountll((size_t)0b10111011)));
|
||||
}
|
||||
|
||||
void test_ignored(void) {
|
||||
ASSERT(123, __builtin_assume_aligned(123, 8));
|
||||
ASSERT(123, __builtin_assume_aligned(123, 32, 8));
|
||||
ASSERT(123, __builtin_expect(123, 0));
|
||||
}
|
||||
|
||||
void __attribute__((__aligned__(16))) test_clz(void) {
|
||||
ASSERT(31, __builtin_clz(1));
|
||||
ASSERT(63, __builtin_clzl(1));
|
||||
ASSERT(63, __builtin_clzll(1));
|
||||
ASSERT(25, __builtin_clz(77));
|
||||
ASSERT(4, __builtin_clz(0x08000000));
|
||||
ASSERT(4, __builtin_clz(0xfff08000000));
|
||||
ASSERT(25, __builtin_clz(conceal(77)));
|
||||
__builtin_clz(conceal(77));
|
||||
}
|
||||
|
||||
__attribute__((__weak__)) void test_ctz(void) {
|
||||
ASSERT(0, __builtin_ctz(1));
|
||||
ASSERT(0, __builtin_ctz(77));
|
||||
ASSERT(27, __builtin_ctz(0x08000000));
|
||||
ASSERT(27, __builtin_ctz(0xffff08000000));
|
||||
ASSERT(63, __builtin_ctzl(0x8000000000000000));
|
||||
ASSERT(63, __builtin_ctzll(0x8000000000000000));
|
||||
ASSERT(0, __builtin_ctz(conceal(77)));
|
||||
}
|
||||
|
||||
void test_ffs(void) {
|
||||
ASSERT(0, __builtin_ffs(0));
|
||||
ASSERT(1, __builtin_ffs(1));
|
||||
ASSERT(1, __builtin_ffs(77));
|
||||
ASSERT(28, __builtin_ffs(0x08000000));
|
||||
ASSERT(28, __builtin_ffs(0xffff08000000));
|
||||
ASSERT(1, __builtin_ffs(conceal(77)));
|
||||
}
|
||||
|
||||
void test_popcnt(void) {
|
||||
ASSERT(0, __builtin_popcount(0));
|
||||
ASSERT(1, __builtin_popcount(1));
|
||||
ASSERT(6, __builtin_popcount(0b10111011));
|
||||
ASSERT(6, __builtin_popcountl(0b10111011));
|
||||
ASSERT(6, __builtin_popcountll(0xbb00000000000000));
|
||||
ASSERT(6, __builtin_popcountl(conceal(0b10111011)));
|
||||
}
|
||||
|
||||
void test_bswap(void) {
|
||||
ASSERT(0x3412, __builtin_bswap16(0x1234));
|
||||
ASSERT(0x78563412, __builtin_bswap32(0x12345678));
|
||||
ASSERT(0xefcdab8967452301, __builtin_bswap64(0x0123456789abcdef));
|
||||
ASSERT(0xefcdab89, __builtin_bswap32(0x0123456789abcdef));
|
||||
ASSERT(0x78563412, __builtin_bswap32(conceal(0x12345678)));
|
||||
}
|
||||
|
||||
void test_fpclassify(void) {
|
||||
|
@ -38,48 +115,34 @@ void test_fpclassify(void) {
|
|||
ASSERT(FPNAN, FPCLASSIFY(__builtin_nanl("")));
|
||||
}
|
||||
|
||||
void __attribute__((__aligned__(16))) test_clz(void) {
|
||||
ASSERT(31, __builtin_clz(1));
|
||||
ASSERT(63, __builtin_clzl(1));
|
||||
ASSERT(63, __builtin_clzll(1));
|
||||
ASSERT(25, __builtin_clz(77));
|
||||
ASSERT(4, __builtin_clz(0x08000000));
|
||||
ASSERT(4, __builtin_clz(0xfff08000000));
|
||||
void test_strlen(void) {
|
||||
ASSERT(5, strlen("hello"));
|
||||
ASSERT(5, __builtin_strlen("hello"));
|
||||
}
|
||||
|
||||
__attribute__((__weak__)) void test_ctz(void) {
|
||||
ASSERT(0, __builtin_ctz(1));
|
||||
ASSERT(0, __builtin_ctz(77));
|
||||
ASSERT(27, __builtin_ctz(0x08000000));
|
||||
ASSERT(27, __builtin_ctz(0xffff08000000));
|
||||
ASSERT(63, __builtin_ctzl(0x8000000000000000));
|
||||
ASSERT(63, __builtin_ctzll(0x8000000000000000));
|
||||
void test_strchr(void) {
|
||||
ASSERT(1, __builtin_strchr("hello", 'z') == NULL);
|
||||
ASSERT(0, (strcmp)(__builtin_strchr("hello", 'e'), "ello"));
|
||||
}
|
||||
|
||||
void test_ffs(void) {
|
||||
ASSERT(0, __builtin_ffs(0));
|
||||
ASSERT(1, __builtin_ffs(1));
|
||||
ASSERT(1, __builtin_ffs(77));
|
||||
ASSERT(28, __builtin_ffs(0x08000000));
|
||||
ASSERT(28, __builtin_ffs(0xffff08000000));
|
||||
void test_strpbrk(void) {
|
||||
ASSERT(1, __builtin_strpbrk("hello", "z") == NULL);
|
||||
ASSERT(0, (strcmp)(__builtin_strpbrk("hello", "ze"), "ello"));
|
||||
}
|
||||
|
||||
void test_popcnt(void) {
|
||||
ASSERT(0, __builtin_popcount(0));
|
||||
ASSERT(1, __builtin_popcount(1));
|
||||
ASSERT(6, __builtin_popcount(0b10111011));
|
||||
ASSERT(6, __builtin_popcountl(0b10111011));
|
||||
ASSERT(6, __builtin_popcountll(0xbb00000000000000));
|
||||
}
|
||||
|
||||
void test_bswap(void) {
|
||||
ASSERT(0x3412, __builtin_bswap16(0x1234));
|
||||
ASSERT(0x78563412, __builtin_bswap32(0x12345678));
|
||||
ASSERT(0xefcdab8967452301, __builtin_bswap64(0x0123456789abcdef));
|
||||
ASSERT(0xefcdab89, __builtin_bswap32(0x0123456789abcdef));
|
||||
void test_strstr(void) {
|
||||
ASSERT(1, __builtin_strstr("hello", "sup") == NULL);
|
||||
ASSERT(0, (strcmp)(__builtin_strstr("hello", "ell"), "ello"));
|
||||
}
|
||||
|
||||
void test_memcpy(void) {
|
||||
{
|
||||
char x[5] = {4, 3, 2, 1, 0};
|
||||
char y[5] = {0, 1, 2, 3, 4};
|
||||
char z[5] = {2, 3, 4, 1, 0};
|
||||
ASSERT(1, x == (memcpy)(x, y + 2, 3));
|
||||
ASSERT(0, memcmp(x, z, 5));
|
||||
}
|
||||
{
|
||||
char x[5] = {4, 3, 2, 1, 0};
|
||||
char y[5] = {0, 1, 2, 3, 4};
|
||||
|
@ -95,6 +158,109 @@ void test_memcpy(void) {
|
|||
ASSERT(1, x == __builtin_memcpy(x, y + 2, n));
|
||||
ASSERT(0, memcmp(x, z, 5));
|
||||
}
|
||||
{
|
||||
char x[5] = {4, 3, 2, 1, 0};
|
||||
ASSERT(1, x == __builtin_memcpy(x, x + 1, 4));
|
||||
ASSERT(0, memcmp(x, (char[5]){3, 2, 1, 0, 0}, 5));
|
||||
}
|
||||
}
|
||||
|
||||
void test_add_overflow(void) {
|
||||
{
|
||||
int z;
|
||||
ASSERT(0, __builtin_add_overflow(2, 3, &z));
|
||||
ASSERT(5, z);
|
||||
}
|
||||
{
|
||||
int x, y, z;
|
||||
x = 2;
|
||||
y = 3;
|
||||
ASSERT(0, __builtin_add_overflow(x, y, &z));
|
||||
ASSERT(5, z);
|
||||
}
|
||||
{
|
||||
int x, y, z;
|
||||
x = 0x7fffffff;
|
||||
y = 1;
|
||||
ASSERT(1, __builtin_add_overflow(x, y, &z));
|
||||
ASSERT(-2147483648, z);
|
||||
}
|
||||
{
|
||||
long x, y, z;
|
||||
x = 0x7fffffff;
|
||||
y = 1;
|
||||
ASSERT(0, __builtin_add_overflow(x, y, &z));
|
||||
ASSERT(2147483648, z);
|
||||
}
|
||||
}
|
||||
|
||||
void test_sub_overflow(void) {
|
||||
{
|
||||
int x, y, z;
|
||||
x = 2;
|
||||
y = 3;
|
||||
ASSERT(0, __builtin_sub_overflow(x, y, &z));
|
||||
ASSERT(-1, z);
|
||||
}
|
||||
{
|
||||
int x, y, z;
|
||||
x = -2147483648;
|
||||
y = 1;
|
||||
ASSERT(1, __builtin_sub_overflow(x, y, &z));
|
||||
ASSERT(2147483647, z);
|
||||
}
|
||||
{
|
||||
long x, y, z;
|
||||
x = -2147483648;
|
||||
y = 1;
|
||||
ASSERT(0, __builtin_sub_overflow(x, y, &z));
|
||||
ASSERT(-2147483649, z);
|
||||
}
|
||||
}
|
||||
|
||||
void test_mul_overflow(void) {
|
||||
{
|
||||
int x, y, z;
|
||||
x = 2;
|
||||
y = 3;
|
||||
ASSERT(0, __builtin_mul_overflow(x, y, &z));
|
||||
ASSERT(6, z);
|
||||
}
|
||||
{
|
||||
int x, y, z;
|
||||
x = 2147483647;
|
||||
y = 2;
|
||||
ASSERT(1, __builtin_mul_overflow(x, y, &z));
|
||||
ASSERT(-2, z);
|
||||
}
|
||||
{
|
||||
long x, y, z;
|
||||
x = 2147483647;
|
||||
y = 2;
|
||||
ASSERT(0, __builtin_mul_overflow(x, y, &z));
|
||||
ASSERT(4294967294, z);
|
||||
}
|
||||
}
|
||||
|
||||
void test_neg_overflow(void) {
|
||||
{
|
||||
int x, z;
|
||||
x = 2;
|
||||
ASSERT(0, __builtin_neg_overflow(x, &z));
|
||||
ASSERT(-2, z);
|
||||
}
|
||||
{
|
||||
int x, z;
|
||||
x = -2147483648;
|
||||
ASSERT(1, __builtin_neg_overflow(x, &z));
|
||||
ASSERT(-2147483648, z);
|
||||
}
|
||||
{
|
||||
long x, z;
|
||||
x = -2147483648;
|
||||
ASSERT(0, __builtin_neg_overflow(x, &z));
|
||||
ASSERT(2147483648, z);
|
||||
}
|
||||
}
|
||||
|
||||
void test_inf(void) {
|
||||
|
@ -225,6 +391,7 @@ void test_offsetof(void) {
|
|||
|
||||
int main() {
|
||||
test_constant();
|
||||
test_frame_address();
|
||||
test_types_compatible_p();
|
||||
test_clz();
|
||||
test_ctz();
|
||||
|
@ -238,5 +405,14 @@ int main() {
|
|||
test_signbit();
|
||||
test_memcpy();
|
||||
test_offsetof();
|
||||
test_ignored();
|
||||
test_add_overflow();
|
||||
test_sub_overflow();
|
||||
test_mul_overflow();
|
||||
test_neg_overflow();
|
||||
test_strlen();
|
||||
test_strchr();
|
||||
test_strpbrk();
|
||||
test_strstr();
|
||||
return 0;
|
||||
}
|
||||
|
|
2
third_party/chibicc/test/constexpr_test.c
vendored
2
third_party/chibicc/test/constexpr_test.c
vendored
|
@ -176,6 +176,4 @@ int main() {
|
|||
|
||||
ASSERT(1, g40 == 1.5);
|
||||
ASSERT(1, g41 == 11);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
42
third_party/chibicc/test/dce_test.c
vendored
Normal file
42
third_party/chibicc/test/dce_test.c
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
int x;
|
||||
|
||||
int main(void) {
|
||||
if (0) {
|
||||
asm(".error \"the assembler shall fail\"");
|
||||
}
|
||||
|
||||
x = 1 ? 777 : ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
|
||||
x = 0;
|
||||
x = 777 ?: ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
|
||||
x = 0;
|
||||
x = __builtin_popcount(strlen("hihi")) == 1 ? 777 : ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
|
||||
x = 0;
|
||||
x = strpbrk("hihi", "ei") ? 777 : ({
|
||||
asm(".error \"the system is down!\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
|
||||
x = 0;
|
||||
x = !__builtin_strpbrk("HELLO\n", "bxdinupo") ? 777 : ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
}
|
28
third_party/chibicc/test/function_test.c
vendored
28
third_party/chibicc/test/function_test.c
vendored
|
@ -87,26 +87,8 @@ unsigned short ushort_fn();
|
|||
char schar_fn();
|
||||
short sshort_fn();
|
||||
|
||||
int add_all(int n, ...);
|
||||
|
||||
typedef struct {
|
||||
int gp_offset;
|
||||
int fp_offset;
|
||||
void *overflow_arg_area;
|
||||
void *reg_save_area;
|
||||
} __va_elem;
|
||||
|
||||
typedef __va_elem va_list[1];
|
||||
|
||||
int add_all(int n, ...);
|
||||
int sprintf(char *buf, char *fmt, ...);
|
||||
int vsprintf(char *buf, char *fmt, va_list ap);
|
||||
|
||||
char *fmt(char *buf, char *fmt, ...) {
|
||||
va_list ap;
|
||||
*ap = *(__va_elem *)__va_area__;
|
||||
vsprintf(buf, fmt, ap);
|
||||
}
|
||||
int add_all(int, ...);
|
||||
int add_all(int, ...);
|
||||
|
||||
double add_double(double x, double y);
|
||||
float add_float(float x, float y);
|
||||
|
@ -307,7 +289,7 @@ int main() {
|
|||
|
||||
{
|
||||
char buf[100];
|
||||
fmt(buf, "%d %d %s", 1, 2, "foo");
|
||||
sprintf(buf, "%d %d %s", 1, 2, "foo");
|
||||
fprintf(f, "%s\n", buf);
|
||||
}
|
||||
|
||||
|
@ -319,7 +301,7 @@ int main() {
|
|||
|
||||
ASSERT(0, ({
|
||||
char buf[100];
|
||||
fmt(buf, "%d %d %s", 1, 2, "foo");
|
||||
sprintf(buf, "%d %d %s", 1, 2, "foo");
|
||||
strcmp("1 2 foo", buf);
|
||||
}));
|
||||
|
||||
|
@ -342,7 +324,7 @@ int main() {
|
|||
|
||||
ASSERT(0, ({
|
||||
char buf[100];
|
||||
fmt(buf, "%.1f", (float)3.5);
|
||||
sprintf(buf, "%.1f", (float)3.5);
|
||||
strcmp(buf, "3.5");
|
||||
}));
|
||||
|
||||
|
|
4
third_party/chibicc/test/hog_test.c
vendored
Normal file
4
third_party/chibicc/test/hog_test.c
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
main(void) {
|
||||
void *p;
|
||||
p = "hello";
|
||||
}
|
38
third_party/chibicc/test/int128_test.c
vendored
38
third_party/chibicc/test/int128_test.c
vendored
|
@ -33,7 +33,17 @@ __int128 sub128x5(__int128 a, __int128 b, __int128 c, __int128 d, __int128 e) {
|
|||
return a - b - c - d - e;
|
||||
}
|
||||
|
||||
__int128 sub128x6(int f, __int128 a, __int128 b, __int128 c, __int128 d,
|
||||
__int128 e) {
|
||||
return f - a - b - c - d - e;
|
||||
}
|
||||
|
||||
void lotsOfArgs(const char *file, int line, const char *func, intmax_t beg,
|
||||
intmax_t end, intmax_t got, const char *gotcode, bool isfatal) {
|
||||
}
|
||||
|
||||
void testLang128(void) {
|
||||
lotsOfArgs(__FILE__, __LINE__, __FUNCTION__, 0, 0, 0, "", false);
|
||||
ASSERT(16, sizeof(__int128));
|
||||
ASSERT(16, sizeof(unsigned __int128));
|
||||
ASSERT(16, _Alignof(__int128));
|
||||
|
@ -64,6 +74,12 @@ void testLang128(void) {
|
|||
I128(0x19a0da005190a5ac, 0x755fa06484419e38),
|
||||
I128(0xafc6e44400b9eadd, 0x05e5afdb2e66cdb8),
|
||||
I128(0x5380c8796909a165, 0x47657977e6c4f381)));
|
||||
ASSERT128(I128(0x1f1b109234418f84, 0x21f9f24c8535e4f0),
|
||||
sub128x6(0x5ab6ba38, I128(0x0db9cd085ab6ba38, 0xdaf9c05f15896b5f),
|
||||
I128(0xb6429ba7b5b38454, 0x4061839d268a0a78),
|
||||
I128(0x19a0da005190a5ac, 0x755fa06484419e38),
|
||||
I128(0xafc6e44400b9eadd, 0x05e5afdb2e66cdb8),
|
||||
I128(0x5380c8796909a165, 0x47657977e6c4f381)));
|
||||
}
|
||||
|
||||
void testCompare128(void) {
|
||||
|
@ -8157,6 +8173,27 @@ void testNot128(void) {
|
|||
ASSERT128(I128(0, 0), ~x);
|
||||
}
|
||||
|
||||
void testAbi(void) {
|
||||
ASSERT(0, ({
|
||||
char buf[200];
|
||||
sprintf(buf, "%d %d %d %d %032jx %032jx", 1, 2, 3, 4,
|
||||
I128(0x1ffffffff, 0x2ffffffff),
|
||||
I128(0x3eeeeeeee, 0x4eeeeeeee));
|
||||
strcmp("1 2 3 4 00000001ffffffff00000002ffffffff "
|
||||
"00000003eeeeeeee00000004eeeeeeee",
|
||||
buf);
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
char buf[200];
|
||||
sprintf(buf, "%d %d %d %d %d %032jx %032jx", 1, 2, 3, 4, 5,
|
||||
I128(0x1ffffffff, 0x2ffffffff),
|
||||
I128(0x3eeeeeeee, 0x4eeeeeeee));
|
||||
strcmp("1 2 3 4 5 00000001ffffffff00000002ffffffff "
|
||||
"00000003eeeeeeee00000004eeeeeeee",
|
||||
buf);
|
||||
}));
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
testLang128();
|
||||
testCompare128();
|
||||
|
@ -8179,5 +8216,6 @@ int main(void) {
|
|||
testCastDblUint128();
|
||||
testCastLdblInt128();
|
||||
testCastLdblUint128();
|
||||
testAbi();
|
||||
return 0;
|
||||
}
|
||||
|
|
3
third_party/chibicc/test/string_test.c
vendored
3
third_party/chibicc/test/string_test.c
vendored
|
@ -1,6 +1,9 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
int main() {
|
||||
typeof("str") StringInitParen1 = ("str");
|
||||
char StringInitParen2[] = ("str");
|
||||
|
||||
ASSERT(0, ""[0]);
|
||||
ASSERT(1, sizeof(""));
|
||||
|
||||
|
|
6
third_party/chibicc/test/test.mk
vendored
6
third_party/chibicc/test/test.mk
vendored
|
@ -49,6 +49,8 @@ THIRD_PARTY_CHIBICC_TEST_DIRECTDEPS = \
|
|||
LIBC_NEXGEN32E \
|
||||
LIBC_UNICODE \
|
||||
LIBC_MEM \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_CHIBICC \
|
||||
THIRD_PARTY_COMPILER_RT
|
||||
|
||||
THIRD_PARTY_CHIBICC_TEST_DEPS := \
|
||||
|
@ -95,6 +97,4 @@ o/$(MODE)/third_party/chibicc/test/%2.com.dbg: \
|
|||
.PHONY: o/$(MODE)/third_party/chibicc/test
|
||||
o/$(MODE)/third_party/chibicc/test: \
|
||||
$(THIRD_PARTY_CHIBICC_TEST_BINS) \
|
||||
$(THIRD_PARTY_CHIBICC_TEST_CHECKS) \
|
||||
$(THIRD_PARTY_CHIBICC_TEST_SRCS:%.c=o/$(MODE)/%.chibicc.s) \
|
||||
$(THIRD_PARTY_CHIBICC_TEST_SRCS:%.c=o/$(MODE)/%.chibicc2.s)
|
||||
$(THIRD_PARTY_CHIBICC_TEST_CHECKS)
|
||||
|
|
10
third_party/chibicc/test/typeof_test.c
vendored
10
third_party/chibicc/test/typeof_test.c
vendored
|
@ -24,6 +24,12 @@ int main() {
|
|||
sizeof(x);
|
||||
}));
|
||||
ASSERT(12, sizeof(typeof(struct { int a, b, c; })));
|
||||
|
||||
return 0;
|
||||
ASSERT(3, ({
|
||||
label:
|
||||
3;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
__typeof(int) x = 3;
|
||||
x;
|
||||
}));
|
||||
}
|
||||
|
|
26
third_party/chibicc/tokenize.c
vendored
26
third_party/chibicc/tokenize.c
vendored
|
@ -1,6 +1,6 @@
|
|||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
#define LOOKINGAT(TOK, OP) lookingat(TOK, OP, strlen(OP))
|
||||
#define LOOKINGAT(TOK, OP) (!memcmp(TOK, OP, strlen(OP)))
|
||||
|
||||
// Input file
|
||||
static File *current_file;
|
||||
|
@ -75,29 +75,18 @@ void warn_tok(Token *tok, char *fmt, ...) {
|
|||
ap);
|
||||
}
|
||||
|
||||
forceinline int compare_strings(const char *a, const char *b, size_t n) {
|
||||
size_t i = 0;
|
||||
if (!n-- || a == b) return 0;
|
||||
while (a[i] == b[i] && b[i] && i < n) ++i;
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
}
|
||||
|
||||
static int is_space(int c) {
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' ||
|
||||
c == '\v';
|
||||
}
|
||||
|
||||
static bool lookingat(const char *a, const char *b, size_t n) {
|
||||
return !compare_strings(a, b, n);
|
||||
}
|
||||
|
||||
// Consumes the current token if it matches `op`.
|
||||
bool equal(Token *tok, char *op, size_t n) {
|
||||
return n == tok->len && !compare_strings(tok->loc, op, tok->len);
|
||||
return n == tok->len && !memcmp(tok->loc, op, tok->len);
|
||||
}
|
||||
|
||||
bool consume(Token **rest, Token *tok, char *str, size_t n) {
|
||||
if (n == tok->len && !compare_strings(tok->loc, str, n)) {
|
||||
if (n == tok->len && !memcmp(tok->loc, str, n)) {
|
||||
*rest = tok->next;
|
||||
return true;
|
||||
}
|
||||
|
@ -106,9 +95,12 @@ bool consume(Token **rest, Token *tok, char *str, size_t n) {
|
|||
}
|
||||
|
||||
// Ensure that the current token is `op`.
|
||||
Token *skip(Token *tok, char *op) {
|
||||
if (!EQUAL(tok, op)) error_tok(tok, "expected '%s'", op);
|
||||
return tok->next;
|
||||
Token *skip(Token *tok, char op) {
|
||||
if (tok->len == 1 && *tok->loc == op) {
|
||||
return tok->next;
|
||||
} else {
|
||||
error_tok(tok, "expected '%c'", op);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new token and add it as the next token of `cur`.
|
||||
|
|
25
third_party/chibicc/type.c
vendored
25
third_party/chibicc/type.c
vendored
|
@ -166,10 +166,10 @@ void add_type(Node *node) {
|
|||
case ND_SUB:
|
||||
case ND_MUL:
|
||||
case ND_DIV:
|
||||
case ND_MOD:
|
||||
case ND_BITAND:
|
||||
case ND_BITOR:
|
||||
case ND_BITXOR:
|
||||
case ND_REM:
|
||||
case ND_BINAND:
|
||||
case ND_BINOR:
|
||||
case ND_BINXOR:
|
||||
usual_arith_conv(&node->lhs, &node->rhs);
|
||||
node->ty = node->lhs->ty;
|
||||
return;
|
||||
|
@ -226,10 +226,11 @@ void add_type(Node *node) {
|
|||
return;
|
||||
case ND_ADDR: {
|
||||
Type *ty = node->lhs->ty;
|
||||
if (ty->kind == TY_ARRAY)
|
||||
if (ty->kind == TY_ARRAY) {
|
||||
node->ty = pointer_to(ty->base);
|
||||
else
|
||||
} else {
|
||||
node->ty = pointer_to(ty);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ND_DEREF:
|
||||
|
@ -251,7 +252,17 @@ void add_type(Node *node) {
|
|||
case ND_STMT_EXPR:
|
||||
if (node->body) {
|
||||
Node *stmt = node->body;
|
||||
while (stmt->next) stmt = stmt->next;
|
||||
for (;;) {
|
||||
if (stmt->next) {
|
||||
stmt = stmt->next;
|
||||
} else {
|
||||
if (stmt->kind == ND_LABEL && stmt->lhs) {
|
||||
stmt = stmt->lhs;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stmt->kind == ND_EXPR_STMT) {
|
||||
node->ty = stmt->lhs->ty;
|
||||
return;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue