810 likes | 957 Views
Virtual Machines and Compilers. Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn. Our Goal. We ’ ve defined miniC and miniPentium and written some sample programs Store them in memory But how to run these miniC and miniPentium programs? At least two approaches:
E N D
Virtual Machines and Compilers Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn
Our Goal • We’ve defined miniC and miniPentium and written some sample programs • Store them in memory • But how to run these miniC and miniPentium programs? • At least two approaches: • Compile (translate) them to real Pentium • Design and implement virtual machines • we discuss this first
What’s a Virtual Machine? • A virtual machine (VM) is machine which built with software to execute programs like a real machine • Long history: • Date back at least to 70’s last century • the Pascal P-Code, etc. • Renew industry’s interest in the recent decade • Sun’s JVM and Microsoft’s CLR, etc.
Programs Programs VM In Picture Programs Programs
Why VM Important? • Portability: • VM is relatively high-level • Easy to port to different machines • Managed code: • Easy to control the behavior of program • many may be hard to implement on real machine
CVM • A virtual machine to run miniC programs (CVM) • CVM = (store, prog) • prog is a miniC program (in assignment #2) • store is a machine memory, essentially a mapping from identifiers to numbers • store: id -> n
x x = 8; y = 9; z = x+y; print (z); y z An Example • Right hand are a sample program and a store • Store could be read and written • store (id) • store [id |-> n]
x = 8; y = 9; z = x+y; print (z); Execution
8 x x = 8; y = 9; z = x+y; print (z); Execution
8 x x = 8; y = 9; z = x+y; print (z); y 9 Execution
8 x x = 8; y = 9; z = x+y; print (z); y 9 z 17 Execution
8 x x = 8; y = 9; z = x+y; print (z); y 9 z 17 Execution // print “17” on screen terminated with a new line
Formalization We need three relations: (store, exp) -> v (store, stm) -> store’ (store, prog) -> store’ More specifically, we write them as functions: E(st, e) = v S(st, s) = st’ P(st, p) = st’ The definitions follows in next slides:
Formalization E(st, num) = num E(st, id) = st (id) E(st, e1+e2) = E(st, e1) + E(st, e2) E(st, e1-e2) = E(st, e1) - E(st, e2) E(st, e1*e2) = E(st, e1) * E(st, e2) S(st, id=e) = st [id |-> E(st, e)] S(st, print(e)) = st // print E(st, e) P(st, stm prog) = P(S(st, stm), prog) P(st, stm) = S(st, stm)
Execution // we denote store as {x1|->n1, x2|->n2, …} P({}, x=8; y=9; z=x+y; print(z))
Execution P({}, x=8; y=9; z=x+y; print(z)) => P(S({}, x=8), y=9; z=x+y; print(z))
Execution P({}, x=8; y=9; z=x+y; print(z)) => P(S({}, x=8), y=9; z=x+y; print(z)) => P({}[x |-> E({}, 8)], y=9; z=x+y; print(z))
Execution P({}, x=8; y=9; z=x+y; print(z)) => P(S({}, x=8), y=9; z=x+y; print(z)) => P({}[x |-> E({}, 8)], y=9; z=x+y; print(z)) => P({}[x |-> 8], y = 9; z=x+y; print(z))
Execution P({}, x=8; y=9; z=x+y; print(z)) => P(S({}, x=8), y=9; z=x+y; print(z)) => P({}[x |-> E({}, 8)], y=9; z=x+y; print(z)) => P({}[x |-> 8], y = 9; z=x+y; print(z)) => P({x|->8}, y=9; z=x+y; print(z))
Execution P({}, x=8; y=9; z=x+y; print(z)) => P(S({}, x=8), y=9; z=x+y; print(z)) => P({}[x |-> E({}, 8)], y=9; z=x+y; print(z)) => P({}[x |-> 8], y = 9; z=x+y; print(z)) => P({x|->8}, y=9; z=x+y; print(z)) => // the rest leave to you
What’s a Store? // Just an ADT, :-) // file “store.h” #ifndef STORE_H #define STORE_H typdef struct store *store; store newStore (); // st[id |-> n] void storeUpdate (store st, str id, nat n); // st(id) nat storeLookup (store st, str id); #endif
(x, 8) (y, 9) (z, 17) What’s a Store? // file “store.c” #include “linkedList.h” #include “store.h” struct store { linkedList list; // any representation works :-) }; // functions are straightforward
CVM Interface in C // file “cvm.h” #ifndef CVM_H #define CVM_H #include “miniC.h” void cvmRun (prog p); #endif
CVM Implementation in C // file “cvm.c” #include “miniC.h” #include “store.h” // the memory #include “cvm.h” void cvmRun (prog p) { store st = newStore (); while (p not empty) { stm = …; // take one statement from p; runStm (st, stm); } return; }
CVM Implementation in C // file “cvm.c” continued void runStm (store st, stm s) { switch (s->kind){ case ASSIGN: { // x = e; nat n = runExp (st, e); storeUpdate (st, x, n); break; } case PRINT: { // print (e) … } }}
CVM Implementation in C // file “cvm.c” continued nat runExp (store st, exp e) { switch (e->kind){ case ADD: { // e1 + e2; nat n1 = runExp (st, e1); nat n2 = runExp (st, e2); nat n = n1+n2; return n; } case … : // other cases are similar } }
Client Code #include “miniC.h” #include “cvm.h” int main() { // build the syntax tree for: // p = “x = 8; y = 9; z = x+y; print(z);” cvmRun (p); return 0; }
PVM---miniPentium VM • The design and implementation of a virtual machine PVM for miniPentium is similar • Some modules may be even reused • say the “store” module • And also, the Java implementation for CVM and PVM is similar • All leave to you
What’s a Stack Machine? • A stack machine has few (if no) registers, and all computation is done on a stack • hence the name • popular in 60-70’ last century, but rare now • What’s the pros and cons of it? • Answer this after we implement it
Stack Machine for CVM • SCVM (Stack-based C Virtual Machine) • SCVM is a triple: (store, stack, prog) • the new part is a stack • Operations on stack: • push, pop • +, -, *, print (all implicit call pop) • +: push(stk, pop(stk)+pop(stk))
Formalization We need three relations: (store, stack, exp) -> stack’ (store, stack, stm) -> store’ (store, stack, prog) -> store’ More specifically, we write them as functions: E(st, stk, e) = stk’ S(st, stk, s) = st’ P(st, stk, p) = st’ The definitions follows in next slides:
Formalization E(st, stk, num) = push(stk, num) E(st, stk, id) = push(stk, st (id)) E(st, stk, e1+e2) = E(st, stk, e1); E(st, stk, e2); + E(st, stk, e1-e2) = E(st, stk, e1); E(st, stk, e2); - E(st, stk, e1*e2) = E(st, stk, e1); E(st, stk, e2); * S(st, stk, id=e) = st [id |->(E(st, e); pop(stk)] S(st, stk, print(e)) = st // print E(st, stk, e) P(st, stk, stm prog) = P(S(st, stm), stk, prog) P(st, stk, stm) = S(st, stk, stm)
x x = 8; y = 9; z = x+y; print (z); y z An Example • Right hand are a sample program, a store and a stack top
x = 8; y = 9; z = x+y; print (z); Execution top ####
x = 8; y = 9; z = x+y; print (z); Execution top 8 ####
8 x x = 8; y = 9; z = x+y; print (z); Execution top ####
8 x x = 8; y = 9; z = x+y; print (z); Execution top 9 ####
8 x x = 8; y = 9; z = x+y; print (z); y 9 Execution top ####
8 x x = 8; y = 9; z = x+y; print (z); y 9 Execution top 8 ####
8 x x = 8; y = 9; z = x+y; print (z); y 9 Execution top 9 8 ####
8 x x = 8; y = 9; z = x+y; print (z); y 9 Execution top 17 ####
8 x x = 8; y = 9; z = x+y; print (z); y 9 z 17 Execution top ####
8 x x = 8; y = 9; z = x+y; print (z); y 9 z 17 Execution top 17 ####
8 x x = 8; y = 9; z = x+y; print (z); y 9 z 17 Execution // print “17” on screen terminated with a new line top ####
Implementation • It’s relatively straightforward to implement all these above stuffs • Leave to you • A stack-based virtual machine for miniPentium (SPVM) is similar • However, some instructions should be revised to make the stack operations explicit
Stack Machine Summary • Tow machine models: • register machines (CVM, PVM) • stack machines (SCVM, SPVM) • What are the pros and cons of stack machines and register machines? • Why real machines are register-based? • Say: Pentium, MIPS, ARM, … • Why virtual machines are stack-based? • Say: P-Code, JVM, CLR, …
A Compiler miniVC from miniC to miniPentium
What’s a Compiler? • A compiler is a program that takes as input programs written in one (typically high-level) language, and output equivalent programs written in another (typically low-level) language High-level Programs Compiler Low-level Programs