From 3bd9e4c1ad1d4d4d58009c9a0f1474071aa8d665 Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Sat, 1 Feb 2020 19:26:57 -0500 Subject: [PATCH] Added C prototype for cc_aarch64 --- .../cc_aarch64/.gitignore | 21 + stage2/High_level_prototypes/cc_aarch64/cc.c | 61 + stage2/High_level_prototypes/cc_aarch64/cc.h | 81 ++ .../cc_aarch64/cc_core.c | 1172 +++++++++++++++++ .../cc_aarch64/cc_reader.c | 218 +++ .../cc_aarch64/cc_strings.c | 171 +++ .../cc_aarch64/cc_types.c | 260 ++++ .../cc_aarch64/functions/file_print.c | 27 + .../cc_aarch64/functions/match.c | 35 + .../cc_aarch64/functions/numerate_number.c | 148 +++ .../cc_aarch64/functions/string.c | 61 + .../cc_aarch64/gcc_req.h | 21 + .../High_level_prototypes/cc_aarch64/makefile | 39 + 13 files changed, 2315 insertions(+) create mode 100644 stage2/High_level_prototypes/cc_aarch64/.gitignore create mode 100644 stage2/High_level_prototypes/cc_aarch64/cc.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/cc.h create mode 100644 stage2/High_level_prototypes/cc_aarch64/cc_core.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/cc_reader.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/cc_strings.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/cc_types.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/functions/file_print.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/functions/match.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/functions/numerate_number.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/functions/string.c create mode 100644 stage2/High_level_prototypes/cc_aarch64/gcc_req.h create mode 100644 stage2/High_level_prototypes/cc_aarch64/makefile diff --git a/stage2/High_level_prototypes/cc_aarch64/.gitignore b/stage2/High_level_prototypes/cc_aarch64/.gitignore new file mode 100644 index 0000000..85eac6c --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/.gitignore @@ -0,0 +1,21 @@ +## Copyright (C) 2020 Jeremiah Orians +## This file is part of stage0. +## +## stage0 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 3 of the License, or +## (at your option) any later version. +## +## stage0 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 stage0. If not, see . + + +# The compiled C compiler +cc_aarch64 +# temp files +*.tmp diff --git a/stage2/High_level_prototypes/cc_aarch64/cc.c b/stage2/High_level_prototypes/cc_aarch64/cc.c new file mode 100644 index 0000000..a6db429 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/cc.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ +#include +#include +#include +#include"cc.h" + +/* The core functions */ +void initialize_types(); +struct token_list* read_all_tokens(FILE* a, struct token_list* current, char* filename); +struct token_list* reverse_list(struct token_list* head); +struct token_list* program(); +void recursive_output(struct token_list* i, FILE* out); +int match(char* a, char* b); +void file_print(char* s, FILE* f); +char* parse_string(char* string); + +int main() +{ + hold_string = calloc(MAX_STRING, sizeof(char)); + FILE* in = fopen("tape_01", "r"); + FILE* destination_file = fopen("tape_02", "w"); + + global_token = read_all_tokens(in, global_token, "tape_01"); + + if(NULL == global_token) + { + file_print("Either no input files were given or they were empty\n", stderr); + exit(EXIT_FAILURE); + } + global_token = reverse_list(global_token); + + initialize_types(); + reset_hold_string(); + struct token_list* output_list = program(); + + /* Output the program we have compiled */ + file_print("\n# Core program\n", destination_file); + recursive_output(output_list, destination_file); + /* file_print("\n:ELF_data\n", destination_file); */ + file_print("\n# Program global variables\n", destination_file); + recursive_output(globals_list, destination_file); + file_print("\n# Program strings\n", destination_file); + recursive_output(strings_list, destination_file); + file_print("\n:ELF_end\n", destination_file); + return EXIT_SUCCESS; +} diff --git a/stage2/High_level_prototypes/cc_aarch64/cc.h b/stage2/High_level_prototypes/cc_aarch64/cc.h new file mode 100644 index 0000000..9e74146 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/cc.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ + +#include +#include +#include + +#define MAX_STRING 4096 +// CONSTANT MAX_STRING 4096 +#define FALSE 0 +// CONSTANT FALSE 0 +#define TRUE 1 +// CONSTANT TRUE 1 + +void file_print(char* s, FILE* f); +int match(char* a, char* b); +char* copy_string(char* target, char* source); +void reset_hold_string(); +int in_set(int c, char* s); + +struct type +{ + struct type* next; + int size; + int offset; + struct type* indirect; + struct type* members; + struct type* type; + char* name; +}; + +struct token_list +{ + struct token_list* next; + union + { + struct token_list* locals; + struct token_list* prev; + }; + char* s; + union + { + struct type* type; + char* filename; + }; + union + { + struct token_list* arguments; + int depth; + int linenumber; + }; +}; + +/* What types we have */ +struct type* global_types; +struct type* prim_types; + +/* What we are currently working on */ +struct token_list* global_token; + +/* Output reorder collections*/ +struct token_list* strings_list; +struct token_list* globals_list; + +/* Make our string collection more efficient */ +char* hold_string; +int string_index; diff --git a/stage2/High_level_prototypes/cc_aarch64/cc_core.c b/stage2/High_level_prototypes/cc_aarch64/cc_core.c new file mode 100644 index 0000000..7b1f117 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/cc_core.c @@ -0,0 +1,1172 @@ +/* Copyright (C) 2016 Jeremiah Orians + * Copyright (C) 2018 Jan (janneke) Nieuwenhuizen + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ + +#include "cc.h" +#include "gcc_req.h" +#include + +/* Global lists */ +struct token_list* global_symbol_list; +struct token_list* global_function_list; +struct token_list* global_constant_list; + +/* Core lists for this file */ +struct token_list* function; +struct token_list* out; + +/* What we are currently working on */ +struct type* current_target; +char* break_target_head; +char* break_target_func; +char* break_target_num; +struct token_list* break_frame; +int current_count; +struct type* last_type; +int Address_of; + +/* Imported functions */ +char* parse_string(char* string); +int escape_lookup(char* c); +char* numerate_number(int a); + + +struct token_list* emit(char *s, struct token_list* head) +{ + struct token_list* t = calloc(1, sizeof(struct token_list)); + t->next = head; + t->s = s; + return t; +} + +void emit_out(char* s) +{ + out = emit(s, out); +} + +struct token_list* uniqueID(char* s, struct token_list* l, char* num) +{ + l = emit(s, l); + l = emit("_", l); + l = emit(num, l); + l = emit("\n", l); + return l; +} + +void uniqueID_out(char* s, char* num) +{ + out = uniqueID(s, out, num); +} + +struct token_list* sym_declare(char *s, struct type* t, struct token_list* list) +{ + struct token_list* a = calloc(1, sizeof(struct token_list)); + a->next = list; + a->s = s; + a->type = t; + return a; +} + +struct token_list* sym_lookup(char *s, struct token_list* symbol_list) +{ + struct token_list* i; + for(i = symbol_list; NULL != i; i = i->next) + { + if(match(i->s, s)) return i; + } + return NULL; +} + +void line_error() +{ + file_print(global_token->filename, stderr); + file_print(":", stderr); + file_print(numerate_number(global_token->linenumber), stderr); + file_print(":", stderr); +} + +void require_match(char* message, char* required) +{ + if(!match(global_token->s, required)) + { + line_error(); + file_print(message, stderr); + exit(EXIT_FAILURE); + } + global_token = global_token->next; +} + +void expression(); +void function_call(char* s, int bool) +{ + require_match("ERROR in process_expression_list\nNo ( was found\n", "("); + int passed = 0; + emit_out("PUSH_X16\t# Protect a tmp register we're going to use\n"); + emit_out("PUSH_LR\t# Protect the old return pointer (link)\n"); + emit_out("PUSH_BP\t# Protect the old base pointer\n"); + emit_out("SET_X16_FROM_SP\t# The base pointer to-be\n"); + + if(global_token->s[0] != ')') + { + expression(); + emit_out("PUSH_X0\t#_process_expression1\n"); + passed = 1; + + while(global_token->s[0] == ',') + { + global_token = global_token->next; + expression(); + emit_out("PUSH_X0\t#_process_expression2\n"); + passed = passed + 1; + } + } + + require_match("ERROR in process_expression_list\nNo ) was found\n", ")"); + + if(TRUE == bool) + { + emit_out("SET_X0_FROM_BP\n"); + emit_out("LOAD_W1_AHEAD\nSKIP_32_DATA\n%"); + emit_out(s); + emit_out("\nSUB_X0_X0_X1\n"); + emit_out("DEREF_X0\n"); + emit_out("SET_BP_FROM_X16\n"); + emit_out("SET_X16_FROM_X0\n"); + emit_out("BLR_X16\n"); + } + else + { + emit_out("SET_BP_FROM_X16\n"); + emit_out("LOAD_W16_AHEAD\nSKIP_32_DATA\n&FUNCTION_"); + emit_out(s); + emit_out("\n"); + emit_out("BLR_X16\n"); + } + + for(; passed > 0; passed = passed - 1) + { + emit_out("POP_X1\t# _process_expression_locals\n"); + } + emit_out("POP_BP\t# Restore the old base pointer\n"); + emit_out("POP_LR\t# Restore the old return pointer (link)\n"); + emit_out("POP_X16\t# Restore a register we used as tmp\n"); +} + +void constant_load(struct token_list* a) +{ + emit_out("LOAD_W0_AHEAD\nSKIP_32_DATA\n%"); + emit_out(a->arguments->s); + emit_out("\n"); +} + +void variable_load(struct token_list* a) +{ + if(match("FUNCTION", a->type->name) && match("(", global_token->s)) + { + function_call(numerate_number(a->depth), TRUE); + return; + } + current_target = a->type; + emit_out("SET_X0_FROM_BP\nLOAD_W1_AHEAD\nSKIP_32_DATA\n%"); + emit_out(numerate_number(a->depth)); + emit_out("\nSUB_X0_X0_X1\n\n"); + + if(TRUE == Address_of) return; + if(match("=", global_token->s)) return; + + emit_out("DEREF_X0\n"); +} + +void function_load(struct token_list* a) +{ + if(match("(", global_token->s)) + { + function_call(a->s, FALSE); + return; + } + + emit_out("LOAD_W0_AHEAD\nSKIP_32_DATA\n&FUNCTION_"); + emit_out(a->s); + emit_out("\n"); +} + +void global_load(struct token_list* a) +{ + current_target = a->type; + emit_out("LOAD_W0_AHEAD\nSKIP_32_DATA\n&GLOBAL_"); + emit_out(a->s); + emit_out("\n"); + if(!match("=", global_token->s)) emit_out("DEREF_X0\n"); +} + +/* + * primary-expr: + * FAILURE + * "String" + * 'Char' + * [0-9]* + * [a-z,A-Z]* + * ( expression ) + */ + +void primary_expr_failure() +{ + line_error(); + file_print("Recieved ", stderr); + file_print(global_token->s, stderr); + file_print(" in primary_expr\n", stderr); + exit(EXIT_FAILURE); +} + +void primary_expr_string() +{ + char* number_string = numerate_number(current_count); + current_count = current_count + 1; + emit_out("LOAD_W0_AHEAD\nSKIP_32_DATA\n&STRING_"); + uniqueID_out(function->s, number_string); + + /* The target */ + strings_list = emit(":STRING_", strings_list); + strings_list = uniqueID(function->s, strings_list, number_string); + + /* Parse the string */ + strings_list = emit(parse_string(global_token->s), strings_list); + global_token = global_token->next; +} + +void primary_expr_char() +{ + emit_out("LOAD_W0_AHEAD\nSKIP_32_DATA\n%"); + emit_out(numerate_number(escape_lookup(global_token->s + 1))); + emit_out("\n"); + global_token = global_token->next; +} + +void primary_expr_number() +{ + emit_out("LOAD_W0_AHEAD\nSKIP_32_DATA\n%"); + emit_out(global_token->s); + emit_out("\n"); + global_token = global_token->next; +} + +void primary_expr_variable() +{ + char* s = global_token->s; + global_token = global_token->next; + struct token_list* a = sym_lookup(s, global_constant_list); + if(NULL != a) + { + constant_load(a); + return; + } + + a= sym_lookup(s, function->locals); + if(NULL != a) + { + variable_load(a); + return; + } + + a = sym_lookup(s, function->arguments); + if(NULL != a) + { + variable_load(a); + return; + } + + a= sym_lookup(s, global_function_list); + if(NULL != a) + { + function_load(a); + return; + } + + a = sym_lookup(s, global_symbol_list); + if(NULL != a) + { + global_load(a); + return; + } + + line_error(); + file_print(s ,stderr); + file_print(" is not a defined symbol\n", stderr); + exit(EXIT_FAILURE); +} + +void primary_expr(); +struct type* promote_type(struct type* a, struct type* b) +{ + if(NULL == b) + { + return a; + } + if(NULL == a) + { + return b; + } + + struct type* i; + for(i = global_types; NULL != i; i = i->next) + { + if(a->name == i->name) break; + if(b->name == i->name) break; + if(a->name == i->indirect->name) break; + if(b->name == i->indirect->name) break; + } + return i; +} + +void common_recursion(FUNCTION f) +{ + last_type = current_target; + global_token = global_token->next; + emit_out("PUSH_X0\t#_common_recursion\n"); + f(); + current_target = promote_type(current_target, last_type); + emit_out("POP_X1\t# _common_recursion\n"); +} + +void general_recursion( FUNCTION f, char* s, char* name, FUNCTION iterate) +{ + if(match(name, global_token->s)) + { + common_recursion(f); + emit_out(s); + iterate(); + } +} + +int ceil_log2(int a) +{ + int result = 0; + if((a & (a - 1)) == 0) + { + result = -1; + } + + while(a > 0) + { + result = result + 1; + a = a >> 1; + } + + return (result >> 1); +} + +/* + * postfix-expr: + * primary-expr + * postfix-expr [ expression ] + * postfix-expr ( expression-list-opt ) + * postfix-expr -> member + */ +struct type* lookup_member(struct type* parent, char* name); +void postfix_expr_arrow() +{ + emit_out("# looking up offset\n"); + global_token = global_token->next; + + struct type* i = lookup_member(current_target, global_token->s); + current_target = i->type; + global_token = global_token->next; + + if(0 != i->offset) + { + emit_out("# -> offset calculation\n"); + emit_out("LOAD_W1_AHEAD\nSKIP_32_DATA\n%"); + emit_out(numerate_number(i->offset)); + emit_out("\nADD_X0_X1_X0\n"); + } + + if(!match("=", global_token->s) && (8 == i->size)) + { + emit_out("DEREF_X0\n"); + } +} + +void postfix_expr_array() +{ + struct type* array = current_target; + common_recursion(expression); + current_target = array; + char* assign = "DEREF_X0\n"; + + /* Add support for Ints */ + if(match("char*", current_target->name)) + { + assign = "DEREF_X0_BYTE\n"; + } + else + { + emit_out("LOAD_W2_AHEAD\nSKIP_32_DATA\n%"); + emit_out(numerate_number(ceil_log2(current_target->indirect->size))); + emit_out("\nLSHIFT_X0_X0_X2\n"); + } + + emit_out("ADD_X0_X1_X0\n"); + require_match("ERROR in postfix_expr\nMissing ]\n", "]"); + + if(match("=", global_token->s)) + { + assign = ""; + } + + emit_out(assign); +} + +/* + * unary-expr: + * postfix-expr + * - postfix-expr + * !postfix-expr + * sizeof ( type ) + */ +struct type* type_name(); +void unary_expr_sizeof() +{ + global_token = global_token->next; + require_match("ERROR in unary_expr\nMissing (\n", "("); + struct type* a = type_name(); + require_match("ERROR in unary_expr\nMissing )\n", ")"); + + emit_out("LOAD_W0_AHEAD\nSKIP_32_DATA\n%"); + emit_out(numerate_number(a->size)); + emit_out("\n"); +} + +void postfix_expr_stub() +{ + if(match("[", global_token->s)) + { + postfix_expr_array(); + postfix_expr_stub(); + } + + if(match("->", global_token->s)) + { + postfix_expr_arrow(); + postfix_expr_stub(); + } +} + +void postfix_expr() +{ + primary_expr(); + postfix_expr_stub(); +} + +/* + * additive-expr: + * postfix-expr + * additive-expr * postfix-expr + * additive-expr / postfix-expr + * additive-expr % postfix-expr + * additive-expr + postfix-expr + * additive-expr - postfix-expr + * additive-expr << postfix-expr + * additive-expr >> postfix-expr + */ +void additive_expr_stub() +{ + general_recursion(postfix_expr, "ADD_X0_X1_X0\n", "+", additive_expr_stub); + general_recursion(postfix_expr, "SUB_X0_X1_X0\n", "-", additive_expr_stub); + general_recursion(postfix_expr, "MUL_X0_X1_X0\n", "*", additive_expr_stub); + general_recursion(postfix_expr, "UDIV_X0_X1_X0\n", "/", additive_expr_stub); + general_recursion(postfix_expr, "UDIV_X2_X1_X0\nMSUB_X0_X0_X2_X1\n", "%", additive_expr_stub); + general_recursion(postfix_expr, "LSHIFT_X0_X1_X0\n", "<<", additive_expr_stub); + general_recursion(postfix_expr, "RSHIFT_X0_X1_X0\n", ">>", additive_expr_stub); +} + + +void additive_expr() +{ + postfix_expr(); + additive_expr_stub(); +} + + +/* + * relational-expr: + * additive_expr + * relational-expr < additive_expr + * relational-expr <= additive_expr + * relational-expr >= additive_expr + * relational-expr > additive_expr + */ + +void relational_expr_stub() +{ + general_recursion(additive_expr, "CMP_X1_X0\nSET_X0_TO_1\nSKIP_INST_LT\nSET_X0_TO_0\n", "<", relational_expr_stub); + general_recursion(additive_expr, "CMP_X1_X0\nSET_X0_TO_1\nSKIP_INST_LE\nSET_X0_TO_0\n", "<=", relational_expr_stub); + general_recursion(additive_expr, "CMP_X1_X0\nSET_X0_TO_1\nSKIP_INST_GE\nSET_X0_TO_0\n", ">=", relational_expr_stub); + general_recursion(additive_expr, "CMP_X1_X0\nSET_X0_TO_1\nSKIP_INST_GT\nSET_X0_TO_0\n", ">", relational_expr_stub); + general_recursion(additive_expr, "CMP_X1_X0\nSET_X0_TO_1\nSKIP_INST_EQ\nSET_X0_TO_0\n", "==", relational_expr_stub); + general_recursion(additive_expr, "CMP_X1_X0\nSET_X0_TO_1\nSKIP_INST_NE\nSET_X0_TO_0\n", "!=", relational_expr_stub); +} + +void relational_expr() +{ + additive_expr(); + relational_expr_stub(); +} + +/* + * bitwise-expr: + * relational-expr + * bitwise-expr & bitwise-expr + * bitwise-expr && bitwise-expr + * bitwise-expr | bitwise-expr + * bitwise-expr || bitwise-expr + * bitwise-expr ^ bitwise-expr + */ +void bitwise_expr_stub() +{ + general_recursion(relational_expr, "AND_X0_X1_X0\n", "&", bitwise_expr_stub); + general_recursion(relational_expr, "AND_X0_X1_X0\n", "&&", bitwise_expr_stub); + general_recursion(relational_expr, "OR_X0_X1_X0\n", "|", bitwise_expr_stub); + general_recursion(relational_expr, "OR_X0_X1_X0\n", "||", bitwise_expr_stub); + general_recursion(relational_expr, "XOR_X0_X1_X0\n", "^", bitwise_expr_stub); +} + + +void bitwise_expr() +{ + relational_expr(); + bitwise_expr_stub(); +} + +/* + * expression: + * bitwise-or-expr + * bitwise-or-expr = expression + */ + +void primary_expr() +{ + if(match("&", global_token->s)) + { + Address_of = TRUE; + global_token = global_token->next; + } + else + { + Address_of = FALSE; + } + + if(match("sizeof", global_token->s)) unary_expr_sizeof(); + else if('-' == global_token->s[0]) + { + emit_out("SET_X0_TO_0\n"); + common_recursion(primary_expr); + emit_out("SUB_X0_X1_X0\n"); + } + else if('!' == global_token->s[0]) + { + emit_out("SET_X0_TO_1\n"); + common_recursion(postfix_expr); + emit_out("XOR_X0_X1_X0\n"); + } + else if(global_token->s[0] == '(') + { + global_token = global_token->next; + expression(); + require_match("Error in Primary expression\nDidn't get )\n", ")"); + } + else if(global_token->s[0] == '\'') primary_expr_char(); + else if(global_token->s[0] == '"') primary_expr_string(); + else if(in_set(global_token->s[0], "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")) primary_expr_variable(); + else if(in_set(global_token->s[0], "0123456789")) primary_expr_number(); + else primary_expr_failure(); +} + +void expression() +{ + bitwise_expr(); + if(match("=", global_token->s)) + { + char* store; + if(!match("]", global_token->prev->s) || !match("char*", current_target->name)) + { + store = "STR_X0_[X1]\n"; + } + else + { + store = "STR_BYTE_W0_[X1]\n"; + } + + common_recursion(expression); + emit_out(store); + current_target = NULL; + } +} + + +/* Process local variable */ +void collect_local() +{ + struct type* type_size = type_name(); + struct token_list* a = sym_declare(global_token->s, type_size, function->locals); + if(match("main", function->s) && (NULL == function->locals)) + { + a->depth = 64; + } + else if((NULL == function->arguments) && (NULL == function->locals)) + { + a->depth = 16; + } + else if(NULL == function->locals) + { + a->depth = function->arguments->depth + 16; + } + else + { + a->depth = function->locals->depth + 16; + } + + function->locals = a; + + emit_out("# Defining local "); + emit_out(global_token->s); + emit_out("\n"); + + global_token = global_token->next; + + if(match("=", global_token->s)) + { + global_token = global_token->next; + expression(); + } + + require_match("ERROR in collect_local\nMissing ;\n", ";"); + + emit_out("PUSH_X0\t#"); + emit_out(a->s); + emit_out("\n"); +} + +void statement(); + +/* Evaluate if statements */ +void process_if() +{ + char* number_string = numerate_number(current_count); + current_count = current_count + 1; + + emit_out("# IF_"); + uniqueID_out(function->s, number_string); + + global_token = global_token->next; + require_match("ERROR in process_if\nMISSING (\n", "("); + expression(); + + emit_out("CBNZ_X0_PAST_BR\nLOAD_W16_AHEAD\nSKIP_32_DATA\n&ELSE_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n"); + + require_match("ERROR in process_if\nMISSING )\n", ")"); + statement(); + + emit_out("LOAD_W16_AHEAD\nSKIP_32_DATA\n&_END_IF_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n:ELSE_"); + uniqueID_out(function->s, number_string); + + if(match("else", global_token->s)) + { + global_token = global_token->next; + statement(); + } + emit_out(":_END_IF_"); + uniqueID_out(function->s, number_string); +} + +void process_for() +{ + struct token_list* nested_locals = break_frame; + char* nested_break_head = break_target_head; + char* nested_break_func = break_target_func; + char* nested_break_num = break_target_num; + + char* number_string = numerate_number(current_count); + current_count = current_count + 1; + + break_target_head = "FOR_END_"; + break_target_num = number_string; + break_frame = function->locals; + break_target_func = function->s; + + emit_out("# FOR_initialization_"); + uniqueID_out(function->s, number_string); + + global_token = global_token->next; + + require_match("ERROR in process_for\nMISSING (\n", "("); + if(!match(";",global_token->s)) + { + expression(); + } + + emit_out(":FOR_"); + uniqueID_out(function->s, number_string); + + require_match("ERROR in process_for\nMISSING ;1\n", ";"); + expression(); + + emit_out("CBNZ_X0_PAST_BR\nLOAD_W16_AHEAD\nSKIP_32_DATA\n&FOR_END_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\nLOAD_W16_AHEAD\nSKIP_32_DATA\n&FOR_THEN_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n:FOR_ITER_"); + uniqueID_out(function->s, number_string); + + require_match("ERROR in process_for\nMISSING ;2\n", ";"); + expression(); + + emit_out("LOAD_W16_AHEAD\nSKIP_32_DATA\n&FOR_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n:FOR_THEN_"); + uniqueID_out(function->s, number_string); + + require_match("ERROR in process_for\nMISSING )\n", ")"); + statement(); + + emit_out("LOAD_W16_AHEAD\nSKIP_32_DATA\n&FOR_ITER_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n:FOR_END_"); + uniqueID_out(function->s, number_string); + + break_target_head = nested_break_head; + break_target_func = nested_break_func; + break_target_num = nested_break_num; + break_frame = nested_locals; +} + +/* Process Assembly statements */ +void process_asm() +{ + global_token = global_token->next; + require_match("ERROR in process_asm\nMISSING (\n", "("); + while(34 == global_token->s[0]) + {/* 34 == " */ + emit_out((global_token->s + 1)); + emit_out("\n"); + global_token = global_token->next; + } + require_match("ERROR in process_asm\nMISSING )\n", ")"); + require_match("ERROR in process_asm\nMISSING ;\n", ";"); +} + +/* Process do while loops */ +void process_do() +{ + struct token_list* nested_locals = break_frame; + char* nested_break_head = break_target_head; + char* nested_break_func = break_target_func; + char* nested_break_num = break_target_num; + + char* number_string = numerate_number(current_count); + current_count = current_count + 1; + + break_target_head = "DO_END_"; + break_target_num = number_string; + break_frame = function->locals; + break_target_func = function->s; + + emit_out(":DO_"); + uniqueID_out(function->s, number_string); + + global_token = global_token->next; + statement(); + + require_match("ERROR in process_do\nMISSING while\n", "while"); + require_match("ERROR in process_do\nMISSING (\n", "("); + expression(); + require_match("ERROR in process_do\nMISSING )\n", ")"); + require_match("ERROR in process_do\nMISSING ;\n", ";"); + + emit_out("CBZ_X0_PAST_BR\nLOAD_W16_AHEAD\nSKIP_32_DATA\n&DO_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n:DO_END_"); + uniqueID_out(function->s, number_string); + + break_frame = nested_locals; + break_target_head = nested_break_head; + break_target_func = nested_break_func; + break_target_num = nested_break_num; +} + + +/* Process while loops */ +void process_while() +{ + struct token_list* nested_locals = break_frame; + char* nested_break_head = break_target_head; + char* nested_break_func = break_target_func; + char* nested_break_num = break_target_num; + + char* number_string = numerate_number(current_count); + current_count = current_count + 1; + + break_target_head = "END_WHILE_"; + break_target_num = number_string; + break_frame = function->locals; + break_target_func = function->s; + + emit_out(":WHILE_"); + uniqueID_out(function->s, number_string); + + global_token = global_token->next; + require_match("ERROR in process_while\nMISSING (\n", "("); + expression(); + + emit_out("CBNZ_X0_PAST_BR\nLOAD_W16_AHEAD\nSKIP_32_DATA\n&END_WHILE_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n# THEN_while_"); + uniqueID_out(function->s, number_string); + + require_match("ERROR in process_while\nMISSING )\n", ")"); + statement(); + + emit_out("LOAD_W16_AHEAD\nSKIP_32_DATA\n&WHILE_"); + uniqueID_out(function->s, number_string); + emit_out("\nBR_X16\n:END_WHILE_"); + uniqueID_out(function->s, number_string); + + break_target_head = nested_break_head; + break_target_func = nested_break_func; + break_target_num = nested_break_num; + break_frame = nested_locals; +} + +/* Ensure that functions return */ +void return_result() +{ + global_token = global_token->next; + if(global_token->s[0] != ';') expression(); + + require_match("ERROR in return_result\nMISSING ;\n", ";"); + + struct token_list* i; + for(i = function->locals; NULL != i; i = i->next) + { + emit_out("POP_X1\t# _return_result_locals\n"); + } + emit_out("RETURN\n"); +} + +void process_break() +{ + if(NULL == break_target_head) + { + line_error(); + file_print("Not inside of a loop or case statement", stderr); + exit(EXIT_FAILURE); + } + struct token_list* i = function->locals; + while(i != break_frame) + { + if(NULL == i) break; + emit_out("POP_X1\t# break_cleanup_locals\n"); + i = i->next; + } + global_token = global_token->next; + emit_out("LOAD_W16_AHEAD\nSKIP_32_DATA\n&"); + emit_out(break_target_head); + emit_out(break_target_func); + emit_out("_"); + emit_out(break_target_num); + emit_out("\nBR_X16\n"); + require_match("ERROR in break statement\nMissing ;\n", ";"); +} + +void recursive_statement() +{ + global_token = global_token->next; + struct token_list* frame = function->locals; + + while(!match("}", global_token->s)) + { + statement(); + } + global_token = global_token->next; + + /* Clean up any locals added */ + if(!match("RETURN\n", out->s)) + { + struct token_list* i; + for(i = function->locals; frame != i; i = i->next) + { + emit_out( "POP_X1\t# _recursive_statement_locals\n"); + } + } + function->locals = frame; +} + +/* + * statement: + * { statement-list-opt } + * type-name identifier ; + * type-name identifier = expression; + * if ( expression ) statement + * if ( expression ) statement else statement + * do statement while ( expression ) ; + * while ( expression ) statement + * for ( expression ; expression ; expression ) statement + * asm ( "assembly" ... "assembly" ) ; + * goto label ; + * label: + * return ; + * break ; + * expr ; + */ + +struct type* lookup_type(char* s, struct type* start); +void statement() +{ + if(global_token->s[0] == '{') + { + recursive_statement(); + } + else if(':' == global_token->s[0]) + { + emit_out(global_token->s); + emit_out("\t#C goto label\n"); + global_token = global_token->next; + } + else if((NULL != lookup_type(global_token->s, prim_types)) || + match("struct", global_token->s)) + { + collect_local(); + } + else if(match("if", global_token->s)) + { + process_if(); + } + else if(match("do", global_token->s)) + { + process_do(); + } + else if(match("while", global_token->s)) + { + process_while(); + } + else if(match("for", global_token->s)) + { + process_for(); + } + else if(match("asm", global_token->s)) + { + process_asm(); + } + else if(match("goto", global_token->s)) + { + global_token = global_token->next; + emit_out("LOAD_W16_AHEAD\nSKIP_32_DATA\n&"); + emit_out(global_token->s); + emit_out("\nBR_X16\n"); + global_token = global_token->next; + require_match("ERROR in statement\nMissing ;\n", ";"); + } + else if(match("return", global_token->s)) + { + return_result(); + } + else if(match("break", global_token->s)) + { + process_break(); + } + else if(match("continue", global_token->s)) + { + global_token = global_token->next; + emit_out("\n#continue statement\n"); + require_match("ERROR in statement\nMissing ;\n", ";"); + } + else + { + expression(); + require_match("ERROR in statement\nMISSING ;\n", ";"); + } +} + +/* Collect function arguments */ +void collect_arguments() +{ + global_token = global_token->next; + + while(!match(")", global_token->s)) + { + struct type* type_size = type_name(); + if(global_token->s[0] == ')') + { + /* foo(int,char,void) doesn't need anything done */ + continue; + } + else if(global_token->s[0] != ',') + { + /* deal with foo(int a, char b) */ + struct token_list* a = sym_declare(global_token->s, type_size, function->arguments); + if(NULL == function->arguments) + { + a->depth = 16; + } + else + { + a->depth = function->arguments->depth + 16; + } + + global_token = global_token->next; + function->arguments = a; + } + + /* ignore trailing comma (needed for foo(bar(), 1); expressions*/ + if(global_token->s[0] == ',') global_token = global_token->next; + } + global_token = global_token->next; +} + +void declare_function() +{ + current_count = 0; + function = sym_declare(global_token->prev->s, NULL, global_function_list); + + /* allow previously defined functions to be looked up */ + global_function_list = function; + collect_arguments(); + + /* If just a prototype don't waste time */ + if(global_token->s[0] == ';') global_token = global_token->next; + else + { + emit_out("# Defining function "); + emit_out(function->s); + emit_out("\n"); + emit_out(":FUNCTION_"); + emit_out(function->s); + emit_out("\n"); + statement(); + + /* Prevent duplicate RETURNS */ + if(!match("RETURN\n", out->s)) + { + emit_out("RETURN\n"); + } + } +} + +/* + * program: + * declaration + * declaration program + * + * declaration: + * CONSTANT identifer value + * type-name identifier ; + * type-name identifier ( parameter-list ) ; + * type-name identifier ( parameter-list ) statement + * + * parameter-list: + * parameter-declaration + * parameter-list, parameter-declaration + * + * parameter-declaration: + * type-name identifier-opt + */ +struct token_list* program() +{ + Address_of = FALSE; + out = NULL; + function = NULL; + struct type* type_size; + +new_type: + if (NULL == global_token) return out; + if(match("CONSTANT", global_token->s)) + { + global_token = global_token->next; + global_constant_list = sym_declare(global_token->s, NULL, global_constant_list); + global_constant_list->arguments = global_token->next; + global_token = global_token->next->next; + } + else + { + type_size = type_name(); + if(NULL == type_size) + { + goto new_type; + } + /* Add to global symbol table */ + global_symbol_list = sym_declare(global_token->s, type_size, global_symbol_list); + global_token = global_token->next; + if(match(";", global_token->s)) + { + /* Ensure 4 bytes are allocated for the global */ + globals_list = emit(":GLOBAL_", globals_list); + globals_list = emit(global_token->prev->s, globals_list); + globals_list = emit("\nNULL\n", globals_list); + + global_token = global_token->next; + } + else if(match("(", global_token->s)) declare_function(); + else if(match("=",global_token->s)) + { + /* Store the global's value*/ + globals_list = emit(":GLOBAL_", globals_list); + globals_list = emit(global_token->prev->s, globals_list); + globals_list = emit("\n", globals_list); + global_token = global_token->next; + if(in_set(global_token->s[0], "0123456789")) + { /* Assume Int */ + globals_list = emit("%", globals_list); + globals_list = emit(global_token->s, globals_list); + globals_list = emit("\n", globals_list); + } + else if(('"' == global_token->s[0])) + { /* Assume a string*/ + globals_list = emit(parse_string(global_token->s), globals_list); + } + else + { + line_error(); + file_print("Recieved ", stderr); + file_print(global_token->s, stderr); + file_print(" in program\n", stderr); + exit(EXIT_FAILURE); + } + + global_token = global_token->next; + require_match("ERROR in Program\nMissing ;\n", ";"); + } + else + { + line_error(); + file_print("Recieved ", stderr); + file_print(global_token->s, stderr); + file_print(" in program\n", stderr); + exit(EXIT_FAILURE); + } + } + goto new_type; +} + +void recursive_output(struct token_list* i, FILE* out) +{ + if(NULL == i) return; + recursive_output(i->next, out); + file_print(i->s, out); +} diff --git a/stage2/High_level_prototypes/cc_aarch64/cc_reader.c b/stage2/High_level_prototypes/cc_aarch64/cc_reader.c new file mode 100644 index 0000000..f573857 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/cc_reader.c @@ -0,0 +1,218 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ + +#include "cc.h" +FILE* input; +struct token_list* token; +int line; +char* file; + +int clearWhiteSpace(int c) +{ + if((32 == c) || (9 == c)) return clearWhiteSpace(fgetc(input)); + else if (10 == c) + { + line = line + 1; + return clearWhiteSpace(fgetc(input)); + } + return c; +} + +int consume_byte(int c) +{ + hold_string[string_index] = c; + string_index = string_index + 1; + return fgetc(input); +} + +int consume_word(int c, int frequent) +{ + int escape = FALSE; + do + { + if(!escape && '\\' == c ) escape = TRUE; + else escape = FALSE; + c = consume_byte(c); + } while(escape || (c != frequent)); + return fgetc(input); +} + + +void fixup_label() +{ + int hold = ':'; + int prev; + int i = 0; + do + { + prev = hold; + hold = hold_string[i]; + hold_string[i] = prev; + i = i + 1; + } while(0 != hold); +} + +int in_set(int c, char* s) +{ + while(0 != s[0]) + { + if(c == s[0]) return TRUE; + s = s + 1; + } + return FALSE; +} + +int preserve_keyword(int c) +{ + while(in_set(c, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")) + { + c = consume_byte(c); + } + if(':' == c) + { + fixup_label(); + return 32; + } + return c; +} + +int preserve_symbol(int c) +{ + while(in_set(c, "<=>|&!-")) + { + c = consume_byte(c); + } + return c; +} + +int purge_macro(int ch) +{ + while(10 != ch) ch = fgetc(input); + return ch; +} + +void reset_hold_string() +{ + int i = string_index + 2; + while(0 != i) + { + hold_string[i] = 0; + i = i - 1; + } +} + +int get_token(int c) +{ + struct token_list* current = calloc(1, sizeof(struct token_list)); + +reset: + reset_hold_string(); + string_index = 0; + + c = clearWhiteSpace(c); + if('#' == c) + { + c = purge_macro(c); + goto reset; + } + else if(in_set(c, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")) + { + c = preserve_keyword(c); + } + else if(in_set(c, "<=>|&!-")) + { + c = preserve_symbol(c); + } + else if(c == '\'') + { /* 39 == ' */ + c = consume_word(c, '\''); + } + else if(c == '"') + { + c = consume_word(c, '"'); + } + else if(c == '/') + { + c = consume_byte(c); + if(c == '*') + { + c = fgetc(input); + while(c != '/') + { + while(c != '*') + { + c = fgetc(input); + if(10 == c) line = line + 1; + } + c = fgetc(input); + if(10 == c) line = line + 1; + } + c = fgetc(input); + goto reset; + } + else if(c == '/') + { + c = fgetc(input); + goto reset; + } + } + else if(c == EOF) + { + free(current); + return c; + } + else + { + c = consume_byte(c); + } + + /* More efficiently allocate memory for string */ + current->s = calloc(string_index + 2, sizeof(char)); + copy_string(current->s, hold_string); + + current->prev = token; + current->next = token; + current->linenumber = line; + current->filename = file; + token = current; + return c; +} + +struct token_list* reverse_list(struct token_list* head) +{ + struct token_list* root = NULL; + while(NULL != head) + { + struct token_list* next = head->next; + head->next = root; + root = head; + head = next; + } + return root; +} + +struct token_list* read_all_tokens(FILE* a, struct token_list* current, char* filename) +{ + input = a; + line = 1; + file = filename; + token = current; + int ch =fgetc(input); + while(EOF != ch) ch = get_token(ch); + + return token; +} diff --git a/stage2/High_level_prototypes/cc_aarch64/cc_strings.c b/stage2/High_level_prototypes/cc_aarch64/cc_strings.c new file mode 100644 index 0000000..bf054f8 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/cc_strings.c @@ -0,0 +1,171 @@ +/* Copyright (C) 2016 Jeremiah Orians + * Copyright (C) 2018 Jan (janneke) Nieuwenhuizen + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ + +#include "cc.h" +#include + +struct token_list* emit(char *s, struct token_list* head); +int char2hex(int c); + +char upcase(char a) +{ + if(in_set(a, "abcdefghijklmnopqrstuvwxyz")) + { + a = a - 32; + } + + return a; +} + +int hexify(int c, int high) +{ + int i = char2hex(c); + + if(0 > i) + { + file_print("Tried to print non-hex number\n", stderr); + exit(EXIT_FAILURE); + } + + if(high) + { + i = i << 4; + } + return i; +} + +int escape_lookup(char* c); +int weird(char* string) +{ + int c; + string = string + 1; +weird_reset: + c = string[0]; + if(0 == c) return FALSE; + if('\\' == c) + { + c = escape_lookup(string); + if('x' == string[1]) string = string + 2; + string = string + 1; + } + + if(!in_set(c, "\t\n !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")) return TRUE; + if(in_set(c, " \t\n\r") && (':' == string[1])) return TRUE; + string = string + 1; + goto weird_reset; +} + +/* Lookup escape values */ +int escape_lookup(char* c) +{ + if('\\' != c[0]) return c[0]; + + if(c[1] == 'x') + { + int t1 = hexify(c[2], TRUE); + int t2 = hexify(c[3], FALSE); + return t1 + t2; + } + else if(c[1] == 't') return 9; + else if(c[1] == 'n') return 10; + else if(c[1] == 'v') return 11; + else if(c[1] == 'f') return 12; + else if(c[1] == 'r') return 13; + else if(c[1] == 'e') return 27; + else if(c[1] == '"') return 34; + else if(c[1] == '\'') return 39; + else if(c[1] == '\\') return 92; + + file_print("Unknown escape recieved: ", stderr); + file_print(c, stderr); + file_print(" Unable to process\n", stderr); + exit(EXIT_FAILURE); +} + +/* Deal with human strings */ +char* collect_regular_string(char* string) +{ + string_index = 0; + +collect_regular_string_reset: + if(string[0] == '\\') + { + hold_string[string_index] = escape_lookup(string); + if (string[1] == 'x') string = string + 2; + string = string + 2; + } + else + { + hold_string[string_index] = string[0]; + string = string + 1; + } + + string_index = string_index + 1; + if(string[0] != 0) goto collect_regular_string_reset; + + hold_string[string_index] = '"'; + hold_string[string_index + 1] = '\n'; + char* message = calloc(string_index + 3, sizeof(char)); + copy_string(message, hold_string); + reset_hold_string(); + return message; +} + +/* Deal with non-human strings */ +char* collect_weird_string(char* string) +{ + string_index = 1; + int temp; + char* table = "0123456789ABCDEF"; + + hold_string[0] = '\''; +collect_weird_string_reset: + string = string + 1; + hold_string[string_index] = ' '; + temp = escape_lookup(string); + hold_string[string_index + 1] = table[(temp >> 4)]; + hold_string[string_index + 2] = table[(temp & 15)]; + + if(string[0] == '\\') + { + if(string[1] == 'x') string = string + 2; + string = string + 1; + } + + string_index = string_index + 3; + if(string[1] != 0) goto collect_weird_string_reset; + + hold_string[string_index] = ' '; + hold_string[string_index + 1] = '0'; + hold_string[string_index + 2] = '0'; + hold_string[string_index + 3] = '\''; + hold_string[string_index + 4] = '\n'; + + char* hold = calloc(string_index + 6, sizeof(char)); + copy_string(hold, hold_string); + reset_hold_string(); + return hold; +} + +/* Parse string to deal with hex characters*/ +char* parse_string(char* string) +{ + /* the string */ + if(weird(string)) return collect_weird_string(string); + else return collect_regular_string(string); +} diff --git a/stage2/High_level_prototypes/cc_aarch64/cc_types.c b/stage2/High_level_prototypes/cc_aarch64/cc_types.c new file mode 100644 index 0000000..1ceb2ea --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/cc_types.c @@ -0,0 +1,260 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ + +#include "cc.h" +#include +void line_error(); +int numerate_string(char *a); + +/* Initialize default types */ +void initialize_types() +{ + /* Define void */ + global_types = calloc(1, sizeof(struct type)); + global_types->name = "void"; + global_types->size = 8; + global_types->type = global_types; + /* void* has the same properties as void */ + global_types->indirect = global_types; + + /* Define int */ + struct type* a = calloc(1, sizeof(struct type)); + a->name = "int"; + a->size = 8; + /* int* has the same properties as int */ + a->indirect = a; + a->type = a; + + /* Define char* */ + struct type* b = calloc(1, sizeof(struct type)); + b->name = "char*"; + b->size = 8; + b->type = b; + + /* Define char */ + struct type* c = calloc(1, sizeof(struct type)); + c->name = "char"; + c->size = 1; + c->type = c; + + /* Define char** */ + struct type* d = calloc(1, sizeof(struct type)); + d->name = "char**"; + d->size = 8; + d->type = c; + d->indirect = d; + + /*fix up indrects for chars */ + c->indirect = b; + b->indirect = d; + + /* Define FILE */ + struct type* e = calloc(1, sizeof(struct type)); + e->name = "FILE"; + e->size = 8; + e->type = e; + /* FILE* has the same properties as FILE */ + e->indirect = e; + + /* Define FUNCTION */ + struct type* f = calloc(1, sizeof(struct type)); + f->name = "FUNCTION"; + f->size = 8; + f->type = f; + /* FUNCTION* has the same properties as FUNCTION */ + f->indirect = f; + + /* Define UNSIGNED */ + struct type* g = calloc(1, sizeof(struct type)); + g->name = "unsigned"; + g->size = 8; + g->type = g; + /* unsigned* has the same properties as unsigned */ + g->indirect = g; + + /* Finalize type list */ + f->next = g; + e->next = f; + d->next = e; + c->next = e; + a->next = c; + global_types->next = a; + prim_types = global_types; +} + +struct type* lookup_type(char* s, struct type* start) +{ + struct type* i; + for(i = start; NULL != i; i = i->next) + { + if(match(i->name, s)) + { + return i; + } + } + return NULL; +} + +struct type* lookup_member(struct type* parent, char* name) +{ + struct type* i; + for(i = parent->members; NULL != i; i = i->members) + { + if(match(i->name, name)) return i; + } + + file_print("ERROR in lookup_member ", stderr); + file_print(parent->name, stderr); + file_print("->", stderr); + file_print(global_token->s, stderr); + file_print(" does not exist\n", stderr); + line_error(); + file_print("\n", stderr); + exit(EXIT_FAILURE); +} + +struct type* type_name(); +void require_match(char* message, char* required); + +int member_size; +struct type* build_member(struct type* last, int offset) +{ + struct type* member_type = type_name(); + struct type* i = calloc(1, sizeof(struct type)); + i->name = global_token->s; + global_token = global_token->next; + i->members = last; + + /* Check to see if array */ + if(match( "[", global_token->s)) + { + global_token = global_token->next; + i->size = member_type->type->size * numerate_string(global_token->s); + global_token = global_token->next; + require_match("Struct only supports [num] form\n", "]"); + } + else + { + i->size = member_type->size; + } + member_size = i->size; + i->type = member_type; + i->offset = offset; + return i; +} + +struct type* build_union(struct type* last, int offset) +{ + int size = 0; + global_token = global_token->next; + require_match("ERROR in build_union\nMissing {\n", "{"); + while('}' != global_token->s[0]) + { + last = build_member(last, offset); + if(member_size > size) + { + size = member_size; + } + require_match("ERROR in build_union\nMissing ;\n", ";"); + } + member_size = size; + global_token = global_token->next; + return last; +} + +void create_struct() +{ + int offset = 0; + member_size = 0; + struct type* head = calloc(1, sizeof(struct type)); + struct type* i = calloc(1, sizeof(struct type)); + head->name = global_token->s; + i->name = global_token->s; + head->indirect = i; + i->indirect = head; + head->next = global_types; + global_types = head; + global_token = global_token->next; + i->size = 8; + require_match("ERROR in create_struct\n Missing {\n", "{"); + struct type* last = NULL; + while('}' != global_token->s[0]) + { + if(match(global_token->s, "union")) + { + last = build_union(last, offset); + } + else + { + last = build_member(last, offset); + } + offset = offset + member_size; + require_match("ERROR in create_struct\n Missing ;\n", ";"); + } + + global_token = global_token->next; + require_match("ERROR in create_struct\n Missing ;\n", ";"); + + head->size = offset; + head->members = last; + i->members = last; +} + + +/* + * type-name: + * char * + * int + * struct + * FILE + * void + */ +struct type* type_name() +{ + int structure = match("struct", global_token->s); + + if(structure) + { + global_token = global_token->next; + } + + struct type* ret = lookup_type(global_token->s, global_types); + + if(NULL == ret && !structure) + { + file_print("Unknown type ", stderr); + file_print(global_token->s, stderr); + file_print("\n", stderr); + line_error(); + exit(EXIT_FAILURE); + } + else if(NULL == ret) + { + create_struct(); + return NULL; + } + + global_token = global_token->next; + + while(global_token->s[0] == '*') + { + ret = ret->indirect; + global_token = global_token->next; + } + + return ret; +} diff --git a/stage2/High_level_prototypes/cc_aarch64/functions/file_print.c b/stage2/High_level_prototypes/cc_aarch64/functions/file_print.c new file mode 100644 index 0000000..19c065f --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/functions/file_print.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ +#include +// void fputc(char s, FILE* f); + +void file_print(char* s, FILE* f) +{ + while(0 != s[0]) + { + fputc(s[0], f); + s = s + 1; + } +} diff --git a/stage2/High_level_prototypes/cc_aarch64/functions/match.c b/stage2/High_level_prototypes/cc_aarch64/functions/match.c new file mode 100644 index 0000000..bb33361 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/functions/match.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ + +#define FALSE 0 +// CONSTANT FALSE 0 +#define TRUE 1 +// CONSTANT TRUE 1 + +int match(char* a, char* b) +{ + int i = -1; + do + { + i = i + 1; + if(a[i] != b[i]) + { + return FALSE; + } + } while((0 != a[i]) && (0 !=b[i])); + return TRUE; +} diff --git a/stage2/High_level_prototypes/cc_aarch64/functions/numerate_number.c b/stage2/High_level_prototypes/cc_aarch64/functions/numerate_number.c new file mode 100644 index 0000000..bf2672a --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/functions/numerate_number.c @@ -0,0 +1,148 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ +#include +#include +// void* calloc(int count, int size); +#define TRUE 1 +//CONSTANT TRUE 1 +#define FALSE 0 +//CONSTANT FALSE 0 + +char* numerate_number(int a) +{ + char* result = calloc(16, sizeof(char)); + int i = 0; + + /* Deal with Zero case */ + if(0 == a) + { + result[0] = '0'; + return result; + } + + /* Deal with negatives */ + if(0 > a) + { + result[0] = '-'; + i = 1; + a = a * -1; + } + + /* Using the largest 10^n number possible in 32bits */ + int divisor = 0x3B9ACA00; + /* Skip leading Zeros */ + while(0 == (a / divisor)) divisor = divisor / 10; + + /* Now simply collect numbers until divisor is gone */ + while(0 < divisor) + { + result[i] = ((a / divisor) + 48); + a = a % divisor; + divisor = divisor / 10; + i = i + 1; + } + + return result; +} + +int char2hex(int c) +{ + if (c >= '0' && c <= '9') return (c - 48); + else if (c >= 'a' && c <= 'f') return (c - 87); + else if (c >= 'A' && c <= 'F') return (c - 55); + else return -1; +} + +int hex2char(int c) +{ + if((c >= 0) && (c <= 9)) return (c + 48); + else if((c >= 10) && (c <= 15)) return (c + 55); + else return -1; +} + +int char2dec(int c) +{ + if (c >= '0' && c <= '9') return (c - 48); + else return -1; +} + +int dec2char(int c) +{ + if((c >= 0) && (c <= 9)) return (c + 48); + else return -1; +} + +int numerate_string(char *a) +{ + int count = 0; + int index; + int negative; + + /* If NULL string */ + if(0 == a[0]) + { + return 0; + } + /* Deal with hex */ + else if (a[0] == '0' && a[1] == 'x') + { + if('-' == a[2]) + { + negative = TRUE; + index = 3; + } + else + { + negative = FALSE; + index = 2; + } + + while(0 != a[index]) + { + if(-1 == char2hex(a[index])) return 0; + count = (16 * count) + char2hex(a[index]); + index = index + 1; + } + } + /* Deal with decimal */ + else + { + if('-' == a[0]) + { + negative = TRUE; + index = 1; + } + else + { + negative = FALSE; + index = 0; + } + + while(0 != a[index]) + { + if(-1 == char2dec(a[index])) return 0; + count = (10 * count) + char2dec(a[index]); + index = index + 1; + } + } + + if(negative) + { + count = count * -1; + } + return count; +} diff --git a/stage2/High_level_prototypes/cc_aarch64/functions/string.c b/stage2/High_level_prototypes/cc_aarch64/functions/string.c new file mode 100644 index 0000000..91282a5 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/functions/string.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ +#include +#define MAX_STRING 4096 +//CONSTANT MAX_STRING 4096 +// void* calloc(int count, int size); + +char* copy_string(char* target, char* source) +{ + while(0 != source[0]) + { + target[0] = source[0]; + target = target + 1; + source = source + 1; + } + return target; +} + +char* postpend_char(char* s, char a) +{ + char* ret = calloc(MAX_STRING, sizeof(char)); + char* hold = copy_string(ret, s); + hold[0] = a; + return ret; +} + +char* prepend_char(char a, char* s) +{ + char* ret = calloc(MAX_STRING, sizeof(char)); + ret[0] = a; + copy_string((ret+1), s); + return ret; +} + +char* prepend_string(char* add, char* base) +{ + char* ret = calloc(MAX_STRING, sizeof(char)); + copy_string(copy_string(ret, add), base); + return ret; +} + +int string_length(char* a) +{ + int i = 0; + while(0 != a[i]) i = i + 1; + return i; +} diff --git a/stage2/High_level_prototypes/cc_aarch64/gcc_req.h b/stage2/High_level_prototypes/cc_aarch64/gcc_req.h new file mode 100644 index 0000000..f0c1d07 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/gcc_req.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of stage0. + * + * stage0 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 3 of the License, or + * (at your option) any later version. + * + * stage0 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 stage0. If not, see . + */ + +// Exists only because gcc doesn't support naked Function pointers +// And thus adds just enough support that M2-Plant can leverage the feature +// in its self-host +typedef void (*FUNCTION) (); diff --git a/stage2/High_level_prototypes/cc_aarch64/makefile b/stage2/High_level_prototypes/cc_aarch64/makefile new file mode 100644 index 0000000..271d551 --- /dev/null +++ b/stage2/High_level_prototypes/cc_aarch64/makefile @@ -0,0 +1,39 @@ +## Copyright (C) 2016 Jeremiah Orians +## This file is part of stage0. +## +## stage0 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 3 of the License, or +## (at your option) any later version. +## +## stage0 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 stage0. If not, see . + + +all: cc_aarch64 + +CC?=gcc +CFLAGS=-D_GNU_SOURCE -O0 -std=c99 -ggdb + +cc_aarch64: cc_reader.c cc_strings.c cc_core.c cc.c cc_types.c cc.h + $(CC) $(CFLAGS) \ + functions/match.c \ + functions/numerate_number.c \ + functions/file_print.c \ + functions/string.c \ + cc_reader.c \ + cc_strings.c \ + cc_types.c \ + cc_core.c \ + cc.c \ + cc.h \ + gcc_req.h \ + -o cc_aarch64 + +clean: cc_aarch64 + rm -f cc_aarch64