mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-01 08:48:29 +00:00
Make minor improvements
This commit is contained in:
parent
04caf6f9ad
commit
95b142e4e5
95 changed files with 3818 additions and 2760 deletions
1
third_party/chibicc/README.cosmo
vendored
1
third_party/chibicc/README.cosmo
vendored
|
@ -30,6 +30,7 @@ local bug fixes
|
|||
- 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
|
||||
- make enums unsigned (like gcc) so we don't suffer the msvc enum bitfield bug
|
||||
|
||||
local changes
|
||||
|
||||
|
|
3858
third_party/chibicc/as.c
vendored
3858
third_party/chibicc/as.c
vendored
File diff suppressed because it is too large
Load diff
3
third_party/chibicc/asm.c
vendored
3
third_party/chibicc/asm.c
vendored
|
@ -679,8 +679,7 @@ static void StoreAsmOutputs(Asm *a) {
|
|||
println("\tmov\t%%%s,(%%rax)", kGreg[z][a->ops[i].reg]);
|
||||
} else {
|
||||
println("\tpush\t%%rbx");
|
||||
push();
|
||||
pop("%rbx");
|
||||
println("\tmov\t%%rax,%%rbx");
|
||||
gen_addr(a->ops[i].node);
|
||||
println("\tmov\t%%%s,(%%rax)", kGreg[z][3]);
|
||||
println("\tpop\t%%rbx");
|
||||
|
|
8
third_party/chibicc/chibicc.c
vendored
8
third_party/chibicc/chibicc.c
vendored
|
@ -41,6 +41,7 @@ static bool opt_c;
|
|||
static bool opt_cc1;
|
||||
static bool opt_hash_hash_hash;
|
||||
static bool opt_static;
|
||||
static bool opt_save_temps;
|
||||
static char *opt_MF;
|
||||
static char *opt_MT;
|
||||
static char *opt_o;
|
||||
|
@ -140,6 +141,7 @@ static char *quote_makefile(char *s) {
|
|||
|
||||
static void PrintMemoryUsage(void) {
|
||||
struct mallinfo mi;
|
||||
malloc_trim(0);
|
||||
mi = mallinfo();
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "allocated %,ld bytes of memory\n", mi.arena);
|
||||
|
@ -342,7 +344,7 @@ static char *replace_extn(char *tmpl, char *extn) {
|
|||
}
|
||||
|
||||
static void cleanup(void) {
|
||||
if (tmpfiles) {
|
||||
if (tmpfiles && !opt_save_temps) {
|
||||
for (int i = 0; tmpfiles[i]; i++) {
|
||||
unlink(tmpfiles[i]);
|
||||
}
|
||||
|
@ -350,7 +352,7 @@ static void cleanup(void) {
|
|||
}
|
||||
|
||||
static char *create_tmpfile(void) {
|
||||
char *path = xstrcat(kTmpPath, "chibicc-XXXXXX");
|
||||
char *path = xjoinpaths(kTmpPath, "chibicc-XXXXXX");
|
||||
int fd = mkstemp(path);
|
||||
if (fd == -1) error("mkstemp failed: %s", strerror(errno));
|
||||
close(fd);
|
||||
|
@ -383,6 +385,7 @@ static void run_subprocess(char **argv) {
|
|||
}
|
||||
}
|
||||
if (status != 0) {
|
||||
opt_save_temps = true;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -545,6 +548,7 @@ static void cc1(void) {
|
|||
static void assemble(char *input, char *output) {
|
||||
char *as = getenv("AS");
|
||||
if (!as || !*as) as = "as";
|
||||
/* as = "o//third_party/chibicc/as.com"; */
|
||||
StringArray arr = {};
|
||||
strarray_push(&arr, as);
|
||||
strarray_push(&arr, "-W");
|
||||
|
|
5
third_party/chibicc/chibicc.h
vendored
5
third_party/chibicc/chibicc.h
vendored
|
@ -16,6 +16,7 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsf.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
|
@ -126,8 +127,8 @@ char *read_file(char *);
|
|||
int read_escaped_char(char **, char *);
|
||||
|
||||
#define UNREACHABLE() error("internal error at %s:%d", __FILE__, __LINE__)
|
||||
#define EQUAL(T, S) equal(T, S, strlen(S))
|
||||
#define CONSUME(R, T, S) consume(R, T, S, strlen(S))
|
||||
#define EQUAL(T, S) equal(T, S, sizeof(S) - 1)
|
||||
#define CONSUME(R, T, S) consume(R, T, S, sizeof(S) - 1)
|
||||
|
||||
//
|
||||
// preprocess.c
|
||||
|
|
13
third_party/chibicc/codegen.c
vendored
13
third_party/chibicc/codegen.c
vendored
|
@ -616,11 +616,9 @@ static bool has_flonum2(Type *ty) {
|
|||
static void push_struct(Type *ty) {
|
||||
int sz = ROUNDUP(ty->size, 8);
|
||||
println("\tsub\t$%d,%%rsp", sz);
|
||||
println("\tmov\t%%rsp,%%rdi");
|
||||
depth += sz / 8;
|
||||
for (int i = 0; i < ty->size; i++) {
|
||||
println("\tmov\t%d(%%rax),%%r10b", i);
|
||||
println("\tmov\t%%r10b,%d(%%rsp)", i);
|
||||
}
|
||||
gen_memcpy(ty->size);
|
||||
}
|
||||
|
||||
static void push_args2(Node *args, bool first_pass) {
|
||||
|
@ -781,7 +779,7 @@ static void copy_ret_buffer(Obj *var) {
|
|||
}
|
||||
} else {
|
||||
char *reg1 = (gp == 0) ? "%al" : "%dl";
|
||||
char *reg2 = (gp == 0) ? "%rax" : "%rdx";
|
||||
char *reg2 = (gp == 0) ? "%rax" : "%rdx"; /* TODO: isn't ax clobbered? */
|
||||
for (int i = 8; i < MIN(16, ty->size); i++) {
|
||||
println("\tmov\t%s,%d(%%rbp)", reg1, var->offset + i);
|
||||
println("\tshr\t$8,%s", reg2);
|
||||
|
@ -2241,7 +2239,7 @@ static void emit_data(Obj *prog) {
|
|||
}
|
||||
print_align(align);
|
||||
println("\t.type\t%s,@object", nameof(var));
|
||||
println("\t.size\t%s,%d", nameof(var), var->ty->size);
|
||||
/* println("\t.size\t%s,%d", nameof(var), var->ty->size); */
|
||||
println("%s:", nameof(var));
|
||||
if (var->init_data) {
|
||||
int pos = 0;
|
||||
|
@ -2425,7 +2423,7 @@ static void emit_text(Obj *prog) {
|
|||
emitlin("\tleave");
|
||||
emitlin("\tret");
|
||||
}
|
||||
println("\t.size\t%s,.-%s", nameof(fn), nameof(fn));
|
||||
/* println("\t.size\t%s,.-%s", nameof(fn), nameof(fn)); */
|
||||
if (fn->is_constructor) {
|
||||
emitlin("\t.section .ctors,\"aw\",@progbits");
|
||||
emitlin("\t.align\t8");
|
||||
|
@ -2448,6 +2446,7 @@ static void emit_staticasms(StaticAsm *a) {
|
|||
void codegen(Obj *prog, FILE *out) {
|
||||
output_stream = out;
|
||||
File **files = get_input_files();
|
||||
println("# -*- mode:unix-assembly -*-");
|
||||
for (int i = 0; files[i]; i++) {
|
||||
println("\t.file\t%d %`'s", files[i]->file_no, files[i]->name);
|
||||
}
|
||||
|
|
3
third_party/chibicc/hashmap.c
vendored
3
third_party/chibicc/hashmap.c
vendored
|
@ -35,8 +35,9 @@ static void rehash(HashMap *map) {
|
|||
map2.capacity = cap;
|
||||
for (int i = 0; i < map->capacity; i++) {
|
||||
HashEntry *ent = &map->buckets[i];
|
||||
if (ent->key && ent->key != TOMBSTONE)
|
||||
if (ent->key && ent->key != TOMBSTONE) {
|
||||
hashmap_put2(&map2, ent->key, ent->keylen, ent->val);
|
||||
}
|
||||
}
|
||||
assert(map2.used == nkeys);
|
||||
*map = map2;
|
||||
|
|
34
third_party/chibicc/hog.s
vendored
34
third_party/chibicc/hog.s
vendored
|
@ -1,34 +0,0 @@
|
|||
.globl _start
|
||||
_start: rep movsb
|
||||
/ add $333333,%rcx
|
||||
/ test %eax,(%rcx) # 85 0001
|
||||
push %r15
|
||||
pop %r15
|
||||
mov %al,%bl
|
||||
mov %eax,%ecx # 89 0301
|
||||
mov %ecx,%eax # 89 0310
|
||||
mov %ecx,(%rbx)
|
||||
mov (%rbx),%ecx
|
||||
mov %xmm0,%xmm1
|
||||
movb $1,(%rax)
|
||||
movl $1,(%rax)
|
||||
movl $1,0xffffff(%rax,%rbx,8)
|
||||
mov $1,%bl
|
||||
mov $123,%r8d
|
||||
/ mov %ebx,%r8d
|
||||
/ mov (%r8),%ebx
|
||||
/ mov %ebx,(%r8)
|
||||
/ movd %eax,%xmm0
|
||||
/ movdqa %xmm0,%xmm8
|
||||
/ movdqa %xmm8,%xmm1
|
||||
/ paddw %xmm8,%xmm1
|
||||
/ paddw %xmm1,%xmm8
|
||||
hlt
|
||||
ret $1
|
||||
|
||||
a: .asciz "ho","ggg"
|
||||
.align 8
|
||||
.section .text.yo
|
||||
.zero 1
|
||||
.byte 1
|
||||
.hidden doge
|
15
third_party/chibicc/parse.c
vendored
15
third_party/chibicc/parse.c
vendored
|
@ -16,6 +16,7 @@
|
|||
// So it is very easy to lookahead arbitrary number of tokens in this
|
||||
// parser.
|
||||
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
typedef struct InitDesg InitDesg;
|
||||
|
@ -577,6 +578,8 @@ static Token *thing_attributes(Token *tok, void *arg) {
|
|||
error_tok(tok, "unknown function attribute");
|
||||
}
|
||||
|
||||
Token *to;
|
||||
|
||||
// declspec = ("void" | "_Bool" | "char" | "short" | "int" | "long"
|
||||
// | "typedef" | "static" | "extern" | "inline"
|
||||
// | "_Thread_local" | "__thread"
|
||||
|
@ -641,6 +644,7 @@ static Type *declspec(Token **rest, Token *tok, VarAttr *attr) {
|
|||
if (attr->is_typedef &&
|
||||
attr->is_static + attr->is_extern + attr->is_inline + attr->is_tls >
|
||||
1) {
|
||||
to = tok;
|
||||
error_tok(tok, "typedef may not be used together with static,"
|
||||
" extern, inline, __thread or _Thread_local");
|
||||
}
|
||||
|
@ -2577,8 +2581,9 @@ static Node *unary(Token **rest, Token *tok) {
|
|||
if (EQUAL(tok, "&")) {
|
||||
Node *lhs = cast(rest, tok->next);
|
||||
add_type(lhs);
|
||||
if (lhs->kind == ND_MEMBER && lhs->member->is_bitfield)
|
||||
if (lhs->kind == ND_MEMBER && lhs->member->is_bitfield) {
|
||||
error_tok(tok, "cannot take address of bitfield");
|
||||
}
|
||||
return new_unary(ND_ADDR, lhs, tok);
|
||||
}
|
||||
if (EQUAL(tok, "*")) {
|
||||
|
@ -2995,13 +3000,13 @@ static Node *primary(Token **rest, Token *tok) {
|
|||
if (node->ty->kind == TY_VLA) return new_var_node(node->ty->vla_size, tok);
|
||||
return new_ulong(node->ty->size, tok);
|
||||
}
|
||||
if (EQUAL(tok, "_Alignof") && EQUAL(tok->next, "(") &&
|
||||
is_typename(tok->next->next)) {
|
||||
if ((EQUAL(tok, "_Alignof") || EQUAL(tok, "__alignof__")) &&
|
||||
EQUAL(tok->next, "(") && is_typename(tok->next->next)) {
|
||||
Type *ty = typename(&tok, tok->next->next);
|
||||
*rest = skip(tok, ')');
|
||||
return new_ulong(ty->align, tok);
|
||||
}
|
||||
if (EQUAL(tok, "_Alignof")) {
|
||||
if (EQUAL(tok, "_Alignof") || EQUAL(tok, "__alignof__")) {
|
||||
Node *node = unary(rest, tok->next);
|
||||
add_type(node);
|
||||
return new_ulong(node->ty->align, tok);
|
||||
|
@ -3338,7 +3343,7 @@ static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
|||
fn->asmname = ConsumeStringLiteral(&tok, tok);
|
||||
tok = skip(tok, ')');
|
||||
}
|
||||
tok = attribute_list(tok, &attr, thing_attributes);
|
||||
tok = attribute_list(tok, attr, thing_attributes);
|
||||
if (CONSUME(&tok, tok, ";")) return tok;
|
||||
current_fn = fn;
|
||||
locals = NULL;
|
||||
|
|
2
third_party/chibicc/preprocess.c
vendored
2
third_party/chibicc/preprocess.c
vendored
|
@ -686,7 +686,7 @@ static char *detect_include_guard(Token *tok) {
|
|||
char *macro = strndup(tok->loc, tok->len);
|
||||
tok = tok->next;
|
||||
if (!is_hash(tok) || !EQUAL(tok->next, "define") ||
|
||||
!EQUAL(tok->next->next, macro))
|
||||
!equal(tok->next->next, macro, strlen(macro)))
|
||||
return NULL;
|
||||
// Read until the end of the file.
|
||||
while (tok->kind != TK_EOF) {
|
||||
|
|
23
third_party/chibicc/test/bitfield_test.c
vendored
23
third_party/chibicc/test/bitfield_test.c
vendored
|
@ -1,5 +1,7 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
#define TYPE_SIGNED(type) (((type)-1) < 0)
|
||||
|
||||
struct {
|
||||
char a;
|
||||
int b : 5;
|
||||
|
@ -7,6 +9,27 @@ struct {
|
|||
} g45 = {1, 2, 3}, g46 = {};
|
||||
|
||||
int main() {
|
||||
|
||||
/* NOTE: Consistent w/ GCC (but MSVC would fail this) */
|
||||
ASSERT(1, 2 == ({
|
||||
struct {
|
||||
enum { a, b, c } e : 2;
|
||||
} x = {
|
||||
.e = 2,
|
||||
};
|
||||
x.e;
|
||||
}));
|
||||
|
||||
/* NOTE: GCC forbids typeof(bitfield). */
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
enum { a, b, c } e : 2;
|
||||
} x = {
|
||||
.e = 2,
|
||||
};
|
||||
TYPE_SIGNED(typeof(x.e));
|
||||
}));
|
||||
|
||||
ASSERT(4, sizeof(struct { int x : 1; }));
|
||||
ASSERT(8, sizeof(struct { long x : 1; }));
|
||||
|
||||
|
|
50
third_party/chibicc/test/dce_test.c
vendored
50
third_party/chibicc/test/dce_test.c
vendored
|
@ -1,42 +1,26 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
int x;
|
||||
#define CRASH \
|
||||
({ \
|
||||
asm(".err"); \
|
||||
666; \
|
||||
})
|
||||
|
||||
int main(void) {
|
||||
|
||||
if (0) {
|
||||
asm(".error \"the assembler shall fail\"");
|
||||
return CRASH;
|
||||
}
|
||||
|
||||
x = 1 ? 777 : ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
if (1) {
|
||||
} else {
|
||||
return CRASH;
|
||||
}
|
||||
|
||||
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);
|
||||
ASSERT(777, 777 ?: CRASH);
|
||||
ASSERT(777, 1 ? 777 : CRASH);
|
||||
ASSERT(777, 0 ? CRASH : 777);
|
||||
ASSERT(777, __builtin_popcount(__builtin_strlen("hihi")) == 1 ? 777 : CRASH);
|
||||
ASSERT(777, !__builtin_strpbrk("HELLO\n", "bxdinupo") ? 777 : CRASH);
|
||||
ASSERT(777, strpbrk("hihi", "ei") ? 777 : CRASH);
|
||||
}
|
||||
|
|
802
third_party/chibicc/test/initializer_test.c
vendored
802
third_party/chibicc/test/initializer_test.c
vendored
|
@ -1,802 +0,0 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
char g3 = 3;
|
||||
short g4 = 4;
|
||||
int g5 = 5;
|
||||
long g6 = 6;
|
||||
int g9[3] = {0, 1, 2};
|
||||
struct {
|
||||
char a;
|
||||
int b;
|
||||
} g11[2] = {{1, 2}, {3, 4}};
|
||||
struct {
|
||||
int a[2];
|
||||
} g12[2] = {{{1, 2}}};
|
||||
union {
|
||||
int a;
|
||||
char b[8];
|
||||
} g13[2] = {0x01020304, 0x05060708};
|
||||
char g17[] = "foobar";
|
||||
char g18[10] = "foobar";
|
||||
char g19[3] = "foobar";
|
||||
char *g20 = g17 + 0;
|
||||
char *g21 = g17 + 3;
|
||||
char *g22 = &g17 - 3;
|
||||
char *g23[] = {g17 + 0, g17 + 3, g17 - 3};
|
||||
int g24 = 3;
|
||||
int *g25 = &g24;
|
||||
int g26[3] = {1, 2, 3};
|
||||
int *g27 = g26 + 1;
|
||||
int *g28 = &g11[1].a;
|
||||
long g29 = (long)(long)g26;
|
||||
struct {
|
||||
struct {
|
||||
int a[3];
|
||||
} a;
|
||||
} g30 = {{{1, 2, 3}}};
|
||||
int *g31 = g30.a.a;
|
||||
struct {
|
||||
int a[2];
|
||||
} g40[2] = {{1, 2}, 3, 4};
|
||||
struct {
|
||||
int a[2];
|
||||
} g41[2] = {1, 2, 3, 4};
|
||||
char g43[][4] = {'f', 'o', 'o', 0, 'b', 'a', 'r', 0};
|
||||
char *g44 = {"foo"};
|
||||
union {
|
||||
int a;
|
||||
char b[4];
|
||||
} g50 = {.b[2] = 0x12};
|
||||
union {
|
||||
int a;
|
||||
} g51[2] = {};
|
||||
|
||||
typedef char T60[];
|
||||
T60 g60 = {1, 2, 3};
|
||||
T60 g61 = {1, 2, 3, 4, 5, 6};
|
||||
|
||||
typedef struct {
|
||||
char a, b[];
|
||||
} T65;
|
||||
T65 g65 = {'f', 'o', 'o', 0};
|
||||
T65 g66 = {'f', 'o', 'o', 'b', 'a', 'r', 0};
|
||||
|
||||
int main() {
|
||||
ASSERT(1, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[0];
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[1];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[2];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[2];
|
||||
}));
|
||||
|
||||
ASSERT(2, ({
|
||||
int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(6, ({
|
||||
int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
int x[3] = {};
|
||||
x[0];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[3] = {};
|
||||
x[1];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[3] = {};
|
||||
x[2];
|
||||
}));
|
||||
|
||||
ASSERT(2, ({
|
||||
int x[2][3] = {{1, 2}};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[2][3] = {{1, 2}};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[2][3] = {{1, 2}};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT('a', ({
|
||||
char x[4] = "abc";
|
||||
x[0];
|
||||
}));
|
||||
ASSERT('c', ({
|
||||
char x[4] = "abc";
|
||||
x[2];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
char x[4] = "abc";
|
||||
x[3];
|
||||
}));
|
||||
ASSERT('a', ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[0][3];
|
||||
}));
|
||||
ASSERT('d', ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT('f', ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(4, ({
|
||||
int x[] = {1, 2, 3, 4};
|
||||
x[3];
|
||||
}));
|
||||
ASSERT(16, ({
|
||||
int x[] = {1, 2, 3, 4};
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
char x[] = "foo";
|
||||
sizeof(x);
|
||||
}));
|
||||
|
||||
ASSERT(4, ({
|
||||
typedef char T[];
|
||||
T x = "foo";
|
||||
T y = "x";
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef char T[];
|
||||
T x = "foo";
|
||||
T y = "x";
|
||||
sizeof(y);
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef char T[];
|
||||
T x = "x";
|
||||
T y = "foo";
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
typedef char T[];
|
||||
T x = "x";
|
||||
T y = "foo";
|
||||
sizeof(y);
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1, 2, 3};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1, 2, 3};
|
||||
x.b;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1, 2, 3};
|
||||
x.c;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1};
|
||||
x.b;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1};
|
||||
x.c;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[0].a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[0].b;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[1].a;
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[1].b;
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}};
|
||||
x[1].b;
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x = {};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x = {};
|
||||
x.b;
|
||||
}));
|
||||
|
||||
ASSERT(5, ({
|
||||
typedef struct {
|
||||
int a, b, c, d, e, f;
|
||||
} T;
|
||||
T x = {1, 2, 3, 4, 5, 6};
|
||||
T y;
|
||||
y = x;
|
||||
y.e;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y, z;
|
||||
z = y = x;
|
||||
z.b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y = x;
|
||||
y.a;
|
||||
}));
|
||||
|
||||
ASSERT(4, ({
|
||||
union {
|
||||
int a;
|
||||
char b[4];
|
||||
} x = {0x01020304};
|
||||
x.b[0];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
union {
|
||||
int a;
|
||||
char b[4];
|
||||
} x = {0x01020304};
|
||||
x.b[1];
|
||||
}));
|
||||
|
||||
ASSERT(0x01020304, ({
|
||||
union {
|
||||
struct {
|
||||
char a, b, c, d;
|
||||
} e;
|
||||
int f;
|
||||
} x = {{4, 3, 2, 1}};
|
||||
x.f;
|
||||
}));
|
||||
|
||||
ASSERT(3, g3);
|
||||
ASSERT(4, g4);
|
||||
ASSERT(5, g5);
|
||||
ASSERT(6, g6);
|
||||
|
||||
ASSERT(0, g9[0]);
|
||||
ASSERT(1, g9[1]);
|
||||
ASSERT(2, g9[2]);
|
||||
|
||||
ASSERT(1, g11[0].a);
|
||||
ASSERT(2, g11[0].b);
|
||||
ASSERT(3, g11[1].a);
|
||||
ASSERT(4, g11[1].b);
|
||||
|
||||
ASSERT(1, g12[0].a[0]);
|
||||
ASSERT(2, g12[0].a[1]);
|
||||
ASSERT(0, g12[1].a[0]);
|
||||
ASSERT(0, g12[1].a[1]);
|
||||
|
||||
ASSERT(4, g13[0].b[0]);
|
||||
ASSERT(3, g13[0].b[1]);
|
||||
ASSERT(8, g13[1].b[0]);
|
||||
ASSERT(7, g13[1].b[1]);
|
||||
|
||||
ASSERT(7, sizeof(g17));
|
||||
ASSERT(10, sizeof(g18));
|
||||
ASSERT(3, sizeof(g19));
|
||||
|
||||
ASSERT(0, memcmp(g17, "foobar", 7));
|
||||
ASSERT(0, memcmp(g18, "foobar\0\0\0", 10));
|
||||
ASSERT(0, memcmp(g19, "foo", 3));
|
||||
|
||||
ASSERT(0, strcmp(g20, "foobar"));
|
||||
ASSERT(0, strcmp(g21, "bar"));
|
||||
ASSERT(0, strcmp(g22 + 3, "foobar"));
|
||||
|
||||
ASSERT(0, strcmp(g23[0], "foobar"));
|
||||
ASSERT(0, strcmp(g23[1], "bar"));
|
||||
ASSERT(0, strcmp(g23[2] + 3, "foobar"));
|
||||
|
||||
ASSERT(3, g24);
|
||||
ASSERT(3, *g25);
|
||||
ASSERT(2, *g27);
|
||||
ASSERT(3, *g28);
|
||||
ASSERT(1, *(int *)g29);
|
||||
|
||||
ASSERT(1, g31[0]);
|
||||
ASSERT(2, g31[1]);
|
||||
ASSERT(3, g31[2]);
|
||||
|
||||
ASSERT(1, g40[0].a[0]);
|
||||
ASSERT(2, g40[0].a[1]);
|
||||
ASSERT(3, g40[1].a[0]);
|
||||
ASSERT(4, g40[1].a[1]);
|
||||
|
||||
ASSERT(1, g41[0].a[0]);
|
||||
ASSERT(2, g41[0].a[1]);
|
||||
ASSERT(3, g41[1].a[0]);
|
||||
ASSERT(4, g41[1].a[1]);
|
||||
|
||||
ASSERT(0, ({
|
||||
int x[2][3] = {0, 1, 2, 3, 4, 5};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[2][3] = {0, 1, 2, 3, 4, 5};
|
||||
x[1][0];
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {0, 1, 2, 3};
|
||||
x[0].a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {0, 1, 2, 3};
|
||||
x[1].a;
|
||||
}));
|
||||
|
||||
ASSERT(0, strcmp(g43[0], "foo"));
|
||||
ASSERT(0, strcmp(g43[1], "bar"));
|
||||
ASSERT(0, strcmp(g44, "foo"));
|
||||
|
||||
ASSERT(3, ({
|
||||
int a[] = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
a[2];
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a, b, c;
|
||||
} x = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
union {
|
||||
int a;
|
||||
char b;
|
||||
} x = {
|
||||
1,
|
||||
};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
enum {
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
};
|
||||
z;
|
||||
}));
|
||||
|
||||
ASSERT(3, sizeof(g60));
|
||||
ASSERT(6, sizeof(g61));
|
||||
|
||||
ASSERT(4, sizeof(g65));
|
||||
ASSERT(7, sizeof(g66));
|
||||
ASSERT(0, strcmp(g65.b, "oo"));
|
||||
ASSERT(0, strcmp(g66.b, "oobar"));
|
||||
|
||||
ASSERT(4, ({
|
||||
int x[3] = {1, 2, 3, [0] = 4, 5};
|
||||
x[0];
|
||||
}));
|
||||
ASSERT(5, ({
|
||||
int x[3] = {1, 2, 3, [0] = 4, 5};
|
||||
x[1];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[3] = {1, 2, 3, [0] = 4, 5};
|
||||
x[2];
|
||||
}));
|
||||
|
||||
ASSERT(10, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(11, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(8, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[0][2];
|
||||
}));
|
||||
ASSERT(12, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(5, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[1][1];
|
||||
}));
|
||||
ASSERT(6, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(7, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(8, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[0][2];
|
||||
}));
|
||||
ASSERT(9, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(10, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[1][1];
|
||||
}));
|
||||
ASSERT(6, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(7, ((int[10]){[3] = 7})[3]);
|
||||
ASSERT(0, ((int[10]){[3] = 7})[4]);
|
||||
|
||||
ASSERT(10, ({
|
||||
char x[] = {[10 - 3] = 1, 2, 3};
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(20, ({
|
||||
char x[][2] = {[8][1] = 1, 2};
|
||||
sizeof(x);
|
||||
}));
|
||||
|
||||
ASSERT(3, sizeof(g60));
|
||||
ASSERT(6, sizeof(g61));
|
||||
|
||||
ASSERT(4, sizeof(g65));
|
||||
ASSERT(7, sizeof(g66));
|
||||
ASSERT(0, strcmp(g65.b, "oo"));
|
||||
ASSERT(0, strcmp(g66.b, "oobar"));
|
||||
|
||||
ASSERT(7, ((int[10]){[3] 7})[3]);
|
||||
ASSERT(0, ((int[10]){[3] 7})[4]);
|
||||
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x = {1, 2, .b = 3, .a = 4};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x = {1, 2, .b = 3, .a = 4};
|
||||
x.b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c = 1, 2};
|
||||
x.c.a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c = 1, 2};
|
||||
x.c.b;
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c.b = 1};
|
||||
x.c.a;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c.b = 1};
|
||||
x.c.b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a = 1, 2};
|
||||
x.a[0];
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a = 1, 2};
|
||||
x.a[1];
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a[1] = 1};
|
||||
x.a[0];
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a[1] = 1};
|
||||
x.a[1];
|
||||
}));
|
||||
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[0].a;
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[0].b;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[1].a;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[1].b;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[2].a;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[2].b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x};
|
||||
y[0].a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x};
|
||||
y[0].b;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x, [0].b = 3};
|
||||
y[0].a;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x, [0].b = 3};
|
||||
y[0].b;
|
||||
}));
|
||||
|
||||
ASSERT(5, ((struct { int a, b, c; }){.c = 5}).c);
|
||||
ASSERT(0, ((struct { int a, b, c; }){.c = 5}).a);
|
||||
|
||||
ASSERT(0x00ff, ({
|
||||
union {
|
||||
unsigned short a;
|
||||
char b[2];
|
||||
} x = {.b[0] = 0xff};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(0xff00, ({
|
||||
union {
|
||||
unsigned short a;
|
||||
char b[2];
|
||||
} x = {.b[1] = 0xff};
|
||||
x.a;
|
||||
}));
|
||||
|
||||
ASSERT(0x00120000, g50.a);
|
||||
ASSERT(0, g51[0].a);
|
||||
ASSERT(0, g51[1].a);
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
struct {
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
};
|
||||
int c;
|
||||
} x = {1, 2, 3, .b = 4, 5};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
struct {
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
};
|
||||
int c;
|
||||
} x = {1, 2, 3, .b = 4, 5};
|
||||
x.b;
|
||||
}));
|
||||
ASSERT(5, ({
|
||||
struct {
|
||||
struct {
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
};
|
||||
int c;
|
||||
} x = {1, 2, 3, .b = 4, 5};
|
||||
x.c;
|
||||
}));
|
||||
|
||||
ASSERT(16, ({
|
||||
char x[] = {[2 ... 10] = 'a', [7] = 'b', [15 ... 15] = 'c', [3 ... 5] = 'd'};
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
char x[] = {[2 ... 10] = 'a', [7] = 'b', [15 ... 15] = 'c', [3 ... 5] = 'd'};
|
||||
memcmp(x, "\0\0adddabaaa\0\0\0\0c", 16);
|
||||
}));
|
||||
|
||||
return 0;
|
||||
}
|
4
third_party/chibicc/test/sizeof_test.c
vendored
4
third_party/chibicc/test/sizeof_test.c
vendored
|
@ -109,5 +109,9 @@ int main() {
|
|||
|
||||
ASSERT(1, sizeof(main));
|
||||
|
||||
ASSERT(1, sizeof(""));
|
||||
ASSERT(2, sizeof("h"));
|
||||
ASSERT(6, sizeof("hello"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
2
third_party/chibicc/tokenize.c
vendored
2
third_party/chibicc/tokenize.c
vendored
|
@ -1,6 +1,6 @@
|
|||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
#define LOOKINGAT(TOK, OP) (!memcmp(TOK, OP, strlen(OP)))
|
||||
#define LOOKINGAT(TOK, OP) (!memcmp(TOK, OP, sizeof(OP) - 1))
|
||||
|
||||
// Input file
|
||||
static File *current_file;
|
||||
|
|
4
third_party/chibicc/type.c
vendored
4
third_party/chibicc/type.c
vendored
|
@ -113,7 +113,9 @@ Type *vla_of(Type *base, Node *len) {
|
|||
}
|
||||
|
||||
Type *enum_type(void) {
|
||||
return new_type(TY_ENUM, 4, 4);
|
||||
Type *ty = new_type(TY_ENUM, 4, 4);
|
||||
ty->is_unsigned = true;
|
||||
return ty;
|
||||
}
|
||||
|
||||
Type *struct_type(void) {
|
||||
|
|
183
third_party/compiler_rt/clear_cache.c
vendored
183
third_party/compiler_rt/clear_cache.c
vendored
|
@ -1,183 +0,0 @@
|
|||
/* clang-format off */
|
||||
/* ===-- clear_cache.c - Implement __clear_cache ---------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
STATIC_YOINK("huge_compiler_rt_license");
|
||||
|
||||
#include "third_party/compiler_rt/int_lib.h"
|
||||
|
||||
#if __APPLE__
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* Forward declare Win32 APIs since the GCC mode driver does not handle the
|
||||
newer SDKs as well as needed. */
|
||||
uint32_t FlushInstructionCache(uintptr_t hProcess, void *lpBaseAddress,
|
||||
uintptr_t dwSize);
|
||||
uintptr_t GetCurrentProcess(void);
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__mips__)
|
||||
#if defined(__ANDROID__) && defined(__LP64__)
|
||||
/*
|
||||
* clear_mips_cache - Invalidates instruction cache for Mips.
|
||||
*/
|
||||
static void clear_mips_cache(const void* Addr, size_t Size) {
|
||||
__asm__ volatile (
|
||||
".set push\n"
|
||||
".set noreorder\n"
|
||||
".set noat\n"
|
||||
"beq %[Size], $zero, 20f\n" /* If size == 0, branch around. */
|
||||
"nop\n"
|
||||
"daddu %[Size], %[Addr], %[Size]\n" /* Calculate end address + 1 */
|
||||
"rdhwr $v0, $1\n" /* Get step size for SYNCI.
|
||||
$1 is $HW_SYNCI_Step */
|
||||
"beq $v0, $zero, 20f\n" /* If no caches require
|
||||
synchronization, branch
|
||||
around. */
|
||||
"nop\n"
|
||||
"10:\n"
|
||||
"synci 0(%[Addr])\n" /* Synchronize all caches around
|
||||
address. */
|
||||
"daddu %[Addr], %[Addr], $v0\n" /* Add step size. */
|
||||
"sltu $at, %[Addr], %[Size]\n" /* Compare current with end
|
||||
address. */
|
||||
"bne $at, $zero, 10b\n" /* Branch if more to do. */
|
||||
"nop\n"
|
||||
"sync\n" /* Clear memory hazards. */
|
||||
"20:\n"
|
||||
"bal 30f\n"
|
||||
"nop\n"
|
||||
"30:\n"
|
||||
"daddiu $ra, $ra, 12\n" /* $ra has a value of $pc here.
|
||||
Add offset of 12 to point to the
|
||||
instruction after the last nop.
|
||||
*/
|
||||
"jr.hb $ra\n" /* Return, clearing instruction
|
||||
hazards. */
|
||||
"nop\n"
|
||||
".set pop\n"
|
||||
: [Addr] "+r"(Addr), [Size] "+r"(Size)
|
||||
:: "at", "ra", "v0", "memory"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The compiler generates calls to __clear_cache() when creating
|
||||
* trampoline functions on the stack for use with nested functions.
|
||||
* It is expected to invalidate the instruction cache for the
|
||||
* specified range.
|
||||
*/
|
||||
|
||||
void __clear_cache(void *start, void *end) {
|
||||
#if __i386__ || __x86_64__ || defined(_M_IX86) || defined(_M_X64)
|
||||
/*
|
||||
* Intel processors have a unified instruction and data cache
|
||||
* so there is nothing to do
|
||||
*/
|
||||
#elif defined(_WIN32) && (defined(__arm__) || defined(__aarch64__))
|
||||
FlushInstructionCache(GetCurrentProcess(), start, end - start);
|
||||
#elif defined(__arm__) && !defined(__APPLE__)
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
struct arm_sync_icache_args arg;
|
||||
|
||||
arg.addr = (uintptr_t)start;
|
||||
arg.len = (uintptr_t)end - (uintptr_t)start;
|
||||
|
||||
sysarch(ARM_SYNC_ICACHE, &arg);
|
||||
#elif defined(__linux__)
|
||||
/*
|
||||
* We used to include asm/unistd.h for the __ARM_NR_cacheflush define, but
|
||||
* it also brought many other unused defines, as well as a dependency on
|
||||
* kernel headers to be installed.
|
||||
*
|
||||
* This value is stable at least since Linux 3.13 and should remain so for
|
||||
* compatibility reasons, warranting it's re-definition here.
|
||||
*/
|
||||
#define __ARM_NR_cacheflush 0x0f0002
|
||||
register int start_reg __asm("r0") = (int) (intptr_t) start;
|
||||
const register int end_reg __asm("r1") = (int) (intptr_t) end;
|
||||
const register int flags __asm("r2") = 0;
|
||||
const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush;
|
||||
__asm __volatile("svc 0x0"
|
||||
: "=r"(start_reg)
|
||||
: "r"(syscall_nr), "r"(start_reg), "r"(end_reg),
|
||||
"r"(flags));
|
||||
assert(start_reg == 0 && "Cache flush syscall failed.");
|
||||
#else
|
||||
compilerrt_abort();
|
||||
#endif
|
||||
#elif defined(__linux__) && defined(__mips__)
|
||||
const uintptr_t start_int = (uintptr_t) start;
|
||||
const uintptr_t end_int = (uintptr_t) end;
|
||||
#if defined(__ANDROID__) && defined(__LP64__)
|
||||
// Call synci implementation for short address range.
|
||||
const uintptr_t address_range_limit = 256;
|
||||
if ((end_int - start_int) <= address_range_limit) {
|
||||
clear_mips_cache(start, (end_int - start_int));
|
||||
} else {
|
||||
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
|
||||
}
|
||||
#else
|
||||
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
|
||||
#endif
|
||||
#elif defined(__mips__) && defined(__OpenBSD__)
|
||||
cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE);
|
||||
#elif defined(__aarch64__) && !defined(__APPLE__)
|
||||
uint64_t xstart = (uint64_t)(uintptr_t) start;
|
||||
uint64_t xend = (uint64_t)(uintptr_t) end;
|
||||
uint64_t addr;
|
||||
|
||||
// Get Cache Type Info
|
||||
uint64_t ctr_el0;
|
||||
__asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
|
||||
|
||||
/*
|
||||
* dc & ic instructions must use 64bit registers so we don't use
|
||||
* uintptr_t in case this runs in an IPL32 environment.
|
||||
*/
|
||||
const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
|
||||
for (addr = xstart & ~(dcache_line_size - 1); addr < xend;
|
||||
addr += dcache_line_size)
|
||||
__asm __volatile("dc cvau, %0" :: "r"(addr));
|
||||
__asm __volatile("dsb ish");
|
||||
|
||||
const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
|
||||
for (addr = xstart & ~(icache_line_size - 1); addr < xend;
|
||||
addr += icache_line_size)
|
||||
__asm __volatile("ic ivau, %0" :: "r"(addr));
|
||||
__asm __volatile("isb sy");
|
||||
#elif defined (__powerpc64__)
|
||||
const size_t line_size = 32;
|
||||
const size_t len = (uintptr_t)end - (uintptr_t)start;
|
||||
|
||||
const uintptr_t mask = ~(line_size - 1);
|
||||
const uintptr_t start_line = ((uintptr_t)start) & mask;
|
||||
const uintptr_t end_line = ((uintptr_t)start + len + line_size - 1) & mask;
|
||||
|
||||
for (uintptr_t line = start_line; line < end_line; line += line_size)
|
||||
__asm__ volatile("dcbf 0, %0" : : "r"(line));
|
||||
__asm__ volatile("sync");
|
||||
|
||||
for (uintptr_t line = start_line; line < end_line; line += line_size)
|
||||
__asm__ volatile("icbi 0, %0" : : "r"(line));
|
||||
__asm__ volatile("isync");
|
||||
#else
|
||||
#if __APPLE__
|
||||
/* On Darwin, sys_icache_invalidate() provides this functionality */
|
||||
sys_icache_invalidate(start, end-start);
|
||||
#else
|
||||
compilerrt_abort();
|
||||
#endif
|
||||
#endif
|
||||
}
|
51
third_party/compiler_rt/trampoline_setup.c
vendored
51
third_party/compiler_rt/trampoline_setup.c
vendored
|
@ -1,51 +0,0 @@
|
|||
/* clang-format off */
|
||||
/* ===----- trampoline_setup.c - Implement __trampoline_setup -------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
STATIC_YOINK("huge_compiler_rt_license");
|
||||
|
||||
#include "third_party/compiler_rt/int_lib.h"
|
||||
|
||||
extern void __clear_cache(void* start, void* end);
|
||||
|
||||
/*
|
||||
* The ppc compiler generates calls to __trampoline_setup() when creating
|
||||
* trampoline functions on the stack for use with nested functions.
|
||||
* This function creates a custom 40-byte trampoline function on the stack
|
||||
* which loads r11 with a pointer to the outer function's locals
|
||||
* and then jumps to the target nested function.
|
||||
*/
|
||||
|
||||
#if __ppc__ && !defined(__powerpc64__)
|
||||
COMPILER_RT_ABI void
|
||||
__trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
|
||||
const void* realFunc, void* localsPtr)
|
||||
{
|
||||
/* should never happen, but if compiler did not allocate */
|
||||
/* enough space on stack for the trampoline, abort */
|
||||
if ( trampSizeAllocated < 40 )
|
||||
compilerrt_abort();
|
||||
|
||||
/* create trampoline */
|
||||
trampOnStack[0] = 0x7c0802a6; /* mflr r0 */
|
||||
trampOnStack[1] = 0x4800000d; /* bl Lbase */
|
||||
trampOnStack[2] = (uint32_t)realFunc;
|
||||
trampOnStack[3] = (uint32_t)localsPtr;
|
||||
trampOnStack[4] = 0x7d6802a6; /* Lbase: mflr r11 */
|
||||
trampOnStack[5] = 0x818b0000; /* lwz r12,0(r11) */
|
||||
trampOnStack[6] = 0x7c0803a6; /* mtlr r0 */
|
||||
trampOnStack[7] = 0x7d8903a6; /* mtctr r12 */
|
||||
trampOnStack[8] = 0x816b0004; /* lwz r11,4(r11) */
|
||||
trampOnStack[9] = 0x4e800420; /* bctr */
|
||||
|
||||
/* clear instruction cache */
|
||||
__clear_cache(trampOnStack, &trampOnStack[10]);
|
||||
}
|
||||
#endif /* __ppc__ && !defined(__powerpc64__) */
|
4
third_party/duktape/duk_config.h
vendored
4
third_party/duktape/duk_config.h
vendored
|
@ -800,8 +800,8 @@
|
|||
* because of bugs in gcc-4.4
|
||||
* (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
|
||||
*/
|
||||
#define DUK_LIKELY(x) likely(x)
|
||||
#define DUK_UNLIKELY(x) unlikely(x)
|
||||
#define DUK_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define DUK_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
/* XXX: equivalent of clang __builtin_unpredictable? */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue