aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assembler.c191
-rw-r--r--lib.c2
-rw-r--r--lib.h12
-rw-r--r--parser.h24
4 files changed, 109 insertions, 120 deletions
diff --git a/assembler.c b/assembler.c
index faf7bb3..87a672b 100644
--- a/assembler.c
+++ b/assembler.c
@@ -14,44 +14,6 @@ struct Label
u64 cur, next;
};
-/* First, the functions to call external utilities (badly written, I know). They
- * presume a filled asm_buffer. */
-
-void asm_write(const char *asm_name, vec_t *asm_buffer)
-{
- FILE *fp = fopen(asm_name, "w");
- fwrite(asm_buffer->data, asm_buffer->size, 1, fp);
- fclose(fp);
-}
-
-int asm_assemble(const char *asm_name, const char *objname)
-{
-#ifdef DEBUG
- char *format_str = "yasm -f elf64 -g dwarf2 -o %s %s";
-#else
- char *format_str = "yasm -f elf64 -o %s %s";
-#endif
- char command[snprintf(NULL, 0, format_str, objname, asm_name) + 1];
- sprintf(command, format_str, objname, asm_name);
- return system(command);
-}
-
-int asm_link(const char *objname, const char *outname)
-{
- char *format_str = "ld -o %s %s";
- char command[snprintf(NULL, 0, format_str, outname, objname) + 1];
- sprintf(command, format_str, outname, objname);
- return system(command);
-}
-
-int asm_compile(vec_t *asm_buffer, const char *asm_name, const char *objname,
- const char *outname)
-{
- asm_write(asm_name, asm_buffer);
- asm_assemble(asm_name, objname);
- return asm_link(objname, outname);
-}
-
// A table which translates brainfuck operations into generic assembly code (I
// love C's array indexing)
static const struct
@@ -85,16 +47,18 @@ i64 get_abs_label(u64, struct Label *, u64);
// and next items in given pointers.
void ast_ref_to_asm_label(u64, struct Label *, u64, i64 *, i64 *);
-// Write the initial boilerplate of the assembly file
-void asm_write_init(vec_t *asm_buffer);
-
-// Write the exit code boilerplate for the assembly file
-void asm_write_exit(vec_t *asm_buffer);
-
void asm_translate_nodes(vec_t *asm_buffer, struct PResult nodes,
const char *src_name)
{
- asm_write_init(asm_buffer);
+ vec_append_fmt(asm_buffer,
+ "section .bss\n"
+ " memory resb %d\n"
+ "section .text\n"
+ "global _start\n"
+ "_start:\n"
+ " mov r9, memory\n",
+ MEMORY_DEFAULT);
+
// First pass: Setup the ASM label array
struct Label labels[nodes.labels ? nodes.labels * 2 : 1];
if (nodes.labels)
@@ -110,55 +74,56 @@ void asm_translate_nodes(vec_t *asm_buffer, struct PResult nodes,
for (size_t i = 0; i < nodes.size; ++i)
{
node_t node = nodes.nodes[i];
- if (node.type == LIN || node.type == LOUT)
+ // Something we can compile with only the information at hand
+ if (!(node.type == LIN || node.type == LOUT))
{
- // Translate the node-relative addresses to assembly-label-relative
- // addresses
- i64 cur_asm_label = 0, next_asm_label = 0;
- ast_ref_to_asm_label(i, labels, nodes.labels * 2, &cur_asm_label,
- &next_asm_label);
- if (cur_asm_label == -1 || next_asm_label == -1)
- {
- print_error(
- src_name, node.row, node.col,
- "[ASSEMBLY ERROR]: Could not find label for current jump!\n");
- exit(1);
- }
-
- // Format labels
- char current_label[128], next_label[128];
-
- sprintf(current_label, ".L%lu", cur_asm_label);
- sprintf(next_label, ".L%lu", next_asm_label);
-
- // Setup format string for assembly jump code
- char *format_string = NULL;
- if (node.type == LIN)
- {
- format_string = "%s:\n"
- " cmp byte [r9], 0\n"
- " je %s\n";
- }
- else
- {
- format_string = "%s:\n"
- " cmp byte [r9], 0\n"
- " jne %s\n";
- }
- char formatted_string[snprintf(NULL, 0, format_string, current_label,
- next_label) +
- 1];
- snprintf(formatted_string, sizeof(formatted_string), format_string,
- current_label, next_label);
- vec_append(asm_buffer, formatted_string, sizeof(formatted_string) - 1);
+ // I love tables so goddamn much
+ vec_append(asm_buffer, table[node.type].str, table[node.type].len);
+ continue;
+ }
+
+ // NOTE: Must be a label
+
+ // Translate the node-relative addresses to assembly-label-relative
+ // addresses
+ i64 cur_asm_label = 0, next_asm_label = 0;
+ ast_ref_to_asm_label(i, labels, nodes.labels * 2, &cur_asm_label,
+ &next_asm_label);
+ if (cur_asm_label == -1 || next_asm_label == -1)
+ {
+ print_error(src_name, node.row, node.col,
+ "[ASSEMBLY ERROR]: Could not find label for current jump!\n");
+ exit(1);
+ }
+
+ // Format labels
+ char current_label[128], next_label[128];
+
+ sprintf(current_label, ".L%lu", cur_asm_label);
+ sprintf(next_label, ".L%lu", next_asm_label);
+
+ // Setup format string for assembly jump code
+ char *format_string = NULL;
+ if (node.type == LIN)
+ {
+ format_string = "%s:\n"
+ " cmp byte [r9], 0\n"
+ " je %s\n";
}
else
{
- // I love tables so goddamn much
- vec_append(asm_buffer, table[node.type].str, table[node.type].len);
+ format_string = "%s:\n"
+ " cmp byte [r9], 0\n"
+ " jne %s\n";
}
+ vec_append_fmt(asm_buffer, format_string, current_label, next_label);
}
- asm_write_exit(asm_buffer);
+
+ vec_append(asm_buffer,
+ " mov rax, 60\n"
+ " mov rdi, 0\n"
+ " syscall\n",
+ 37);
}
/* Implementations for throwaway functions */
@@ -180,27 +145,39 @@ void ast_ref_to_asm_label(u64 ref, struct Label *labels, u64 size, i64 *cur,
*next = get_abs_label(labels[*cur].next, labels, size);
}
-// Write the initial boilerplate of the assembly file
-void asm_write_init(vec_t *asm_buffer)
+/* The system calling code - not exactly pretty, but it is what it is. */
+
+void asm_write(const char *asm_name, vec_t *asm_buffer)
{
- const char format_string[] = "section .bss\n"
- " memory resb %d\n"
- "section .text\n"
- "global _start\n"
- "_start:\n"
- " mov r9, memory\n";
- char initial_assembly[snprintf(NULL, 0, format_string, MEMORY_DEFAULT) + 1];
- snprintf(initial_assembly, sizeof(initial_assembly), format_string,
- MEMORY_DEFAULT);
- vec_append(asm_buffer, initial_assembly, sizeof(initial_assembly) - 1);
+ FILE *fp = fopen(asm_name, "w");
+ fwrite(asm_buffer->data, asm_buffer->size, 1, fp);
+ fclose(fp);
}
-// Write the exit code for the assembly file
-void asm_write_exit(vec_t *asm_buffer)
+int asm_assemble(const char *asm_name, const char *objname)
{
- vec_append(asm_buffer,
- " mov rax, 60\n"
- " mov rdi, 0\n"
- " syscall\n",
- 37);
+#ifdef DEBUG
+ char *format_str = "yasm -f elf64 -g dwarf2 -o %s %s";
+#else
+ char *format_str = "yasm -f elf64 -o %s %s";
+#endif
+ char command[SIZE_FMT(format_str, objname, asm_name) + 1];
+ sprintf(command, format_str, objname, asm_name);
+ return system(command);
+}
+
+int asm_link(const char *objname, const char *outname)
+{
+ char *format_str = "ld -o %s %s";
+ char command[SIZE_FMT(format_str, outname, objname) + 1];
+ sprintf(command, format_str, outname, objname);
+ return system(command);
+}
+
+int asm_compile(vec_t *asm_buffer, const char *asm_name, const char *objname,
+ const char *outname)
+{
+ asm_write(asm_name, asm_buffer);
+ asm_assemble(asm_name, objname);
+ return asm_link(objname, outname);
}
diff --git a/lib.c b/lib.c
index 0c32c3b..3be6e0a 100644
--- a/lib.c
+++ b/lib.c
@@ -67,7 +67,7 @@ char *fread_all(FILE *fp)
return buffer.data;
}
-void vec_append(vec_t *vec, void *ptr, u64 size)
+void vec_append(vec_t *vec, const void *const ptr, u64 size)
{
vec_ensure_free(vec, size);
memcpy(vec->data + vec->size, ptr, size);
diff --git a/lib.h b/lib.h
index 4fb390e..9d964f7 100644
--- a/lib.h
+++ b/lib.h
@@ -26,6 +26,8 @@ char *fread_all(FILE *fp);
void print_error(const char *handle, size_t row, size_t column,
const char *reason);
+#define SIZE_FMT(FMT, ...) (snprintf(NULL, 0, (FMT), __VA_ARGS__))
+
typedef struct Buffer
{
const char *name;
@@ -41,9 +43,17 @@ typedef struct
u8 *data;
} vec_t;
-void vec_append(vec_t *vec, void *ptr, u64 size);
+void vec_append(vec_t *vec, const void *const ptr, u64 size);
void vec_ensure(vec_t *vec, u64 abs_size);
void vec_ensure_free(vec_t *vec, u64 rel_size);
void vec_free(vec_t *vec);
+#define vec_append_fmt(VEC, FMT, ...) \
+ do \
+ { \
+ char f[SIZE_FMT(FMT, __VA_ARGS__) + 1]; \
+ snprintf(f, sizeof(f), (FMT), __VA_ARGS__); \
+ vec_append((VEC), f, sizeof(f) - 1); \
+ } while (0)
+
#endif
diff --git a/parser.h b/parser.h
index 1b3718e..e78f116 100644
--- a/parser.h
+++ b/parser.h
@@ -3,20 +3,22 @@
#include "./lib.h"
+typedef enum
+{
+ NEXT = 0,
+ PREV,
+ INC,
+ DEC,
+ OUT,
+ READ,
+ LIN,
+ LOUT
+} node_type_t;
+
typedef struct
{
size_t col, row;
- enum
- {
- NEXT = 0,
- PREV,
- INC,
- DEC,
- OUT,
- READ,
- LIN,
- LOUT
- } type;
+ node_type_t type;
int loop_ref;
} node_t;