Enhance chibicc

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 100644
View 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);
}
}

View File

@ -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);

View File

@ -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;
}

View 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");
}

View File

@ -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;

View File

@ -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;
}

View File

@ -176,6 +176,4 @@ int main() {
ASSERT(1, g40 == 1.5);
ASSERT(1, g41 == 11);
return 0;
}

View 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);
}

View File

@ -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");
}));

View File

@ -0,0 +1,4 @@
main(void) {
void *p;
p = "hello";
}

View File

@ -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;
}

View File

@ -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(""));

View File

@ -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)

View File

@ -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;
}));
}

View File

@ -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`.

View File

@ -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;

View File

@ -88,12 +88,6 @@ o/$(MODE)/tool/build/emulator.o: \
OVERRIDE_COPTS += \
-fno-sanitize=pointer-overflow
# ifeq (,$(MODE))
# $(TOOL_BUILD_OBJS): \
# OVERRIDE_COPTS += \
# -fsanitize=address
# endif
.PHONY: o/$(MODE)/tool/build
o/$(MODE)/tool/build: \
o/$(MODE)/tool/build/emucrt \

View File

@ -1,230 +0,0 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "dsp/core/half.h"
#include "dsp/core/q.h"
#include "libc/conv/conv.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "libc/x/x.h"
#include "third_party/gdtoa/gdtoa.h"
#include "third_party/getopt/getopt.h"
#define USAGE \
" [FLAGS] [INT|FLOAT...]\n\
\n\
Example:\n\
\n\
coefficients -n -- 1 4 6 4 1 # Gaussian Blur\n\
coefficients -L16 -H235 -- .299 .587 .114 # BT.601 RGBY\n\
\n\
Flags:\n\
-v verbose\n\
-n normalize\n\
-m FLEX explicit Q(bits)\n\
-L FLEX low data value [default 0]\n\
-H FLEX high data value [default 255]\n\
-? shows this information\n\
\n"
static struct Flags {
bool n;
long L, H, m;
} flags_ = {
.L = 0,
.H = 255,
};
static wontreturn void PrintUsage(int rc, FILE *f) {
fprintf(f, "Usage: %s%s", program_invocation_name, USAGE);
exit(rc);
}
static void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?nvrL:H:m:")) != -1) {
switch (opt) {
case 'v':
g_loglevel++;
break;
case 'n':
flags_.n = true;
break;
case 'L':
flags_.L = strtol(optarg, NULL, 0);
break;
case 'H':
flags_.H = strtol(optarg, NULL, 0);
break;
case 'm':
flags_.m = strtol(optarg, NULL, 0);
break;
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
}
static void *Normalize(int n, double A[static 8]) {
int i;
double sum, rnorm;
for (sum = i = 0; i < n; ++i) {
sum += A[i];
}
if (fabs(sum - 1) > DBL_MIN * n) {
rnorm = 1 / sum;
for (i = 0; i < n; ++i) {
A[i] *= rnorm;
}
}
return A;
}
static void GetLimits(int n, const long I[static 8], long m, long L, long H,
long res[2][2]) {
int i, j[8];
long x, p[2] = {L, H};
DCHECK(0 < n && n <= 8);
memset(res, 0, sizeof(long) * 2 * 2);
for (j[0] = 0; j[0] < ARRAYLEN(p); ++j[0]) {
for (j[1] = 0; j[1] < ARRAYLEN(p); ++j[1]) {
for (j[2] = 0; j[2] < ARRAYLEN(p); ++j[2]) {
for (j[3] = 0; j[3] < ARRAYLEN(p); ++j[3]) {
for (j[4] = 0; j[4] < ARRAYLEN(p); ++j[4]) {
for (j[5] = 0; j[5] < ARRAYLEN(p); ++j[5]) {
for (j[6] = 0; j[6] < ARRAYLEN(p); ++j[6]) {
for (j[7] = 0; j[7] < ARRAYLEN(p); ++j[7]) {
x = 0;
for (i = 0; i < ARRAYLEN(j); ++i) {
x += p[j[i]] * I[i];
if (x < res[0][0]) res[0][0] = x;
if (x > res[0][1]) res[0][1] = x;
}
x += 1l << (m - 1);
if (x < res[0][0]) res[0][0] = x;
if (x > res[0][1]) res[0][1] = x;
x >>= m;
if (x < res[1][0]) res[1][0] = x;
if (x > res[1][1]) res[1][1] = x;
}
}
}
}
}
}
}
}
}
static const char *GetFittingMachineWord(long L, long H) {
if (-128 <= L && H <= 127) return "int8";
if (0 <= L && H <= 255) return "uint8";
if (-0x8000 <= L && H <= 0x7fff) return "int16";
if (~0x7fffffff <= L && H <= 0x7fffffff) return "int32";
if (0 <= L && H <= 0xffffffff) return "uint32";
return "INT64";
}
static char *DescribeMachineWord(long L, long H) {
return xasprintf("%s[%,ld..%,ld]", GetFittingMachineWord(L, H), L, H);
}
static void ShowBetterCoefficients(int n, double C[static 8], long L, long H) {
long err, I[8], lim[2][2];
char buf[32], kAlphabet[] = "abcdefgh";
int i, j, m, emitted, count, indices[8];
CHECK_LT(L, H);
DCHECK(0 < n && n <= 8);
for (m = 2; m < 40; ++m) {
memset(I, 0, sizeof(I));
if (C[6] || C[7]) {
err = GetIntegerCoefficients8(I, C, m, L, H);
} else {
err = GetIntegerCoefficients(I, C, m, L, H);
}
GetLimits(n, I, m, L, H, lim);
for (count = i = 0; i < n; ++i) {
if (I[i]) {
indices[count++] = i;
}
}
if (count) {
emitted = 0;
if (m) emitted += printf("(");
for (i = 0; i < count; ++i) {
if (i) emitted += printf(" + ");
if (I[indices[i]] != 1) {
emitted += printf("%ld*%c", I[indices[i]], kAlphabet[indices[i]]);
} else {
emitted += printf("%c", kAlphabet[indices[i]]);
}
}
if (m) {
if (m > 1) {
emitted += printf(" + %ld", 1l << (m - 1));
}
emitted += printf(")>>%d", m);
}
printf("%*s", MAX(0, 80 - emitted), " ");
printf("/* %s %s %s ε=%,ld */\n", gc(DescribeMachineWord(L, H)),
gc(DescribeMachineWord(lim[0][0], lim[0][1])),
gc(DescribeMachineWord(lim[1][0], lim[1][1])), err);
}
}
}
static int ReadIdealCoefficients(double C[static 8], int sn, char *S[sn]) {
int i, n;
if ((n = MIN(8, sn)) > 0) {
C[0] = C[1] = C[2] = C[3] = C[4] = C[5] = 0;
for (i = 0; i < n; ++i) {
C[i] = strtod(S[i], NULL);
}
}
return n;
}
int ToolBuildCoefficients(int argc, char *argv[]) {
int n;
double C[8];
GetOpts(argc, argv);
setvbuf(stdout, malloc(PAGESIZE), _IOLBF, PAGESIZE);
if ((n = ReadIdealCoefficients(C, argc - optind, argv + optind))) {
if (flags_.n) Normalize(n, C);
ShowBetterCoefficients(n, C, flags_.L, flags_.H);
}
return 0;
}
int main(int argc, char *argv[]) {
g_loglevel = kLogWarn;
showcrashreports();
return ToolBuildCoefficients(argc, argv);
}

View File

@ -1,267 +0,0 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "dsp/scale/scale.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/conv/conv.h"
#include "libc/fmt/bing.internal.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/testlib/testlib.h"
#include "third_party/gdtoa/gdtoa.h"
#include "third_party/getopt/getopt.h"
#include "third_party/stb/stb_image.h"
#include "third_party/xed/x86.h"
#define USAGE \
" [FLAGS] [PATH]\n\
\n\
Example:\n\
\n\
img2code -cw79 -p2 foo.png\n\
\n\
Flags:\n\
-c compress range\n\
-o PATH out\n\
-r FLEX ratio\n\
-w FLEX new width\n\
-h FLEX new height\n\
-p FLEX pixel y ratio\n\
-? shows this information\n\
\n"
static struct Flags {
const char *o;
double r, p;
int w, h;
bool c;
} flags_ = {
.o = "-",
.p = 1,
};
static wontreturn void PrintUsage(int rc, FILE *f) {
fprintf(f, "Usage: %s%s", program_invocation_name, USAGE);
exit(rc);
}
static void GetOpts(int *argc, char *argv[]) {
int opt;
if (*argc == 2 &&
(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-help") == 0)) {
PrintUsage(EXIT_SUCCESS, stdout);
}
while ((opt = getopt(*argc, argv, "?co:r:w:h:p:")) != -1) {
switch (opt) {
case 'c':
flags_.c = true;
break;
case 'o':
flags_.o = optarg;
break;
case 'r':
flags_.r = strtod(optarg, NULL);
break;
case 'p':
flags_.p = strtod(optarg, NULL);
break;
case 'w':
flags_.w = strtol(optarg, NULL, 0);
break;
case 'h':
flags_.h = strtol(optarg, NULL, 0);
break;
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
if (optind == *argc) {
argv[(*argc)++] = "-";
}
}
static void GetOutputGeometry(long syn, long sxn, long *out_dyn, long *out_dxn,
double *out_ry, double *out_rx) {
double ry, rx;
long dyn, dxn;
if (!flags_.h && !flags_.w) {
if (flags_.r) {
ry = flags_.r * flags_.p;
rx = flags_.r;
} else {
ry = flags_.p;
rx = 1;
}
dyn = round(syn / ry);
dxn = round(sxn / rx);
} else if (flags_.w && !flags_.h) {
if (flags_.r) {
rx = 1. * sxn / flags_.w;
ry = flags_.r * flags_.p;
dxn = flags_.w;
dyn = round(syn / ry);
} else {
rx = 1. * sxn / flags_.w;
ry = flags_.p * rx;
dxn = flags_.w;
dyn = round(syn / ry);
}
} else if (flags_.h && !flags_.w) {
if (flags_.r) {
rx = flags_.r;
ry = flags_.p * syn / flags_.h;
dxn = flags_.w;
dyn = round(syn / ry);
} else {
ry = flags_.p * syn / flags_.h;
rx = ry;
dyn = flags_.h;
dxn = round(syn / rx);
}
} else {
ry = flags_.p;
rx = 1;
dyn = round(flags_.h / ry);
dxn = flags_.w;
}
*out_dyn = dyn;
*out_dxn = dxn;
*out_ry = ry;
*out_rx = rx;
}
static void *Deinterlace(long dcn, long dyn, long dxn,
unsigned char dst[dcn][dyn][dxn], long syw, long sxw,
long scw, const unsigned char src[syw][sxw][scw],
long syn, long sxn, long sy0, long sx0, long sc0) {
long y, x, c;
for (y = 0; y < dyn; ++y) {
for (x = 0; x < dxn; ++x) {
for (c = 0; c < dcn; ++c) {
dst[c][y][x] = src[sy0 + y][sx0 + x][sc0 + c];
}
}
}
return dst;
}
static void CompressRange(long cn, long yn, long xn,
unsigned char img[cn][yn][xn]) {
static const char R[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
double f;
long c, y, x, L, H;
L = R[0], H = R[strlen(R) - 1];
for (c = 0; c < cn; ++c) {
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
f = img[c][y][x];
f /= 255;
f *= H - L;
f += L;
img[c][y][x] = MIN(H, MAX(L, lround(f)));
}
}
}
}
static void PrintCode(FILE *f, long cn, long yn, long xn,
unsigned char img[cn][yn][xn]) {
long c, y, x;
if (flags_.c) CompressRange(cn, yn, xn, img);
for (c = 0; c < cn; ++c) {
fputc('\n', f);
for (y = 0; y < yn; ++y) {
fputc('\n', f);
for (x = 0; x < xn; ++x) {
fputwc(bing(img[c][y][x], 0), f);
}
}
}
fputc('\n', f);
}
static void ProcessImage(const char *path, long scn, long syn, long sxn,
unsigned char img[syn][sxn][scn], FILE *f) {
double ry, rx;
long dyn, dxn, cn;
GetOutputGeometry(syn, sxn, &dyn, &dxn, &ry, &rx);
if (dyn == syn && dxn == sxn) {
/* TODO(jart): Why doesn't Gyarados no-op? */
PrintCode(f, scn, dyn, dxn,
Deinterlace(scn, syn, sxn, gc(memalign(32, scn * syn * sxn)), syn,
sxn, scn, img, syn, sxn, 0, 0, 0));
} else {
PrintCode(
f, scn, dyn, dxn,
EzGyarados(scn, dyn, dxn, gc(memalign(32, scn * dyn * dxn)), scn, syn,
sxn,
Deinterlace(scn, syn, sxn, gc(memalign(32, scn * syn * sxn)),
syn, sxn, scn, img, syn, sxn, 0, 0, 0),
0, scn, dyn, dxn, syn, sxn, ry, rx, 0, 0));
}
}
static void WithImageFile(const char *path, FILE *f,
void fn(const char *path, long cn, long yn, long xn,
unsigned char src[yn][xn][cn], FILE *f)) {
struct stat st;
void *map, *data;
int fd, yn, xn, cn;
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
CHECK_NE(-1, fstat(fd, &st));
CHECK_GT(st.st_size, 0);
CHECK_LE(st.st_size, INT_MAX);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_NOTNULL(
(data = stbi_load_from_memory(map, st.st_size, &xn, &yn, &cn, 0)), "%s",
path);
CHECK_NE(-1, munmap(map, st.st_size));
CHECK_NE(-1, close(fd));
fn(path, cn, yn, xn, data, f);
free(data);
}
int main(int argc, char *argv[]) {
int i;
FILE *f;
showcrashreports();
GetOpts(&argc, argv);
stbi_set_unpremultiply_on_load(true);
CHECK_NOTNULL((f = fopen(flags_.o, "w")));
for (i = optind; i < argc; ++i) {
WithImageFile(argv[i], f, ProcessImage);
}
return fclose(f);
}

View File

@ -164,8 +164,8 @@ void OpMulAxAlEbSigned(struct Machine *m, uint32_t rde) {
int16_t ax;
uint8_t *p;
p = GetModrmRegisterBytePointerRead(m, rde);
__builtin_mul_overflow((int8_t)Read8(m->ax), (int8_t)Read8(p), &ax);
of = (int)ax != (int8_t)ax;
ax = (int8_t)Read8(m->ax) * (int8_t)Read8(p);
of = ax != (int8_t)ax;
m->flags = SetFlag(m->flags, FLAGS_CF, of);
m->flags = SetFlag(m->flags, FLAGS_OF, of);
Write16(m->ax, ax);
@ -176,8 +176,8 @@ void OpMulAxAlEbUnsigned(struct Machine *m, uint32_t rde) {
bool of;
uint8_t *p;
p = GetModrmRegisterBytePointerRead(m, rde);
__builtin_mul_overflow(Read8(m->ax), Read8(p), &ax);
of = (uint8_t)ax != ax;
ax = Read8(m->ax) * Read8(p);
of = ax != (uint8_t)ax;
m->flags = SetFlag(m->flags, FLAGS_CF, of);
m->flags = SetFlag(m->flags, FLAGS_OF, of);
Write16(m->ax, ax);
@ -256,10 +256,12 @@ static void AluImul(struct Machine *m, uint32_t rde, uint8_t *a, uint8_t *b) {
of = __builtin_mul_overflow(x, y, &z);
Write64(RegRexrReg(m, rde), z & 0xffffffff);
} else {
int16_t x, y, z;
int z;
int16_t x, y;
x = Read16(a);
y = Read16(b);
of = __builtin_mul_overflow(x, y, &z);
z = x * y;
of = z != (int16_t)z;
Write16(RegRexrReg(m, rde), z);
}
m->flags = SetFlag(m->flags, FLAGS_CF, of);

View File

@ -169,7 +169,7 @@ void *ReserveAddress(struct Machine *m, int64_t v, size_t n) {
}
void *AccessRam(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t tmp[n], bool copy) {
uint8_t *tmp, bool copy) {
unsigned k;
uint8_t *a, *b;
DCHECK_LE(n, 0x1000);
@ -188,32 +188,31 @@ void *AccessRam(struct Machine *m, int64_t v, size_t n, void *p[2],
return tmp;
}
void *Load(struct Machine *m, int64_t v, size_t n, uint8_t b[n]) {
void *Load(struct Machine *m, int64_t v, size_t n, uint8_t *b) {
void *p[2];
SetReadAddr(m, v, n);
return AccessRam(m, v, n, p, b, true);
}
void *BeginStore(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t b[n]) {
uint8_t *b) {
SetWriteAddr(m, v, n);
return AccessRam(m, v, n, p, b, false);
}
void *BeginStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t b[n]) {
uint8_t *b) {
if (!v) return NULL;
return BeginStore(m, v, n, p, b);
}
void *BeginLoadStore(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t b[n]) {
uint8_t *b) {
SetWriteAddr(m, v, n);
return AccessRam(m, v, n, p, b, true);
}
void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t b[n]) {
void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2], uint8_t *b) {
uint8_t *a;
unsigned k;
DCHECK_LE(n, 0x1000);
@ -228,7 +227,7 @@ void EndStore(struct Machine *m, int64_t v, size_t n, void *p[2],
}
void EndStoreNp(struct Machine *m, int64_t v, size_t n, void *p[2],
uint8_t b[n]) {
uint8_t *b) {
if (v) EndStore(m, v, n, p, b);
}

View File

@ -39,7 +39,7 @@
* @return -1 w/ errno if an error happened
* @see nblack's notcurses project too!
*/
ssize_t PrintPanels(int fd, long pn, struct Panel p[pn], long tyn, long txn) {
ssize_t PrintPanels(int fd, long pn, struct Panel *p, long tyn, long txn) {
wint_t wc;
ssize_t rc;
size_t wrote;

View File

@ -34,173 +34,6 @@
#include "tool/build/lib/ssefloat.h"
#include "tool/build/lib/throw.h"
#define SSE_BUILTINS \
(!IsModeDbg() && __SSE3__ + 0 && \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408)
typedef int int_v _Vector_size(16) forcealign(16);
typedef long long_v _Vector_size(16) forcealign(16);
static float_v Addps(struct Machine *m, float_v x, float_v y) {
return x + y;
}
static double_v Addpd(struct Machine *m, double_v x, double_v y) {
return x + y;
}
static float_v Mulps(struct Machine *m, float_v x, float_v y) {
return x * y;
}
static double_v Mulpd(struct Machine *m, double_v x, double_v y) {
return x * y;
}
static float_v Subps(struct Machine *m, float_v x, float_v y) {
return x - y;
}
static double_v Subpd(struct Machine *m, double_v x, double_v y) {
return x - y;
}
static float_v Divps(struct Machine *m, float_v x, float_v y) {
return x / y;
}
static double_v Divpd(struct Machine *m, double_v x, double_v y) {
return x / y;
}
static float_v Andps(struct Machine *m, float_v x, float_v y) {
return (float_v)((int_v)x & (int_v)y);
}
static double_v Andpd(struct Machine *m, double_v x, double_v y) {
return (double_v)((long_v)x & (long_v)y);
}
static float_v Andnps(struct Machine *m, float_v x, float_v y) {
return (float_v)(~(int_v)x & (int_v)y);
}
static double_v Andnpd(struct Machine *m, double_v x, double_v y) {
return (double_v)(~(long_v)x & (long_v)y);
}
static float_v Orps(struct Machine *m, float_v x, float_v y) {
return (float_v)((int_v)x | (int_v)y);
}
static double_v Orpd(struct Machine *m, double_v x, double_v y) {
return (double_v)((long_v)x | (long_v)y);
}
static float_v Xorps(struct Machine *m, float_v x, float_v y) {
return (float_v)((int_v)x ^ (int_v)y);
}
static double_v Xorpd(struct Machine *m, double_v x, double_v y) {
return (double_v)((long_v)x ^ (long_v)y);
}
static float_v Minps(struct Machine *m, float_v x, float_v y) {
#if SSE_BUILTINS
return __builtin_ia32_minps(x, y);
#else
unsigned i;
for (i = 0; i < 4; ++i) {
x[i] = MIN(x[i], y[i]);
}
return x;
#endif
}
static double_v Minpd(struct Machine *m, double_v x, double_v y) {
#if SSE_BUILTINS
return __builtin_ia32_minpd(x, y);
#else
unsigned i;
for (i = 0; i < 2; ++i) {
x[i] = MIN(x[i], y[i]);
}
return x;
#endif
}
static float_v Maxps(struct Machine *m, float_v x, float_v y) {
#if SSE_BUILTINS
return __builtin_ia32_maxps(x, y);
#else
unsigned i;
for (i = 0; i < 4; ++i) {
x[i] = MAX(x[i], y[i]);
}
return x;
#endif
}
static double_v Maxpd(struct Machine *m, double_v x, double_v y) {
#if SSE_BUILTINS
return __builtin_ia32_maxpd(x, y);
#else
unsigned i;
for (i = 0; i < 2; ++i) {
x[i] = MAX(x[i], y[i]);
}
return x;
#endif
}
static double_v Haddpd(struct Machine *m, double_v x, double_v y) {
#if SSE_BUILTINS
return __builtin_ia32_haddpd(x, y);
#else
return (double_v){x[0] + x[1], y[0] + y[1]};
#endif
}
static float_v Haddps(struct Machine *m, float_v x, float_v y) {
#if SSE_BUILTINS
return __builtin_ia32_haddps(x, y);
#else
return (float_v){x[0] + x[1], x[2] + x[3], y[0] + y[1], y[2] + y[3]};
#endif
}
static double_v Hsubpd(struct Machine *m, double_v x, double_v y) {
#if SSE_BUILTINS
return __builtin_ia32_hsubpd(x, y);
#else
return (double_v){x[0] - x[1], y[0] - y[1]};
#endif
}
static float_v Hsubps(struct Machine *m, float_v x, float_v y) {
#if SSE_BUILTINS
return __builtin_ia32_hsubps(x, y);
#else
return (float_v){x[0] - x[1], x[2] - x[3], y[0] - y[1], y[2] - y[3]};
#endif
}
static double_v Addsubpd(struct Machine *m, double_v x, double_v y) {
#if SSE_BUILTINS
return __builtin_ia32_addsubpd(x, y);
#else
return (double_v){x[0] - y[0], x[1] + y[1]};
#endif
}
static float_v Addsubps(struct Machine *m, float_v x, float_v y) {
#if SSE_BUILTINS
return __builtin_ia32_addsubps(x, y);
#else
return (float_v){x[0] - y[0], x[1] + y[1], x[2] - y[2], x[3] + y[3]};
#endif
}
void OpUnpcklpsd(struct Machine *m, uint32_t rde) {
uint8_t *a, *b;
a = XmmRexrReg(m, rde);
@ -294,28 +127,28 @@ void OpShufpsd(struct Machine *m, uint32_t rde) {
void OpSqrtpsd(struct Machine *m, uint32_t rde) {
long i;
float_v xf;
double_v xd;
float xf[4];
double xd[2];
switch (Rep(rde) | Osz(rde)) {
case 0:
memcpy(&xf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(xf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 4; ++i) xf[i] = sqrtf(xf[i]);
memcpy(XmmRexrReg(m, rde), &xf, 16);
memcpy(XmmRexrReg(m, rde), xf, 16);
break;
case 1:
memcpy(&xd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(xd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 2; ++i) xd[i] = sqrt(xd[i]);
memcpy(XmmRexrReg(m, rde), &xd, 16);
memcpy(XmmRexrReg(m, rde), xd, 16);
break;
case 2:
memcpy(&xd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(xd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
xd[0] = sqrt(xd[0]);
memcpy(XmmRexrReg(m, rde), &xd, 8);
memcpy(XmmRexrReg(m, rde), xd, 8);
break;
case 3:
memcpy(&xf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(xf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
xf[0] = sqrtf(xf[0]);
memcpy(XmmRexrReg(m, rde), &xf, 4);
memcpy(XmmRexrReg(m, rde), xf, 4);
break;
default:
unreachable;
@ -323,91 +156,30 @@ void OpSqrtpsd(struct Machine *m, uint32_t rde) {
}
void OpRsqrtps(struct Machine *m, uint32_t rde) {
float_v x;
float x[4];
unsigned i;
if (Rep(rde) != 3) {
memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 4; ++i) x[i] = 1.f / sqrtf(x[i]);
memcpy(XmmRexrReg(m, rde), &x, 16);
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
x[0] = 1.f / sqrtf(x[0]);
memcpy(XmmRexrReg(m, rde), &x, 4);
memcpy(XmmRexrReg(m, rde), x, 4);
}
}
void OpRcpps(struct Machine *m, uint32_t rde) {
float_v x;
float x[4];
unsigned i;
if (Rep(rde) != 3) {
memcpy(&x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, GetModrmRegisterXmmPointerRead16(m, rde), 16);
for (i = 0; i < 4; ++i) x[i] = 1.f / x[i];
memcpy(XmmRexrReg(m, rde), &x, 16);
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
memcpy(&x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(x, GetModrmRegisterXmmPointerRead4(m, rde), 4);
x[0] = 1.f / x[0];
memcpy(XmmRexrReg(m, rde), &x, 4);
}
}
static void VpsdWpsd(struct Machine *m, uint32_t rde,
float_v opf(struct Machine *, float_v, float_v),
double_v opd(struct Machine *, double_v, double_v),
bool isfloat, bool isdouble) {
float_v xf, yf;
double_v xd, yd;
if (isfloat) {
memcpy(&xf, XmmRexrReg(m, rde), 16);
memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
xf = opf(m, xf, yf);
memcpy(XmmRexrReg(m, rde), &xf, 16);
} else if (isdouble) {
memcpy(&xd, XmmRexrReg(m, rde), 16);
memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
xd = opd(m, xd, yd);
memcpy(XmmRexrReg(m, rde), &xd, 16);
} else {
OpUd(m, rde);
}
}
static void VpsdWpsd66(struct Machine *m, uint32_t rde,
float_v opf(struct Machine *, float_v, float_v),
double_v opd(struct Machine *, double_v, double_v)) {
VpsdWpsd(m, rde, opf, opd, !Osz(rde), Osz(rde));
}
static void VpsdWpsd66f2(struct Machine *m, uint32_t rde,
float_v opf(struct Machine *, float_v, float_v),
double_v opd(struct Machine *, double_v, double_v)) {
VpsdWpsd(m, rde, opf, opd, Rep(rde) == 2, Osz(rde));
}
static void VspsdWspsd(struct Machine *m, uint32_t rde,
float_v opf(struct Machine *, float_v, float_v),
double_v opd(struct Machine *, double_v, double_v)) {
float_v xf, yf;
double_v xd, yd;
if (Rep(rde) == 2) {
memcpy(&yd, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&xd, XmmRexrReg(m, rde), 8);
xd = opd(m, xd, yd);
memcpy(XmmRexrReg(m, rde), &xd, 8);
} else if (Rep(rde) == 3) {
memcpy(&yf, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&xf, XmmRexrReg(m, rde), 4);
xf = opf(m, xf, yf);
memcpy(XmmRexrReg(m, rde), &xf, 4);
} else if (Osz(rde)) {
memcpy(&yd, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(&xd, XmmRexrReg(m, rde), 16);
xd = opd(m, xd, yd);
memcpy(XmmRexrReg(m, rde), &xd, 16);
} else {
memcpy(&yf, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(&xf, XmmRexrReg(m, rde), 16);
xf = opf(m, xf, yf);
memcpy(XmmRexrReg(m, rde), &xf, 16);
memcpy(XmmRexrReg(m, rde), x, 4);
}
}
@ -448,118 +220,376 @@ void OpComissVsWs(struct Machine *m, uint32_t rde) {
}
}
static float_v Cmpps(struct Machine *m, float_v x, float_v y) {
long i;
switch (m->xedd->op.uimm0) {
static int Cmps(int imm, float x, float y) {
switch (imm) {
case 0:
return x == y;
return x == y ? -1 : 0;
case 1:
return x < y;
return x < y ? -1 : 0;
case 2:
return x <= y;
return x <= y ? -1 : 0;
case 3:
for (i = 0; i < 4; ++i) {
x[i] = isnan(x[i]) || isnan(y[i]);
}
return x;
return isnan(x) || isnan(y) ? -1 : 0;
case 4:
return x != y;
return x != y ? -1 : 0;
case 5:
return x >= y;
return x >= y ? -1 : 0;
case 6:
return x > y;
return x > y ? -1 : 0;
case 7:
for (i = 0; i < 4; ++i) {
x[i] = !(isnan(x[i]) || isnan(y[i]));
}
return x;
return !(isnan(x) || isnan(y)) ? -1 : 0;
default:
OpUd(m, 0);
return 0;
}
}
static double_v Cmppd(struct Machine *m, double_v x, double_v y) {
static int32_t Cmpd(int imm, double x, double y) {
long i;
switch (m->xedd->op.uimm0) {
switch (imm) {
case 0:
return x == y;
return x == y ? -1 : 0;
case 1:
return x < y;
return x < y ? -1 : 0;
case 2:
return x <= y;
return x <= y ? -1 : 0;
case 3:
for (i = 0; i < 2; ++i) {
x[i] = isnan(x[i]) || isnan(y[i]);
}
return x;
return isnan(x) || isnan(y) ? -1 : 0;
case 4:
return x != y;
return x != y ? -1 : 0;
case 5:
return x >= y;
return x >= y ? -1 : 0;
case 6:
return x > y;
return x > y ? -1 : 0;
case 7:
for (i = 0; i < 2; ++i) {
x[i] = !(isnan(x[i]) || isnan(y[i]));
}
return x;
return !(isnan(x) || isnan(y)) ? -1 : 0;
default:
OpUd(m, 0);
return 0;
}
}
void OpAddpsd(struct Machine *m, uint32_t rde) {
VspsdWspsd(m, rde, Addps, Addpd);
if (Rep(rde) == 2) {
double x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&x, XmmRexrReg(m, rde), 8);
x += y;
memcpy(XmmRexrReg(m, rde), &x, 8);
} else if (Rep(rde) == 3) {
float x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&x, XmmRexrReg(m, rde), 4);
x += y;
memcpy(XmmRexrReg(m, rde), &x, 4);
} else if (Osz(rde)) {
double x[2], y[2];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] += y[0];
x[1] += y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
float x[4], y[4];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] += y[0];
x[1] += y[1];
x[2] += y[2];
x[3] += y[3];
memcpy(XmmRexrReg(m, rde), x, 16);
}
}
void OpMulpsd(struct Machine *m, uint32_t rde) {
VspsdWspsd(m, rde, Mulps, Mulpd);
if (Rep(rde) == 2) {
double x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&x, XmmRexrReg(m, rde), 8);
x *= y;
memcpy(XmmRexrReg(m, rde), &x, 8);
} else if (Rep(rde) == 3) {
float x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&x, XmmRexrReg(m, rde), 4);
x *= y;
memcpy(XmmRexrReg(m, rde), &x, 4);
} else if (Osz(rde)) {
double x[2], y[2];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] *= y[0];
x[1] *= y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
float x[4], y[4];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] *= y[0];
x[1] *= y[1];
x[2] *= y[2];
x[3] *= y[3];
memcpy(XmmRexrReg(m, rde), x, 16);
}
}
void OpSubpsd(struct Machine *m, uint32_t rde) {
VspsdWspsd(m, rde, Subps, Subpd);
if (Rep(rde) == 2) {
double x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&x, XmmRexrReg(m, rde), 8);
x -= y;
memcpy(XmmRexrReg(m, rde), &x, 8);
} else if (Rep(rde) == 3) {
float x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&x, XmmRexrReg(m, rde), 4);
x -= y;
memcpy(XmmRexrReg(m, rde), &x, 4);
} else if (Osz(rde)) {
double x[2], y[2];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] -= y[0];
x[1] -= y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
float x[4], y[4];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] -= y[0];
x[1] -= y[1];
x[2] -= y[2];
x[3] -= y[3];
memcpy(XmmRexrReg(m, rde), x, 16);
}
}
void OpDivpsd(struct Machine *m, uint32_t rde) {
VspsdWspsd(m, rde, Divps, Divpd);
if (Rep(rde) == 2) {
double x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&x, XmmRexrReg(m, rde), 8);
x /= y;
memcpy(XmmRexrReg(m, rde), &x, 8);
} else if (Rep(rde) == 3) {
float x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&x, XmmRexrReg(m, rde), 4);
x /= y;
memcpy(XmmRexrReg(m, rde), &x, 4);
} else if (Osz(rde)) {
double x[2], y[2];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] /= y[0];
x[1] /= y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
float x[4], y[4];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] /= y[0];
x[1] /= y[1];
x[2] /= y[2];
x[3] /= y[3];
memcpy(XmmRexrReg(m, rde), x, 16);
}
}
void OpMinpsd(struct Machine *m, uint32_t rde) {
VspsdWspsd(m, rde, Minps, Minpd);
if (Rep(rde) == 2) {
double x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&x, XmmRexrReg(m, rde), 8);
x = MIN(x, y);
memcpy(XmmRexrReg(m, rde), &x, 8);
} else if (Rep(rde) == 3) {
float x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&x, XmmRexrReg(m, rde), 4);
x = MIN(x, y);
memcpy(XmmRexrReg(m, rde), &x, 4);
} else if (Osz(rde)) {
double x[2], y[2];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] = MIN(x[0], y[0]);
x[1] = MIN(x[1], y[1]);
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
float x[4], y[4];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] = MIN(x[0], y[0]);
x[1] = MIN(x[1], y[1]);
x[2] = MIN(x[2], y[2]);
x[3] = MIN(x[3], y[3]);
memcpy(XmmRexrReg(m, rde), x, 16);
}
}
void OpMaxpsd(struct Machine *m, uint32_t rde) {
VspsdWspsd(m, rde, Maxps, Maxpd);
if (Rep(rde) == 2) {
double x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&x, XmmRexrReg(m, rde), 8);
x = MAX(x, y);
memcpy(XmmRexrReg(m, rde), &x, 8);
} else if (Rep(rde) == 3) {
float x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&x, XmmRexrReg(m, rde), 4);
x = MAX(x, y);
memcpy(XmmRexrReg(m, rde), &x, 4);
} else if (Osz(rde)) {
double x[2], y[2];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] = MAX(x[0], y[0]);
x[1] = MAX(x[1], y[1]);
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
float x[4], y[4];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] = MAX(x[0], y[0]);
x[1] = MAX(x[1], y[1]);
x[2] = MAX(x[2], y[2]);
x[3] = MAX(x[3], y[3]);
memcpy(XmmRexrReg(m, rde), x, 16);
}
}
void OpCmppsd(struct Machine *m, uint32_t rde) {
VspsdWspsd(m, rde, Cmpps, Cmppd);
int imm = m->xedd->op.uimm0;
if (Rep(rde) == 2) {
double x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead8(m, rde), 8);
memcpy(&x, XmmRexrReg(m, rde), 8);
x = Cmpd(imm, x, y);
memcpy(XmmRexrReg(m, rde), &x, 8);
} else if (Rep(rde) == 3) {
float x, y;
memcpy(&y, GetModrmRegisterXmmPointerRead4(m, rde), 4);
memcpy(&x, XmmRexrReg(m, rde), 4);
x = Cmps(imm, x, y);
memcpy(XmmRexrReg(m, rde), &x, 4);
} else if (Osz(rde)) {
double x[2], y[2];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] = Cmpd(imm, x[0], y[0]);
x[1] = Cmpd(imm, x[1], y[1]);
memcpy(XmmRexrReg(m, rde), x, 16);
} else {
float x[4], y[4];
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
memcpy(x, XmmRexrReg(m, rde), 16);
x[0] = Cmps(imm, x[0], y[0]);
x[1] = Cmps(imm, x[1], y[1]);
x[2] = Cmps(imm, x[2], y[2]);
x[3] = Cmps(imm, x[3], y[3]);
memcpy(XmmRexrReg(m, rde), x, 16);
}
}
void OpAndpsd(struct Machine *m, uint32_t rde) {
VpsdWpsd66(m, rde, Andps, Andpd);
uint64_t x[2], y[2];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
x[0] &= y[0];
x[1] &= y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
}
void OpAndnpsd(struct Machine *m, uint32_t rde) {
VpsdWpsd66(m, rde, Andnps, Andnpd);
uint64_t x[2], y[2];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
x[0] = ~x[0] & y[0];
x[1] = ~x[1] & y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
}
void OpOrpsd(struct Machine *m, uint32_t rde) {
VpsdWpsd66(m, rde, Orps, Orpd);
uint64_t x[2], y[2];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
x[0] |= y[0];
x[1] |= y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
}
void OpXorpsd(struct Machine *m, uint32_t rde) {
VpsdWpsd66(m, rde, Xorps, Xorpd);
uint64_t x[2], y[2];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
x[0] ^= y[0];
x[1] ^= y[1];
memcpy(XmmRexrReg(m, rde), x, 16);
}
void OpHaddpsd(struct Machine *m, uint32_t rde) {
VpsdWpsd66f2(m, rde, Haddps, Haddpd);
if (Rep(rde) == 2) {
float x[4], y[4], z[4];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
z[0] = x[0] + x[1];
z[1] = x[2] + x[3];
z[2] = y[0] + y[1];
z[3] = y[2] + y[3];
memcpy(XmmRexrReg(m, rde), x, 16);
} else if (Osz(rde)) {
double x[2], y[2], z[2];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
z[0] = x[0] + x[1];
z[1] = y[0] + y[1];
memcpy(XmmRexrReg(m, rde), z, 16);
} else {
OpUd(m, rde);
}
}
void OpHsubpsd(struct Machine *m, uint32_t rde) {
VpsdWpsd66f2(m, rde, Hsubps, Hsubpd);
if (Rep(rde) == 2) {
float x[4], y[4], z[4];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
z[0] = x[0] - x[1];
z[1] = x[2] - x[3];
z[2] = y[0] - y[1];
z[3] = y[2] - y[3];
memcpy(XmmRexrReg(m, rde), x, 16);
} else if (Osz(rde)) {
double x[2], y[2], z[2];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
z[0] = x[0] - x[1];
z[1] = y[0] - y[1];
memcpy(XmmRexrReg(m, rde), z, 16);
} else {
OpUd(m, rde);
}
}
void OpAddsubpsd(struct Machine *m, uint32_t rde) {
VpsdWpsd66f2(m, rde, Addsubps, Addsubpd);
if (Rep(rde) == 2) {
float x[4], y[4], z[4];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
z[0] = x[0] - y[0];
z[1] = x[1] + y[1];
z[2] = x[2] - y[2];
z[3] = x[3] + y[3];
memcpy(XmmRexrReg(m, rde), x, 16);
} else if (Osz(rde)) {
double x[2], y[2], z[2];
memcpy(x, XmmRexrReg(m, rde), 16);
memcpy(y, GetModrmRegisterXmmPointerRead16(m, rde), 16);
z[0] = x[0] - y[0];
z[1] = x[1] + y[1];
memcpy(XmmRexrReg(m, rde), z, 16);
} else {
OpUd(m, rde);
}
}

View File

@ -442,7 +442,7 @@ static int AppendIovsReal(struct Machine *m, struct Iovs *ib, int64_t addr,
static int AppendIovsGuest(struct Machine *m, struct Iovs *iv, int64_t iovaddr,
long iovlen) {
int rc;
long i, iovsize;
size_t i, iovsize;
struct iovec *guestiovs;
if (!__builtin_mul_overflow(iovlen, sizeof(struct iovec), &iovsize) &&
(0 <= iovsize && iovsize <= 0x7ffff000)) {

View File

@ -69,6 +69,9 @@
"__builtin_va_end"
"__builtin_abs"
"__builtin_strcpy"
"__builtin_strstr"
"__builtin_strpbrk"
"__builtin_strchr"
"__builtin_stpcpy"
"__builtin_setjmp"
"__builtin_longjmp"

View File

@ -1,6 +1,6 @@
(defconst cosmo-c-keywords-regex
(let (
;; (kar
;; '("case"
;; "do"
@ -237,6 +237,7 @@
"__aligned__"
"__alloc_align__"
"__alloc_size__"
"__warn_if_not_aligned__"
"__artificial__"
"__assume_aligned__"
"__cold__"