From d9c8ec257f374172923fd2174364df815c71899a Mon Sep 17 00:00:00 2001 From: jakob Date: Sun, 19 Mar 2017 12:06:21 -0400 Subject: Added basic loop optimizations. --- Makefile | 2 +- skullfuck.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index ac2a6ff..fdff5d7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC := gcc CFLAGS = -Wall -Os -std=c99 -pedantic -MACROS = -D$(shell uname -m) -DAS=\"$(shell which as)\" -DLD=\"$(shell which ld)\" +MACROS = -D__$(shell uname -m)__ -DAS=\"$(shell which as)\" -DLD=\"$(shell which ld)\" all: skullfuck diff --git a/skullfuck.c b/skullfuck.c index 47cb772..a8de668 100644 --- a/skullfuck.c +++ b/skullfuck.c @@ -25,7 +25,7 @@ #include -#if defined(x86_64) +#if defined(__x86_64__) #define ARCH "x86_64" #define OS "Linux" #define INC_DATA_PTR "\tincq %rsi\n" @@ -36,6 +36,7 @@ #define ADD_DATA "\taddb $0x%x, (%%rsi)\n" #define DEC_DATA "\tdecb (%rsi)\n" #define SUB_DATA "\tsubb $0x%x, (%%rsi)\n" +#define ZERO_DATA "\tmovb $0x00, (%rsi)\n" #define PRINT_DATA "\tmovq $0x01, %rax\n" \ "\tmovq $0x01, %rdi\n" \ "\tsyscall\n" @@ -58,7 +59,7 @@ #define EXIT "\tmovq $0x3c, %rax\n" \ "\tmovq $0x00, %rdi\n" \ "\tsyscall\n" -#elif defined(i686) +#elif defined(__i686__) #define ARCH "i686" #define OS "Linux" #define INC_DATA_PTR "\tincl %ecx\n" @@ -69,6 +70,7 @@ #define ADD_DATA "\taddb $0x%x, (%%ecx)\n" #define DEC_DATA "\tdecb (%ecx)\n" #define SUB_DATA "\tsubb $0x%x, (%%ecx)\n" +#define ZERO_DATA "\tmovb $0x00, (%ecx)\n" #define PRINT_DATA "\tmovl $0x04, %eax\n" \ "\tmovl $0x01, %ebx\n" \ "\tint $0x80\n" @@ -116,12 +118,14 @@ struct loop_stack { int _stack_index; }; + /* Pushes `n` onto the stack specified by `s`. */ static void push_loop_index(struct loop_stack *s, int n) { s->_mem[s->_stack_index] = n; s->_stack_index++; } + /* Pops the top of `s` off and returns it. */ static int pop_loop_index(struct loop_stack *s) { s->_stack_index--; @@ -129,6 +133,30 @@ static int pop_loop_index(struct loop_stack *s) { } +/* Loop optimizations. */ +enum { + NONE, + LOOP_EMPTY, + LOOP_ZERO, +}; + + +/* Optimization subroutine which detects common loop patterns, such as + `[-]`, increments the `in` pointer to beyond them, and returns the + identity of the pattern. */ +static int optimize_loops(char **in) { + if (*(*in + 1) == '-' && *(*in + 2) == ']') { + *in += 2; + return LOOP_ZERO; + } + if (*(*in + 1) == ']') { + *in += 1; + return LOOP_EMPTY; + } + return NONE; +} + + /* Minor optimization subroutine. Increments the `in` pointer to beyond the collection of adjacent `op` characters, and returns the number of operations counted. */ @@ -144,7 +172,7 @@ static int reduce(char **in, char op) { instructions and writes them to `out`. `in` is expected to be null-terminated. */ static void write_instructions(FILE *out, char *in) { - int next_loop = 0, cur_loop = 0, op_count; + int next_loop = 0, cur_loop = 0, op_count, optimization; struct loop_stack *loops = calloc(sizeof(struct loop_stack), 1); for (char *cur = in; *cur != '\0'; cur++) { @@ -188,11 +216,16 @@ static void write_instructions(FILE *out, char *in) { fputs(READ_DATA, out); break; case '[': - cur_loop = next_loop; - push_loop_index(loops, next_loop++); - fprintf(out, "S%d:\n", cur_loop); - fputs(DATA_IS_ZERO, out); - fprintf(out, JMP_END, cur_loop); + optimization = optimize_loops(&cur); + if (optimization == LOOP_ZERO) { + fputs(ZERO_DATA, out); + } else if (optimization == NONE) { + cur_loop = next_loop; + push_loop_index(loops, next_loop++); + fprintf(out, "S%d:\n", cur_loop); + fputs(DATA_IS_ZERO, out); + fprintf(out, JMP_END, cur_loop); + } break; case ']': cur_loop = pop_loop_index(loops); -- cgit v1.3