Added support for passing of function pointers via FUNCTION

This commit is contained in:
Jeremiah Orians 2018-05-02 20:56:44 -04:00
parent a035d955e9
commit fdbb577784
No known key found for this signature in database
GPG Key ID: 7457821534D2ACCD
10 changed files with 207 additions and 52 deletions

124
cc_core.c
View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -1 +1 @@
aacd70427396379f16862809eacd1a881b74e0ceafd6b99304f74e2893e48b98 test/test100/proof
ebee1401bceb90f543c7656d98264271ce477f527470f5050d5cdb8c8871cb86 test/test100/proof

6
test/test20/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
# Ignore the files created by script
*.M1
*.hex2
# A place to put a good run for comparison
actual.M1

4
test/test20/cleanup.sh Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
rm -f test/test20/struct.M1
rm -f test/test20/struct.hex2
exit 0

18
test/test20/gcc_req.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
typedef int (FUNCTION)(int);

29
test/test20/hello.sh Executable file
View File

@ -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

59
test/test20/struct.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include<stdlib.h>
#include<stdio.h>
#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);
}