Single file interpreter (or naive virtual machine) for my intermediate representation. SSA support has been added.
You can use LLIRInterpreter::main
.
cd src # enter the source directory
javac LLIRInterpreter.java # compile
java LLIRInterpreter # run the VM (read from stdin)
# or my favourite: paste from the pasteboard and run the VM in SSA Mode
pbpaste | java LLIRInterpreter +ssa
Or you can copy src/LLIRInterpreter.java
to your code and use it as a library.
Read IR from in
and build internal data structures. Enable SSA mode if isSSAMode
is true. If nothing goes wrong, mark isReady()
true.
Run the virtual machine.
Set the maximum instructions that the virtual machine can operate.
Check if the virtual machine is ready to run.
Get the exitcode of the virtual machine.
Return true if the virtual machine is terminated by an exception.
- Infinite number of registers.
- Registers are writeable if not in SSA Mode.
- Registers' name start with
$
. e.g.$t1
,$arr_addr
,$arr.addr
, ... - Blocks' name starts with
%
. e.g.%entry
,%if_true
,%if.true
, ... - A block must end with a jump instruction, i.e., fall-through is not allowed.
- Function call:
$dest = call name $arg1 $arg2 ...
. - Use
func name $arg1 $arg2 ... {
to start a function definition.func
can be replaced withvoid
if no return value. - The entry block of a function is the first block in it.
- Heap allocation:
$dest = alloc $size
will acquire$size
bytes from heap.
In SSA Mode,
- A register can only be defined once statically (not dynamically).
- A
phi
node must have source register for all possible incoming blocks. - A source register in a
phi
node can take a special valueundef
, which says any value is acceptable in that context. - All
phi
nodes should be placed in the front of a block, i.e.,phi
nodes are forbidden in the middle of a block.
- All registers are 32-bit integer register.
- All integers are signed integer.
- Functions do not share any register.
- Will terminate if memory access violation occurs.
- Will terminate if arithmetic error occurs.
- Will terminate if you try to read a register that has no value.
- Execution starts at
main
function. - A random padding
(< 4KB)
is added afteralloc
in order to help detect memory access violation.
You can guess the meaning from their names. All register except $dest
and $reg*
can be replaced by immediate number. $reg*
can also be replaced by undef
.
Jump Instruction:
ret $src
jump %target
br $cond %ifTrue %ifFalse
Memory Access Instruction:
store size $addr $src offset // M[$addr+offset : $addr+offset+size-1] <- $src
$dest = load size $addr offset // $dest <- M[$addr+offset : $addr+offset+size-1]
$dest = alloc $size
Function Call Instruction:
call funcname $op1 $op2 $op3 ...
$dest = call funcname $op1 $op2 $op3 ...
Register Transfer Instruction:
$dest = move $src
Phi Instruction:
$dest = phi %block1 $reg1 %block2 $reg2 ...
Arithmetic Instruction:
$dest = neg $src
$dest = add $src1 $src2
$dest = sub $src1 $src2
$dest = mul $src1 $src2
$dest = div $src1 $src2
$dest = rem $src1 $src2
Bitwise Instruction:
$dest = shl $src1 $src2
$dest = shr $src1 $src2
$dest = and $src1 $src2
$dest = xor $src1 $src2
$dest = or $src1 $src2
$dest = not $src
Condition Set Instruction:
$dest = slt $src1 $src2
$dest = sgt $src1 $src2
$dest = sle $src1 $src2
$dest = sge $src1 $src2
$dest = seq $src1 $src2
$dest = sne $src1 $src2
func min $a $b {
%min_entry:
$t = sle $a $b
br $t %if_true %if_merge
%if_true:
ret $a
%if_merge:
ret $b
}
func main {
%main_entry:
$x = move 10
$y = move 20
$x = call min $x $y
ret $x
}
func main {
%main.entry:
$n.1 = move 10
$f0.1 = move 0
$f1.1 = move 1
$i.1 = move 1
jump %for_cond
%for_cond:
$f2.1 = phi %for_step $f2.2 %main.entry undef
$f1.2 = phi %for_step $f1.3 %main.entry $f1.1
$i.2 = phi %for_step $i.3 %main.entry $i.1
$f0.2 = phi %for_step $f0.3 %main.entry $f0.1
$t.1 = slt $i.2 $n.1
br $t.1 %for_loop %for_after
%for_loop:
$t_2.1 = add $f0.2 $f1.2
$f2.2 = move $t_2.1
$f0.3 = move $f1.2
$f1.3 = move $f2.2
jump %for_step
%for_step:
$i.3 = add $i.2 1
jump %for_cond
%for_after:
ret $f2.2
}
- Void function support
- Static data
print
read