Broke out globals and now reduce the memory churn in string creation

This commit is contained in:
Jeremiah Orians 2017-12-15 18:17:29 -05:00
parent e25401c0b8
commit 18e433def4
No known key found for this signature in database
GPG Key ID: 7457821534D2ACCD
4 changed files with 292 additions and 221 deletions

388
cc.c
View File

@ -18,7 +18,6 @@
#include "cc.h" #include "cc.h"
#include <stdint.h> #include <stdint.h>
#define GLOBAL 1 #define GLOBAL 1
#define FUNCTION 2 #define FUNCTION 2
#define LOCAL_VARIABLE 4 #define LOCAL_VARIABLE 4
@ -28,27 +27,72 @@
struct token_list* global_symbol_list; struct token_list* global_symbol_list;
struct token_list* global_token; struct token_list* global_token;
struct token_list* current_target; struct token_list* current_target;
struct token_list* strings; struct token_list* strings_list;
struct token_list* globals_list;
/* Imported functions */ /* Imported functions */
int asprintf(char **strp, const char *fmt, ...);
struct token_list* read_all_tokens(char* source_file); struct token_list* read_all_tokens(char* source_file);
char* parse_string(char* string);
struct token_list* emit(char *s, bool hands_off, struct token_list* head) struct token_list* emit(char *s, struct token_list* head)
{ {
struct token_list* t = calloc(1, sizeof(struct token_list)); struct token_list* t = calloc(1, sizeof(struct token_list));
t->next = head; t->next = head;
t->hands_off = hands_off;
t->s = s; t->s = s;
return t; return t;
} }
struct token_list* sym_declare(char *s, int type, struct type* size) struct token_list* double_emit(char* a, char* b, struct token_list* out, int flag)
{
out = emit(a, out);
out = emit(b, out);
if(flag) out = emit("\n", out);
return out;
}
char* numerate_number(int a)
{
char* result = calloc(16, sizeof(char));
int i = 0;
/* Deal with Zero case */
if(0 == a)
{
result[0] = '0';
result[1] = '\n';
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;
}
result[i] = '\n';
return result;
}
struct token_list* sym_declare(char *s, int type, struct type* size, struct token_list* list)
{ {
struct token_list* a = calloc(1, sizeof(struct token_list)); struct token_list* a = calloc(1, sizeof(struct token_list));
a->next = global_symbol_list; a->next = list;
global_symbol_list = a;
a->type = type; a->type = type;
a->s = s; a->s = s;
a->size = size; a->size = size;
@ -66,20 +110,20 @@ struct token_list* sym_lookup(char *s, struct token_list* symbol_list)
int stack_index(struct token_list* a, struct token_list* function) int stack_index(struct token_list* a, struct token_list* function)
{ {
int depth = function->temps; int depth = 4 * function->temps;
for(struct token_list* i = function->locals; NULL != i; i = i->locals) for(struct token_list* i = function->locals; NULL != i; i = i->next)
{ {
if(i == a) return depth; if(i == a) return depth;
else depth = depth + 1; else depth = depth + 4;
} }
/* Deal with offset caused by return pointer */ /* Deal with offset caused by return pointer */
depth = depth+ 1; depth = depth+ 4;
for(struct token_list* i = function->arguments; NULL != i; i = i->arguments) for(struct token_list* i = function->arguments; NULL != i; i = i->next)
{ {
if(i == a) return depth; if(i == a) return depth;
else depth = depth + 1; else depth = depth + 4;
} }
fprintf(stderr, "%s does not exist in function %s\n", a->s, function->s); fprintf(stderr, "%s does not exist in function %s\n", a->s, function->s);
@ -88,8 +132,9 @@ int stack_index(struct token_list* a, struct token_list* function)
struct token_list* sym_get_value(char *s, struct token_list* out, struct token_list* function) struct token_list* sym_get_value(char *s, struct token_list* out, struct token_list* function)
{ {
char* label; struct token_list* a = sym_lookup(s, function->locals);
struct token_list* a = sym_lookup(s, global_symbol_list); if(NULL == a) a = sym_lookup(s, function->arguments);
if(NULL == a) a = sym_lookup(s, global_symbol_list);
if(a == NULL) if(a == NULL)
{ {
fprintf(stderr, "%s is not a defined symbol\n", s); fprintf(stderr, "%s is not a defined symbol\n", s);
@ -97,17 +142,15 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l
} }
current_target = a; current_target = a;
global_token = global_token->next;
switch(a->type) switch(a->type)
{ {
case GLOBAL: asprintf(&label, "LOAD_IMMEDIATE_eax &GLOBAL_%s\n", s); break;
case LOCAL_VARIABLE: asprintf(&label, "LOAD_EFFECTIVE_ADDRESS %c%d\n", 37, 4 * stack_index(a, function)); break;
case ARGUEMENT: asprintf(&label, "LOAD_EFFECTIVE_ADDRESS %c%d\n", 37, 4 * (stack_index(a, function))); break;
case FUNCTION: return out; case FUNCTION: return out;
default: exit(EXIT_FAILURE); case GLOBAL: out = double_emit("LOAD_IMMEDIATE_eax &GLOBAL_", s, out, true); break;
default: out = double_emit("LOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function)), out, false);
} }
out = emit(label, true, out); if(strcmp(global_token->s, "=")) out = emit("LOAD_INTEGER\n", out);
if(strcmp(global_token->next->s, "=")) out = emit("LOAD_INTEGER\n", true, out);
return out; return out;
} }
@ -122,7 +165,6 @@ void require_char(char* message, char required)
} }
struct token_list* expression(struct token_list* out, struct token_list* function); struct token_list* expression(struct token_list* out, struct token_list* function);
struct token_list* parse_string(struct token_list* output_list, char* string);
/* /*
* primary-expr: * primary-expr:
@ -132,18 +174,14 @@ struct token_list* parse_string(struct token_list* output_list, char* string);
*/ */
struct token_list* primary_expr(struct token_list* out, struct token_list* function) struct token_list* primary_expr(struct token_list* out, struct token_list* function)
{ {
char* label;
if(('0' <= global_token->s[0]) & (global_token->s[0] <= '9')) if(('0' <= global_token->s[0]) & (global_token->s[0] <= '9'))
{ {
asprintf(&label, "LOAD_IMMEDIATE_eax %c%s\n", 37, global_token->s); out = double_emit("LOAD_IMMEDIATE_eax %", global_token->s, out, true);
out = emit(label, true, out);
global_token = global_token->next; global_token = global_token->next;
} }
else if(('a' <= global_token->s[0]) & (global_token->s[0] <= 'z')) else if(('a' <= global_token->s[0]) & (global_token->s[0] <= 'z'))
{ {
out = sym_get_value(global_token->s, out, function); out = sym_get_value(global_token->s, out, function);
global_token = global_token->next;
} }
else if(global_token->s[0] == '(') else if(global_token->s[0] == '(')
{ {
@ -153,27 +191,32 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct
} }
else if(global_token->s[0] == '\'') else if(global_token->s[0] == '\'')
{ {
asprintf(&label, "LOAD_IMMEDIATE_eax %c%d\n", 37, global_token->s[1]); out = emit("LOAD_IMMEDIATE_eax %", out);
out = emit(label, true, out); out = emit(numerate_number(global_token->s[1]), out);
global_token = global_token->next; global_token = global_token->next;
} }
else if(global_token->s[0] == '"') else if(global_token->s[0] == '"')
{ {
static int string_num; static int string_num;
asprintf(&label, "LOAD_IMMEDIATE_eax &STRING_%d\n", string_num); char* number_string = numerate_number(string_num);
out = emit(label, true, out); out = emit("LOAD_IMMEDIATE_eax &STRING_", out);
out = emit(number_string, out);
/* The target */ /* The target */
asprintf(&label, ":STRING_%d\n", string_num); strings_list = emit(":STRING_", strings_list);
strings = emit(label, true, strings); strings_list = emit(number_string, strings_list);
/* Parse the string */ /* Parse the string */
strings = parse_string(strings, global_token->s); strings_list = emit(parse_string(global_token->s), strings_list);
global_token = global_token->next; global_token = global_token->next;
string_num = string_num + 1; string_num = string_num + 1;
} }
else exit(EXIT_FAILURE); else
{
fprintf(stderr, "Recieved %s in primary_expr\n", global_token->s);
exit(EXIT_FAILURE);
}
return out; return out;
} }
@ -181,55 +224,46 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct
/* Deal with Expression lists */ /* Deal with Expression lists */
struct token_list* process_expression_list(struct token_list* out, struct token_list* function) struct token_list* process_expression_list(struct token_list* out, struct token_list* function)
{ {
struct token_list* func = sym_lookup(global_token->prev->s, global_symbol_list); char* func = global_token->prev->s;
global_token = global_token->next; global_token = global_token->next;
int temp = function->temps; int temp = function->temps;
if(global_token->s[0] != ')') if(global_token->s[0] != ')')
{ {
char* label;
out = expression(out, function); out = expression(out, function);
asprintf(&label, "PUSH_eax\t#%s\n", "_process_expression1"); out = emit("PUSH_eax\t#_process_expression1\n", out);
out = emit(label, true, out);
function->temps = function->temps + 1; function->temps = function->temps + 1;
while(global_token->s[0] == ',') while(global_token->s[0] == ',')
{ {
global_token = global_token->next; global_token = global_token->next;
out = expression(out, function); out = expression(out, function);
asprintf(&label, "PUSH_eax\t#%s\n", "_process_expression2"); out = emit("PUSH_eax\t#_process_expression2\n", out);
out = emit(label, true, out);
function->temps = function->temps + 1; function->temps = function->temps + 1;
} }
require_char("ERROR in process_expression_list\nNo ) was found\n", ')'); require_char("ERROR in process_expression_list\nNo ) was found\n", ')');
} }
else global_token = global_token->next; else global_token = global_token->next;
function->temps = temp;
char* label; out = double_emit("CALL_IMMEDIATE %FUNCTION_", func, out, true);
asprintf(&label, "CALL_IMMEDIATE %cFUNCTION_%s\n", 37, func->s);
out = emit(label, true, out);
for(struct token_list* i = func->arguments; NULL != i; i = i->arguments) for(int i = function->temps - temp; 0 != i; i = i - 1)
{ {
asprintf(&label, "POP_ebx\t# %s\n", "_process_expression_locals"); out = emit("POP_ebx\t# _process_expression_locals\n", out);
out = emit(label, true, out);
} }
function->temps = temp;
return out; return out;
} }
struct token_list* common_recursion(struct token_list* (*function) (struct token_list*, struct token_list*), struct token_list* out, struct token_list* func) struct token_list* common_recursion(struct token_list* (*function) (struct token_list*, struct token_list*), struct token_list* out, struct token_list* func)
{ {
char* label;
global_token = global_token->next; global_token = global_token->next;
asprintf(&label, "PUSH_eax\t#%s\n", "_common_recursion"); out = emit("PUSH_eax\t#_common_recursion\n", out);
out = emit(label, true, out);
func->temps = func->temps + 1; func->temps = func->temps + 1;
out = function(out, func); out = function(out, func);
func->temps = func->temps - 1; func->temps = func->temps - 1;
asprintf(&label, "POP_ebx\t# %s\n", "_common_recursion"); out = emit("POP_ebx\t# _common_recursion\n", out);
out = emit(label, true, out);
return out; return out;
} }
@ -251,21 +285,21 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct
/* Add support for Ints*/ /* Add support for Ints*/
if( 4 == target->size->member_size) if( 4 == target->size->member_size)
{ {
out = emit("SAL_eax_Immediate8 !2\n", true, out); out = emit("SAL_eax_Immediate8 !2\n", out);
} }
out = emit("ADD_ebx_to_eax\n", true, out); out = emit("ADD_ebx_to_eax\n", out);
current_target = target; current_target = target;
if(strcmp(global_token->next->s, "=")) if(strcmp(global_token->next->s, "="))
{ {
if( 4 == target->size->member_size) if( 4 == target->size->member_size)
{ {
out = emit("LOAD_INTEGER\n", true, out); out = emit("LOAD_INTEGER\n", out);
} }
else else
{ {
out = emit("LOAD_BYTE\n", true, out); out = emit("LOAD_BYTE\n", out);
} }
} }
require_char("ERROR in postfix_expr\nMissing ]\n", ']'); require_char("ERROR in postfix_expr\nMissing ]\n", ']');
@ -293,12 +327,12 @@ struct token_list* additive_expr(struct token_list* out, struct token_list* func
if(global_token->s[0] == '+') if(global_token->s[0] == '+')
{ {
out = common_recursion(postfix_expr, out, function); out = common_recursion(postfix_expr, out, function);
out = emit("ADD_ebx_to_eax\n", true, out); out = emit("ADD_ebx_to_eax\n", out);
} }
else if(global_token->s[0] == '-') else if(global_token->s[0] == '-')
{ {
out = common_recursion(postfix_expr, out, function); out = common_recursion(postfix_expr, out, function);
out = emit("SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n", true, out); out = emit("SUBTRACT_eax_from_ebx_into_ebx\nMOVE_ebx_to_eax\n", out);
} }
else return out; else return out;
} }
@ -322,7 +356,7 @@ struct token_list* shift_expr(struct token_list* out, struct token_list* functio
// Ugly hack to Work around flaw in x86 // Ugly hack to Work around flaw in x86
struct token_list* old = out->next; struct token_list* old = out->next;
free(out); free(out);
out = emit("COPY_eax_to_ecx\nPOP_eax\nSAL_eax_cl\n", true, old); out = emit("COPY_eax_to_ecx\nPOP_eax\nSAL_eax_cl\n", old);
} }
else if(!strcmp(global_token->s, ">>")) else if(!strcmp(global_token->s, ">>"))
{ {
@ -330,7 +364,7 @@ struct token_list* shift_expr(struct token_list* out, struct token_list* functio
// Ugly hack to Work around flaw in x86 // Ugly hack to Work around flaw in x86
struct token_list* old = out->next; struct token_list* old = out->next;
free(out); free(out);
out = emit("COPY_eax_to_ecx\nPOP_eax\nSAR_eax_cl\n", true, old); out = emit("COPY_eax_to_ecx\nPOP_eax\nSAR_eax_cl\n", old);
} }
else else
{ {
@ -351,7 +385,7 @@ struct token_list* relational_expr(struct token_list* out, struct token_list* fu
while(!strcmp(global_token->s, "<=")) while(!strcmp(global_token->s, "<="))
{ {
out = common_recursion(shift_expr, out, function); out = common_recursion(shift_expr, out, function);
out = emit("CMP\nSETLE\nMOVEZBL\n", true, out); out = emit("CMP\nSETLE\nMOVEZBL\n", out);
} }
return out; return out;
} }
@ -371,12 +405,12 @@ struct token_list* equality_expr(struct token_list* out, struct token_list* func
if(!strcmp(global_token->s, "==")) if(!strcmp(global_token->s, "=="))
{ {
out = common_recursion(relational_expr, out, function); out = common_recursion(relational_expr, out, function);
out = emit("CMP\nSETE\nMOVEZBL\n", true, out); out = emit("CMP\nSETE\nMOVEZBL\n", out);
} }
else if(!strcmp(global_token->s, "!=")) else if(!strcmp(global_token->s, "!="))
{ {
out = common_recursion(relational_expr, out, function); out = common_recursion(relational_expr, out, function);
out = emit("CMP\nSETNE\nMOVEZBL\n", true, out); out = emit("CMP\nSETNE\nMOVEZBL\n", out);
} }
else return out; else return out;
} }
@ -394,7 +428,7 @@ struct token_list* bitwise_and_expr(struct token_list* out, struct token_list* f
while(global_token->s[0] == '&') while(global_token->s[0] == '&')
{ {
out = common_recursion(equality_expr, out, function); out = common_recursion(equality_expr, out, function);
out = emit("AND_eax_ebx\n", true, out); out = emit("AND_eax_ebx\n", out);
} }
return out; return out;
} }
@ -411,7 +445,7 @@ struct token_list* bitwise_or_expr(struct token_list* out, struct token_list* fu
while(global_token->s[0] == '|') while(global_token->s[0] == '|')
{ {
out = common_recursion(bitwise_and_expr, out, function); out = common_recursion(bitwise_and_expr, out, function);
out = emit("OR_eax_ebx\n", true, out); out = emit("OR_eax_ebx\n", out);
} }
return out; return out;
} }
@ -433,15 +467,15 @@ struct token_list* expression(struct token_list* out, struct token_list* functio
if(member) if(member)
{ {
if(1 == target->size->member_size) out = emit("STORE_CHAR\n", true, out); if(1 == target->size->member_size) out = emit("STORE_CHAR\n", out);
else if(4 == target->size->member_size) else if(4 == target->size->member_size)
{ {
out = emit("STORE_INTEGER\n", true, out); out = emit("STORE_INTEGER\n", out);
} }
} }
else else
{ {
out = emit("STORE_INTEGER\n", true, out); out = emit("STORE_INTEGER\n", out);
} }
} }
return out; return out;
@ -486,12 +520,9 @@ struct type* type_name()
struct token_list* collect_local(struct token_list* out, struct token_list* function) struct token_list* collect_local(struct token_list* out, struct token_list* function)
{ {
struct type* type_size = type_name(); struct type* type_size = type_name();
char* label; out = double_emit("# Defining local ", global_token->s, out, true);
asprintf(&label, "# Defining local %s\n", global_token->s);
out = emit(label, true, out);
struct token_list* a = sym_declare(global_token->s, LOCAL_VARIABLE, type_size); struct token_list* a = sym_declare(global_token->s, LOCAL_VARIABLE, type_size, function->locals);
a->locals = function->locals;
function->locals = a; function->locals = a;
global_token = global_token->next; global_token = global_token->next;
function->temps = function->temps - 1; function->temps = function->temps - 1;
@ -504,8 +535,8 @@ struct token_list* collect_local(struct token_list* out, struct token_list* func
function->temps = function->temps + 1; function->temps = function->temps + 1;
require_char("ERROR in collect_local\nMissing ;\n", ';'); require_char("ERROR in collect_local\nMissing ;\n", ';');
asprintf(&label, "PUSH_eax\t#%s\n", a->s);
out = emit(label, true, out); out = double_emit("PUSH_eax\t#", a->s, out, true);
return out; return out;
} }
@ -515,71 +546,66 @@ struct token_list* statement(struct token_list* out, struct token_list* function
int if_count; int if_count;
struct token_list* process_if(struct token_list* out, struct token_list* function) struct token_list* process_if(struct token_list* out, struct token_list* function)
{ {
char* label; char* number_string = numerate_number(if_count);
int number = if_count; int number = if_count;
if_count = if_count + 1; if_count = if_count + 1;
asprintf(&label, "# IF_%d\n", number); out = double_emit("# IF_",number_string, out, false);
out = emit(label, true, out);
global_token = global_token->next; global_token = global_token->next;
require_char("ERROR in process_if\nMISSING (\n", '('); require_char("ERROR in process_if\nMISSING (\n", '(');
out = expression(out, function); out = expression(out, function);
asprintf(&label, "TEST\nJUMP_EQ %c%s_%d\n", 37, "ELSE", number); out = double_emit("TEST\nJUMP_EQ %ELSE_", number_string, out, false);
out = emit(label, true, out);
require_char("ERROR in process_if\nMISSING )\n", ')'); require_char("ERROR in process_if\nMISSING )\n", ')');
out = statement(out, function); out = statement(out, function);
asprintf(&label, "JUMP %c_END_IF_%d\n:ELSE_%d\n", 37, number, number); out = double_emit("JUMP %_END_IF_", number_string, out, false);
out = emit(label, true, out); out = double_emit(":ELSE_", number_string, out, false);
if(!strcmp(global_token->s, "else")) if(!strcmp(global_token->s, "else"))
{ {
global_token = global_token->next; global_token = global_token->next;
out = statement(out, function); out = statement(out, function);
} }
asprintf(&label, ":_END_IF_%d\n", number); out = double_emit(":_END_IF_", number_string, out, false);
out = emit(label, true, out);
return out; return out;
} }
int for_count; int for_count;
struct token_list* process_for(struct token_list* out, struct token_list* function) struct token_list* process_for(struct token_list* out, struct token_list* function)
{ {
char* label; char* number_string = numerate_number(for_count);
int number = for_count;
for_count = for_count + 1; for_count = for_count + 1;
asprintf(&label, "# FOR_initialization_%d\n", number); out = double_emit("# FOR_initialization_", number_string, out, false);
out = emit(label, true, out);
global_token = global_token->next; global_token = global_token->next;
require_char("ERROR in process_for\nMISSING (\n", '('); require_char("ERROR in process_for\nMISSING (\n", '(');
out = expression(out, function); out = expression(out, function);
asprintf(&label, ":FOR_%d\n", number); out = double_emit(":FOR_", number_string, out , false);
out = emit(label, true, out);
require_char("ERROR in process_for\nMISSING ;1\n", ';'); require_char("ERROR in process_for\nMISSING ;1\n", ';');
out = expression(out, function); out = expression(out, function);
asprintf(&label, "TEST\nJUMP_EQ %c%s_%d\nJUMP %c%s_%d\n:FOR_ITER_%d\n", 37, "FOR_END", number, 37, "FOR_THEN", number, number); out = double_emit("TEST\nJUMP_EQ %FOR_END_", number_string, out, false);
out = emit(label, true, out); out = double_emit("JUMP %FOR_THEN_", number_string, out, false);
out = double_emit(":FOR_ITER_", number_string, out, false);
require_char("ERROR in process_for\nMISSING ;2\n", ';'); require_char("ERROR in process_for\nMISSING ;2\n", ';');
out = expression(out, function); out = expression(out, function);
asprintf(&label, "JUMP %c%s_%d\n:FOR_THEN_%d\n", 37, "FOR", number, number); out = double_emit("JUMP %FOR_", number_string, out, false);
out = emit(label, true, out); out = double_emit(":FOR_THEN_", number_string, out, false);
require_char("ERROR in process_for\nMISSING )\n", ')'); require_char("ERROR in process_for\nMISSING )\n", ')');
out = statement(out, function); out = statement(out, function);
asprintf(&label, "JUMP %c%s_ITER_%d\n:FOR_END_%d\n", 37, "FOR", number, number); out = double_emit("JUMP %FOR_ITER_", number_string, out, false);
out = emit(label, true, out); out = double_emit(":FOR_END_", number_string, out, false);
return out; return out;
} }
@ -590,8 +616,8 @@ struct token_list* process_asm(struct token_list* out)
require_char("ERROR in process_asm\nMISSING (\n", '('); require_char("ERROR in process_asm\nMISSING (\n", '(');
while('"' == global_token->s[0]) while('"' == global_token->s[0])
{ {
out = emit((global_token->s + 1), true, out); out = emit((global_token->s + 1), out);
out = emit("\n", true, out); out = emit("\n", out);
global_token = global_token->next; global_token = global_token->next;
} }
require_char("ERROR in process_asm\nMISSING )\n", ')'); require_char("ERROR in process_asm\nMISSING )\n", ')');
@ -603,26 +629,23 @@ struct token_list* process_asm(struct token_list* out)
int while_count; int while_count;
struct token_list* process_while(struct token_list* out, struct token_list* function) struct token_list* process_while(struct token_list* out, struct token_list* function)
{ {
char* label; char* number_string = numerate_number(while_count);
int number = while_count;
while_count = while_count + 1; while_count = while_count + 1;
asprintf(&label, ":WHILE_%d\n", number); out = double_emit(":WHILE_", number_string, out, false);
out = emit(label, true, out);
global_token = global_token->next; global_token = global_token->next;
require_char("ERROR in process_while\nMISSING (\n", '('); require_char("ERROR in process_while\nMISSING (\n", '(');
out = expression(out, function); out = expression(out, function);
asprintf(&label, "TEST\nJUMP_EQ %c%s_WHILE_%d\n# THEN_while_%d\n", 37, "END", number, number); out = double_emit("TEST\nJUMP_EQ %END_WHILE_", number_string, out, false);
out = emit(label, true, out); out = double_emit("# THEN_while_", number_string, out, false);
require_char("ERROR in process_while\nMISSING )\n", ')'); require_char("ERROR in process_while\nMISSING )\n", ')');
out = statement(out, function); out = statement(out, function);
asprintf(&label, "JUMP %c%s_%d\n:END_WHILE_%d\n", 37, "WHILE", number, number); out = double_emit("JUMP %WHILE_", number_string, out, false);
out = emit(label, true, out); out = double_emit(":END_WHILE_", number_string, out, false);
return out; return out;
} }
@ -634,14 +657,12 @@ struct token_list* return_result(struct token_list* out, struct token_list* func
require_char("ERROR in return_result\nMISSING ;\n", ';'); require_char("ERROR in return_result\nMISSING ;\n", ';');
for(struct token_list* i = function->locals; NULL != i; i = i->locals) for(struct token_list* i = function->locals; NULL != i; i = i->next)
{ {
char* label; out = emit("POP_ebx\t# _return_result_locals\n", out);
asprintf(&label, "POP_ebx\t# %s\n", "_return_result_locals"); function->locals = function->locals->next;
out = emit(label, true, out);
function->locals = function->locals->locals;
} }
out = emit("RETURN\n", true, out); out = emit("RETURN\n", out);
return out; return out;
} }
@ -659,12 +680,10 @@ struct token_list* recursive_statement(struct token_list* out, struct token_list
/* Clean up any locals added */ /* Clean up any locals added */
if(NULL != function->locals) if(NULL != function->locals)
{ {
for(struct token_list* i = function->locals; frame != i; i = i->locals) for(struct token_list* i = function->locals; frame != i; i = i->next)
{ {
char* label; out = emit( "POP_ebx\t# _recursive_statement_locals\n", out);
asprintf(&label, "POP_ebx\t# %s\n", "_recursive_statement_locals"); function->locals = function->locals->next;
out = emit(label, true, out);
function->locals = function->locals->locals;
} }
} }
return out; return out;
@ -685,13 +704,34 @@ struct token_list* recursive_statement(struct token_list* out, struct token_list
*/ */
struct token_list* statement(struct token_list* out, struct token_list* function) struct token_list* statement(struct token_list* out, struct token_list* function)
{ {
if(global_token->s[0] == '{') out = recursive_statement(out, function); if(global_token->s[0] == '{')
else if((!strcmp(global_token->s, "char")) | (!strcmp(global_token->s, "int"))) out = collect_local(out, function); {
else if(!strcmp(global_token->s, "if")) out = process_if(out, function); out = recursive_statement(out, function);
else if(!strcmp(global_token->s, "while")) out = process_while(out, function); }
else if(!strcmp(global_token->s, "for")) out = process_for(out, function); else if((!strcmp(global_token->s, "char")) | (!strcmp(global_token->s, "int")))
else if(!strcmp(global_token->s, "asm")) out = process_asm(out); {
else if(!strcmp(global_token->s, "return")) out = return_result(out, function); out = collect_local(out, function);
}
else if(!strcmp(global_token->s, "if"))
{
out = process_if(out, function);
}
else if(!strcmp(global_token->s, "while"))
{
out = process_while(out, function);
}
else if(!strcmp(global_token->s, "for"))
{
out = process_for(out, function);
}
else if(!strcmp(global_token->s, "asm"))
{
out = process_asm(out);
}
else if(!strcmp(global_token->s, "return"))
{
out = return_result(out, function);
}
else else
{ {
out = expression(out, function); out = expression(out, function);
@ -709,28 +749,19 @@ void collect_arguments(struct token_list* function)
{ {
struct type* type_size = type_name(); struct type* type_size = type_name();
if(global_token->s[0] == ')') if(global_token->s[0] == ')')
{ /* deal with foo(int,char) */
if((!type_size->_void) || (type_size->indirect))
{
struct token_list* a = calloc(1, sizeof(struct token_list));
a->arguments = function->arguments;
function->arguments = a;
}
}
else if(global_token->s[0] == ',')
{ /* deal with foo(int,char) */
struct token_list* a = calloc(1, sizeof(struct token_list));
a->arguments = function->arguments;
function->arguments = a;
global_token = global_token->next;
}
else
{ {
struct token_list* a = sym_declare(global_token->s, ARGUEMENT, type_size); /* deal with foo(int|char|void) */
a->arguments = function->arguments; global_token = global_token->prev;
function->arguments = a;
global_token = global_token->next;
} }
else if(global_token->s[0] != ',')
{
/* deal with foo(int a, char b) */
struct token_list* a = sym_declare(global_token->s, ARGUEMENT, type_size, function->arguments);
function->arguments = a;
}
/* foo(int,char,void) doesn't need anything done */
global_token = global_token->next;
/* ignore trailing comma (needed for foo(bar(), 1); expressions*/ /* ignore trailing comma (needed for foo(bar(), 1); expressions*/
if(global_token->s[0] == ',') global_token = global_token->next; if(global_token->s[0] == ',') global_token = global_token->next;
@ -740,41 +771,41 @@ void collect_arguments(struct token_list* function)
struct token_list* declare_global(struct token_list* out, struct type* type_size) struct token_list* declare_global(struct token_list* out, struct type* type_size)
{ {
char* label; /* Add to global symbol table */
asprintf(&label, "# Defining global %s\n:GLOBAL_%s\n", global_token->prev->s, global_token->prev->s); global_symbol_list = sym_declare(global_token->prev->s, GLOBAL, type_size, global_symbol_list);
out = emit(label, true, out);
sym_declare(global_token->prev->s, GLOBAL, type_size); /* Ensure 4 bytes are allocated for the global */
globals_list = double_emit(":GLOBAL_", global_token->prev->s, globals_list, true);
globals_list = emit("NOP\n", globals_list);
global_token = global_token->next; global_token = global_token->next;
return emit("NOP\n", true, out); return out;
} }
struct token_list* declare_function(struct token_list* out, struct type* type) struct token_list* declare_function(struct token_list* out, struct type* type)
{ {
char* label; char* essential = global_token->prev->s;
asprintf(&label, "# Defining function %s\n:FUNCTION_%s\n", global_token->prev->s, global_token->prev->s); struct token_list* func = sym_declare(global_token->prev->s, FUNCTION, calloc(1, sizeof(struct type)), global_symbol_list);
struct token_list* func = sym_declare(global_token->prev->s, FUNCTION, calloc(1, sizeof(struct type)));
struct token_list* current = global_symbol_list;
func->size = type; func->size = type;
collect_arguments(func); collect_arguments(func);
if(global_token->s[0] != ';') /* allow previously defined functions to be looked up */
global_symbol_list = func;
/* If just a prototype don't waste time */
if(global_token->s[0] == ';') global_token = global_token->next;
else
{ {
out = emit(label, true, out); out = double_emit("# Defining function ", essential, out, true);
out = double_emit(":FUNCTION_", essential, out, true);
out = statement(out, func); out = statement(out, func);
/* Prevent duplicate RETURNS */ /* Prevent duplicate RETURNS */
if(strcmp(out->s, "RETURN\n")) if(strcmp(out->s, "RETURN\n"))
{ {
out = emit("RETURN\n", true, out); out = emit("RETURN\n", out);
} }
} }
else
{
global_token = global_token->next;
}
global_symbol_list = current;
return out; return out;
} }
@ -803,7 +834,11 @@ struct token_list* program(struct token_list* out)
global_token = global_token->next; global_token = global_token->next;
if(global_token->s[0] == ';') out = declare_global(out, type_size); if(global_token->s[0] == ';') out = declare_global(out, type_size);
else if(global_token->s[0] == '(') out = declare_function(out, type_size); else if(global_token->s[0] == '(') out = declare_function(out, type_size);
else exit(EXIT_FAILURE); else
{
fprintf(stderr, "Recieved %s in program\n", global_token->s);
exit(EXIT_FAILURE);
}
} }
return out; return out;
} }
@ -811,20 +846,8 @@ struct token_list* program(struct token_list* out)
void recursive_output(FILE* out, struct token_list* i) void recursive_output(FILE* out, struct token_list* i)
{ {
if(NULL == i) return; if(NULL == i) return;
recursive_output(out, i->next); recursive_output(out, i->next);
fprintf(out, "%s", i->s);
if(i->hands_off) fprintf(out, "%s", i->s);
else
{
fprintf(out, "'");
for(int j = 0; 0 != i->s[j]; j = j + 1)
{
fputc(i->s[j], out);
}
fprintf(out, "'\t# NONE\n");
}
free(i);
} }
/* Our essential organizer */ /* Our essential organizer */
@ -839,9 +862,12 @@ int main(int argc, char **argv)
global_token = read_all_tokens(argv[1]); global_token = read_all_tokens(argv[1]);
struct token_list* output_list = program(NULL); struct token_list* output_list = program(NULL);
FILE* output = fopen(argv[2], "w"); FILE* output = fopen(argv[2], "w");
fprintf(output, "\n# Core program\n\n");
recursive_output(output, output_list); recursive_output(output, output_list);
fprintf(output, "\n# Program global variables\n\n");
recursive_output(output, globals_list);
fprintf(output, "\n# Program strings\n\n"); fprintf(output, "\n# Program strings\n\n");
recursive_output(output, strings); recursive_output(output, strings_list);
fclose(output); fclose(output);
return 0; return 0;
} }

3
cc.h
View File

@ -20,6 +20,8 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#define MAX_STRING 4096
struct type struct type
{ {
int size; int size;
@ -41,7 +43,6 @@ struct token_list
{ {
int length; int length;
int type; int type;
bool hands_off;
}; };
struct type* size; struct type* size;
struct token_list* arguments; struct token_list* arguments;

View File

@ -52,7 +52,7 @@ int get_token(int c)
bool w = true; bool w = true;
struct token_list* current = calloc(1, sizeof(struct token_list)); struct token_list* current = calloc(1, sizeof(struct token_list));
current->s = calloc(64, sizeof(char)); current->s = calloc(MAX_STRING, sizeof(char));
while(w) while(w)
{ {

View File

@ -18,7 +18,7 @@
#include "cc.h" #include "cc.h"
#include <stdint.h> #include <stdint.h>
struct token_list* emit(char *s, bool hands_off, struct token_list* head); struct token_list* emit(char *s, struct token_list* head);
int asprintf(char **strp, const char *fmt, ...); int asprintf(char **strp, const char *fmt, ...);
char upcase(char a) char upcase(char a)
@ -57,27 +57,82 @@ int8_t hex(int c, bool high)
return c; return c;
} }
bool weird(char c) bool weird(char* string)
{ {
if(32 > c) return true; if(0 == string[0]) return false;
if(34 == c) return true; // Don't deal with lines with " in them if('\\' == string[0])
if(126 < c) return true; {
return false; if('x' == string[1])
{
switch(string[2])
{
case '0': return true;
case '1': return true;
case '8': return true;
case '9': return true;
case 'a': return true;
case 'A': return true;
case 'b': return true;
case 'B': return true;
case 'c': return true;
case 'C': return true;
case 'd': return true;
case 'D': return true;
case 'e': return true;
case 'E': return true;
case 'f': return true;
case 'F': return true;
default: return weird(string+3);
}
}
else
{
return weird(string+3);
}
}
return weird(string+1);
} }
/* Parse string to deal with hex characters*/ /* Deal with human strings */
char table[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}; char* collect_regular_string(char* string)
struct token_list* parse_string(struct token_list* output_list, char* string)
{ {
int i = 1; int j = 0;
int j = 1; int i = 0;
int k = 0; char* message = calloc(MAX_STRING, sizeof(char));
char* hold = calloc(4096, sizeof(char));
char* message = calloc(4096, sizeof(char));
bool hexit = false;
message[0] = '"'; message[0] = '"';
while(string[j] != 0) while(string[j] != 0)
{
if((string[j] == '\\') & (string[j + 1] == 'x'))
{
int t1 = hex(string[j + 2], true);
int t2 = hex(string[j + 3], false);
message[i] = t1 + t2;
j = j + 4;
}
else
{
message[i] = string[j];
j = j + 1;
}
i = i + 1;
}
message[i] = '"';
message[i + 1] = '\n';
return message;
}
/* Deal with non-human strings */
char table[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
char* collect_weird_string(char* string)
{
int j = 1;
int k = 1;
char* hold = calloc(MAX_STRING, sizeof(char));
hold[0] = '\'';
while(string[j] != 0)
{ {
hold[k] = ' '; hold[k] = ' ';
@ -85,41 +140,30 @@ struct token_list* parse_string(struct token_list* output_list, char* string)
{ {
hold[k + 1] = upcase(string[j + 2]); hold[k + 1] = upcase(string[j + 2]);
hold[k + 2] = upcase(string[j + 3]); hold[k + 2] = upcase(string[j + 3]);
int t1 = hex(string[j + 2], true);
int t2 = hex(string[j + 3], false);
message[i] = t1 + t2;
if(weird(message[i])) hexit = true;
j = j + 4; j = j + 4;
} }
else else
{ {
hold[k + 1] = table[(string[j] >> 4)]; hold[k + 1] = table[(string[j] >> 4)];
hold[k + 2] = table[(string[j] & 15)]; hold[k + 2] = table[(string[j] & 15)];
message[i] = string[j];
j = j + 1; j = j + 1;
} }
i = i + 1;
k = k + 3; k = k + 3;
} }
hold[k] = ' '; hold[k] = ' ';
hold[k + 1] = '0'; hold[k + 1] = '0';
hold[k + 2] = '0'; hold[k + 2] = '0';
message[i] = '"'; hold[k + 3] = '\'';
message[i + 1] = '\n'; hold[k + 4] = '\n';
return hold;
/* the string */ }
if(hexit)
{ /* Parse string to deal with hex characters*/
output_list = emit(hold, false, output_list); char* parse_string(char* string)
free(message); {
} /* the string */
else if(weird(string)) return collect_weird_string(string);
{ else return collect_regular_string(string);
output_list = emit(message, true, output_list);
free(hold);
}
return output_list;
} }