Date post: | 20-Dec-2015 |
Category: |
Documents |
View: | 229 times |
Download: | 2 times |
Our Goal We’ve defined miniC and miniPentium an
d 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.
In Picture
Programs Programs
VM
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
An Example
Right hand are a sample program and a store
Store could be read and written store (id) store [id |-> n]
x
z
yx = 8;
y = 9;
z = x+y;
print (z);
Execution
x = 8;
y = 9;
z = x+y;
print (z);
Execution
8xx = 8;
y = 9;
z = x+y;
print (z);
Execution
8
9xy
x = 8;
y = 9;
z = x+y;
print (z);
Execution
8
9
17
x
z
yx = 8;
y = 9;
z = x+y;
print (z);
Execution
8
9
17
x
z
yx = 8;
y = 9;
z = x+y;
print (z);
// print “17” on screen terminated with a new line
FormalizationWe need three relations:(store, exp) -> v(store, stm) -> store’(store, prog) -> store’
More specifically, we write them as functions:E(st, e) = vS(st, s) = st’P(st, p) = st’
The definitions follows in next slides:
FormalizationE(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))
ExecutionP({}, x=8; y=9; z=x+y; print(z)) =>
P(S({}, x=8), y=9; z=x+y; print(z))
ExecutionP({}, 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))
ExecutionP({}, 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))
ExecutionP({}, 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))
ExecutionP({}, 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
CVM in C
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
What’s a Store?// file “store.c”#include “linkedList.h”#include “store.h”
struct store{ linkedList list; // any representation works :-)};
// functions are straightforward
(x, 8) (y, 9) (z, 17)
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 v
irtual 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
Stack Machine
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))
FormalizationWe 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:
FormalizationE(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)
An Example
Right hand are a sample program, a store and a stack
x
z
yx = 8;
y = 9;
z = x+y;
print (z);
top
Execution
x = 8;
y = 9;
z = x+y;
print (z);
####top
Execution
x = 8;
y = 9;
z = x+y;
print (z);
####
top 8
Execution
8xx = 8;
y = 9;
z = x+y;
print (z);
####top
Execution
8xx = 8;
y = 9;
z = x+y;
print (z);
####
top 9
Execution
8
9xy
x = 8;
y = 9;
z = x+y;
print (z);
####top
Execution
8
9xy
x = 8;
y = 9;
z = x+y;
print (z);
####
top 8
Execution
8
9xy
x = 8;
y = 9;
z = x+y;
print (z);
####
top
8
9
Execution
8
9xy
x = 8;
y = 9;
z = x+y;
print (z);
####
top 17
Execution
8
9
17
x
z
yx = 8;
y = 9;
z = x+y;
print (z);
####top
Execution
8
9
17
x
z
yx = 8;
y = 9;
z = x+y;
print (z);
####
top 17
Execution
8
9
17
x
z
yx = 8;
y = 9;
z = x+y;
print (z);
// 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 re
vised 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 miniVCfrom 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-levelPrograms
Low-levelPrograms
Compiler
In Picture
Programs Programs
VM
Programs Programs
Compiler
Compiler1
Compiler2
Relation
The relation is:miniVC: miniC -> miniPentium Defined via three code translation fun
ctions: P, S and E
miniC miniPentiumminiVC
FormalizationP(stm prog) =
S(stm)P(prog)
P(stm) =S(stm)
S(x=e) =E(e)movl result, x
S(print(e)) =E(e)print result
FormalizationE(id) =
movl id, result
E(num) =movl num, result
E(e1+e2) =E(e1)movl result, t_1 // t1 is freshE(e2)movl result, t_2 // t2 is fresh
addl t2, t1movl t1, result
Example
x = 8;
y = 9;
z = x+y;
print (z);
Example
P( x=8; y=9; z = x+y; print (z); ) =
S(x=8)
P( y=9; z=x+y; print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) =
S(x=8)
P( y=9; z=x+y; print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) =
S(x=8)
P( y=9; z=x+y; print (z); )
S(x=8) =
E(8)
movl result, x
Example
P( x=8; y=9; z = x+y; print (z); ) =
S(x=8)
P( y=9; z=x+y; print (z); )
S(x=8) =
E(8)
movl result, x
Example
P( x=8; y=9; z = x+y; print (z); ) =
S(x=8)
P( y=9; z=x+y; print (z); )
S(x=8) =
E(8)
movl result, x
S(x=8) =
movl 8, result
movl result, x
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x P( y=9; z=x+y; print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x P( y=9; z=x+y; print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x S( y=9;) P (z=x+y; print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y P(z=x+y; print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y S(z=x+y; ) P(print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y E(x) movl result, t_1 E(y) movl result, t_2 addl t2, t1 movl t1, result P(print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y movl x, result movl result, t_1 movl y, result movl result, t_2 addl t2, t1 movl t1, result P(print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y movl x, result movl result, t_1 movl y, result movl result, t_2 addl t2, t1 movl t1, result P(print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y movl x, result movl result, t_1 movl y, result movl result, t_2 addl t2, t1 movl t1, result S(print (z); )
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y movl x, result movl result, t_1 movl y, result movl result, t_2 addl t2, t1 movl t1, result E(z) print result
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y movl x, result movl result, t_1 movl y, result movl result, t_2 addl t2, t1 movl t1, result movl z, result print result
Example
P( x=8; y=9; z = x+y; print (z); ) = movl 8, result movl result, x movl 9, result movl result, y movl x, result movl result, t_1 movl y, result movl result, t_2 addl t2, t1 movl t1, result movl z, result print result
miniVC in C
Interface// file “miniVC.h”
#ifndef MINIVC_H
#define MINIVC_H
#include “miniC.h”
#include “miniPentium.h”
miniPentium miniVC (miniC p);
#endif
Implementation// file “miniVC.c”#include “linkedList.h”#include “miniVC.h”
static linkedList pool; // any rep’ will do
miniPentuim miniVC (miniC p){ while (p not empty){ stm s = …; // take one statement from p; compileStm (s); } return …; // return the Pentium program}
Implementation// file “miniVC.c” contiuned
void compileStm (stm s){ switch (s->kind){ case ASSIGN: { // x = e; compileExp (e); enterPool (movl result, x); break; } case …; }}
Implementation// file “miniVC.c” contiunedvoid compileExp (exp e){ switch (e->kind){ case ADD: { // e1 + e2; compileExp (e1); enterPool (movl result, t_1); compileExp (e2); enterPool (movl result, t_2); enterPool (addl t2, t1); enterPool (movl t1, result); break; } case …;}}
Client Code#include “miniC.h”#include “miniPentium.h”#include “miniVC.h”
int main(){ // build the syntax tree for: // p = “x = 8; y = 9; z = x+y; print(z);” cvm (p); // print out 17
miniPentium q = compile (p); pvm (q); // print out 17
return 0;}
Rest of the Story Type checker:
Not all programs are meaningful Ex: y=x; print (y);
Statically check whether a program is valid Optimizer:
The output of a compiler may be stupid Ex: too many movs, :-(
Decrease space use and increase performance Generate real Pentium code
Which called JIT: Just-In-Time compiler (a hot research field)
All leave to you