From 77124400643fd0dfbc6dd68d50d5f98bbdb1a985 Mon Sep 17 00:00:00 2001 From: AlexVanin Date: Mon, 27 Jan 2014 16:09:25 +0400 Subject: [PATCH] Added support for functions and dynamic contexts. Improved work with constant pool --- VaninVM/CodeHeader.h | 39 ++++++++++++++++++++++++++++++ VaninVM/Context.c | 33 ++++++++++++++++++++++++++ VaninVM/Context.h | 27 +++++++++++++++++++++ VaninVM/IOcode.c | 55 ++++++++++++++++++++++++++++++------------- VaninVM/IOcode.h | 3 ++- VaninVM/Main.c | 43 +++++++++++++++++++++++---------- VaninVM/OpCode.h | 4 +++- VaninVM/ReturnStack.c | 20 ++++++++++++++++ VaninVM/ReturnStack.h | 9 +++++++ 9 files changed, 202 insertions(+), 31 deletions(-) create mode 100644 VaninVM/CodeHeader.h create mode 100644 VaninVM/Context.c create mode 100644 VaninVM/Context.h create mode 100644 VaninVM/ReturnStack.c create mode 100644 VaninVM/ReturnStack.h diff --git a/VaninVM/CodeHeader.h b/VaninVM/CodeHeader.h new file mode 100644 index 0000000..8e00649 --- /dev/null +++ b/VaninVM/CodeHeader.h @@ -0,0 +1,39 @@ +#ifndef CODE_HEADER +#define CODE_HEADER +#pragma pack(push, 1) +struct +{ + char signature[4]; + int version; + int count_const; + int size_const; +}First_Header; + +struct +{ + short id_start; + int count_code; +}ByteCodeH_Common; + +struct +{ + int size_func; + int size_bytecode; + int size_signature; +}ByteCodeH_Signat; + +struct +{ + short id; + int count_locals; + int count_args; +}ByteCodeH_Primary; + +typedef struct +{ + int count_locals; + int count_args; + char* code; +} func; +#endif +#pragma pop \ No newline at end of file diff --git a/VaninVM/Context.c b/VaninVM/Context.c new file mode 100644 index 0000000..b798f11 --- /dev/null +++ b/VaninVM/Context.c @@ -0,0 +1,33 @@ +#include "Context.h" +#include +context* create_context(int function, func** hash, char** code) +{ + context* cont; + cont = (context*)malloc(sizeof(context)); + + cont->id = function; + cont->locals=malloc(8*hash[function]->count_locals); + *(code)=hash[function]->code; + return cont; +} + +void remove_context(context* cont) +{ + free(cont->locals); + free(cont); +} + +void push_context(context* cont) +{ + c_node* node; + node = (c_node*)malloc(sizeof(c_node)); + node->obj=cont; + node->prev = node_last; + node_last = node; +} +context* pop_context() +{ + c_node* last = node_last; + node_last = node_last->prev; + return last->obj; +} \ No newline at end of file diff --git a/VaninVM/Context.h b/VaninVM/Context.h new file mode 100644 index 0000000..d0208e3 --- /dev/null +++ b/VaninVM/Context.h @@ -0,0 +1,27 @@ +#ifndef CONTEXT_H +#define CONTEXT_H + +#include "CodeHeader.h" +#include + + +typedef struct +{ + int id; + void* locals; +} context; + +typedef struct NODE +{ + context* obj; + struct NODE* prev; +} c_node; + +c_node* node_last; + +context* create_context(int function, func** hash,char** code); +void push_context(context*); +context* pop_context(); +void remove_context(context*); + +#endif \ No newline at end of file diff --git a/VaninVM/IOcode.c b/VaninVM/IOcode.c index c9c3c21..43b898c 100644 --- a/VaninVM/IOcode.c +++ b/VaninVM/IOcode.c @@ -1,12 +1,37 @@ #include "IOcode.h" #include "CodeHeader.h" +#include -char* read_bytecode(FILE* stream) +int read_bytecode(FILE* stream, func*** hash) { - char* buffer = (char*)calloc(1, 1000); //Early version without bytecode file - fread_s(buffer, 1000, sizeof(char), 1000, stream); //Early version without bytecode file + int i; + char* name; + char* code; + func* function; + + *(hash) = (func**)malloc(sizeof(func*)*65536); + fread_s(&ByteCodeH_Common, sizeof(ByteCodeH_Common), sizeof(ByteCodeH_Common), 1, stream); + + for (i=0; icode=code; + function->count_args=ByteCodeH_Primary.count_args; + function->count_locals=ByteCodeH_Primary.count_locals; + (*(hash))[ByteCodeH_Primary.id]=function; + } + return ByteCodeH_Common.id_start; - return buffer; } int read_constant(FILE* stream, int* count, char*** index) @@ -17,24 +42,22 @@ int read_constant(FILE* stream, int* count, char*** index) fread_s(&First_Header, sizeof(First_Header), sizeof(First_Header), 1, stream); //Reading first part of header *(count) = First_Header.count_const; - buffer = (char*)malloc(First_Header.size_const); - *(index) = (char**)malloc(sizeof(char**)*2); + buffer = (char*)malloc(First_Header.size_const+1); + buffer[0]=0; + *(index) = (char**)malloc(sizeof(char**)*First_Header.count_const); - fread_s(buffer, First_Header.size_const, sizeof(char), First_Header.size_const, stream); //Reading constant values + fread_s(buffer+1, First_Header.size_const, sizeof(char), First_Header.size_const, stream); //Reading constant values j=0; - if (First_Header.count_const>0) + (*(index))[j++]=buffer; + for (i = 0; i #include -char* read_bytecode(FILE*); +int read_bytecode(FILE*, func***); int read_constant(FILE*, int*, char***); #endif \ No newline at end of file diff --git a/VaninVM/Main.c b/VaninVM/Main.c index ed562bf..cb96402 100644 --- a/VaninVM/Main.c +++ b/VaninVM/Main.c @@ -2,6 +2,8 @@ #include "TOS.h" #include "OpCode.h" #include "CodeHeader.h" +#include "Context.h" +#include "ReturnStack.h" @@ -15,29 +17,33 @@ int main(int argc, char** argv) long long i1, i2; short s1; char* code; - int ip; + int ip, startfunc; //ConstSection Variables int const_count; char** const_index; - //Execution Variable + //CodeSection Variables + func** phash_table; + context* current_context; + + //Running Variable int exec_status = 1; fopen_s(&input, "bytecode", "rb"); - //const_pull read_constant(input, &const_count, &const_index); - - code=read_bytecode(input); - + //code_pull + startfunc = read_bytecode(input, &phash_table); fclose(input); initTOS(); - + initRStack(); ip = 0; + current_context = create_context(startfunc, phash_table, &code); + while (exec_status) { switch (code[ip]) @@ -54,11 +60,11 @@ int main(int argc, char** argv) //DO(ILOAD, "Load int on TOS, inlined into insn stream.", 9) i1 = *((long long*)(code+(++ip))); push_int(i1); - ip++; break; + ip+=8; break; case SLOAD: s1 = *((short*)(code+(++ip))); push_int((long long)(const_index[s1])); - ip++; break; + ip+=2; break; case DLOAD0: // DO(DLOAD0, "Load double 0 on TOS.", 1) push_double(0); @@ -173,18 +179,16 @@ int main(int argc, char** argv) case IPRINT: //DO(IPRINT, "Pop and print integer TOS.", 1) i1 = pop_int(); - push_int(i1); printf("%d", i1); ip++; break; case DPRINT: //DO(DPRINT, "Pop and print double TOS.", 1) d1 = pop_double(); - push_double(d1); printf("%f", d1); ip++; break; case SPRINT: + //DO(SPRINT, "Pop and print string TOS.", 1) i1 = pop_int(); - push_int(i1); printf("%s", (char*)i1); ip++; break; case I2D: @@ -213,9 +217,22 @@ int main(int argc, char** argv) case STOP: //DO(STOP, "Stop execution.", 1) exec_status = 0; - break; + break; + case CALL: + s1 = *((short*)(code+(++ip))); + ip+=2; push_ret(ip); + push_context(current_context); + current_context = create_context(s1, phash_table, &code); + ip = 0; break; + case RETURN: + remove_context(current_context); + current_context = pop_context(); + code = phash_table[current_context->id]->code; + ip = pop_ret(); break; + } } + remove_context(current_context); getchar(); return 0; } \ No newline at end of file diff --git a/VaninVM/OpCode.h b/VaninVM/OpCode.h index ee490e1..af9e9da 100644 --- a/VaninVM/OpCode.h +++ b/VaninVM/OpCode.h @@ -33,6 +33,8 @@ enum opcode D2I, SWAP, POP, - STOP + STOP, + CALL, + RETURN }; #endif \ No newline at end of file diff --git a/VaninVM/ReturnStack.c b/VaninVM/ReturnStack.c new file mode 100644 index 0000000..45e33b1 --- /dev/null +++ b/VaninVM/ReturnStack.c @@ -0,0 +1,20 @@ +#include +#include "ReturnStack.h" + +void push_ret(int num) +{ + RStack[rp++] = num; +} + +int pop_ret() +{ + int num = RStack[--rp]; + return num; +} + +int initRStack() +{ + RStack = (int*)calloc(1, 1000); + rp = 0; + return 0; +} \ No newline at end of file diff --git a/VaninVM/ReturnStack.h b/VaninVM/ReturnStack.h new file mode 100644 index 0000000..317baf1 --- /dev/null +++ b/VaninVM/ReturnStack.h @@ -0,0 +1,9 @@ +#ifndef RETURNSTACK_H +#define RETURNSTACK_H + +int* RStack; +int rp; +int initRStack(); +void push_ret(int); +int pop_ret(); +#endif \ No newline at end of file