From fdbb57778478cf5c936c3ac6e8e258dd1c877760 Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Wed, 2 May 2018 20:56:44 -0400 Subject: [PATCH] Added support for passing of function pointers via FUNCTION --- cc_core.c | 124 +++++++++++++++++++++++--------------- cc_types.c | 9 +++ makefile | 5 ++ test/test.answers | 3 +- test/test100/proof.answer | 2 +- test/test20/.gitignore | 6 ++ test/test20/cleanup.sh | 4 ++ test/test20/gcc_req.h | 18 ++++++ test/test20/hello.sh | 29 +++++++++ test/test20/struct.c | 59 ++++++++++++++++++ 10 files changed, 207 insertions(+), 52 deletions(-) create mode 100644 test/test20/.gitignore create mode 100755 test/test20/cleanup.sh create mode 100644 test/test20/gcc_req.h create mode 100755 test/test20/hello.sh create mode 100644 test/test20/struct.c diff --git a/cc_core.c b/cc_core.c index 6a2afab..c9b5875 100644 --- a/cc_core.c +++ b/cc_core.c @@ -97,6 +97,51 @@ int stack_index(struct token_list* a, struct token_list* function) exit(EXIT_FAILURE); } +struct token_list* expression(struct token_list* out, struct token_list* function); +struct token_list* function_call(struct token_list* out, struct token_list* function, char* s, int bool) +{ + require_match("ERROR in process_expression_list\nNo ( was found\x0A", "("); + int passed = 0; + + if(global_token->s[0] != ')') + { + out = expression(out, function); + out = emit("PUSH_eax\t#_process_expression1\x0A", out); + function->temps = function->temps + 1; + passed = 1; + + while(global_token->s[0] == ',') + { + global_token = global_token->next; + out = expression(out, function); + out = emit("PUSH_eax\t#_process_expression2\x0A", out); + function->temps = function->temps + 1; + passed = passed + 1; + } + } + + require_match("ERROR in process_expression_list\nNo ) was found\n", ")"); + + if(bool) + { + struct token_list* a = sym_lookup(s, function->arguments); + out = emit(prepend_string("LOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function))), out); + out = emit("LOAD_INTEGER\n", out); + out = emit("CALL_eax\n", out); + } + else + { + out = emit(prepend_string("CALL_IMMEDIATE %FUNCTION_", postpend_char(s, LF)), out); + } + + for(; passed > 0; passed = passed - 1) + { + out = emit("POP_ebx\t# _process_expression_locals\x0A", out); + function->temps = function->temps - 1; + } + return out; +} + struct token_list* sym_get_value(char *s, struct token_list* out, struct token_list* function) { global_token = global_token->next; @@ -106,12 +151,6 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l out = emit(prepend_string("LOAD_IMMEDIATE_eax %", postpend_char(a->arguments->s, LF)), out); return out; } - a= sym_lookup(s, global_function_list); - if(NULL != a) - { - return out; - } - a= sym_lookup(s, function->locals); if(NULL != a) { @@ -120,16 +159,40 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l if(!match("=", global_token->s)) out = emit("LOAD_INTEGER\x0A", out); return out; } - a = sym_lookup(s, function->arguments); + a = sym_lookup(s, function->arguments); if(NULL != a) { current_target = a->type; + if(match("FUNCTION", a->type->name)) + { + if(!match("(", global_token->s)) + { + out = emit(prepend_string("#Loading address of function\nLOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function))), out); + out = emit("LOAD_INTEGER\n", out); + return out; + } + return function_call(out, function, s, TRUE); + } out = emit(prepend_string("LOAD_EFFECTIVE_ADDRESS %", numerate_number(stack_index(a, function))), out); if(!match("=", global_token->s) && !match("argv", s)) out = emit("LOAD_INTEGER\x0A", out); return out; } + a= sym_lookup(s, global_function_list); + if(NULL != a) + { + if(!match("(", global_token->s)) + { + out = emit(prepend_string("LOAD_IMMEDIATE_eax &FUNCTION_", postpend_char(s, LF)), out); + return out; + } + else + { + return function_call(out, function, s, FALSE); + } + } + a = sym_lookup(s, global_symbol_list); if(NULL != a) { @@ -144,8 +207,6 @@ struct token_list* sym_get_value(char *s, struct token_list* out, struct token_l exit(EXIT_FAILURE); } -struct token_list* expression(struct token_list* out, struct token_list* function); - /* * primary-expr: * identifier @@ -203,42 +264,6 @@ struct token_list* primary_expr(struct token_list* out, struct token_list* funct return out; } -/* Deal with Expression lists */ -struct token_list* process_expression_list(struct token_list* out, struct token_list* function) -{ - char* func = global_token->prev->s; - global_token = global_token->next; - int temp = function->temps; - - if(global_token->s[0] != ')') - { - out = expression(out, function); - out = emit("PUSH_eax\t#_process_expression1\x0A", out); - function->temps = function->temps + 1; - - while(global_token->s[0] == ',') - { - global_token = global_token->next; - out = expression(out, function); - out = emit("PUSH_eax\t#_process_expression2\x0A", out); - function->temps = function->temps + 1; - } - require_match("ERROR in process_expression_list\nNo ) was found\x0A", ")"); - } - else global_token = global_token->next; - - out = emit(prepend_string("CALL_IMMEDIATE %FUNCTION_", postpend_char(func, LF)), out); - - int i; - for(i = function->temps - temp; 0 != i; i = i - 1) - { - out = emit("POP_ebx\t# _process_expression_locals\x0A", out); - } - - function->temps = temp; - return out; -} - struct type* last_type; struct token_list* pre_recursion(struct token_list* out, struct token_list* func) @@ -352,10 +377,6 @@ struct token_list* postfix_expr(struct token_list* out, struct token_list* funct } require_match("ERROR in postfix_expr\nMissing ]\x0A", "]"); } - else if(global_token->s[0] == '(') - { - out = process_expression_list(out, function); - } else if(match("->", global_token->s)) { out = emit("# looking up offset\x0A", out); @@ -744,7 +765,10 @@ struct token_list* process_for(struct token_list* out, struct token_list* functi global_token = global_token->next; require_match("ERROR in process_for\nMISSING (\x0A", "("); - out = expression(out, function); + if(!match(";",global_token->s)) + { + out = expression(out, function); + } out = emit(prepend_string(":FOR_", number_string), out); diff --git a/cc_types.c b/cc_types.c index adf3a21..e3a08f7 100644 --- a/cc_types.c +++ b/cc_types.c @@ -61,7 +61,16 @@ void initialize_types() /* FILE* has the same properties as FILE */ d->indirect = d; + /* Define FUNCTION */ + struct type* e = calloc(1, sizeof(struct type)); + e->name = "FUNCTION"; + e->size = 4; + e->type = e; + /* FUNCTION* has the same properties as FUNCTION */ + e->indirect = e; + /* Finalize type list */ + d->next = e; c->next = d; a->next = c; global_types->next = a; diff --git a/makefile b/makefile index be1010f..4a88e29 100644 --- a/makefile +++ b/makefile @@ -51,6 +51,7 @@ clean: ./test/test17/cleanup.sh ./test/test18/cleanup.sh ./test/test19/cleanup.sh + ./test/test20/cleanup.sh ./test/test99/cleanup.sh ./test/test100/cleanup.sh @@ -82,6 +83,7 @@ test: test00-binary \ test17-binary \ test18-binary \ test19-binary \ + test20-binary \ test99-binary \ test100-binary | results sha256sum -c test/test.answers @@ -146,6 +148,9 @@ test18-binary: M2-Planet | results test19-binary: M2-Planet | results test/test19/hello.sh +test20-binary: M2-Planet | results + test/test20/hello.sh + test99-binary: M2-Planet | results test/test99/hello.sh diff --git a/test/test.answers b/test/test.answers index fe91b93..e36d066 100644 --- a/test/test.answers +++ b/test/test.answers @@ -9,7 +9,7 @@ d27eb315d694324650b11a421d6990eee60ac5921a5625bbccb43d806f09e156 test/results/t 8cc38294fb1261843cfc3956fad5a451c95bbc2ed687435d4e2d59df2c4a8567 test/results/test08-binary cc8f252877a85c0d7832094ff574d7173ac33940917bc1591358b8970651a81c test/results/test09-binary 3857aee4183de41bd00b014d616a5d73f4bfc57aa60a6073bb4113d6ff2fb8d5 test/results/test10-binary -a5764dc3aa8b9021beb2388d42357653315a21b0111a5c15f9e82301d88b5a79 test/results/test100-binary +9d70fbcb87a3002f8d6f8831d421926b482544f5363fd291387b57e34fb57f3e test/results/test100-binary dce2f0b35323cf6a2b01f74a9335100f2d8626028af545832dbdb503573db0e5 test/results/test11-binary 88602970fa07b5da7a42b4f2b2486fe03accc6796e05453c4ab934e986790bef test/results/test12-binary c85a57b5b1d65288efd47a3b12c6fca1efade9e7ec91e65efda5531d2c40d293 test/results/test13-binary @@ -19,4 +19,5 @@ b1de0d8c35068420d8f15d2fea74496e4f86c905f7c1b8601d569cd5c61d2796 test/results/t 15f1fc51d559b74d7515d3e978a835f7edc765f0763fdbae328f4b03a6b2b92b test/results/test17-binary f2245dea4a08a26f1f63383acedd5a67e918b8c9d8e484f037aee7b71c7f8a50 test/results/test18-binary 6f1331ad820cdf9d45506eaac3053b80f4357fe955c30a113d1ec2bf829d79a2 test/results/test19-binary +6fa44153ee3f27f0df49b282c0bb3017dbfaea906073c8c02b8bf5ad4d4a7860 test/results/test20-binary ba3d9623c6512bc327cf934d994e5327e5fad3f7500896e2d8458467fae9b9e9 test/results/test99-binary diff --git a/test/test100/proof.answer b/test/test100/proof.answer index d303d49..c104982 100644 --- a/test/test100/proof.answer +++ b/test/test100/proof.answer @@ -1 +1 @@ -aacd70427396379f16862809eacd1a881b74e0ceafd6b99304f74e2893e48b98 test/test100/proof +ebee1401bceb90f543c7656d98264271ce477f527470f5050d5cdb8c8871cb86 test/test100/proof diff --git a/test/test20/.gitignore b/test/test20/.gitignore new file mode 100644 index 0000000..e483926 --- /dev/null +++ b/test/test20/.gitignore @@ -0,0 +1,6 @@ +# Ignore the files created by script +*.M1 +*.hex2 + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test20/cleanup.sh b/test/test20/cleanup.sh new file mode 100755 index 0000000..3aa2aba --- /dev/null +++ b/test/test20/cleanup.sh @@ -0,0 +1,4 @@ +#! /bin/sh +rm -f test/test20/struct.M1 +rm -f test/test20/struct.hex2 +exit 0 diff --git a/test/test20/gcc_req.h b/test/test20/gcc_req.h new file mode 100644 index 0000000..4d6c907 --- /dev/null +++ b/test/test20/gcc_req.h @@ -0,0 +1,18 @@ +/* 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 . + */ + +typedef int (FUNCTION)(int); diff --git a/test/test20/hello.sh b/test/test20/hello.sh new file mode 100755 index 0000000..288eac3 --- /dev/null +++ b/test/test20/hello.sh @@ -0,0 +1,29 @@ +#! /bin/sh +set -x +# Build the test +bin/M2-Planet -f test/functions/putchar.c \ + -f test/functions/exit.c \ + -f test/functions/malloc.c \ + -f test/test20/struct.c \ + -o test/test20/struct.M1 || exit 1 + +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 \ + -f test/functions/libc-core.M1 \ + -f test/test20/struct.M1 \ + --LittleEndian \ + --Architecture 1 \ + -o test/test20/struct.hex2 || exit 2 + +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386.hex2 -f test/test20/struct.hex2 --LittleEndian --Architecture 1 --BaseAddress 0x8048000 -o test/results/test20-binary --exec_enable || exit 3 + +# Ensure binary works if host machine supports test +if [ "$(get_machine)" = "x86_64" ] +then + # Verify that the compiled program returns the correct result + out=$(./test/results/test20-binary 2>&1 ) + [ 20 = $? ] || exit 4 + [ "$out" = "35419896642975313541989657891634" ] || exit 5 +fi +exit 0 diff --git a/test/test20/struct.c b/test/test20/struct.c new file mode 100644 index 0000000..bc46108 --- /dev/null +++ b/test/test20/struct.c @@ -0,0 +1,59 @@ +/* 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 "gcc_req.h" + +struct foo +{ + struct foo* next; + struct foo* prev; + FUNCTION* run; + int a; + int b; +}; + +void print_hex(int a, int count, FUNCTION foo2) +{ + if(count <= 0) return; + print_hex(a >> 4, count - 1, foo2); + foo2((a & 15) + 48); +} + +int main() +{ + struct foo* a = malloc(sizeof(struct foo)); + struct foo* b = malloc(sizeof(struct foo)); + + a->run = putchar; + a->a = 0x35419896; + a->b = 0x57891634; + b->a = 0x13579246; + b->b = 0x64297531; + a->next = b; + a->prev = b; + b->next = a; + b->prev = a; + + print_hex(a->next->next->a, 8, a->run); + print_hex(b->prev->prev->b, 8, putchar); + print_hex(b->next->a, 8, putchar); + print_hex(b->prev->b, 8, putchar); + putchar(10); + return sizeof(struct foo); +}