Make it possible to compile redbean with chibicc

This cuts build latency down from 5 seconds to 500 milliseconds.
This commit is contained in:
Justine Tunney 2022-04-22 15:03:32 -07:00
parent 552525cbdd
commit 6ff46ca373
50 changed files with 898 additions and 824 deletions

View file

@ -1752,6 +1752,14 @@ static void OnSize(struct As *a, struct Slice s) {
a->symbols.p[i].size = GetInt(a);
}
static void OnEqu(struct As *a, struct Slice s) {
int i, j;
i = GetSymbol(a, a->things.p[a->i++].i);
ConsumeComma(a);
a->symbols.p[i].offset = GetInt(a);
a->symbols.p[i].section = SHN_ABS;
}
static void OnComm(struct As *a, struct Slice s) {
int i;
i = GetSymbol(a, a->things.p[a->i++].i);
@ -2132,12 +2140,24 @@ static void EmitRexOpModrm(struct As *a, long op, int reg, int modrm, int disp,
EmitOpModrm(a, op, reg, modrm, disp, skew);
}
static void OnLea(struct As *a, struct Slice s) {
static void OnLoad(struct As *a, struct Slice s, int op) {
int modrm, reg, disp;
modrm = ParseModrm(a, &disp);
ConsumeComma(a);
reg = GetRegisterReg(a);
EmitRexOpModrm(a, 0x8D, reg, modrm, disp, 0);
EmitRexOpModrm(a, op, reg, modrm, disp, 0);
}
static void OnLea(struct As *a, struct Slice s) {
return OnLoad(a, s, 0x8D);
}
static void OnLar(struct As *a, struct Slice s) {
return OnLoad(a, s, 0x0f02);
}
static void OnLsl(struct As *a, struct Slice s) {
return OnLoad(a, s, 0x0f03);
}
static void OnMov(struct As *a, struct Slice s) {
@ -2593,6 +2613,12 @@ static void OnPush(struct As *a, struct Slice s) {
}
}
static void OnRdpid(struct As *a, struct Slice s) {
int modrm, disp;
EmitVarword(a, 0xf30fc7);
EmitByte(a, 0370 | GetRegisterReg(a));
}
static void OnPop(struct As *a, struct Slice s) {
int modrm, disp;
modrm = RemoveRexw(ParseModrm(a, &disp));
@ -2901,6 +2927,7 @@ static void OnMinsd(struct As *a, struct Slice s) { OpSse(a, 0xF20F5D); }
static void OnMinss(struct As *a, struct Slice s) { OpSse(a, 0xF30F5D); }
static void OnMovmskpd(struct As *a, struct Slice s) { OpSse(a, 0x660F50); }
static void OnMovmskps(struct As *a, struct Slice s) { OpSse(a, 0x0F50); }
static void OnMovntdq(struct As *a, struct Slice s) { OpMovntdq(a); }
static void OnMovsb(struct As *a, struct Slice s) { EmitByte(a, 0xA4); }
static void OnMovsl(struct As *a, struct Slice s) { EmitByte(a, 0xA5); }
static void OnMovsq(struct As *a, struct Slice s) { EmitVarword(a, 0x48A5); }
@ -3013,12 +3040,13 @@ static void OnPunpcklbw(struct As *a, struct Slice s) { OpSse(a, 0x660F60); }
static void OnPunpckldq(struct As *a, struct Slice s) { OpSse(a, 0x660F62); }
static void OnPunpcklqdq(struct As *a, struct Slice s) { OpSse(a, 0x660F6C); }
static void OnPunpcklwd(struct As *a, struct Slice s) { OpSse(a, 0x660F61); }
static void OnMovntdq(struct As *a, struct Slice s) { OpMovntdq(a); }
static void OnPxor(struct As *a, struct Slice s) { OpSse(a, 0x660FEF); }
static void OnRcl(struct As *a, struct Slice s) { OpBsu(a, s, 2); }
static void OnRcpps(struct As *a, struct Slice s) { OpSse(a, 0x0F53); }
static void OnRcpss(struct As *a, struct Slice s) { OpSse(a, 0xF30F53); }
static void OnRcr(struct As *a, struct Slice s) { OpBsu(a, s, 3); }
static void OnRdtsc(struct As *a, struct Slice s) { EmitVarword(a, 0x0f31); }
static void OnRdtscp(struct As *a, struct Slice s) { EmitVarword(a, 0x0f01f9); }
static void OnRol(struct As *a, struct Slice s) { OpBsu(a, s, 0); }
static void OnRor(struct As *a, struct Slice s) { OpBsu(a, s, 1); }
static void OnRoundsd(struct As *a, struct Slice s) { OpSseIb(a, 0x660F3A0B); }
@ -3088,6 +3116,7 @@ static const struct Directive8 {
{".comm", OnComm}, //
{".data", OnData}, //
{".double", OnDouble}, //
{".equ", OnEqu}, //
{".err", OnErr}, //
{".error", OnError}, //
{".file", OnFile}, //
@ -3329,12 +3358,14 @@ static const struct Directive8 {
{"jpo", OnJnp}, //
{"js", OnJs}, //
{"jz", OnJz}, //
{"lar", OnLar}, //
{"lea", OnLea}, //
{"leave", OnLeave}, //
{"lodsb", OnLodsb}, //
{"lodsl", OnLodsl}, //
{"lodsq", OnLodsq}, //
{"lodsw", OnLodsw}, //
{"lsl", OnLsl}, //
{"maxpd", OnMaxpd}, //
{"maxps", OnMaxps}, //
{"maxsd", OnMaxsd}, //
@ -3507,6 +3538,9 @@ static const struct Directive8 {
{"rcrl", OnRcr}, //
{"rcrq", OnRcr}, //
{"rcrw", OnRcr}, //
{"rdpid", OnRdpid}, //
{"rdtsc", OnRdtsc}, //
{"rdtscp", OnRdtscp}, //
{"ret", OnRet}, //
{"rol", OnRol}, //
{"rolb", OnRol}, //

View file

@ -39,12 +39,12 @@
"\taddsd\t%xmm0,%xmm0\n" \
"2:"
#define u64f80 \
PUSHPOPRAX("fildq\t(%rsp)\n" \
"\ttest\t%rax,%rax\n" \
"\tjns\t1f\n" \
"\tmov\t$0x5f800000,(%rsp)\n" \
"\tfadds\t(%rsp)\n" \
#define u64f80 \
PUSHPOPRAX("fildq\t(%rsp)\n" \
"\ttest\t%rax,%rax\n" \
"\tjns\t1f\n" \
"\tmovq\t$0x5f800000,(%rsp)\n" \
"\tfadds\t(%rsp)\n" \
"1:")
#define i32i8 "movsbl\t%al,%eax"

View file

@ -134,6 +134,8 @@ o/$(MODE)/third_party/chibicc/chibicc.o: \
o/$(MODE)/third_party/chibicc/chibicc.chibicc.o: \
CHIBICC_FLAGS += $(THIRD_PARTY_CHIBICC_DEFINES)
o/$(MODE)/%.chibicc.o: %.s o/$(MODE)/third_party/chibicc/chibicc.com.dbg
@$(COMPILE) -ACHIBICC -T$@ $(CHIBICC) $(CHIBICC_FLAGS) -c -o $@ $<
o/$(MODE)/%.chibicc.o: %.c o/$(MODE)/third_party/chibicc/chibicc.com.dbg
@$(COMPILE) -ACHIBICC -T$@ $(CHIBICC) $(CHIBICC_FLAGS) -c -o $@ $<
o/$(MODE)/%.chibicc2.o: %.c o/$(MODE)/third_party/chibicc/chibicc2.com.dbg

View file

@ -192,9 +192,9 @@ void print_loc(int64_t file, int64_t line) {
if (file != lastfile || line != lastline) {
locbuf = malloc(2 + 4 + 1 + 20 + 1 + 20 + 1);
p = stpcpy(locbuf, "\t.loc\t");
p += int64toarray_radix10(file, p);
p = FormatInt64(p, file);
*p++ = ' ';
int64toarray_radix10(line, p);
FormatInt64(p, line);
emitlin(locbuf);
free(locbuf);
lastfile = file;

View file

@ -19,6 +19,7 @@
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/ffs.h"
#include "libc/testlib/testlib.h"
@ -352,7 +353,10 @@ static Obj *new_string_literal(char *p, Type *ty) {
}
static char *get_ident(Token *tok) {
if (tok->kind != TK_IDENT) error_tok(tok, "expected an identifier");
if (tok->kind != TK_IDENT) {
__die();
error_tok(tok, "expected an identifier");
}
return strndup(tok->loc, tok->len);
}
@ -1088,6 +1092,10 @@ static Type *enum_specifier(Token **rest, Token *tok) {
int val = 0;
while (!consume_end(rest, tok)) {
if (i++ > 0) tok = skip(tok, ',');
if (tok->kind == TK_JAVADOWN) {
current_javadown = tok;
tok = tok->next;
}
char *name = get_ident(tok);
tok = tok->next;
if (EQUAL(tok, "=")) val = const_expr(&tok, tok->next);
@ -1282,6 +1290,10 @@ static void array_designator(Token **rest, Token *tok, Type *ty, int *begin,
static Member *struct_designator(Token **rest, Token *tok, Type *ty) {
Token *start = tok;
tok = skip(tok, '.');
if (tok->kind == TK_JAVADOWN) {
current_javadown = tok;
tok = tok->next;
}
if (tok->kind != TK_IDENT) error_tok(tok, "expected a field designator");
for (Member *mem = ty->members; mem; mem = mem->next) {
// Anonymous struct member
@ -2775,6 +2787,10 @@ static void struct_members(Token **rest, Token *tok, Type *ty) {
// Regular struct members
while (!CONSUME(&tok, tok, ";")) {
if (!first) tok = skip(tok, ',');
if (tok->kind == TK_JAVADOWN) {
current_javadown = tok;
tok = tok->next;
}
first = false;
Member *mem = calloc(1, sizeof(Member));
mem->ty = declarator(&tok, tok, basety);
@ -2833,6 +2849,10 @@ static Type *struct_union_decl(Token **rest, Token *tok) {
ty->name = tag;
tok = skip(tok, '{');
// Construct a struct object.
if (tok->kind == TK_JAVADOWN) {
current_javadown = tok;
tok = tok->next;
}
struct_members(&tok, tok, ty);
*rest = attribute_list(tok, ty, type_attributes);
if (tag) {
@ -3510,7 +3530,9 @@ static Node *primary(Token **rest, Token *tok) {
static Token *parse_typedef(Token *tok, Type *basety) {
bool first = true;
while (!CONSUME(&tok, tok, ";")) {
if (!first) tok = skip(tok, ',');
if (!first) {
tok = skip(tok, ',');
}
first = false;
Type *ty = declarator(&tok, tok, basety);
if (!ty->name) error_tok(ty->name_pos, "typedef name omitted");
@ -3648,11 +3670,18 @@ static Token *function(Token *tok, Type *basety, VarAttr *attr) {
static Token *global_variable(Token *tok, Type *basety, VarAttr *attr) {
bool first = true;
bool isjavadown = tok->kind == TK_JAVADOWN;
while (!CONSUME(&tok, tok, ";")) {
if (!first) tok = skip(tok, ',');
first = false;
Type *ty = declarator(&tok, tok, basety);
if (!ty->name) error_tok(ty->name_pos, "variable name omitted");
if (!ty->name) {
if (isjavadown) {
return tok;
} else {
error_tok(ty->name_pos, "variable name omitted");
}
}
Obj *var = new_gvar(get_ident(ty->name), ty);
if (!var->tok) var->tok = ty->name;
var->javadown = current_javadown;

View file

@ -284,7 +284,9 @@ static long eval_const_expr(Token **rest, Token *tok) {
convert_pp_tokens(expr);
Token *rest2;
long val = const_expr(&rest2, expr);
if (rest2->kind != TK_EOF) error_tok(rest2, "extra token");
if (rest2->kind != TK_EOF && rest2->kind != TK_JAVADOWN) {
error_tok(rest2, "extra token");
}
__arena_pop();
return val;
}
@ -324,7 +326,12 @@ static MacroParam *read_macro_params(Token **rest, Token *tok,
*rest = skip(tok->next, ')');
return head.next;
}
if (tok->kind != TK_IDENT) error_tok(tok, "expected an identifier");
if (tok->kind == TK_JAVADOWN) {
tok = tok->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, ')');

View file

@ -97,10 +97,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) {
while (tok->kind == TK_JAVADOWN) {
tok = tok->next;
}
if (tok->len == 1 && *tok->loc == op) {
return tok->next;
} else {
// __die();
error_tok(tok, "expected '%c'", op);
}
}