From aca8d7937e1ebb3655f5b85865f1f0bb602e605b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 9 Dec 2018 19:27:26 +0100 Subject: [PATCH] asm: adding AST --- src/as/ast.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/as/ast.h | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 src/as/ast.c create mode 100644 src/as/ast.h diff --git a/src/as/ast.c b/src/as/ast.c new file mode 100644 index 0000000..392517e --- /dev/null +++ b/src/as/ast.c @@ -0,0 +1,95 @@ + +#include +#include +#include +#include +#include "ast.h" + +void ast_init(struct ast* ast) { + + vector_init(&ast->instr, 16 * sizeof(struct ast)); + vector_init(&ast->labels, 16 * sizeof(char**)); + ast->symbols = symtab_init(); +} + +void ast_free(struct ast* ast) { + + int i; + + // Free all label strings + for(int i = 0; i < ast->labels.size; i++) { + char *ptr = *((char**) ast->labels.base + i); + free(ptr); + } + vector_destory(&ast->labels); + vector_destory(&ast->instr); + symtab_free(ast->symbols); +} + +void ast_instr(struct ast* ast, uint8_t opcode) { + + struct ast_instr instr = { 0 }; + + instr.opcode = opcode; + vector_append(&ast->instr, &instr, sizeof(struct ast_instr)); +} + +void ast_instr_operand(struct ast* ast, enum ast_datatype type, void* value) { + + struct ast_instr *instr; + + if (ast->instr.size < 1) + return; + + // Fetch latest instruction. + instr = ast->instr.base + (ast->instr.size - sizeof(struct ast_instr)); + + if (instr->n_operands < 3) { + struct ast_instr_operand *n = instr->operands + instr->n_operands; + + n->type = type; + if (n->type == DATATYPE_STRING) { + n->s = strdup(value); + vector_append(&ast->labels, &n->s, sizeof(char**)); + } else { + n->r = ((intptr_t) value) & 0xFF; + } + + instr->n_operands++; + } +} + +void ast_location(struct ast* ast, const char *label, uint16_t loc) { + + symtab_set(ast->symbols, label, loc); +} + +void ast_print(struct ast* ast) { + + printf("{\n"); + + for(int i = 0; i < ast->instr.size; i += sizeof(struct ast_instr)) { + struct ast_instr *instr = ast->instr.base + i; + + printf("\topcode: %u", instr->opcode); + for(int j = 0; j < instr->n_operands; j++) { + struct ast_instr_operand *op = instr->operands + j; + printf(", operand%i: ", j); + switch(op->type) { + case DATATYPE_REGISTER : + printf("%u (reg)", op->r); + break; + case DATATYPE_NUMBER : + printf("%i (num)", op->n); + break; + case DATATYPE_STRING : + printf("%s (string)", op->s); + break; + } + } + printf("\n"); + } + + printf("}\n"); + +} diff --git a/src/as/ast.h b/src/as/ast.h new file mode 100644 index 0000000..6c23334 --- /dev/null +++ b/src/as/ast.h @@ -0,0 +1,81 @@ +/* ast.h + * + * Copyright (C) 2018 Henrik Hautakoski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#ifndef ASM_AST_H +#define ASM_AST_H + +#include +#include "symtab.h" + +// All datatypes in the language. +enum ast_datatype { + DATATYPE_NONE = 0, // Not an actual type. + DATATYPE_REGISTER, // 4 bit unsigned. + DATATYPE_NUMBER, // 8 bit signed. + DATATYPE_STRING +}; + +// Struct to represent a single operand to a instruction. +struct ast_instr_operand { + enum ast_datatype type; + union { + uint8_t r; + int8_t n; + uint16_t addr; + const char *s; + }; +}; + +// Struct to represent a single instruction. +struct ast_instr { + uint8_t opcode; + uint8_t n_operands; + struct ast_instr_operand operands[3]; +}; + +// Structure to represent a program. +struct ast { + + // List of instructions. + struct vector instr; + + // List for storing label pointers (so we can free) + struct vector labels; + + // Symbol table with label - location mapping. + symtab_t *symbols; +}; + +void ast_init(struct ast* ast); + +void ast_free(struct ast* ast); + +// Add an instruction +void ast_instr(struct ast* ast, uint8_t opcode); + +// Add an operand to the latest instruction. +//void ast_instr_operand(struct ast* ast, const struct ast_instr_operand* op); +void ast_instr_operand(struct ast* ast, enum ast_datatype type, void* value); + +void ast_location(struct ast* ast, const char *label, uint16_t loc); + +// For debugging :) +void ast_print(struct ast* ast); + +#endif /* ASM_AST_H */