mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-24 06:49:02 +00:00
Add atomics to chibicc
This change also fixes #434 and makes the chibicc assembler better.
This commit is contained in:
parent
5ddf43332e
commit
a988896048
21 changed files with 650 additions and 445 deletions
|
@ -1,7 +0,0 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_INTRIN_REFCOUNT_H_
|
|
||||||
#define COSMOPOLITAN_LIBC_INTRIN_REFCOUNT_H_
|
|
||||||
|
|
||||||
#define _incref(x) __atomic_fetch_add(x, 1, __ATOMIC_RELAXED)
|
|
||||||
#define _decref(x) __atomic_sub_fetch(x, 1, __ATOMIC_SEQ_CST)
|
|
||||||
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_REFCOUNT_H_ */
|
|
43
libc/intrin/wait0.c
Normal file
43
libc/intrin/wait0.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*-*- 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 2022 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/bits/atomic.h"
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/wait0.internal.h"
|
||||||
|
#include "libc/linux/futex.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks until memory location becomes zero.
|
||||||
|
*
|
||||||
|
* This is intended to be used on the child thread id, which is updated
|
||||||
|
* by the clone() system call when a thread terminates. The purpose of
|
||||||
|
* this operation is to know when it's safe to munmap() a thread stack.
|
||||||
|
*/
|
||||||
|
void _wait0(int *ptid) {
|
||||||
|
int x;
|
||||||
|
for (;;) {
|
||||||
|
if (!(x = atomic_load_explicit(ptid, memory_order_relaxed))) {
|
||||||
|
break;
|
||||||
|
} else if (IsLinux()) {
|
||||||
|
LinuxFutexWait(ptid, x, 0);
|
||||||
|
} else {
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,10 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_
|
#ifndef COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_
|
||||||
#define COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_
|
#define COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_
|
||||||
#include "libc/bits/atomic.h"
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
#include "libc/calls/calls.h"
|
COSMOPOLITAN_C_START_
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/linux/futex.h"
|
|
||||||
|
|
||||||
#define _wait0(ptid) \
|
void _wait0(int *) hidden;
|
||||||
do { \
|
|
||||||
int x; \
|
|
||||||
if (!(x = atomic_load_explicit(ptid, memory_order_relaxed))) { \
|
|
||||||
break; \
|
|
||||||
} else if (IsLinux()) { \
|
|
||||||
LinuxFutexWait(ptid, x, 0); \
|
|
||||||
} else { \
|
|
||||||
sched_yield(); \
|
|
||||||
} \
|
|
||||||
} while (1)
|
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_ */
|
#endif /* COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_ */
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_LINUX_FUTEX_H_
|
#ifndef COSMOPOLITAN_LIBC_LINUX_FUTEX_H_
|
||||||
#define COSMOPOLITAN_LIBC_LINUX_FUTEX_H_
|
#define COSMOPOLITAN_LIBC_LINUX_FUTEX_H_
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
|
||||||
forceinline int LinuxFutexWait(void *addr, int expect,
|
forceinline int LinuxFutexWait(void *addr, int expect,
|
||||||
struct timespec *timeout) {
|
struct timespec *timeout) {
|
||||||
int ax;
|
int ax;
|
||||||
register void *r10 asm("r10") = timeout;
|
asm volatile("mov\t%5,%%r10\n\t"
|
||||||
asm volatile("syscall"
|
"syscall"
|
||||||
: "=a"(ax)
|
: "=a"(ax)
|
||||||
: "0"(202), "D"(addr), "S"(0), "d"(expect), "r"(r10)
|
: "0"(202), "D"(addr), "S"(0), "d"(expect), "g"(timeout)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r10", "r11", "memory");
|
||||||
return ax;
|
return ax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
third_party/chibicc/README.cosmo
vendored
2
third_party/chibicc/README.cosmo
vendored
|
@ -13,11 +13,11 @@ local enhancements
|
||||||
- support _Static_assert
|
- support _Static_assert
|
||||||
- support __vector_size__
|
- support __vector_size__
|
||||||
- support __builtin_add_overflow, etc.
|
- support __builtin_add_overflow, etc.
|
||||||
|
- support GCC C11 __atomic_* primitives
|
||||||
- support __builtin_memcpy, strlen, strpbrk, etc.
|
- support __builtin_memcpy, strlen, strpbrk, etc.
|
||||||
- support __builtin_constant_p, __builtin_likely, etc.
|
- support __builtin_constant_p, __builtin_likely, etc.
|
||||||
- support __builtin_isunordered, __builtin_islessgreater, etc.
|
- support __builtin_isunordered, __builtin_islessgreater, etc.
|
||||||
- support __builtin_ctz, __builtin_bswap, __builtin_popcount, etc.
|
- support __builtin_ctz, __builtin_bswap, __builtin_popcount, etc.
|
||||||
- support __atomic_load, __sync_lock_test_and_set, __sync_lock_release, etc.
|
|
||||||
- support __force_align_arg_pointer__, __no_caller_saved_registers__, etc.
|
- support __force_align_arg_pointer__, __no_caller_saved_registers__, etc.
|
||||||
- support __constructor__, __section__, __cold__, -ffunction-sections, etc.
|
- support __constructor__, __section__, __cold__, -ffunction-sections, etc.
|
||||||
- support building -x assembler-with-cpp a.k.a. .S files
|
- support building -x assembler-with-cpp a.k.a. .S files
|
||||||
|
|
13
third_party/chibicc/as.c
vendored
13
third_party/chibicc/as.c
vendored
|
@ -2356,6 +2356,14 @@ static void OnTest(struct As *a, struct Slice s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void OnCmpxchg(struct As *a, struct Slice s) {
|
||||||
|
int reg, modrm, disp;
|
||||||
|
reg = GetRegisterReg(a);
|
||||||
|
ConsumeComma(a);
|
||||||
|
modrm = ParseModrm(a, &disp);
|
||||||
|
EmitRexOpModrm(a, 0x0FB0, reg, modrm, disp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void OnImul(struct As *a, struct Slice s) {
|
static void OnImul(struct As *a, struct Slice s) {
|
||||||
int reg, modrm, imm, disp;
|
int reg, modrm, imm, disp;
|
||||||
if (IsPunct(a, a->i, '$')) {
|
if (IsPunct(a, a->i, '$')) {
|
||||||
|
@ -3074,6 +3082,7 @@ static void OnSeto(struct As *a, struct Slice s) { OpSetcc(a, 0); }
|
||||||
static void OnSetp(struct As *a, struct Slice s) { OpSetcc(a, 10); }
|
static void OnSetp(struct As *a, struct Slice s) { OpSetcc(a, 10); }
|
||||||
static void OnSets(struct As *a, struct Slice s) { OpSetcc(a, 8); }
|
static void OnSets(struct As *a, struct Slice s) { OpSetcc(a, 8); }
|
||||||
static void OnSetz(struct As *a, struct Slice s) { OpSetcc(a, 4); }
|
static void OnSetz(struct As *a, struct Slice s) { OpSetcc(a, 4); }
|
||||||
|
static void OnSfence(struct As *a, struct Slice s) { EmitVarword(a, 0x0faef8); }
|
||||||
static void OnShl(struct As *a, struct Slice s) { OpBsu(a, s, 4); }
|
static void OnShl(struct As *a, struct Slice s) { OpBsu(a, s, 4); }
|
||||||
static void OnShr(struct As *a, struct Slice s) { OpBsu(a, s, 5); }
|
static void OnShr(struct As *a, struct Slice s) { OpBsu(a, s, 5); }
|
||||||
static void OnShufpd(struct As *a, struct Slice s) { OpSseIb(a, 0x660FC6); }
|
static void OnShufpd(struct As *a, struct Slice s) { OpSseIb(a, 0x660FC6); }
|
||||||
|
@ -3094,6 +3103,7 @@ static void OnSubpd(struct As *a, struct Slice s) { OpSse(a, 0x660F5C); }
|
||||||
static void OnSubps(struct As *a, struct Slice s) { OpSse(a, 0x0F5C); }
|
static void OnSubps(struct As *a, struct Slice s) { OpSse(a, 0x0F5C); }
|
||||||
static void OnSubsd(struct As *a, struct Slice s) { OpSse(a, 0xF20F5C); }
|
static void OnSubsd(struct As *a, struct Slice s) { OpSse(a, 0xF20F5C); }
|
||||||
static void OnSubss(struct As *a, struct Slice s) { OpSse(a, 0xF30F5C); }
|
static void OnSubss(struct As *a, struct Slice s) { OpSse(a, 0xF30F5C); }
|
||||||
|
static void OnSyscall(struct As *a, struct Slice s) { EmitVarword(a, 0x0F05); }
|
||||||
static void OnUcomisd(struct As *a, struct Slice s) { OpSse(a, 0x660F2E); }
|
static void OnUcomisd(struct As *a, struct Slice s) { OpSse(a, 0x660F2E); }
|
||||||
static void OnUcomiss(struct As *a, struct Slice s) { OpSse(a, 0x0F2E); }
|
static void OnUcomiss(struct As *a, struct Slice s) { OpSse(a, 0x0F2E); }
|
||||||
static void OnUd2(struct As *a, struct Slice s) { EmitVarword(a, 0x0F0B); }
|
static void OnUd2(struct As *a, struct Slice s) { EmitVarword(a, 0x0F0B); }
|
||||||
|
@ -3229,6 +3239,7 @@ static const struct Directive8 {
|
||||||
{"cmpsd", OnCmpsd}, //
|
{"cmpsd", OnCmpsd}, //
|
||||||
{"cmpss", OnCmpss}, //
|
{"cmpss", OnCmpss}, //
|
||||||
{"cmpw", OnCmp}, //
|
{"cmpw", OnCmp}, //
|
||||||
|
{"cmpxchg", OnCmpxchg}, //
|
||||||
{"comisd", OnComisd}, //
|
{"comisd", OnComisd}, //
|
||||||
{"comiss", OnComiss}, //
|
{"comiss", OnComiss}, //
|
||||||
{"cqo", OnCqto}, //
|
{"cqo", OnCqto}, //
|
||||||
|
@ -3604,6 +3615,7 @@ static const struct Directive8 {
|
||||||
{"setpo", OnSetnp}, //
|
{"setpo", OnSetnp}, //
|
||||||
{"sets", OnSets}, //
|
{"sets", OnSets}, //
|
||||||
{"setz", OnSetz}, //
|
{"setz", OnSetz}, //
|
||||||
|
{"sfence", OnSfence}, //
|
||||||
{"shl", OnShl}, //
|
{"shl", OnShl}, //
|
||||||
{"shlb", OnShl}, //
|
{"shlb", OnShl}, //
|
||||||
{"shld", OnShld}, //
|
{"shld", OnShld}, //
|
||||||
|
@ -3638,6 +3650,7 @@ static const struct Directive8 {
|
||||||
{"subsd", OnSubsd}, //
|
{"subsd", OnSubsd}, //
|
||||||
{"subss", OnSubss}, //
|
{"subss", OnSubss}, //
|
||||||
{"subw", OnSub}, //
|
{"subw", OnSub}, //
|
||||||
|
{"syscall", OnSyscall}, //
|
||||||
{"test", OnTest}, //
|
{"test", OnTest}, //
|
||||||
{"testb", OnTest}, //
|
{"testb", OnTest}, //
|
||||||
{"testl", OnTest}, //
|
{"testl", OnTest}, //
|
||||||
|
|
22
third_party/chibicc/asm.c
vendored
22
third_party/chibicc/asm.c
vendored
|
@ -232,7 +232,9 @@ static int PickAsmOperandType(Asm *a, AsmOperand *op) {
|
||||||
op->type &= ~kAsmImm;
|
op->type &= ~kAsmImm;
|
||||||
if (!IsLvalue(op)) error_tok(op->tok, "lvalue required");
|
if (!IsLvalue(op)) error_tok(op->tok, "lvalue required");
|
||||||
}
|
}
|
||||||
if ((op->type & kAsmImm) && is_const_expr(op->node)) {
|
if ((op->type & kAsmImm) && (is_const_expr(op->node) ||
|
||||||
|
// TODO(jart): confirm this is what we want
|
||||||
|
op->node->ty->kind == TY_FUNC)) {
|
||||||
op->val = eval2(op->node, &op->label);
|
op->val = eval2(op->node, &op->label);
|
||||||
return kAsmImm;
|
return kAsmImm;
|
||||||
}
|
}
|
||||||
|
@ -277,13 +279,13 @@ static Token *ParseAsmOperands(Asm *a, Token *tok) {
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CouldNotAllocateRegister(AsmOperand *op) {
|
static void CouldNotAllocateRegister(AsmOperand *op, const char *kind) {
|
||||||
error_tok(op->tok, "could not allocate register");
|
error_tok(op->tok, "could not allocate %s register", kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PickAsmRegisters(Asm *a) {
|
static void PickAsmRegisters(Asm *a) {
|
||||||
int i, j, m, regset, xmmset, x87sts;
|
int i, j, m, pick, regset, xmmset, x87sts;
|
||||||
regset = 0b0000111111000111; // exclude bx,sp,bp,r12-r15
|
regset = 0b1111111111000111; // exclude bx,sp,bp
|
||||||
xmmset = 0b1111111111111111;
|
xmmset = 0b1111111111111111;
|
||||||
x87sts = 0b0000000011111111;
|
x87sts = 0b0000000011111111;
|
||||||
regset ^= regset & a->regclob; // don't allocate from clobber list
|
regset ^= regset & a->regclob; // don't allocate from clobber list
|
||||||
|
@ -296,20 +298,22 @@ static void PickAsmRegisters(Asm *a) {
|
||||||
case kAsmReg:
|
case kAsmReg:
|
||||||
if (!(m = a->ops[i].regmask)) break;
|
if (!(m = a->ops[i].regmask)) break;
|
||||||
if (popcnt(m) != j) break;
|
if (popcnt(m) != j) break;
|
||||||
if (!(m &= regset)) CouldNotAllocateRegister(&a->ops[i]);
|
if (!(m &= regset)) CouldNotAllocateRegister(&a->ops[i], "rm");
|
||||||
regset &= ~(1 << (a->ops[i].reg = bsf(m)));
|
pick = 1 << (a->ops[i].reg = bsf(m));
|
||||||
|
if (pick & PRECIOUS) a->regclob |= pick;
|
||||||
|
regset &= ~pick;
|
||||||
a->ops[i].regmask = 0;
|
a->ops[i].regmask = 0;
|
||||||
break;
|
break;
|
||||||
case kAsmXmm:
|
case kAsmXmm:
|
||||||
if (!(m = a->ops[i].regmask)) break;
|
if (!(m = a->ops[i].regmask)) break;
|
||||||
if (!(m &= xmmset)) CouldNotAllocateRegister(&a->ops[i]);
|
if (!(m &= xmmset)) CouldNotAllocateRegister(&a->ops[i], "xmm");
|
||||||
xmmset &= ~(1 << (a->ops[i].reg = bsf(m)));
|
xmmset &= ~(1 << (a->ops[i].reg = bsf(m)));
|
||||||
a->ops[i].regmask = 0;
|
a->ops[i].regmask = 0;
|
||||||
break;
|
break;
|
||||||
case kAsmFpu:
|
case kAsmFpu:
|
||||||
if (!(m = a->ops[i].x87mask)) break;
|
if (!(m = a->ops[i].x87mask)) break;
|
||||||
if (popcnt(m) != j) break;
|
if (popcnt(m) != j) break;
|
||||||
if (!(m &= x87sts)) CouldNotAllocateRegister(&a->ops[i]);
|
if (!(m &= x87sts)) CouldNotAllocateRegister(&a->ops[i], "fpu");
|
||||||
x87sts &= ~(1 << (a->ops[i].reg = bsf(m)));
|
x87sts &= ~(1 << (a->ops[i].reg = bsf(m)));
|
||||||
a->ops[i].x87mask = 0;
|
a->ops[i].x87mask = 0;
|
||||||
break;
|
break;
|
||||||
|
|
12
third_party/chibicc/chibicc.h
vendored
12
third_party/chibicc/chibicc.h
vendored
|
@ -344,14 +344,20 @@ typedef enum {
|
||||||
ND_MEMZERO, // Zero-clear a stack variable
|
ND_MEMZERO, // Zero-clear a stack variable
|
||||||
ND_ASM, // "asm"
|
ND_ASM, // "asm"
|
||||||
ND_CAS, // Atomic compare-and-swap
|
ND_CAS, // Atomic compare-and-swap
|
||||||
ND_EXCH, // Atomic exchange
|
ND_EXCH_N, // Atomic exchange with value
|
||||||
ND_LOAD, // Atomic load
|
ND_LOAD, // Atomic load to pointer
|
||||||
ND_STORE, // Atomic store
|
ND_LOAD_N, // Atomic load to result
|
||||||
|
ND_STORE, // Atomic store to pointer
|
||||||
|
ND_STORE_N, // Atomic store to result
|
||||||
ND_TESTANDSET, // Sync lock test and set
|
ND_TESTANDSET, // Sync lock test and set
|
||||||
ND_TESTANDSETA, // Atomic lock test and set
|
ND_TESTANDSETA, // Atomic lock test and set
|
||||||
ND_CLEAR, // Atomic clear
|
ND_CLEAR, // Atomic clear
|
||||||
ND_RELEASE, // Atomic lock release
|
ND_RELEASE, // Atomic lock release
|
||||||
ND_FETCHADD, // Atomic fetch and add
|
ND_FETCHADD, // Atomic fetch and add
|
||||||
|
ND_FETCHSUB, // Atomic fetch and sub
|
||||||
|
ND_FETCHXOR, // Atomic fetch and xor
|
||||||
|
ND_FETCHAND, // Atomic fetch and and
|
||||||
|
ND_FETCHOR, // Atomic fetch and or
|
||||||
ND_SUBFETCH, // Atomic sub and fetch
|
ND_SUBFETCH, // Atomic sub and fetch
|
||||||
ND_FPCLASSIFY, // floating point classify
|
ND_FPCLASSIFY, // floating point classify
|
||||||
ND_MOVNTDQ, // Intel MOVNTDQ
|
ND_MOVNTDQ, // Intel MOVNTDQ
|
||||||
|
|
3
third_party/chibicc/chibicc.mk
vendored
3
third_party/chibicc/chibicc.mk
vendored
|
@ -15,7 +15,8 @@ CHIBICC2 = o/$(MODE)/third_party/chibicc/chibicc2.com
|
||||||
CHIBICC_FLAGS = \
|
CHIBICC_FLAGS = \
|
||||||
-fno-common \
|
-fno-common \
|
||||||
-include libc/integral/normalize.inc \
|
-include libc/integral/normalize.inc \
|
||||||
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL)
|
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \
|
||||||
|
-DMODE='"$(MODE)"'
|
||||||
|
|
||||||
PKGS += THIRD_PARTY_CHIBICC
|
PKGS += THIRD_PARTY_CHIBICC
|
||||||
THIRD_PARTY_CHIBICC_ARTIFACTS += THIRD_PARTY_CHIBICC_A
|
THIRD_PARTY_CHIBICC_ARTIFACTS += THIRD_PARTY_CHIBICC_A
|
||||||
|
|
98
third_party/chibicc/codegen.c
vendored
98
third_party/chibicc/codegen.c
vendored
|
@ -262,6 +262,20 @@ static char *reg_ax(int sz) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *reg_r8(int sz) {
|
||||||
|
switch (sz) {
|
||||||
|
case 1:
|
||||||
|
return "%r8b";
|
||||||
|
case 2:
|
||||||
|
return "%r8w";
|
||||||
|
case 4:
|
||||||
|
return "%r8d";
|
||||||
|
case 8:
|
||||||
|
return "%r8";
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
static char *reg_di(int sz) {
|
static char *reg_di(int sz) {
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -276,6 +290,20 @@ static char *reg_di(int sz) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *reg_si(int sz) {
|
||||||
|
switch (sz) {
|
||||||
|
case 1:
|
||||||
|
return "%sil";
|
||||||
|
case 2:
|
||||||
|
return "%si";
|
||||||
|
case 4:
|
||||||
|
return "%esi";
|
||||||
|
case 8:
|
||||||
|
return "%rsi";
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
static const char *gotpcrel(void) {
|
static const char *gotpcrel(void) {
|
||||||
if (opt_pic) {
|
if (opt_pic) {
|
||||||
return "@gotpcrel(%rip)";
|
return "@gotpcrel(%rip)";
|
||||||
|
@ -1136,6 +1164,21 @@ static void HandleOverflow(const char *ax) {
|
||||||
emitlin("\tmovzbl\t%al,%eax");
|
emitlin("\tmovzbl\t%al,%eax");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void HandleAtomicArithmetic(Node *node, const char *op) {
|
||||||
|
gen_expr(node->lhs);
|
||||||
|
push();
|
||||||
|
gen_expr(node->rhs);
|
||||||
|
pop("%r9");
|
||||||
|
println("\tmov\t%s,%s", reg_ax(node->ty->size), reg_si(node->ty->size));
|
||||||
|
println("\tmov\t(%%r9),%s", reg_ax(node->ty->size));
|
||||||
|
println("1:\tmov\t%s,%s", reg_ax(node->ty->size), reg_dx(node->ty->size));
|
||||||
|
println("\tmov\t%s,%s", reg_ax(node->ty->size), reg_di(node->ty->size));
|
||||||
|
println("\t%s\t%s,%s", op, reg_si(node->ty->size), reg_dx(node->ty->size));
|
||||||
|
println("\tlock cmpxchg\t%s,(%%r9)", reg_dx(node->ty->size));
|
||||||
|
println("\tjnz\t1b");
|
||||||
|
println("\tmov\t%s,%s", reg_di(node->ty->size), reg_ax(node->ty->size));
|
||||||
|
}
|
||||||
|
|
||||||
// Generate code for a given node.
|
// Generate code for a given node.
|
||||||
void gen_expr(Node *node) {
|
void gen_expr(Node *node) {
|
||||||
char fbuf[32];
|
char fbuf[32];
|
||||||
|
@ -1520,7 +1563,7 @@ void gen_expr(Node *node) {
|
||||||
println("\tmov\t$%s,%%eax", node->unique_label);
|
println("\tmov\t$%s,%%eax", node->unique_label);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case ND_CAS: {
|
case ND_CAS:
|
||||||
gen_expr(node->cas_addr);
|
gen_expr(node->cas_addr);
|
||||||
push();
|
push();
|
||||||
gen_expr(node->cas_new);
|
gen_expr(node->cas_new);
|
||||||
|
@ -1531,14 +1574,11 @@ void gen_expr(Node *node) {
|
||||||
pop("%rdx"); // new
|
pop("%rdx"); // new
|
||||||
pop("%rdi"); // addr
|
pop("%rdi"); // addr
|
||||||
println("\tlock cmpxchg %s,(%%rdi)", reg_dx(node->ty->size));
|
println("\tlock cmpxchg %s,(%%rdi)", reg_dx(node->ty->size));
|
||||||
emitlin("\tsete\t%cl");
|
|
||||||
emitlin("\tje\t1f");
|
|
||||||
println("\tmov\t%s,(%%r8)", reg_ax(node->ty->size));
|
println("\tmov\t%s,(%%r8)", reg_ax(node->ty->size));
|
||||||
emitlin("1:");
|
emitlin("\tsetz\t%al");
|
||||||
emitlin("\tmovzbl\t%cl,%eax");
|
emitlin("\tmovzbl\t%al,%eax");
|
||||||
return;
|
return;
|
||||||
}
|
case ND_EXCH_N:
|
||||||
case ND_EXCH:
|
|
||||||
case ND_TESTANDSET: {
|
case ND_TESTANDSET: {
|
||||||
gen_expr(node->lhs);
|
gen_expr(node->lhs);
|
||||||
push();
|
push();
|
||||||
|
@ -1564,6 +1604,11 @@ void gen_expr(Node *node) {
|
||||||
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
|
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case ND_LOAD_N: {
|
||||||
|
gen_expr(node->lhs);
|
||||||
|
println("\tmov\t(%%rax),%s", reg_ax(node->ty->size));
|
||||||
|
return;
|
||||||
|
}
|
||||||
case ND_STORE: {
|
case ND_STORE: {
|
||||||
gen_expr(node->lhs);
|
gen_expr(node->lhs);
|
||||||
push();
|
push();
|
||||||
|
@ -1576,7 +1621,17 @@ void gen_expr(Node *node) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case ND_CLEAR: {
|
case ND_STORE_N:
|
||||||
|
gen_expr(node->lhs);
|
||||||
|
push();
|
||||||
|
gen_expr(node->rhs);
|
||||||
|
pop("%rdi");
|
||||||
|
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
|
||||||
|
if (node->memorder) {
|
||||||
|
println("\tmfence");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case ND_CLEAR:
|
||||||
gen_expr(node->lhs);
|
gen_expr(node->lhs);
|
||||||
println("\tmov\t%%rax,%%rdi");
|
println("\tmov\t%%rax,%%rdi");
|
||||||
println("\txor\t%%eax,%%eax");
|
println("\txor\t%%eax,%%eax");
|
||||||
|
@ -1585,16 +1640,31 @@ void gen_expr(Node *node) {
|
||||||
println("\tmfence");
|
println("\tmfence");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
case ND_FETCHADD:
|
||||||
case ND_FETCHADD: {
|
|
||||||
gen_expr(node->lhs);
|
gen_expr(node->lhs);
|
||||||
push();
|
push();
|
||||||
gen_expr(node->rhs);
|
gen_expr(node->rhs);
|
||||||
pop("%rdi");
|
pop("%rdi");
|
||||||
println("\txadd\t%s,(%%rdi)", reg_ax(node->ty->size));
|
println("\txadd\t%s,(%%rdi)", reg_ax(node->ty->size));
|
||||||
return;
|
return;
|
||||||
}
|
case ND_FETCHSUB:
|
||||||
case ND_SUBFETCH: {
|
gen_expr(node->lhs);
|
||||||
|
push();
|
||||||
|
gen_expr(node->rhs);
|
||||||
|
pop("%rdi");
|
||||||
|
println("\tneg\t%s", reg_ax(node->ty->size));
|
||||||
|
println("\txadd\t%s,(%%rdi)", reg_ax(node->ty->size));
|
||||||
|
return;
|
||||||
|
case ND_FETCHXOR:
|
||||||
|
HandleAtomicArithmetic(node, "xor");
|
||||||
|
return;
|
||||||
|
case ND_FETCHAND:
|
||||||
|
HandleAtomicArithmetic(node, "and");
|
||||||
|
return;
|
||||||
|
case ND_FETCHOR:
|
||||||
|
HandleAtomicArithmetic(node, "or");
|
||||||
|
return;
|
||||||
|
case ND_SUBFETCH:
|
||||||
gen_expr(node->lhs);
|
gen_expr(node->lhs);
|
||||||
push();
|
push();
|
||||||
gen_expr(node->rhs);
|
gen_expr(node->rhs);
|
||||||
|
@ -1605,15 +1675,13 @@ void gen_expr(Node *node) {
|
||||||
pop("%rdi");
|
pop("%rdi");
|
||||||
println("\tsub\t%s,%s", reg_di(node->ty->size), reg_ax(node->ty->size));
|
println("\tsub\t%s,%s", reg_di(node->ty->size), reg_ax(node->ty->size));
|
||||||
return;
|
return;
|
||||||
}
|
case ND_RELEASE:
|
||||||
case ND_RELEASE: {
|
|
||||||
gen_expr(node->lhs);
|
gen_expr(node->lhs);
|
||||||
push();
|
push();
|
||||||
pop("%rdi");
|
pop("%rdi");
|
||||||
println("\txor\t%%eax,%%eax");
|
println("\txor\t%%eax,%%eax");
|
||||||
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
|
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
case ND_FPCLASSIFY:
|
case ND_FPCLASSIFY:
|
||||||
gen_fpclassify(node->fpc);
|
gen_fpclassify(node->fpc);
|
||||||
return;
|
return;
|
||||||
|
|
12
third_party/chibicc/help.txt
vendored
12
third_party/chibicc/help.txt
vendored
|
@ -196,7 +196,6 @@ BUILTIN FUNCTIONS
|
||||||
int __builtin_unreachable()
|
int __builtin_unreachable()
|
||||||
void * __builtin_frame_address(int)
|
void * __builtin_frame_address(int)
|
||||||
_Bool __builtin_types_compatible_p(typename, typename)
|
_Bool __builtin_types_compatible_p(typename, typename)
|
||||||
T __builtin_compare_and_swap(T *addr, T old, T neu)
|
|
||||||
T __builtin_atomic_exchange(T *addr, T neu)
|
T __builtin_atomic_exchange(T *addr, T neu)
|
||||||
T * __builtin_assume_aligned(T *addr)
|
T * __builtin_assume_aligned(T *addr)
|
||||||
_Bool __builtin_add_overflow(T, T, T *)
|
_Bool __builtin_add_overflow(T, T, T *)
|
||||||
|
@ -261,11 +260,18 @@ BUILTIN FUNCTIONS
|
||||||
long double __builtin_copysignl(long double, long double)
|
long double __builtin_copysignl(long double, long double)
|
||||||
void __builtin_ia32_movntq(di *, di)
|
void __builtin_ia32_movntq(di *, di)
|
||||||
int __builtin_ia32_pmovmskb128(v16qi)
|
int __builtin_ia32_pmovmskb128(v16qi)
|
||||||
T __atomic_load(T *addr, int memorder)
|
T __atomic_load_n(T *addr, int memorder)
|
||||||
|
void __atomic_load(T *addr, T *res, int memorder)
|
||||||
|
void __atomic_store_n(T *addr, T val, int memorder)
|
||||||
|
void __atomic_store(T *addr, T *val, int memorder)
|
||||||
void __atomic_clear(_Bool *addr, int memorder)
|
void __atomic_clear(_Bool *addr, int memorder)
|
||||||
_Bool __atomic_test_and_set(void *addr, int memorder)
|
_Bool __atomic_test_and_set(void *addr, int memorder)
|
||||||
T __atomic_sub_fetch(T *addr, T amt, int memorder)
|
|
||||||
T __atomic_fetch_add(T *addr, T amt, int memorder)
|
T __atomic_fetch_add(T *addr, T amt, int memorder)
|
||||||
|
T __atomic_fetch_sub(T *addr, T amt, int memorder)
|
||||||
|
T __atomic_fetch_xor(T *addr, T amt, int memorder)
|
||||||
|
T __atomic_fetch_and(T *addr, T amt, int memorder)
|
||||||
|
T __atomic_fetch_or(T *addr, T amt, int memorder)
|
||||||
|
_Bool __atomic_compare_exchange_n(T *addr, T *old, T neu, int weak, int goodorder, int failorder)
|
||||||
T __sync_lock_test_and_set(T *addr, T value, ...)
|
T __sync_lock_test_and_set(T *addr, T value, ...)
|
||||||
void __sync_lock_release(T *addr, ...)
|
void __sync_lock_release(T *addr, ...)
|
||||||
|
|
||||||
|
|
11
third_party/chibicc/kw.gperf
vendored
11
third_party/chibicc/kw.gperf
vendored
|
@ -81,8 +81,6 @@ __thread, KW__THREAD_LOCAL
|
||||||
__typeof, KW_TYPEOF
|
__typeof, KW_TYPEOF
|
||||||
__builtin_add_overflow, KW___BUILTIN_ADD_OVERFLOW
|
__builtin_add_overflow, KW___BUILTIN_ADD_OVERFLOW
|
||||||
__builtin_assume_aligned, KW___BUILTIN_ASSUME_ALIGNED
|
__builtin_assume_aligned, KW___BUILTIN_ASSUME_ALIGNED
|
||||||
__atomic_exchange, KW___ATOMIC_EXCHANGE
|
|
||||||
__builtin_compare_and_swap, KW___BUILTIN_COMPARE_AND_SWAP
|
|
||||||
__builtin_constant_p, KW___BUILTIN_CONSTANT_P
|
__builtin_constant_p, KW___BUILTIN_CONSTANT_P
|
||||||
__builtin_expect, KW___BUILTIN_EXPECT
|
__builtin_expect, KW___BUILTIN_EXPECT
|
||||||
__builtin_ffs, KW___BUILTIN_FFS
|
__builtin_ffs, KW___BUILTIN_FFS
|
||||||
|
@ -119,12 +117,19 @@ __builtin_types_compatible_p, KW___BUILTIN_TYPES_COMPATIBLE_P
|
||||||
"->", KW_ARROW
|
"->", KW_ARROW
|
||||||
".", KW_DOT
|
".", KW_DOT
|
||||||
__atomic_load, KW___ATOMIC_LOAD
|
__atomic_load, KW___ATOMIC_LOAD
|
||||||
|
__atomic_load_n, KW___ATOMIC_LOAD_N
|
||||||
__atomic_store, KW___ATOMIC_STORE
|
__atomic_store, KW___ATOMIC_STORE
|
||||||
|
__atomic_store_n, KW___ATOMIC_STORE_N
|
||||||
__atomic_clear, KW___ATOMIC_CLEAR
|
__atomic_clear, KW___ATOMIC_CLEAR
|
||||||
__atomic_sub_fetch, KW___ATOMIC_SUB_FETCH
|
|
||||||
__atomic_fetch_add, KW___ATOMIC_FETCH_ADD
|
__atomic_fetch_add, KW___ATOMIC_FETCH_ADD
|
||||||
|
__atomic_fetch_sub, KW___ATOMIC_FETCH_SUB
|
||||||
|
__atomic_fetch_and, KW___ATOMIC_FETCH_AND
|
||||||
|
__atomic_fetch_xor, KW___ATOMIC_FETCH_XOR
|
||||||
|
__atomic_fetch_or, KW___ATOMIC_FETCH_OR
|
||||||
__atomic_test_and_set, KW___ATOMIC_TEST_AND_SET
|
__atomic_test_and_set, KW___ATOMIC_TEST_AND_SET
|
||||||
__sync_lock_test_and_set, KW___SYNC_LOCK_TEST_AND_SET
|
__sync_lock_test_and_set, KW___SYNC_LOCK_TEST_AND_SET
|
||||||
__sync_lock_release, KW___SYNC_LOCK_RELEASE
|
__sync_lock_release, KW___SYNC_LOCK_RELEASE
|
||||||
__builtin_ia32_movntdq, KW___BUILTIN_IA32_MOVNTDQ
|
__builtin_ia32_movntdq, KW___BUILTIN_IA32_MOVNTDQ
|
||||||
__builtin_ia32_pmovmskb128, KW___BUILTIN_IA32_PMOVMSKB128
|
__builtin_ia32_pmovmskb128, KW___BUILTIN_IA32_PMOVMSKB128
|
||||||
|
__atomic_compare_exchange_n, KW___ATOMIC_COMPARE_EXCHANGE_N
|
||||||
|
__atomic_exchange_n, KW___ATOMIC_EXCHANGE_N
|
||||||
|
|
99
third_party/chibicc/kw.h
vendored
99
third_party/chibicc/kw.h
vendored
|
@ -68,53 +68,58 @@
|
||||||
#define KW___ASM__ 84
|
#define KW___ASM__ 84
|
||||||
#define KW___BUILTIN_ADD_OVERFLOW 85
|
#define KW___BUILTIN_ADD_OVERFLOW 85
|
||||||
#define KW___BUILTIN_ASSUME_ALIGNED 86
|
#define KW___BUILTIN_ASSUME_ALIGNED 86
|
||||||
#define KW___ATOMIC_EXCHANGE 87
|
#define KW___BUILTIN_CONSTANT_P 87
|
||||||
#define KW___BUILTIN_COMPARE_AND_SWAP 88
|
#define KW___BUILTIN_EXPECT 88
|
||||||
#define KW___BUILTIN_CONSTANT_P 89
|
#define KW___BUILTIN_FFS 89
|
||||||
#define KW___BUILTIN_EXPECT 90
|
#define KW___BUILTIN_FFSL 90
|
||||||
#define KW___BUILTIN_FFS 91
|
#define KW___BUILTIN_FFSLL 91
|
||||||
#define KW___BUILTIN_FFSL 92
|
#define KW___BUILTIN_FPCLASSIFY 92
|
||||||
#define KW___BUILTIN_FFSLL 93
|
#define KW___BUILTIN_MUL_OVERFLOW 93
|
||||||
#define KW___BUILTIN_FPCLASSIFY 94
|
#define KW___BUILTIN_NEG_OVERFLOW 94
|
||||||
#define KW___BUILTIN_MUL_OVERFLOW 95
|
#define KW___BUILTIN_OFFSETOF 95
|
||||||
#define KW___BUILTIN_NEG_OVERFLOW 96
|
#define KW___BUILTIN_POPCOUNT 96
|
||||||
#define KW___BUILTIN_OFFSETOF 97
|
#define KW___BUILTIN_POPCOUNTL 97
|
||||||
#define KW___BUILTIN_POPCOUNT 98
|
#define KW___BUILTIN_POPCOUNTLL 98
|
||||||
#define KW___BUILTIN_POPCOUNTL 99
|
#define KW___BUILTIN_REG_CLASS 99
|
||||||
#define KW___BUILTIN_POPCOUNTLL 100
|
#define KW___BUILTIN_STRCHR 100
|
||||||
#define KW___BUILTIN_REG_CLASS 101
|
#define KW___BUILTIN_STRLEN 101
|
||||||
#define KW___BUILTIN_STRCHR 102
|
#define KW___BUILTIN_STRPBRK 102
|
||||||
#define KW___BUILTIN_STRLEN 103
|
#define KW___BUILTIN_STRSTR 103
|
||||||
#define KW___BUILTIN_STRPBRK 104
|
#define KW___BUILTIN_SUB_OVERFLOW 104
|
||||||
#define KW___BUILTIN_STRSTR 105
|
#define KW___BUILTIN_TYPES_COMPATIBLE_P 105
|
||||||
#define KW___BUILTIN_SUB_OVERFLOW 106
|
#define KW_LP 106
|
||||||
#define KW___BUILTIN_TYPES_COMPATIBLE_P 107
|
#define KW_RP 107
|
||||||
#define KW_LP 108
|
#define KW_LB 108
|
||||||
#define KW_RP 109
|
#define KW_RB 109
|
||||||
#define KW_LB 110
|
#define KW_PLUS 110
|
||||||
#define KW_RB 111
|
#define KW_MINUS 111
|
||||||
#define KW_PLUS 112
|
#define KW_AMP 112
|
||||||
#define KW_MINUS 113
|
#define KW_STAR 113
|
||||||
#define KW_AMP 114
|
#define KW_EXCLAIM 114
|
||||||
#define KW_STAR 115
|
#define KW_TILDE 115
|
||||||
#define KW_EXCLAIM 116
|
#define KW_INCREMENT 116
|
||||||
#define KW_TILDE 117
|
#define KW_DECREMENT 117
|
||||||
#define KW_INCREMENT 118
|
#define KW_LOGAND 118
|
||||||
#define KW_DECREMENT 119
|
#define KW_LOGOR 119
|
||||||
#define KW_LOGAND 120
|
#define KW_ARROW 120
|
||||||
#define KW_LOGOR 121
|
#define KW_DOT 121
|
||||||
#define KW_ARROW 122
|
#define KW___ATOMIC_LOAD 122
|
||||||
#define KW_DOT 123
|
#define KW___SYNC_LOCK_TEST_AND_SET 123
|
||||||
#define KW___ATOMIC_LOAD 124
|
#define KW___SYNC_LOCK_RELEASE 124
|
||||||
#define KW___SYNC_LOCK_TEST_AND_SET 125
|
#define KW___BUILTIN_IA32_PMOVMSKB128 125
|
||||||
#define KW___SYNC_LOCK_RELEASE 126
|
#define KW___BUILTIN_IA32_MOVNTDQ 126
|
||||||
#define KW___BUILTIN_IA32_PMOVMSKB128 127
|
#define KW___ATOMIC_FETCH_ADD 127
|
||||||
#define KW___BUILTIN_IA32_MOVNTDQ 128
|
#define KW___ATOMIC_TEST_AND_SET 128
|
||||||
#define KW___ATOMIC_FETCH_ADD 129
|
#define KW___ATOMIC_CLEAR 129
|
||||||
#define KW___ATOMIC_SUB_FETCH 130
|
#define KW___ATOMIC_STORE 130
|
||||||
#define KW___ATOMIC_TEST_AND_SET 131
|
#define KW___ATOMIC_STORE_N 131
|
||||||
#define KW___ATOMIC_CLEAR 132
|
#define KW___ATOMIC_LOAD_N 132
|
||||||
#define KW___ATOMIC_STORE 133
|
#define KW___ATOMIC_FETCH_SUB 133
|
||||||
|
#define KW___ATOMIC_FETCH_AND 134
|
||||||
|
#define KW___ATOMIC_FETCH_OR 135
|
||||||
|
#define KW___ATOMIC_FETCH_XOR 136
|
||||||
|
#define KW___ATOMIC_COMPARE_EXCHANGE_N 137
|
||||||
|
#define KW___ATOMIC_EXCHANGE_N 138
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
513
third_party/chibicc/kw.inc
vendored
513
third_party/chibicc/kw.inc
vendored
|
@ -1,6 +1,6 @@
|
||||||
/* ANSI-C code produced by gperf version 3.1 */
|
/* ANSI-C code produced by gperf version 3.1 */
|
||||||
/* Command-line: gperf kw.gperf */
|
/* Command-line: gperf kw.gperf */
|
||||||
/* Computed positions: -k'1,4,11,14,$' */
|
/* Computed positions: -k'1,4,11,14,17,$' */
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
||||||
|
@ -37,50 +37,55 @@
|
||||||
#line 10 "kw.gperf"
|
#line 10 "kw.gperf"
|
||||||
struct thatispacked KwSlot { char *name; unsigned char code; };
|
struct thatispacked KwSlot { char *name; unsigned char code; };
|
||||||
|
|
||||||
#define TOTAL_KEYWORDS 119
|
#define TOTAL_KEYWORDS 124
|
||||||
#define MIN_WORD_LENGTH 1
|
#define MIN_WORD_LENGTH 1
|
||||||
#define MAX_WORD_LENGTH 28
|
#define MAX_WORD_LENGTH 28
|
||||||
#define MIN_HASH_VALUE 1
|
#define MIN_HASH_VALUE 1
|
||||||
#define MAX_HASH_VALUE 238
|
#define MAX_HASH_VALUE 256
|
||||||
/* maximum key range = 238, duplicates = 0 */
|
/* maximum key range = 256, duplicates = 0 */
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
hash (register const char *str, register size_t len)
|
hash (register const char *str, register size_t len)
|
||||||
{
|
{
|
||||||
static const unsigned char asso_values[] =
|
static const unsigned short asso_values[] =
|
||||||
{
|
{
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 115, 239, 239, 239, 239, 50, 239,
|
257, 257, 257, 100, 257, 257, 257, 257, 25, 257,
|
||||||
110, 105, 100, 5, 239, 0, 95, 239, 239, 239,
|
95, 90, 85, 5, 257, 0, 80, 257, 257, 257,
|
||||||
10, 239, 239, 239, 239, 239, 0, 239, 239, 239,
|
0, 257, 257, 257, 257, 257, 10, 257, 257, 257,
|
||||||
239, 239, 45, 239, 239, 239, 0, 239, 239, 239,
|
257, 257, 35, 257, 257, 257, 0, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 5, 239, 0, 90, 5,
|
257, 257, 257, 257, 257, 5, 257, 15, 120, 5,
|
||||||
55, 10, 0, 25, 75, 105, 15, 10, 20, 15,
|
25, 0, 0, 45, 85, 115, 65, 0, 25, 90,
|
||||||
125, 60, 15, 10, 10, 10, 0, 70, 5, 5,
|
40, 50, 5, 15, 25, 10, 0, 0, 10, 5,
|
||||||
10, 0, 45, 85, 10, 30, 15, 239, 239, 239,
|
20, 5, 90, 75, 20, 70, 65, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
|
257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
|
||||||
239, 239, 239, 239, 239, 239, 239
|
257, 257, 257, 257, 257, 257, 257
|
||||||
};
|
};
|
||||||
register unsigned int hval = len;
|
register unsigned int hval = len;
|
||||||
|
|
||||||
switch (hval)
|
switch (hval)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
hval += asso_values[(unsigned char)str[16]];
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
case 16:
|
||||||
|
case 15:
|
||||||
|
case 14:
|
||||||
hval += asso_values[(unsigned char)str[13]];
|
hval += asso_values[(unsigned char)str[13]];
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
case 13:
|
case 13:
|
||||||
|
@ -112,24 +117,30 @@ LookupKw (register const char *str, register size_t len)
|
||||||
static const struct thatispacked KwSlot wordlist[] =
|
static const struct thatispacked KwSlot wordlist[] =
|
||||||
{
|
{
|
||||||
{""},
|
{""},
|
||||||
#line 110 "kw.gperf"
|
#line 108 "kw.gperf"
|
||||||
{"-", KW_MINUS},
|
{"-", KW_MINUS},
|
||||||
#line 116 "kw.gperf"
|
#line 114 "kw.gperf"
|
||||||
{"--", KW_DECREMENT},
|
{"--", KW_DECREMENT},
|
||||||
{""}, {""}, {""},
|
{""},
|
||||||
|
#line 19 "kw.gperf"
|
||||||
|
{"else", KW_ELSE},
|
||||||
|
#line 64 "kw.gperf"
|
||||||
|
{"undef", KW_UNDEF},
|
||||||
#line 63 "kw.gperf"
|
#line 63 "kw.gperf"
|
||||||
{"typeof", KW_TYPEOF},
|
{"typeof", KW_TYPEOF},
|
||||||
#line 62 "kw.gperf"
|
#line 62 "kw.gperf"
|
||||||
{"typedef", KW_TYPEDEF},
|
{"typedef", KW_TYPEDEF},
|
||||||
{""}, {""},
|
{""},
|
||||||
|
#line 15 "kw.gperf"
|
||||||
|
{"case", KW_CASE},
|
||||||
#line 29 "kw.gperf"
|
#line 29 "kw.gperf"
|
||||||
{"const", KW_CONST},
|
{"const", KW_CONST},
|
||||||
#line 109 "kw.gperf"
|
#line 107 "kw.gperf"
|
||||||
{"+", KW_PLUS},
|
{"+", KW_PLUS},
|
||||||
#line 115 "kw.gperf"
|
#line 113 "kw.gperf"
|
||||||
{"++", KW_INCREMENT},
|
{"++", KW_INCREMENT},
|
||||||
#line 20 "kw.gperf"
|
#line 35 "kw.gperf"
|
||||||
{"for", KW_FOR},
|
{"continue", KW_CONTINUE},
|
||||||
{""},
|
{""},
|
||||||
#line 78 "kw.gperf"
|
#line 78 "kw.gperf"
|
||||||
{"__restrict", KW_RESTRICT},
|
{"__restrict", KW_RESTRICT},
|
||||||
|
@ -137,269 +148,275 @@ LookupKw (register const char *str, register size_t len)
|
||||||
{"sizeof", KW_SIZEOF},
|
{"sizeof", KW_SIZEOF},
|
||||||
#line 75 "kw.gperf"
|
#line 75 "kw.gperf"
|
||||||
{"__asm__", KW___ASM__},
|
{"__asm__", KW___ASM__},
|
||||||
#line 41 "kw.gperf"
|
{""},
|
||||||
{"asm", KW_ASM},
|
#line 121 "kw.gperf"
|
||||||
#line 15 "kw.gperf"
|
{"__atomic_store", KW___ATOMIC_STORE},
|
||||||
{"case", KW_CASE},
|
|
||||||
#line 73 "kw.gperf"
|
#line 73 "kw.gperf"
|
||||||
{"__VA_OPT__", KW___VA_OPT__},
|
{"__VA_OPT__", KW___VA_OPT__},
|
||||||
#line 13 "kw.gperf"
|
#line 16 "kw.gperf"
|
||||||
{"struct", KW_STRUCT},
|
{"static", KW_STATIC},
|
||||||
#line 118 "kw.gperf"
|
|
||||||
{"||", KW_LOGOR},
|
|
||||||
{""},
|
|
||||||
#line 19 "kw.gperf"
|
|
||||||
{"else", KW_ELSE},
|
|
||||||
#line 31 "kw.gperf"
|
|
||||||
{"short", KW_SHORT},
|
|
||||||
#line 61 "kw.gperf"
|
|
||||||
{"strstr", KW_STRSTR},
|
|
||||||
#line 79 "kw.gperf"
|
|
||||||
{"__restrict__", KW_RESTRICT},
|
|
||||||
#line 67 "kw.gperf"
|
|
||||||
{"_Alignof", KW__ALIGNOF},
|
|
||||||
#line 18 "kw.gperf"
|
|
||||||
{"char", KW_CHAR},
|
|
||||||
#line 48 "kw.gperf"
|
|
||||||
{"endif", KW_ENDIF},
|
|
||||||
#line 114 "kw.gperf"
|
|
||||||
{"~", KW_TILDE},
|
|
||||||
#line 68 "kw.gperf"
|
#line 68 "kw.gperf"
|
||||||
{"_Atomic", KW__ATOMIC},
|
{"_Atomic", KW__ATOMIC},
|
||||||
#line 88 "kw.gperf"
|
#line 45 "kw.gperf"
|
||||||
{"__builtin_ffs", KW___BUILTIN_FFS},
|
{"__attribute__", KW___ATTRIBUTE__},
|
||||||
|
{""},
|
||||||
|
#line 31 "kw.gperf"
|
||||||
|
{"short", KW_SHORT},
|
||||||
|
#line 13 "kw.gperf"
|
||||||
|
{"struct", KW_STRUCT},
|
||||||
|
#line 79 "kw.gperf"
|
||||||
|
{"__restrict__", KW_RESTRICT},
|
||||||
|
#line 20 "kw.gperf"
|
||||||
|
{"for", KW_FOR},
|
||||||
#line 55 "kw.gperf"
|
#line 55 "kw.gperf"
|
||||||
{"line", KW_LINE},
|
{"line", KW_LINE},
|
||||||
#line 25 "kw.gperf"
|
|
||||||
{"while", KW_WHILE},
|
|
||||||
{""},
|
{""},
|
||||||
|
#line 85 "kw.gperf"
|
||||||
|
{"__builtin_expect", KW___BUILTIN_EXPECT},
|
||||||
#line 60 "kw.gperf"
|
#line 60 "kw.gperf"
|
||||||
{"strpbrk", KW_STRPBRK},
|
{"strpbrk", KW_STRPBRK},
|
||||||
#line 66 "kw.gperf"
|
#line 57 "kw.gperf"
|
||||||
{"_Alignas", KW__ALIGNAS},
|
{"restrict", KW_RESTRICT},
|
||||||
#line 47 "kw.gperf"
|
{""},
|
||||||
{"elif", KW_ELIF},
|
|
||||||
#line 49 "kw.gperf"
|
#line 49 "kw.gperf"
|
||||||
{"error", KW_ERROR},
|
{"error", KW_ERROR},
|
||||||
#line 74 "kw.gperf"
|
#line 28 "kw.gperf"
|
||||||
{"__alignof__", KW___ALIGNOF__},
|
{"double", KW_DOUBLE},
|
||||||
#line 82 "kw.gperf"
|
#line 117 "kw.gperf"
|
||||||
{"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW},
|
{"->", KW_ARROW},
|
||||||
#line 44 "kw.gperf"
|
#line 86 "kw.gperf"
|
||||||
{"register", KW_REGISTER},
|
{"__builtin_ffs", KW___BUILTIN_FFS},
|
||||||
{""},
|
#line 17 "kw.gperf"
|
||||||
|
{"void", KW_VOID},
|
||||||
#line 69 "kw.gperf"
|
#line 69 "kw.gperf"
|
||||||
{"_Bool", KW__BOOL},
|
{"_Bool", KW__BOOL},
|
||||||
#line 87 "kw.gperf"
|
#line 61 "kw.gperf"
|
||||||
{"__builtin_expect", KW___BUILTIN_EXPECT},
|
{"strstr", KW_STRSTR},
|
||||||
#line 119 "kw.gperf"
|
#line 116 "kw.gperf"
|
||||||
{"->", KW_ARROW},
|
{"||", KW_LOGOR},
|
||||||
#line 95 "kw.gperf"
|
|
||||||
{"__builtin_popcount", KW___BUILTIN_POPCOUNT},
|
|
||||||
{""},
|
{""},
|
||||||
#line 91 "kw.gperf"
|
#line 18 "kw.gperf"
|
||||||
{"__builtin_fpclassify", KW___BUILTIN_FPCLASSIFY},
|
{"char", KW_CHAR},
|
||||||
|
{""},
|
||||||
|
#line 50 "kw.gperf"
|
||||||
|
{"extern", KW_EXTERN},
|
||||||
#line 99 "kw.gperf"
|
#line 99 "kw.gperf"
|
||||||
{"__builtin_strchr", KW___BUILTIN_STRCHR},
|
{"__builtin_strpbrk", KW___BUILTIN_STRPBRK},
|
||||||
#line 103 "kw.gperf"
|
{""},
|
||||||
|
#line 47 "kw.gperf"
|
||||||
|
{"elif", KW_ELIF},
|
||||||
|
#line 26 "kw.gperf"
|
||||||
|
{"union", KW_UNION},
|
||||||
|
#line 109 "kw.gperf"
|
||||||
|
{"&", KW_AMP},
|
||||||
|
#line 115 "kw.gperf"
|
||||||
|
{"&&", KW_LOGAND},
|
||||||
|
#line 102 "kw.gperf"
|
||||||
|
{"__builtin_types_compatible_p", KW___BUILTIN_TYPES_COMPATIBLE_P},
|
||||||
|
{""}, {""},
|
||||||
|
#line 129 "kw.gperf"
|
||||||
|
{"__atomic_test_and_set", KW___ATOMIC_TEST_AND_SET},
|
||||||
|
#line 101 "kw.gperf"
|
||||||
{"__builtin_sub_overflow", KW___BUILTIN_SUB_OVERFLOW},
|
{"__builtin_sub_overflow", KW___BUILTIN_SUB_OVERFLOW},
|
||||||
#line 72 "kw.gperf"
|
#line 72 "kw.gperf"
|
||||||
{"_Thread_local", KW__THREAD_LOCAL},
|
{"_Thread_local", KW__THREAD_LOCAL},
|
||||||
#line 98 "kw.gperf"
|
{""}, {""},
|
||||||
{"__builtin_reg_class", KW___BUILTIN_REG_CLASS},
|
#line 122 "kw.gperf"
|
||||||
{""},
|
{"__atomic_store_n", KW___ATOMIC_STORE_N},
|
||||||
#line 102 "kw.gperf"
|
#line 82 "kw.gperf"
|
||||||
{"__builtin_strstr", KW___BUILTIN_STRSTR},
|
{"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW},
|
||||||
#line 92 "kw.gperf"
|
#line 76 "kw.gperf"
|
||||||
{"__builtin_mul_overflow", KW___BUILTIN_MUL_OVERFLOW},
|
{"__inline", KW_INLINE},
|
||||||
#line 81 "kw.gperf"
|
#line 46 "kw.gperf"
|
||||||
{"__typeof", KW_TYPEOF},
|
{"_Noreturn", KW__NORETURN},
|
||||||
{""},
|
|
||||||
#line 86 "kw.gperf"
|
|
||||||
{"__builtin_constant_p", KW___BUILTIN_CONSTANT_P},
|
|
||||||
#line 108 "kw.gperf"
|
|
||||||
{"}", KW_RB},
|
|
||||||
#line 101 "kw.gperf"
|
|
||||||
{"__builtin_strpbrk", KW___BUILTIN_STRPBRK},
|
|
||||||
#line 104 "kw.gperf"
|
|
||||||
{"__builtin_types_compatible_p", KW___BUILTIN_TYPES_COMPATIBLE_P},
|
|
||||||
#line 89 "kw.gperf"
|
|
||||||
{"__builtin_ffsl", KW___BUILTIN_FFSL},
|
|
||||||
#line 90 "kw.gperf"
|
|
||||||
{"__builtin_ffsll", KW___BUILTIN_FFSLL},
|
|
||||||
{""}, {""}, {""},
|
|
||||||
#line 96 "kw.gperf"
|
|
||||||
{"__builtin_popcountl", KW___BUILTIN_POPCOUNTL},
|
|
||||||
#line 97 "kw.gperf"
|
|
||||||
{"__builtin_popcountll", KW___BUILTIN_POPCOUNTLL},
|
|
||||||
#line 85 "kw.gperf"
|
|
||||||
{"__builtin_compare_and_swap", KW___BUILTIN_COMPARE_AND_SWAP},
|
|
||||||
{""},
|
|
||||||
#line 77 "kw.gperf"
|
|
||||||
{"__int128", KW___INT128},
|
|
||||||
#line 17 "kw.gperf"
|
|
||||||
{"void", KW_VOID},
|
|
||||||
#line 64 "kw.gperf"
|
|
||||||
{"undef", KW_UNDEF},
|
|
||||||
#line 28 "kw.gperf"
|
|
||||||
{"double", KW_DOUBLE},
|
|
||||||
{""},
|
|
||||||
#line 70 "kw.gperf"
|
|
||||||
{"_Generic", KW__GENERIC},
|
|
||||||
#line 43 "kw.gperf"
|
|
||||||
{"auto", KW_AUTO},
|
|
||||||
{""},
|
{""},
|
||||||
#line 58 "kw.gperf"
|
#line 58 "kw.gperf"
|
||||||
{"strchr", KW_STRCHR},
|
{"strchr", KW_STRCHR},
|
||||||
{""},
|
{""},
|
||||||
#line 76 "kw.gperf"
|
#line 70 "kw.gperf"
|
||||||
{"__inline", KW_INLINE},
|
{"_Generic", KW__GENERIC},
|
||||||
|
{""},
|
||||||
|
#line 48 "kw.gperf"
|
||||||
|
{"endif", KW_ENDIF},
|
||||||
|
#line 97 "kw.gperf"
|
||||||
|
{"__builtin_strchr", KW___BUILTIN_STRCHR},
|
||||||
|
{""},
|
||||||
|
#line 77 "kw.gperf"
|
||||||
|
{"__int128", KW___INT128},
|
||||||
|
#line 43 "kw.gperf"
|
||||||
|
{"auto", KW_AUTO},
|
||||||
|
#line 89 "kw.gperf"
|
||||||
|
{"__builtin_fpclassify", KW___BUILTIN_FPCLASSIFY},
|
||||||
|
#line 100 "kw.gperf"
|
||||||
|
{"__builtin_strstr", KW___BUILTIN_STRSTR},
|
||||||
|
#line 21 "kw.gperf"
|
||||||
|
{"do", KW_DO},
|
||||||
|
#line 67 "kw.gperf"
|
||||||
|
{"_Alignof", KW__ALIGNOF},
|
||||||
|
#line 87 "kw.gperf"
|
||||||
|
{"__builtin_ffsl", KW___BUILTIN_FFSL},
|
||||||
|
#line 88 "kw.gperf"
|
||||||
|
{"__builtin_ffsll", KW___BUILTIN_FFSLL},
|
||||||
|
#line 14 "kw.gperf"
|
||||||
|
{"return", KW_RETURN},
|
||||||
|
{""},
|
||||||
|
#line 93 "kw.gperf"
|
||||||
|
{"__builtin_popcount", KW___BUILTIN_POPCOUNT},
|
||||||
|
#line 83 "kw.gperf"
|
||||||
|
{"__builtin_assume_aligned", KW___BUILTIN_ASSUME_ALIGNED},
|
||||||
{""}, {""},
|
{""}, {""},
|
||||||
|
#line 91 "kw.gperf"
|
||||||
|
{"__builtin_neg_overflow", KW___BUILTIN_NEG_OVERFLOW},
|
||||||
|
#line 66 "kw.gperf"
|
||||||
|
{"_Alignas", KW__ALIGNAS},
|
||||||
|
#line 96 "kw.gperf"
|
||||||
|
{"__builtin_reg_class", KW___BUILTIN_REG_CLASS},
|
||||||
|
{""},
|
||||||
|
#line 32 "kw.gperf"
|
||||||
|
{"signed", KW_SIGNED},
|
||||||
|
{""},
|
||||||
|
#line 119 "kw.gperf"
|
||||||
|
{"__atomic_load", KW___ATOMIC_LOAD},
|
||||||
|
#line 123 "kw.gperf"
|
||||||
|
{"__atomic_clear", KW___ATOMIC_CLEAR},
|
||||||
|
#line 84 "kw.gperf"
|
||||||
|
{"__builtin_constant_p", KW___BUILTIN_CONSTANT_P},
|
||||||
#line 39 "kw.gperf"
|
#line 39 "kw.gperf"
|
||||||
{"define", KW_DEFINE},
|
{"define", KW_DEFINE},
|
||||||
{""},
|
{""},
|
||||||
#line 57 "kw.gperf"
|
#line 23 "kw.gperf"
|
||||||
{"restrict", KW_RESTRICT},
|
{"unsigned", KW_UNSIGNED},
|
||||||
{""}, {""},
|
#line 135 "kw.gperf"
|
||||||
#line 16 "kw.gperf"
|
{"__atomic_exchange_n", KW___ATOMIC_EXCHANGE_N},
|
||||||
{"static", KW_STATIC},
|
#line 25 "kw.gperf"
|
||||||
|
{"while", KW_WHILE},
|
||||||
|
#line 27 "kw.gperf"
|
||||||
|
{"switch", KW_SWITCH},
|
||||||
{""},
|
{""},
|
||||||
#line 35 "kw.gperf"
|
#line 81 "kw.gperf"
|
||||||
{"continue", KW_CONTINUE},
|
{"__typeof", KW_TYPEOF},
|
||||||
#line 127 "kw.gperf"
|
|
||||||
{"__sync_lock_test_and_set", KW___SYNC_LOCK_TEST_AND_SET},
|
|
||||||
#line 30 "kw.gperf"
|
|
||||||
{"float", KW_FLOAT},
|
|
||||||
#line 56 "kw.gperf"
|
|
||||||
{"pragma", KW_PRAGMA},
|
|
||||||
{""},
|
|
||||||
#line 94 "kw.gperf"
|
|
||||||
{"__builtin_offsetof", KW___BUILTIN_OFFSETOF},
|
|
||||||
#line 128 "kw.gperf"
|
|
||||||
{"__sync_lock_release", KW___SYNC_LOCK_RELEASE},
|
|
||||||
{""},
|
|
||||||
#line 111 "kw.gperf"
|
|
||||||
{"&", KW_AMP},
|
|
||||||
#line 117 "kw.gperf"
|
|
||||||
{"&&", KW_LOGAND},
|
|
||||||
#line 45 "kw.gperf"
|
|
||||||
{"__attribute__", KW___ATTRIBUTE__},
|
|
||||||
#line 51 "kw.gperf"
|
#line 51 "kw.gperf"
|
||||||
{"goto", KW_GOTO},
|
{"goto", KW_GOTO},
|
||||||
{""}, {""},
|
{""},
|
||||||
|
#line 98 "kw.gperf"
|
||||||
|
{"__builtin_strlen", KW___BUILTIN_STRLEN},
|
||||||
|
{""},
|
||||||
|
#line 41 "kw.gperf"
|
||||||
|
{"asm", KW_ASM},
|
||||||
|
#line 94 "kw.gperf"
|
||||||
|
{"__builtin_popcountl", KW___BUILTIN_POPCOUNTL},
|
||||||
|
#line 95 "kw.gperf"
|
||||||
|
{"__builtin_popcountll", KW___BUILTIN_POPCOUNTLL},
|
||||||
|
#line 56 "kw.gperf"
|
||||||
|
{"pragma", KW_PRAGMA},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
#line 120 "kw.gperf"
|
||||||
|
{"__atomic_load_n", KW___ATOMIC_LOAD_N},
|
||||||
|
#line 74 "kw.gperf"
|
||||||
|
{"__alignof__", KW___ALIGNOF__},
|
||||||
#line 12 "kw.gperf"
|
#line 12 "kw.gperf"
|
||||||
{"if", KW_IF},
|
{"if", KW_IF},
|
||||||
#line 54 "kw.gperf"
|
#line 54 "kw.gperf"
|
||||||
{"int", KW_INT},
|
{"int", KW_INT},
|
||||||
#line 122 "kw.gperf"
|
{""},
|
||||||
{"__atomic_store", KW___ATOMIC_STORE},
|
|
||||||
#line 37 "kw.gperf"
|
#line 37 "kw.gperf"
|
||||||
{"ifdef", KW_IFDEF},
|
{"ifdef", KW_IFDEF},
|
||||||
#line 126 "kw.gperf"
|
#line 38 "kw.gperf"
|
||||||
{"__atomic_test_and_set", KW___ATOMIC_TEST_AND_SET},
|
{"ifndef", KW_IFNDEF},
|
||||||
#line 84 "kw.gperf"
|
#line 40 "kw.gperf"
|
||||||
{"__atomic_exchange", KW___ATOMIC_EXCHANGE},
|
{"defined", KW_DEFINED},
|
||||||
|
#line 44 "kw.gperf"
|
||||||
|
{"register", KW_REGISTER},
|
||||||
|
#line 130 "kw.gperf"
|
||||||
|
{"__sync_lock_test_and_set", KW___SYNC_LOCK_TEST_AND_SET},
|
||||||
|
#line 30 "kw.gperf"
|
||||||
|
{"float", KW_FLOAT},
|
||||||
|
{""}, {""}, {""},
|
||||||
|
#line 131 "kw.gperf"
|
||||||
|
{"__sync_lock_release", KW___SYNC_LOCK_RELEASE},
|
||||||
|
{""},
|
||||||
|
#line 112 "kw.gperf"
|
||||||
|
{"~", KW_TILDE},
|
||||||
|
{""}, {""},
|
||||||
|
#line 34 "kw.gperf"
|
||||||
|
{"enum", KW_ENUM},
|
||||||
|
{""}, {""},
|
||||||
|
#line 90 "kw.gperf"
|
||||||
|
{"__builtin_mul_overflow", KW___BUILTIN_MUL_OVERFLOW},
|
||||||
#line 65 "kw.gperf"
|
#line 65 "kw.gperf"
|
||||||
{"volatile", KW_VOLATILE},
|
{"volatile", KW_VOLATILE},
|
||||||
{""}, {""}, {""},
|
{""}, {""},
|
||||||
#line 21 "kw.gperf"
|
#line 106 "kw.gperf"
|
||||||
{"do", KW_DO},
|
{"}", KW_RB},
|
||||||
{""},
|
#line 134 "kw.gperf"
|
||||||
|
{"__atomic_compare_exchange_n", KW___ATOMIC_COMPARE_EXCHANGE_N},
|
||||||
|
#line 92 "kw.gperf"
|
||||||
|
{"__builtin_offsetof", KW___BUILTIN_OFFSETOF},
|
||||||
|
{""}, {""},
|
||||||
|
#line 59 "kw.gperf"
|
||||||
|
{"strlen", KW_STRLEN},
|
||||||
|
{""}, {""},
|
||||||
#line 71 "kw.gperf"
|
#line 71 "kw.gperf"
|
||||||
{"_Static_assert", KW__STATIC_ASSERT},
|
{"_Static_assert", KW__STATIC_ASSERT},
|
||||||
{""},
|
{""},
|
||||||
#line 38 "kw.gperf"
|
#line 105 "kw.gperf"
|
||||||
{"ifndef", KW_IFNDEF},
|
{"{", KW_LB},
|
||||||
{""}, {""},
|
|
||||||
#line 24 "kw.gperf"
|
|
||||||
{"long", KW_LONG},
|
|
||||||
{""}, {""}, {""}, {""},
|
|
||||||
#line 123 "kw.gperf"
|
|
||||||
{"__atomic_clear", KW___ATOMIC_CLEAR},
|
|
||||||
{""},
|
|
||||||
#line 32 "kw.gperf"
|
|
||||||
{"signed", KW_SIGNED},
|
|
||||||
#line 40 "kw.gperf"
|
|
||||||
{"defined", KW_DEFINED},
|
|
||||||
{""}, {""}, {""},
|
|
||||||
#line 53 "kw.gperf"
|
|
||||||
{"inline", KW_INLINE},
|
|
||||||
#line 36 "kw.gperf"
|
|
||||||
{"include", KW_INCLUDE},
|
|
||||||
{""}, {""}, {""},
|
|
||||||
#line 50 "kw.gperf"
|
|
||||||
{"extern", KW_EXTERN},
|
|
||||||
#line 52 "kw.gperf"
|
|
||||||
{"include_next", KW_INCLUDE_NEXT},
|
|
||||||
{""}, {""}, {""},
|
|
||||||
#line 14 "kw.gperf"
|
|
||||||
{"return", KW_RETURN},
|
|
||||||
{""},
|
|
||||||
#line 23 "kw.gperf"
|
|
||||||
{"unsigned", KW_UNSIGNED},
|
|
||||||
#line 46 "kw.gperf"
|
|
||||||
{"_Noreturn", KW__NORETURN},
|
|
||||||
{""},
|
|
||||||
#line 130 "kw.gperf"
|
|
||||||
{"__builtin_ia32_pmovmskb128", KW___BUILTIN_IA32_PMOVMSKB128},
|
|
||||||
#line 42 "kw.gperf"
|
#line 42 "kw.gperf"
|
||||||
{"default", KW_DEFAULT},
|
{"default", KW_DEFAULT},
|
||||||
{""},
|
|
||||||
#line 34 "kw.gperf"
|
|
||||||
{"enum", KW_ENUM},
|
|
||||||
{""},
|
|
||||||
#line 59 "kw.gperf"
|
|
||||||
{"strlen", KW_STRLEN},
|
|
||||||
#line 129 "kw.gperf"
|
|
||||||
{"__builtin_ia32_movntdq", KW___BUILTIN_IA32_MOVNTDQ},
|
|
||||||
{""},
|
|
||||||
#line 83 "kw.gperf"
|
|
||||||
{"__builtin_assume_aligned", KW___BUILTIN_ASSUME_ALIGNED},
|
|
||||||
{""},
|
|
||||||
#line 27 "kw.gperf"
|
|
||||||
{"switch", KW_SWITCH},
|
|
||||||
{""}, {""}, {""}, {""}, {""},
|
|
||||||
#line 93 "kw.gperf"
|
|
||||||
{"__builtin_neg_overflow", KW___BUILTIN_NEG_OVERFLOW},
|
|
||||||
{""}, {""}, {""},
|
|
||||||
#line 107 "kw.gperf"
|
|
||||||
{"{", KW_LB},
|
|
||||||
{""},
|
|
||||||
#line 80 "kw.gperf"
|
#line 80 "kw.gperf"
|
||||||
{"__thread", KW__THREAD_LOCAL},
|
{"__thread", KW__THREAD_LOCAL},
|
||||||
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
|
||||||
#line 100 "kw.gperf"
|
|
||||||
{"__builtin_strlen", KW___BUILTIN_STRLEN},
|
|
||||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
|
||||||
#line 120 "kw.gperf"
|
|
||||||
{".", KW_DOT},
|
|
||||||
{""}, {""}, {""},
|
{""}, {""}, {""},
|
||||||
#line 33 "kw.gperf"
|
#line 128 "kw.gperf"
|
||||||
{"break", KW_BREAK},
|
{"__atomic_fetch_or", KW___ATOMIC_FETCH_OR},
|
||||||
{""}, {""}, {""}, {""}, {""},
|
#line 124 "kw.gperf"
|
||||||
#line 112 "kw.gperf"
|
{"__atomic_fetch_add", KW___ATOMIC_FETCH_ADD},
|
||||||
|
#line 24 "kw.gperf"
|
||||||
|
{"long", KW_LONG},
|
||||||
|
{""},
|
||||||
|
#line 118 "kw.gperf"
|
||||||
|
{".", KW_DOT},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
#line 110 "kw.gperf"
|
||||||
{"*", KW_STAR},
|
{"*", KW_STAR},
|
||||||
{""},
|
{""},
|
||||||
#line 121 "kw.gperf"
|
#line 126 "kw.gperf"
|
||||||
{"__atomic_load", KW___ATOMIC_LOAD},
|
{"__atomic_fetch_and", KW___ATOMIC_FETCH_AND},
|
||||||
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
#line 106 "kw.gperf"
|
#line 104 "kw.gperf"
|
||||||
{")", KW_RP},
|
{")", KW_RP},
|
||||||
{""}, {""}, {""},
|
{""},
|
||||||
#line 26 "kw.gperf"
|
#line 127 "kw.gperf"
|
||||||
{"union", KW_UNION},
|
{"__atomic_fetch_xor", KW___ATOMIC_FETCH_XOR},
|
||||||
{""}, {""}, {""}, {""}, {""},
|
{""}, {""},
|
||||||
#line 105 "kw.gperf"
|
#line 53 "kw.gperf"
|
||||||
|
{"inline", KW_INLINE},
|
||||||
|
{""}, {""}, {""}, {""},
|
||||||
|
#line 103 "kw.gperf"
|
||||||
{"(", KW_LP},
|
{"(", KW_LP},
|
||||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
#line 113 "kw.gperf"
|
#line 111 "kw.gperf"
|
||||||
{"!", KW_EXCLAIM},
|
{"!", KW_EXCLAIM},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""},
|
||||||
|
#line 36 "kw.gperf"
|
||||||
|
{"include", KW_INCLUDE},
|
||||||
|
{""}, {""}, {""}, {""},
|
||||||
|
#line 132 "kw.gperf"
|
||||||
|
{"__builtin_ia32_movntdq", KW___BUILTIN_IA32_MOVNTDQ},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
{""},
|
{""},
|
||||||
#line 125 "kw.gperf"
|
#line 125 "kw.gperf"
|
||||||
{"__atomic_fetch_add", KW___ATOMIC_FETCH_ADD},
|
{"__atomic_fetch_sub", KW___ATOMIC_FETCH_SUB},
|
||||||
{""}, {""}, {""}, {""},
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
#line 124 "kw.gperf"
|
#line 52 "kw.gperf"
|
||||||
{"__atomic_sub_fetch", KW___ATOMIC_SUB_FETCH}
|
{"include_next", KW_INCLUDE_NEXT},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
#line 33 "kw.gperf"
|
||||||
|
{"break", KW_BREAK},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
{""},
|
||||||
|
#line 133 "kw.gperf"
|
||||||
|
{"__builtin_ia32_pmovmskb128", KW___BUILTIN_IA32_PMOVMSKB128}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||||
|
|
141
third_party/chibicc/parse.c
vendored
141
third_party/chibicc/parse.c
vendored
|
@ -3121,6 +3121,33 @@ static Node *generic_selection(Token **rest, Token *tok) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Node *ParseAtomic2(NodeKind kind, Token *tok, Token **rest) {
|
||||||
|
Node *node = new_node(kind, tok);
|
||||||
|
tok = skip(tok->next, '(');
|
||||||
|
node->lhs = assign(&tok, tok);
|
||||||
|
add_type(node->lhs);
|
||||||
|
node->ty = node->lhs->ty->base;
|
||||||
|
tok = skip(tok, ',');
|
||||||
|
node->memorder = const_expr(&tok, tok);
|
||||||
|
*rest = skip(tok, ')');
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Node *ParseAtomic3(NodeKind kind, Token *tok, Token **rest) {
|
||||||
|
Node *node = new_node(kind, tok);
|
||||||
|
tok = skip(tok->next, '(');
|
||||||
|
node->lhs = assign(&tok, tok);
|
||||||
|
add_type(node->lhs);
|
||||||
|
node->ty = node->lhs->ty->base;
|
||||||
|
tok = skip(tok, ',');
|
||||||
|
node->rhs = assign(&tok, tok);
|
||||||
|
add_type(node->rhs);
|
||||||
|
tok = skip(tok, ',');
|
||||||
|
node->memorder = const_expr(&tok, tok);
|
||||||
|
*rest = skip(tok, ')');
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
// primary = "(" "{" stmt+ "}" ")"
|
// primary = "(" "{" stmt+ "}" ")"
|
||||||
// | "(" expr ")"
|
// | "(" expr ")"
|
||||||
// | "sizeof" "(" type-name ")"
|
// | "sizeof" "(" type-name ")"
|
||||||
|
@ -3228,104 +3255,65 @@ static Node *primary(Token **rest, Token *tok) {
|
||||||
if (is_flonum(ty)) return new_int(1, start);
|
if (is_flonum(ty)) return new_int(1, start);
|
||||||
return new_int(2, start);
|
return new_int(2, start);
|
||||||
}
|
}
|
||||||
if (kw == KW___BUILTIN_COMPARE_AND_SWAP) {
|
if (kw == KW___ATOMIC_COMPARE_EXCHANGE_N) {
|
||||||
Node *node = new_node(ND_CAS, tok);
|
Node *node = new_node(ND_CAS, tok);
|
||||||
tok = skip(tok->next, '(');
|
tok = skip(tok->next, '(');
|
||||||
node->cas_addr = assign(&tok, tok);
|
node->cas_addr = assign(&tok, tok);
|
||||||
|
add_type(node->cas_addr);
|
||||||
tok = skip(tok, ',');
|
tok = skip(tok, ',');
|
||||||
node->cas_old = assign(&tok, tok);
|
node->cas_old = assign(&tok, tok);
|
||||||
|
add_type(node->cas_old);
|
||||||
tok = skip(tok, ',');
|
tok = skip(tok, ',');
|
||||||
node->cas_new = assign(&tok, tok);
|
node->cas_new = assign(&tok, tok);
|
||||||
|
add_type(node->cas_new);
|
||||||
|
tok = skip(tok, ',');
|
||||||
|
/* weak = */ const_expr(&tok, tok);
|
||||||
|
tok = skip(tok, ',');
|
||||||
|
node->memorder = const_expr(&tok, tok);
|
||||||
|
tok = skip(tok, ',');
|
||||||
|
/* memorder_failure = */ const_expr(&tok, tok);
|
||||||
*rest = skip(tok, ')');
|
*rest = skip(tok, ')');
|
||||||
node->ty = node->cas_addr->ty->base;
|
node->ty = node->cas_addr->ty->base;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (kw == KW___ATOMIC_EXCHANGE) {
|
if (kw == KW___ATOMIC_EXCHANGE_N) {
|
||||||
Node *node = new_node(ND_EXCH, tok);
|
return ParseAtomic3(ND_EXCH_N, tok, rest);
|
||||||
tok = skip(tok->next, '(');
|
|
||||||
node->lhs = assign(&tok, tok);
|
|
||||||
add_type(node->lhs);
|
|
||||||
node->ty = node->lhs->ty->base;
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->rhs = assign(&tok, tok);
|
|
||||||
*rest = skip(tok, ')');
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
if (kw == KW___ATOMIC_LOAD) {
|
if (kw == KW___ATOMIC_LOAD) {
|
||||||
Node *node = new_node(ND_LOAD, tok);
|
return ParseAtomic3(ND_LOAD, tok, rest);
|
||||||
tok = skip(tok->next, '(');
|
|
||||||
node->lhs = assign(&tok, tok);
|
|
||||||
add_type(node->lhs);
|
|
||||||
node->ty = node->lhs->ty->base;
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->rhs = assign(&tok, tok);
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->memorder = const_expr(&tok, tok);
|
|
||||||
*rest = skip(tok, ')');
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
if (kw == KW___ATOMIC_STORE) {
|
if (kw == KW___ATOMIC_STORE) {
|
||||||
Node *node = new_node(ND_STORE, tok);
|
return ParseAtomic3(ND_STORE, tok, rest);
|
||||||
tok = skip(tok->next, '(');
|
|
||||||
node->lhs = assign(&tok, tok);
|
|
||||||
add_type(node->lhs);
|
|
||||||
node->ty = node->lhs->ty->base;
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->rhs = assign(&tok, tok);
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->memorder = const_expr(&tok, tok);
|
|
||||||
*rest = skip(tok, ')');
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
if (kw == KW___ATOMIC_TEST_AND_SET) {
|
if (kw == KW___ATOMIC_LOAD_N) {
|
||||||
Node *node = new_node(ND_TESTANDSETA, tok);
|
return ParseAtomic2(ND_LOAD_N, tok, rest);
|
||||||
tok = skip(tok->next, '(');
|
|
||||||
node->lhs = assign(&tok, tok);
|
|
||||||
add_type(node->lhs);
|
|
||||||
node->ty = node->lhs->ty->base;
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->memorder = const_expr(&tok, tok);
|
|
||||||
*rest = skip(tok, ')');
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
if (kw == KW___ATOMIC_CLEAR) {
|
if (kw == KW___ATOMIC_STORE_N) {
|
||||||
Node *node = new_node(ND_CLEAR, tok);
|
return ParseAtomic3(ND_STORE_N, tok, rest);
|
||||||
tok = skip(tok->next, '(');
|
|
||||||
node->lhs = assign(&tok, tok);
|
|
||||||
add_type(node->lhs);
|
|
||||||
node->ty = node->lhs->ty->base;
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->memorder = const_expr(&tok, tok);
|
|
||||||
*rest = skip(tok, ')');
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
if (kw == KW___ATOMIC_FETCH_ADD) {
|
if (kw == KW___ATOMIC_FETCH_ADD) {
|
||||||
Node *node = new_node(ND_FETCHADD, tok);
|
return ParseAtomic3(ND_FETCHADD, tok, rest);
|
||||||
tok = skip(tok->next, '(');
|
|
||||||
node->lhs = assign(&tok, tok);
|
|
||||||
add_type(node->lhs);
|
|
||||||
node->ty = node->lhs->ty->base;
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
node->rhs = assign(&tok, tok);
|
|
||||||
tok = skip(tok, ',');
|
|
||||||
const_expr(&tok, tok);
|
|
||||||
*rest = skip(tok, ')');
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
if (kw == KW___ATOMIC_SUB_FETCH) {
|
if (kw == KW___ATOMIC_FETCH_SUB) {
|
||||||
Node *node = new_node(ND_SUBFETCH, tok);
|
return ParseAtomic3(ND_FETCHSUB, tok, rest);
|
||||||
tok = skip(tok->next, '(');
|
}
|
||||||
node->lhs = assign(&tok, tok);
|
if (kw == KW___ATOMIC_FETCH_XOR) {
|
||||||
add_type(node->lhs);
|
return ParseAtomic3(ND_FETCHXOR, tok, rest);
|
||||||
node->ty = node->lhs->ty->base;
|
}
|
||||||
tok = skip(tok, ',');
|
if (kw == KW___ATOMIC_FETCH_AND) {
|
||||||
node->rhs = assign(&tok, tok);
|
return ParseAtomic3(ND_FETCHAND, tok, rest);
|
||||||
tok = skip(tok, ',');
|
}
|
||||||
const_expr(&tok, tok);
|
if (kw == KW___ATOMIC_FETCH_OR) {
|
||||||
*rest = skip(tok, ')');
|
return ParseAtomic3(ND_FETCHOR, tok, rest);
|
||||||
return node;
|
}
|
||||||
|
if (kw == KW___ATOMIC_TEST_AND_SET) {
|
||||||
|
return ParseAtomic2(ND_TESTANDSETA, tok, rest);
|
||||||
|
}
|
||||||
|
if (kw == KW___ATOMIC_CLEAR) {
|
||||||
|
return ParseAtomic2(ND_CLEAR, tok, rest);
|
||||||
}
|
}
|
||||||
if (kw == KW___SYNC_LOCK_TEST_AND_SET) {
|
if (kw == KW___SYNC_LOCK_TEST_AND_SET) {
|
||||||
|
// TODO(jart): delete me
|
||||||
Node *node = new_node(ND_TESTANDSET, tok);
|
Node *node = new_node(ND_TESTANDSET, tok);
|
||||||
tok = skip(tok->next, '(');
|
tok = skip(tok->next, '(');
|
||||||
node->lhs = assign(&tok, tok);
|
node->lhs = assign(&tok, tok);
|
||||||
|
@ -3337,6 +3325,7 @@ static Node *primary(Token **rest, Token *tok) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (kw == KW___SYNC_LOCK_RELEASE) {
|
if (kw == KW___SYNC_LOCK_RELEASE) {
|
||||||
|
// TODO(jart): delete me
|
||||||
Node *node = new_node(ND_RELEASE, tok);
|
Node *node = new_node(ND_RELEASE, tok);
|
||||||
tok = skip(tok->next, '(');
|
tok = skip(tok->next, '(');
|
||||||
node->lhs = assign(&tok, tok);
|
node->lhs = assign(&tok, tok);
|
||||||
|
|
21
third_party/chibicc/test/asm_test.c
vendored
21
third_party/chibicc/test/asm_test.c
vendored
|
@ -83,6 +83,24 @@ void testFlagOutputs(void) {
|
||||||
ASSERT(false, sf);
|
ASSERT(false, sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testAugmentLoByte_onlyModifiesLowerBits(void) {
|
||||||
|
int x, y;
|
||||||
|
x = 0x01020304;
|
||||||
|
y = 0x00000005;
|
||||||
|
asm("sub\t%b1,%b0" : "+q"(x) : "q"(y));
|
||||||
|
ASSERT(0x010203ff, x);
|
||||||
|
ASSERT(0x00000005, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testAugmentHiByte_onlyModifiesHigherBits(void) {
|
||||||
|
int x, y;
|
||||||
|
x = 0x01020304;
|
||||||
|
y = 0x00000400;
|
||||||
|
asm("sub\t%h1,%h0" : "+Q"(x) : "Q"(y));
|
||||||
|
ASSERT(0x0102ff04, x);
|
||||||
|
ASSERT(0x00000400, y);
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
ASSERT(50, asm_fn1());
|
ASSERT(50, asm_fn1());
|
||||||
ASSERT(55, asm_fn2());
|
ASSERT(55, asm_fn2());
|
||||||
|
@ -135,5 +153,8 @@ int main() {
|
||||||
ASSERT(1, !strcmp(p, "hello"));
|
ASSERT(1, !strcmp(p, "hello"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testAugmentLoByte_onlyModifiesLowerBits();
|
||||||
|
testAugmentHiByte_onlyModifiesHigherBits();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
41
third_party/chibicc/test/atomic_test.c
vendored
Normal file
41
third_party/chibicc/test/atomic_test.c
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include "third_party/chibicc/test/test.h"
|
||||||
|
|
||||||
|
_Atomic(int) lock;
|
||||||
|
|
||||||
|
main() {
|
||||||
|
int x;
|
||||||
|
|
||||||
|
ASSERT(0, __atomic_exchange_n(&lock, 1, __ATOMIC_SEQ_CST));
|
||||||
|
__atomic_load(&lock, &x, __ATOMIC_SEQ_CST);
|
||||||
|
ASSERT(1, x);
|
||||||
|
ASSERT(1, __atomic_exchange_n(&lock, 2, __ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(2, __atomic_exchange_n(&lock, 3, __ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(3, __atomic_load_n(&lock, __ATOMIC_SEQ_CST));
|
||||||
|
__atomic_store_n(&lock, 0, __ATOMIC_SEQ_CST);
|
||||||
|
ASSERT(0, __atomic_fetch_xor(&lock, 3, __ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(3, __atomic_fetch_xor(&lock, 1, __ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(2, __atomic_load_n(&lock, __ATOMIC_SEQ_CST));
|
||||||
|
|
||||||
|
// CAS success #1
|
||||||
|
x = 2;
|
||||||
|
ASSERT(1, __atomic_compare_exchange_n(&lock, &x, 3, 0, __ATOMIC_SEQ_CST,
|
||||||
|
__ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(2, x);
|
||||||
|
ASSERT(3, lock);
|
||||||
|
|
||||||
|
// CAS success #2
|
||||||
|
x = 3;
|
||||||
|
ASSERT(1, __atomic_compare_exchange_n(&lock, &x, 4, 0, __ATOMIC_SEQ_CST,
|
||||||
|
__ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(3, x);
|
||||||
|
ASSERT(4, lock);
|
||||||
|
|
||||||
|
// CAS fail
|
||||||
|
x = 3;
|
||||||
|
ASSERT(0, __atomic_compare_exchange_n(&lock, &x, 7, 0, __ATOMIC_SEQ_CST,
|
||||||
|
__ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(4, x);
|
||||||
|
ASSERT(4, lock);
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
11
third_party/chibicc/type.c
vendored
11
third_party/chibicc/type.c
vendored
|
@ -294,9 +294,16 @@ void add_type(Node *node) {
|
||||||
if (node->cas_old->ty->kind != TY_PTR)
|
if (node->cas_old->ty->kind != TY_PTR)
|
||||||
error_tok(node->cas_old->tok, "pointer expected");
|
error_tok(node->cas_old->tok, "pointer expected");
|
||||||
return;
|
return;
|
||||||
case ND_EXCH:
|
case ND_EXCH_N:
|
||||||
|
case ND_FETCHADD:
|
||||||
|
case ND_FETCHSUB:
|
||||||
|
case ND_FETCHXOR:
|
||||||
|
case ND_FETCHAND:
|
||||||
|
case ND_FETCHOR:
|
||||||
|
case ND_SUBFETCH:
|
||||||
if (node->lhs->ty->kind != TY_PTR)
|
if (node->lhs->ty->kind != TY_PTR)
|
||||||
error_tok(node->cas_addr->tok, "pointer expected");
|
error_tok(node->lhs->tok, "pointer expected");
|
||||||
|
node->rhs = new_cast(node->rhs, node->lhs->ty->base);
|
||||||
node->ty = node->lhs->ty->base;
|
node->ty = node->lhs->ty->base;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,9 +164,7 @@ struct ElfWriter *elfwriter_open(const char *path, int mode) {
|
||||||
struct ElfWriter *elf;
|
struct ElfWriter *elf;
|
||||||
CHECK_NOTNULL((elf = calloc(1, sizeof(struct ElfWriter))));
|
CHECK_NOTNULL((elf = calloc(1, sizeof(struct ElfWriter))));
|
||||||
CHECK_NOTNULL((elf->path = strdup(path)));
|
CHECK_NOTNULL((elf->path = strdup(path)));
|
||||||
CHECK_NE(-1, asprintf(&elf->tmppath, "%s.%d", elf->path, getpid()));
|
CHECK_NE(-1, (elf->fd = open(elf->path, O_CREAT | O_TRUNC | O_RDWR, mode)));
|
||||||
CHECK_NE(-1, (elf->fd = open(elf->tmppath,
|
|
||||||
O_CREAT | O_TRUNC | O_RDWR | O_EXCL, mode)));
|
|
||||||
CHECK_NE(-1, ftruncate(elf->fd, (elf->mapsize = FRAMESIZE)));
|
CHECK_NE(-1, ftruncate(elf->fd, (elf->mapsize = FRAMESIZE)));
|
||||||
CHECK_NE(MAP_FAILED, (elf->map = mmap((void *)(intptr_t)kFixedmapStart,
|
CHECK_NE(MAP_FAILED, (elf->map = mmap((void *)(intptr_t)kFixedmapStart,
|
||||||
elf->mapsize, PROT_READ | PROT_WRITE,
|
elf->mapsize, PROT_READ | PROT_WRITE,
|
||||||
|
@ -187,7 +185,6 @@ void elfwriter_close(struct ElfWriter *elf) {
|
||||||
CHECK_NE(-1, munmap(elf->map, elf->mapsize));
|
CHECK_NE(-1, munmap(elf->map, elf->mapsize));
|
||||||
CHECK_NE(-1, ftruncate(elf->fd, elf->wrote));
|
CHECK_NE(-1, ftruncate(elf->fd, elf->wrote));
|
||||||
CHECK_NE(-1, close(elf->fd));
|
CHECK_NE(-1, close(elf->fd));
|
||||||
CHECK_NE(-1, rename(elf->tmppath, elf->path));
|
|
||||||
freeinterner(elf->shstrtab);
|
freeinterner(elf->shstrtab);
|
||||||
freeinterner(elf->strtab);
|
freeinterner(elf->strtab);
|
||||||
free(elf->shdrs->p);
|
free(elf->shdrs->p);
|
||||||
|
|
|
@ -34,7 +34,6 @@ struct ElfWriterRela {
|
||||||
|
|
||||||
struct ElfWriter {
|
struct ElfWriter {
|
||||||
char *path;
|
char *path;
|
||||||
char *tmppath;
|
|
||||||
int fd;
|
int fd;
|
||||||
void *map;
|
void *map;
|
||||||
size_t mapsize;
|
size_t mapsize;
|
||||||
|
|
|
@ -833,11 +833,11 @@ static void DescribeAddress(char buf[40], uint32_t addr, uint16_t port) {
|
||||||
char *p;
|
char *p;
|
||||||
const char *s;
|
const char *s;
|
||||||
p = buf;
|
p = buf;
|
||||||
p = FormatUint64(p, (addr & 0xFF000000) >> 030), *p++ = '.';
|
p = FormatUint32(p, (addr & 0xFF000000) >> 030), *p++ = '.';
|
||||||
p = FormatUint64(p, (addr & 0x00FF0000) >> 020), *p++ = '.';
|
p = FormatUint32(p, (addr & 0x00FF0000) >> 020), *p++ = '.';
|
||||||
p = FormatUint64(p, (addr & 0x0000FF00) >> 010), *p++ = '.';
|
p = FormatUint32(p, (addr & 0x0000FF00) >> 010), *p++ = '.';
|
||||||
p = FormatUint64(p, (addr & 0x000000FF) >> 000), *p++ = ':';
|
p = FormatUint32(p, (addr & 0x000000FF) >> 000), *p++ = ':';
|
||||||
p = FormatUint64(p, port);
|
p = FormatUint32(p, port);
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
assert(p - buf < 40);
|
assert(p - buf < 40);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue