1
0
Fork 0
mirror of https://github.com/pnx/m16vm synced 2026-06-16 03:44:55 +02:00

asm: adding AST

This commit is contained in:
Henrik Hautakoski 2018-12-09 19:27:26 +01:00
parent 3122da08c9
commit aca8d7937e
No known key found for this signature in database
GPG key ID: 839F3A7EAFAEAFAA
2 changed files with 176 additions and 0 deletions

95
src/as/ast.c Normal file
View file

@ -0,0 +1,95 @@
#include <string.h>
#include <stdlib.h>
#include <vector.h>
#include <stdio.h>
#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");
}

81
src/as/ast.h Normal file
View file

@ -0,0 +1,81 @@
/* ast.h
*
* Copyright (C) 2018 Henrik Hautakoski <henrik.hautakoski@gmail.com>
*
* 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 <vector.h>
#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 */