Compiler: translate code to machine code
generate executable
optimization
recompiling program takes time
running code on new hardware takes source code and new compiler
no safety check
Interpreter: simulate on hardware
cannot do optimization beyond single line
running code on new hardware takes source code and new interpreter
efficiency does not matter
interactive
Advantage of Using Virtual Machine
compiler can perform optimizations
VM is lightweight, little simulation overhead
bytecode: each instruction fits in one byte
To run program, you need:
bytecode
specific virtual machine
(you don't need compiler)
Python: Python bytecode -> Python VM PHP, Js: common bytecode -> LLVM GCC: Clang Pascal: first mainstream language use two-stage approachh Java: popularized this approach. Java bytecode -> JVM
cc0 -s foo.c0 (can produce C code)
cc0 -b foo.c0 (can produce C0VM bytecode, this step is hard)
(this can be executed by c0vm, c0vm is easy)
c0vm foo.bc0
bipush can only push [-128, 127]
new data structure: local variable array V
vload i
: pushi-th value onto operand stack
vstore i
: pops operand stack and save its value in i-th position of V
Second segment of C0VM bytecode
stores number of integers
and integers
ildc i
: push the i-th integer on the stack (with 2 arguments interpret as together)
Where function stores
the first function is always main
argument of function need to be on stack
return pushed back into stack, replacing the arguments
notice that we use fixed size int (we don't want C compiler to modify int length)
Table of Content