Enhance chibicc
parent
8da931a7f6
commit
9df2cef4c4
|
@ -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
|
||||
|
|
|
@ -22,6 +22,11 @@ set -e
|
|||
SPECIAL_TEXT=$(
|
||||
$1 --version |
|
||||
sed -n '
|
||||
/chibicc/ {
|
||||
i\
|
||||
chibicc
|
||||
q
|
||||
}
|
||||
/Free Software/ {
|
||||
i\
|
||||
gcc
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 { \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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]) {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -176,6 +176,4 @@ int main() {
|
|||
|
||||
ASSERT(1, g40 == 1.5);
|
||||
ASSERT(1, g41 == 11);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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");
|
||||
}));
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
main(void) {
|
||||
void *p;
|
||||
p = "hello";
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(""));
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 RGB→Y\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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -69,6 +69,9 @@
|
|||
"__builtin_va_end"
|
||||
"__builtin_abs"
|
||||
"__builtin_strcpy"
|
||||
"__builtin_strstr"
|
||||
"__builtin_strpbrk"
|
||||
"__builtin_strchr"
|
||||
"__builtin_stpcpy"
|
||||
"__builtin_setjmp"
|
||||
"__builtin_longjmp"
|
||||
|
|
|
@ -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__"
|
||||
|
|
Loading…
Reference in New Issue