SIMPL Runtime Support
This section describes code conventions used by the SIMPL compiler, and the parts of the JVM architecture that are pertinent to SIMPL.
All expressions in SIMPL are evaluated in a uniform way. An expression is an operator with several operands, which are themselves expressions. By convention, to evaluate an operator, its operands are first evaluated. As each operand is evaluated it pushes its result on to the system stack. Then, the operator pops the operator pops the operand values off of the stack, processes them, and pushes its result onto the stack. In this way no temporary variables are required. All temporary storage is allocated off of the stack.
SIMPL programs are compiled to a jasmin method (procedure). The Java conventions for function calls are followed. That is to say, arguments are pushed onto the stack, and values are returned on the stack. On the JVM, each method has its own stack, and its own local variables. The jasmin assembler must be informed as to the number of local variables each method is using, and the size of its stack. Local variables are identified by their numbers. All SIMPL variables are stored in local variables. The compiler, therefore, generates labels for use with gotos, and numbers to be used as variables.
If a SIMPL program declares n variables (including IN, OUT, and LOCAL variables), the corresponding jasmin method should allocate n + 1 local variables. Local variable 0 is special purpose, and should not be used by the method. Local variables 1 through n are used to implement the SIMPL variables. A method's stack size is set to one more than the number of leaf nodes (including variable declarations) in the syntax tree. It can be shown that this size exceeds the maximum number of items a SIMPL program can push.
A JVM executable program consists of one or more .class files. Each class file is roughly equivalent to an object file. On the JVM linking is dynamic. This means that if a method is called which is external to the .class file, the method is located during runtime. This eliminates the need for a linker, which performs static linking. To narrow down the search required for the dynamic link, the environment variable, CLASSPATH, contains the paths to all library directives, and only these libraries are searched during dynamic linking.
The JVM is a stack based machine. All instructions use the current method's stack to perform operations.
Below is a list of the jasmin directives and JVM instructions used in the code templates.
Directives
.class public filename |
Specifies the name of the .class file. |
.super superclassFile |
The superclass of the class (a lot like an include statement in C. |
.method public static name(arguments)type |
Tells the assembler that this is the beginning of a new method. |
.end method |
Tells the assembler that this is the end of the current method. |
.limit stack n |
Informs the assembler of the stack size for the current method. |
.limit locals n |
Informs the assembler of the number of local variables (the local variables are numbered 0 to n - 1). |
Types
I |
Integer |
V |
Void |
Z |
Boolean |
Ljava/lang/String |
Character String |
Instructions
invokestatic classFile/method |
Call a procedure, dynamically linking to it, and popping its argument. |
return |
Return from a procedure, pushing the return value. |
sipush constant |
Push a short integer constant. |
istore localVar |
Pop an integer into a local variable. |
ldc constant |
Push a pointer to a constant stored in the data pool. |
iload localVar |
Push an integer from a local variable. |
ifeq label |
Pop the stack and jump if the popped value is equal to zero. |
ifge label |
Pop the stack and jump is the popped value is greater than zero. |
goto label |
Perform a jump. |
if_icmpgt label |
Pop the stack twice, compare the two popped values, and jump if the first is greater than the second. |
if_icmpeq label |
Pop the stack twice, compare the two popped values, and jump if the first is equal to the second. |
dup |
Duplicate the top value on the stack, and push the duplicate. |
pop |
Pop the top element off the stack. |
iadd |
Pop the stack twice, add the two integers popped, and push the result. |
isub |
Pop the stack twice, subtract the two integers popped, and push the result. |
imul |
Pop the stack twice, multiply the two integers popped, and push the result. |
idiv |
Pop the stack twice, divide the two integers popped, and push the result. |
bipush constant |
Push a byte constant |
ior |
Pop the stack twice, bitwise OR the two integers popped, and push the result |
iand |
Pop the stack twice, bitwise AND the two integers popped,
and push the result |
ixor |
Pop the stack twice, bitwise XOR the two integers popped,
and push the result |
ineg |
Pop the stack, negate the integer popped, and push the
result |