aboutsummaryrefslogtreecommitdiff
path: root/assembler.c
diff options
context:
space:
mode:
Diffstat (limited to 'assembler.c')
-rw-r--r--assembler.c191
1 files changed, 84 insertions, 107 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);
}