Jasmin Code Generation Guide

This document provides a guide to the generation of Jasmin assembler code from intermediate three-address instructions. The JVM is strongly typed, which adds a wrinkle to traditional code generators: instead of dealing with exact byte counts and pointer arithmetic, we must deal with the fact that the JVM instructions occasionally require explicit type information. Mainly this will be needed for method invocations. One way to retain this type information is to extend the struct address to allow a pointer to type structure as another option, similar to how we extended it to allow names.

The JVM is a stack machine, so intermediate code instructions generally begin by pushing operands on the stack, and then do their computation, then pop their result off the stack. Loading or storing to a local variable requires one instruction; loading or storing to a class variable requires two instructions. Since storing to a class variable requires the instance be pushed before the result, intermediate instructions that store to a class variable must either push the instance an extra time before working on their operands, or else swap the instance into position.

intermediate
code
instruction
Jasmin equivalentComment
x := y + z
(local variables)
iload_y
iload_z
iadd
istore_x
replace _x, _y, _z by slot offsets
x := y + z
(class foo variables)
(sandwich method)
aload_0
aload_0
getfield foo/y I
aload_0
getfield foo/z I
iadd
putfield foo/x
aload_0 pushes the "self" object
x := y + z
(class foo variables)
(swap method)
aload_0
getfield foo/y I
aload_0
getfield foo/z I
iadd
aload_0
swap
putfield foo/x
aload_0 pushes the "self" object
x := y + z
(strings)
new java/lang/StringBuffer
dup
invokespecial java/lang/StringBuffer/<init>()V
aload_y
invokevirtual java/lang/StringBuffer/append(java/lang/String;)Ljava/lang/StringBuffer;
aload_z
invokevirtual java/lang/StringBuffer/append(java/lang/String;)Ljava/lang/StringBuffer;
invokevirtual java/lang/StringBuffer/toString()Ljava/lang/String;
astore_x
the creation of an implicit StringBuffer object, and three subsequent method invocations, in order to accomplish a string concatenation, looks laughably inefficient, but this is what the javacompiler does with string "+".
x := - y
(local variables)
iload_y
ineg
istore_x
replace _x, _y by slot offsets
x := y
(local variables)
iload_y
istore_x
replace _x, _y by slot offsets
x := &y
x := *y
*x := y
n/a These red dragon book instructions not used
goto L goto L
if x < y then goto L iload_x
iload_y
isub
iflt L
if x then goto L iload_x
ifne L
if !x then goto L iload_x
ifeq L
param x iload_x push object before first parameter for method invocation
call p,n,x invokevirtual foo/x(parms)returntype
return x iload_x
ireturn
global x,n1,n2 treat globals as class variables
proc x,n1,n2 treat procedures as methods
local x,n .limit locals n no local declarations needed other than a count of how many
label Ln Ln:
end .end method
x := y field z iload_y
getfield ysclass/z
istore_x
ysclass is the class name for y
class x,n1,n2 .class public x
.super java/lang/Object
field x,n .field public x type


Clint Jeffery
Last modified: Sat Dec 1 11:11:40 MST 2001