diff options
-rwxr-xr-x | .bin/jrp.c | 303 |
1 files changed, 163 insertions, 140 deletions
diff --git a/.bin/jrp.c b/.bin/jrp.c index 0c6b18f1..f3205924 100755 --- a/.bin/jrp.c +++ b/.bin/jrp.c @@ -1,5 +1,5 @@ #if 0 -exec cc -Wall -Wextra $@ $0 -ledit -o $(dirname $0)/jrp +exec cc -Wall -Wextra -pedantic $@ $0 -ledit -o $(dirname $0)/jrp #endif #include <err.h> @@ -11,220 +11,243 @@ exec cc -Wall -Wextra $@ $0 -ledit -o $(dirname $0)/jrp #include <sysexits.h> #include <unistd.h> -typedef unsigned long long op; -typedef long long value; -typedef unsigned long long uvalue; -typedef value *(*fptr)(value *); +typedef unsigned long qop; +typedef unsigned int dop; -static char *fmt_bin(value val) { - static char buf[sizeof(value) * 8 + 1]; +typedef long qvalue; +typedef int dvalue; +typedef unsigned long uvalue; + +typedef qvalue *(*jitFn)(qvalue *); +typedef void (*rtFn)(qvalue); + +static char *formatBin(qvalue val) { + static char buf[sizeof(qvalue) * 8 + 1]; uvalue uval = val; - int i = sizeof(buf); + size_t i = sizeof(buf); do { buf[--i] = '0' + (uval & 1); } while (uval >>= 1); return &buf[i]; } -static void rt_print_ascii(value val) { +static void rtPrintAscii(qvalue val) { printf("%c\n", (char)val); } -static void rt_print_bin(value val) { - printf("%s\n", fmt_bin(val)); -} -static void rt_print_oct(value val) { - printf("%llo\n", val); -} -static void rt_print_dec(value val) { - printf("%lld\n", val); -} -static void rt_print_hex(value val) { - printf("%llx\n", val); -} - -enum { - HOP_NOP = 0x90666666, // nop - HOP_DROP = 0x9066665f, // pop rdi - HOP_DUP = 0x90666657, // push rdi - HOP_SWAP = 0x243c8748, // xchg rdi, [rsp] - HOP_NEG = 0x90dff748, // neg rdi - HOP_ADD = 0xc7014858, // pop rax; add rdi, rax - HOP_QUO = 0x90c78948, // mov rdi, rax - HOP_REM = 0x90d78948, // mov rdi, rdx - HOP_NOT = 0x90d7f748, // not rdi - HOP_AND = 0xc7214858, // pop rax; and rdi, rax - HOP_OR = 0xc7094858, // pop rax; or rdi, rax - HOP_XOR = 0xc7314858, // pop rax; xor rdi, rax -}; - -enum { - FOP_PROL = 0x5ffc8948e5894855, // push rbp; mov rbp, rsp; mov rsp, rdi; pop rdi - FOP_EPIL = 0x5dec8948e0894857, // push rdi; mov rax, rsp; mov rsp, rbp; pop rbp - FOP_RET = 0x90666690666666c3, // ret - FOP_CRT = 0xb848906666e58748, // xchg rsp, rbp; mov rax, strict qword 0 - FOP_CALL = 0x90665fe58748d0ff, // call rax; xchg rsp, rbp; pop rdi - FOP_PUSH = 0xbf48909066666657, // push rdi; mov rdi, strict qword 0 - FOP_SUB = 0x9066665f243c2948, // sub [rsp], rdi; pop rdi - FOP_MUL = 0x906666f8af0f4858, // pop rax; imul rdi, rax - FOP_DIV = 0x9066fff748994858, // pop rax; cqo; idiv rdi - FOP_SHL = 0x5f2424d348f98948, // mov rcx, rdi; shl qword [rsp], cl; pop rdi - FOP_SHR = 0x5f242cd348f98948, // mov rcx, rdi; shr qword [rsp], cl; pop rdi -}; - -static int page; +static void rtPrintBin(qvalue val) { + printf("%s\n", formatBin(val)); +} +static void rtPrintOct(qvalue val) { + printf("%lo\n", val); +} +static void rtPrintDec(qvalue val) { + printf("%ld\n", val); +} +static void rtPrintHex(qvalue val) { + printf("%lx\n", val); +} + +static const dop DOP_NOP = 0x90666666; // nop +static const dop DOP_PUSH = 0xc7c74857; // push rdi; mov rdi, strict dword 0 +static const dop DOP_DROP = 0x9066665f; // pop rdi +static const dop DOP_DUP = 0x90666657; // push rdi +static const dop DOP_SWAP = 0x243c8748; // xchg rdi, [rsp] +static const dop DOP_NEG = 0x90dff748; // neg rdi +static const dop DOP_ADD = 0xc7014858; // pop rax; add rdi, rax +static const dop DOP_QUO = 0x90c78948; // mov rdi, rax +static const dop DOP_REM = 0x90d78948; // mov rdi, rdx +static const dop DOP_NOT = 0x90d7f748; // not rdi +static const dop DOP_AND = 0xc7214858; // pop rax; and rdi, rax +static const dop DOP_OR = 0xc7094858; // pop rax; or rdi, rax +static const dop DOP_XOR = 0xc7314858; // pop rax; xor rdi, rax + +static const qop QOP_PROL = 0x5ffc8948e5894855; // push rbp; mov rbp, rsp; mov rsp, rdi; pop rdi +static const qop QOP_EPIL = 0x5dec8948e0894857; // push rdi; mov rax, rsp; mov rsp, rbp; pop rbp +static const qop QOP_RET = 0x90666690666666c3; // ret +static const qop QOP_CRT = 0xb848906666e58748; // xchg rsp, rbp; mov rax, strict qword 0 +static const qop QOP_CALL = 0x90665fe58748d0ff; // call rax; xchg rsp, rbp; pop rdi +static const qop QOP_PUSH = 0xbf48909066666657; // push rdi; mov rdi, strict qword 0 +static const qop QOP_SUB = 0x9066665f243c2948; // sub [rsp], rdi; pop rdi +static const qop QOP_MUL = 0x906666f8af0f4858; // pop rax; imul rdi, rax +static const qop QOP_DIV = 0x9066fff748994858; // pop rax; cqo; idiv rdi +static const qop QOP_SHL = 0x5f2424d348f98948; // mov rcx, rdi; shl qword [rsp], cl; pop rdi +static const qop QOP_SHR = 0x5f242cd348f98948; // mov rcx, rdi; shr qword [rsp], cl; pop rdi static int radix = 10; static struct { - value *base; - value *limit; - value *ptr; -} stack; + qop *base; + qop *ptr; + dop dop; +} code; static struct { - op *base; - op *ptr; - op hop; -} code; + qvalue *base; + qvalue *limit; + qvalue *ptr; +} stack; -static void jit_hop(op hop) { - if (code.hop) { - *code.ptr++ = hop << 32 | code.hop; - code.hop = 0; +static void jitDop(dop op) { + if (code.dop) { + *code.ptr++ = (qop)op << 32 | code.dop; + code.dop = 0; } else { - code.hop = hop; + code.dop = op; } } -static void jit_fop(op fop) { - if (code.hop) jit_hop(HOP_NOP); - *code.ptr++ = fop; +static void jitQop(qop op) { + if (code.dop) jitDop(DOP_NOP); + *code.ptr++ = op; } -static void jit_push(value imm) { - jit_fop(FOP_PUSH); - jit_fop((op)imm); +static void jitPush(qvalue imm) { + if ((dvalue)imm == imm) { + jitDop(DOP_PUSH); + jitDop((dop)imm); + } else { + jitQop(QOP_PUSH); + jitQop((qop)imm); + } } -static void jit_call(void (*fn)(value)) { - jit_fop(FOP_CRT); - jit_fop((op)fn); - jit_fop(FOP_CALL); +static void jitCall(rtFn fn) { + jitQop(QOP_CRT); + jitQop((qop)fn); + jitQop(QOP_CALL); } -static void jit(const char *src) { - int error; - +static void jitBegin(void) { code.ptr = code.base; - jit_fop(FOP_PROL); + jitQop(QOP_PROL); +} + +static void jitEnd(void) { + jitQop(QOP_EPIL); + jitQop(QOP_RET); +} +static void jitInit(void) { + code.base = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (code.base == MAP_FAILED) err(EX_OSERR, "mmap"); +} + +static void stackInit(void) { + stack.base = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (stack.base == MAP_FAILED) err(EX_OSERR, "mmap"); + stack.limit = stack.base + getpagesize() / sizeof(qvalue); + stack.ptr = stack.limit - 1; +} + +static void jitExec(void) { + int error; + error = mprotect(code.base, getpagesize(), PROT_READ | PROT_EXEC); + if (error) err(EX_OSERR, "mprotect"); + stack.ptr = ((jitFn)code.base)(stack.ptr); + error = mprotect(code.base, getpagesize(), PROT_READ | PROT_WRITE); + if (error) err(EX_OSERR, "mprotect"); +} + +static void jitSrc(const char *src) { bool quote = false; while (*src) { if (quote) { - jit_push(*src++); + jitPush(*src++); quote = false; continue; } + switch (*src) { case ' ': break; - case 39: quote = true; break; - case 'b': radix = 2; break; - case 'o': radix = 8; break; - case 'd': radix = 10; break; - case 'x': radix = 16; break; - case ';': jit_hop(HOP_DROP); break; - case ':': jit_hop(HOP_DUP); break; - case 92: jit_hop(HOP_SWAP); break; - case '_': jit_hop(HOP_NEG); break; - case '+': jit_hop(HOP_ADD); break; - case '-': jit_fop(FOP_SUB); break; - case '*': jit_fop(FOP_MUL); break; - case '/': jit_fop(FOP_DIV); jit_hop(HOP_QUO); break; - case '%': jit_fop(FOP_DIV); jit_hop(HOP_REM); break; - case '~': jit_hop(HOP_NOT); break; - case '&': jit_hop(HOP_AND); break; - case '|': jit_hop(HOP_OR); break; - case '^': jit_hop(HOP_XOR); break; - case '<': jit_fop(FOP_SHL); break; - case '>': jit_fop(FOP_SHR); break; - case ',': jit_call(rt_print_ascii); break; + case 39: quote = true; break; + case 'B': radix = 2; break; + case 'O': radix = 8; break; + case 'D': radix = 10; break; + case 'X': radix = 16; break; + case ';': jitDop(DOP_DROP); break; + case ':': jitDop(DOP_DUP); break; + case 92: jitDop(DOP_SWAP); break; + case '_': jitDop(DOP_NEG); break; + case '+': jitDop(DOP_ADD); break; + case '-': jitQop(QOP_SUB); break; + case '*': jitQop(QOP_MUL); break; + case '/': jitQop(QOP_DIV); jitDop(DOP_QUO); break; + case '%': jitQop(QOP_DIV); jitDop(DOP_REM); break; + case '~': jitDop(DOP_NOT); break; + case '&': jitDop(DOP_AND); break; + case '|': jitDop(DOP_OR); break; + case '^': jitDop(DOP_XOR); break; + case '<': jitQop(QOP_SHL); break; + case '>': jitQop(QOP_SHR); break; + case ',': jitCall(rtPrintAscii); break; case '.': switch (radix) { - case 2: jit_call(rt_print_bin); break; - case 8: jit_call(rt_print_oct); break; - case 10: jit_call(rt_print_dec); break; - case 16: jit_call(rt_print_hex); break; + case 2: jitCall(rtPrintBin); break; + case 8: jitCall(rtPrintOct); break; + case 10: jitCall(rtPrintDec); break; + case 16: jitCall(rtPrintHex); break; } break; + default: { char *rest; - value val = strtoll(src, &rest, radix); + qvalue val = strtol(src, &rest, radix); if (rest != src) { src = rest; - jit_push(val); + jitPush(val); continue; } } } + src++; } - - jit_fop(FOP_EPIL); - jit_fop(FOP_RET); - - error = mprotect(code.base, page, PROT_READ | PROT_EXEC); - if (error) err(EX_OSERR, "mprotect"); - - stack.ptr = ((fptr)code.base)(stack.ptr); - - error = mprotect(code.base, page, PROT_READ | PROT_WRITE); - if (error) err(EX_OSERR, "mprotect"); } static char *prompt(EditLine *el __attribute((unused))) { static char buf[4096]; - char *bp = buf; - for (value *sp = stack.limit - 1; sp >= stack.ptr; --sp) { - size_t len = sizeof(buf) - (buf - bp) - 2; + char *bufPtr = buf; + for (qvalue *stackPtr = stack.limit - 1; stackPtr >= stack.ptr; --stackPtr) { + size_t bufLen = sizeof(buf) - (buf - bufPtr) - 2; switch (radix) { - case 2: bp += snprintf(bp, len, " %s", fmt_bin(*sp)); break; - case 8: bp += snprintf(bp, len, " %llo", *sp); break; - case 10: bp += snprintf(bp, len, " %lld", *sp); break; - case 16: bp += snprintf(bp, len, " %llx", *sp); break; + case 2: bufPtr += snprintf(bufPtr, bufLen, " %s", formatBin(*stackPtr)); break; + case 8: bufPtr += snprintf(bufPtr, bufLen, " %lo", *stackPtr); break; + case 10: bufPtr += snprintf(bufPtr, bufLen, " %ld", *stackPtr); break; + case 16: bufPtr += snprintf(bufPtr, bufLen, " %lx", *stackPtr); break; } } buf[0] = '['; - *bp++ = ']'; - *bp++ = ' '; - *bp = 0; + *bufPtr++ = ']'; + *bufPtr++ = ' '; + *bufPtr = 0; return buf; } int main(int argc, char *argv[]) { - page = getpagesize(); - - code.base = mmap(0, page, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); - if (code.base == MAP_FAILED) err(EX_OSERR, "mmap"); - - stack.base = mmap(0, page, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); - if (stack.base == MAP_FAILED) err(EX_OSERR, "mmap"); - stack.limit = stack.base + page / sizeof(value); - stack.ptr = stack.limit - 1; + jitInit(); + stackInit(); if (argc > 1) { + jitBegin(); for (int i = 1; i < argc; ++i) - jit(argv[i]); + jitSrc(argv[i]); + jitEnd(); + jitExec(); return EX_OK; } EditLine *el = el_init(argv[0], stdin, stdout, stderr); el_set(el, EL_PROMPT, prompt); - el_set(el, EL_SIGNAL, 1); + el_set(el, EL_SIGNAL, true); for (;;) { int count; const char *line = el_gets(el, &count); if (count < 0) err(EX_IOERR, "el_gets"); if (!line) break; - jit(line); + + jitBegin(); + jitSrc(line); + jitEnd(); + jitExec(); } el_end(el); |