diff --git a/src/vm/Bytecode.java b/src/vm/Bytecode.java index bc75b9b..fa7af64 100644 --- a/src/vm/Bytecode.java +++ b/src/vm/Bytecode.java @@ -49,7 +49,7 @@ public Instruction(String name, int nargs) { new Instruction("gstore", 1), new Instruction("print"), new Instruction("pop"), - new Instruction("call", 2), // call addr, nargs + new Instruction("call", 1), // call index of function in meta-info table new Instruction("ret"), new Instruction("halt") }; diff --git a/src/vm/FuncMetaData.java b/src/vm/FuncMetaData.java new file mode 100644 index 0000000..1727a1e --- /dev/null +++ b/src/vm/FuncMetaData.java @@ -0,0 +1,15 @@ +package vm; + +public class FuncMetaData { + public String name; + public int nargs; + public int nlocals; + public int address; // bytecode address + + public FuncMetaData(String name, int nargs, int nlocals, int address) { + this.name = name; + this.nargs = nargs; + this.nlocals = nlocals; + this.address = address; + } +} diff --git a/src/vm/Test.java b/src/vm/Test.java index 33b48ee..d23a744 100644 --- a/src/vm/Test.java +++ b/src/vm/Test.java @@ -57,9 +57,11 @@ public class Test { HALT // 24 }; - static int fact = 0; + static int FACTORIAL_INDEX = 0; + static int FACTORIAL_ADDRESS = 0; + static int MAIN_ADDRESS = 21; static int[] factorial = { -//.def fact: ARGS=1, LOCALS=0 ADDRESS +//.def factorial: ARGS=1, LOCALS=0 ADDRESS // IF N < 2 RETURN 1 LOAD, 0, // 0 ICONST, 2, // 2 @@ -73,19 +75,24 @@ public class Test { LOAD, 0, // 12 ICONST, 1, // 14 ISUB, // 16 - CALL, fact, 1, // 17 - IMUL, // 20 - RET, // 21 + CALL, FACTORIAL_INDEX, // 17 + IMUL, // 19 + RET, // 20 //.DEF MAIN: ARGS=0, LOCALS=0 // PRINT FACT(1) - ICONST, 5, // 22 <-- MAIN METHOD! - CALL, fact, 1, // 24 - PRINT, // 27 - HALT // 28 + ICONST, 5, // 21 <-- MAIN METHOD! + CALL, FACTORIAL_INDEX, // 23 + PRINT, // 25 + HALT // 26 + }; + + static FuncMetaData[] metadata = { + //.def factorial: ARGS=1, LOCALS=0 ADDRESS + new FuncMetaData("factorial", 1, 0, FACTORIAL_ADDRESS) }; public static void main(String[] args) { - VM vm = new VM(factorial, 22, 0); + VM vm = new VM(factorial, MAIN_ADDRESS, 0, metadata); vm.trace = true; vm.exec(); } diff --git a/src/vm/VM.java b/src/vm/VM.java index 570cc3e..e1d58b3 100644 --- a/src/vm/VM.java +++ b/src/vm/VM.java @@ -42,14 +42,25 @@ public class VM { int[] stack; // Operand stack, grows upwards Context[] callstack;// call stack, grows upwards + /** Metadata about the functions allows us to refer to functions by + * their index in this table. It makes code generation easier for + * the bytecode compiler because it doesn't have to resolve + * addresses for forward references. It can generate simply + * "CALL i" where i is the index of the function. Later, the + * compiler can store the function address in the metadata table + * when the code is generated for that function. + */ + FuncMetaData[] metadata; + public boolean trace = false; - public VM(int[] code, int startip, int nglobals) { + public VM(int[] code, int startip, int nglobals, FuncMetaData[] metadata) { this.code = code; this.startip = startip; globals = new int[nglobals]; stack = new int[DEFAULT_STACK_SIZE]; callstack = new Context[DEFAULT_CALL_STACK_SIZE]; + this.metadata = metadata; } public void exec() { @@ -127,15 +138,15 @@ protected void cpu() { break; case CALL : // expects all args on stack - addr = code[ip++]; // target addr of function - int nargs = code[ip++]; // how many args got pushed + int findex = code[ip++]; // index of target function + int nargs = metadata[findex].nargs; // how many args got pushed callstack[++callsp] = new Context(ip,nargs); // copy args into new context for (int i=0; i