Presentation is loading. Please wait.

Presentation is loading. Please wait.

CS 432: Compiler Construction Lecture 16

Similar presentations


Presentation on theme: "CS 432: Compiler Construction Lecture 16"— Presentation transcript:

1 CS 432: Compiler Construction Lecture 16
Department of Computer Science Salisbury University Fall 2017 Instructor: Dr. Sophie Wang 4/6/2019

2 Java Virtual Machine (JVM) Architecture
Java stack runtime stack Heap area dynamically allocated objects automatic garbage collection Class area code for methods constants pool Native method stacks support native methods, e.g., written in C (not shown) 4/6/2019

3 Java Virtual Machine Architecture, cont’d
The runtime stack contains stack frames. Stack frame = activation record. Each stack frame contains local variables array operand stack program counter (PC) 4/6/2019

4 The JVM’s Java Runtime Stack
Each method invocation pushes a stack frame. The stack frame currently on top of the runtime stack is the active stack frame. A stack frame is popped off when the method returns, possibly leaving behind a return value on top of the stack. Contents of a stack frame: Operand stack for doing computations Local variables array equivalent to the memory map in our Pascal interpreter’s activation record Program counter (PC) keeps track of the currently executing instruction Pointers to method area and heap 4/6/2019

5 JVM Instructions Load and store values Arithmetic operations
Type conversions Object creation and management Runtime stack management (push/pop values) Branching Method call and return Throwing exceptions Concurrency _ 4/6/2019

6 JASMIN JASMIN is an assembler for the JVM Running JASMIN
Takes an ASCII description of a Java class Input written in a simple assembler like syntax Using the JVM instruction set Outputs binary class file Suitable for loading by the JVM Running JASMIN jasmin myfile.j Produces a .class file with the name specified by the .class directive in myfile.j 4/6/2019

7 Jasmin file format Directives Instructions Labels JVM instructions
.catch .class .end .field .implements .interface .limit .line .method .source .super .throws .var Instructions JVM instructions Labels Any name followed by : Foo: Cannot start with = : . * Labels can only be used within method definitions 4/6/2019

8 Jasmin Assembler Download from: Site also includes:
Site also includes: User Guide Instruction set Sample programs _ 4/6/2019

9 Example Jasmin Program
.class public HelloWorld .super java/lang/Object .method public static main([Ljava/lang/String;)V .limit stack 2 .limit locals 1 getstatic java/lang/System/out Ljava/io/PrintStream; ldc " Hello World." invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V return .end method hello.j Assemble: java –jar jasmin.jar hello.j Execute: java HelloWorld 4/6/2019

10 Jasmin Assembly Instructions
An Jasmin instruction consists of a mnemonic optionally followed by arguments. aload 5 ; Push a reference to local variable #5 fstore 5 ; pop off the floating-point value at the ; top of the stack and store it to ; local variable #5 getstatic Newton/number I ; push integer value of the static field ; number of class Newton to operand stack Some instructions require operands on the operand stack. iadd ; Pop the two integer values on top of the ; stack, add them, and push the result on ; the top of the stack _ 4/6/2019

11 Jasmin Assembly Directives
Directive statements provide info to Jasmin assembler. They begins with a period immediately followed by the reserved directive word. For example, the main method of a Java program public static void main(String args[]) would have the following equivalent Jasmin directive .method public static main([Ljava/lang/String;)V 4/6/2019

12 Jasmin Type Descriptors
Java Scalar type Jasmin Type Descriptor int I float F boolean Z char C Java Class Jasmin Type Descriptor java.lang.String Ljava/lang/String; java.util.HashMap Ljava/util/HashMap; Newton LNewton; Java Array type Jasmin Type Descriptor java.lang.String[] [Ljava/lang/String; Newton[][] [[LNewton; int[][][] [[[I; 4/6/2019

13 Compilation Strategy A Pascal program is compiled as if it were a public Java class. The Pascal program name becomes the Java class name. The main program becomes the main method of the class. Each program variable is compiled as if it were a field of the class. Fields do have names in a Jasmin program. A Pascal procedure or function is compiled as if it were a private static method of the Java class. Local variables and formal parameters of the method do not have names in a Jasmin program. Jasmin instructions refer to local variables and parameters by their slot numbers of the local variables array. 4/6/2019

14 Pascal, Java and Jasmin Code Example
1. PROGRAM HelloOnce; BEGIN 4. writeln('Hello, world.') 5. END. public class HelloOnce { private static RunTimer _runTimer; private static PascalTextIn _standardIn; public static void main(String[] args) _runTimer = new RunTimer(); _standardIn = new PascalTextIn(); System.out.println("Hello, world."); _runTimer.printElapsedTime(); } 4/6/2019

15 .class public helloonce .super java/lang/Object
.field private static _runTimer LRunTimer; .field private static _standardIn LPascalTextIn; .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return .limit locals 1 .limit stack 1 .end method .method public static main([Ljava/lang/String;)V new RunTimer dup invokenonvirtual RunTimer/<init>()V putstatic helloonce/_runTimer LRunTimer; new PascalTextIn invokenonvirtual PascalTextIn/<init>()V putstatic helloonce/_standardIn LPascalTextIn; .line 4 getstatic java/lang/System/out Ljava/io/PrintStream; ldc "Hello, world.\n" invokevirtual java/io/PrintStream.print(Ljava/lang/String;)V getstatic helloonce/_runTimer LRunTimer; invokevirtual RunTimer.printElapsedTime()V .limit stack 3 4/6/2019

16 Code Templates Syntax diagrams Code templates
Specify the source language grammar Help us write the parsers Code templates Specify what object code to generate Help us write the code emitters _ 4/6/2019

17 Code Template for a Pascal Program
Translate a Pascal program into a public class. Program variables become class fields. Must have a default constructor. Each procedure or function becomes a private static method. The main program code becomes the public static main method. 4/6/2019

18 Program Header The program header consists of .class public hellomany
.super java/lang/Object 4/6/2019

19 Class Constructor The Pascal compiler always generates the same default constructor <init>. When the constructor executes, slot 0 of local variables array contains the address of the class instance (this). To create an instance of the program class, the ALOAD_0 instruction pushes this address onto the operand stack and the instruction invokenonvirtual passes it to the constructor of java.lang.Object .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return .limit locals 1 .limit stack 1 .end method 4/6/2019

20 Instruction-set … Method invocation: invokevirtual
usual instruction for calling a method on an object. invokespecial/invokenonvirtual for calling things such as constructors. These are not dynamically dispatched invokestatic for calling methods that have the “static” modifier (these methods “belong” to a class, rather an object)

21 invokevirtual Object x; ... x.equals("hello"); aload_1 ; push local variable 1 (i.e. 'x') onto stack ldc "hello" ; push the string "hello" onto stack ; invoke the equals method invokevirtual java/lang/Object/equals(Ljava/lang/Object;)Z ; the boolean result is now on the stack the actual method run depends on the runtime type of the object invokevirtual is used with. if x is an instance of a class that overrides Object's equal method, then the subclasses' overridden version of the equals method will be used.

22 Invokespecial/invokenonvirtual
invoke an object's instance initialization method, <init>, during the construction phase for a new object. new StringBuffer(); == new java/lang/StringBuffer ; create a new StringBuffer dup ; make an extra reference to the new instance ; now call an instance initialization method invokespecial java/lang/StringBuffer/<init>()V ; stack now contains an initialized StringBuffer.

23 Invokespecial/invokenonvirtual
class Example { // override equals public boolean equals(Object x) { // call Object's version of // equals return return super.equals(x); } also used to access a superclass's version of a method. === aload_0 ; push 'this' onto the stack aload_1 ; push the first argument (i.e. x) onto the stack ; now invoke Object's equals() method. invokespecial java/lang/Object/equals(Ljava/lang/Object;)Z

24 Program Fields For example: Compiles to: Pascal program variables
PROGRAM test; VAR i, j, k : integer; x, y : real; p, q : boolean; ch : char; index : 1..10; Pascal program variables Compiles to: .field private static _runTimer LRunTimer; .field private static _standardIn LPascalTextIn; .field private static ch C .field private static i I .field private static index I .field private static j I .field private static k I .field private static p Z .field private static q Z .field private static x F .field private static y F Classes RunTimer and PascalTextIn are defined in the Pascal Runtime Library PascalRTL.jar containing runtime routines written in Java. 4/6/2019

25 Code Template for the Main Method
The main method prologue initializes the runtime timer _runTimer and the standard input _standardIn fields. The main method epilogue prints the elapsed run time. .limit locals .limit stack specify the size of the local variables array and the maximum size of the operand stack, respectively. 4/6/2019

26 Loading a Program Variable’s Value
To load (push) a program variable’s value onto the operand stack: getstatic program-name/variable-name type-descriptor Examples: getstatic Test/count I getstatic Test/radius F Java Scalar type Jasmin Type Descriptor int I float F boolean Z char C 4/6/2019

27 Storing a Program Variable’s Value
To store (pop) a value from the operand stack into program variable: putstatic program-name/variable-name type-descriptor Examples: putstatic Test/count I putstatic Test/radius F Java Scalar type Jasmin Type Descriptor int I float F boolean Z char C 4/6/2019

28 Tips Write special code emitters for loading (pushing) values onto the operand stack. If loading constants: Determine whether to you can emit a shortcut instruction. If loading variables, Determine whether it’s a program variable (emit a getstatic instruction with the field name) or a local variable (emit a load instruction with the slot number). Determine whether you can emit a shortcut instruction for a local variable. Similarly, write special code emitters for storing (popping) values off the operand stack into variables. 4/6/2019

29 Code for Procedures and Functions
Each a private static method. Method signature: Routine’s name Type descriptors of the formal parameters. Type descriptors of the return type 4/6/2019

30 Compiling Local Variables
FUNCTION func(i, j : integer; x, y : real; p : boolean; ch : char; vector : arr; length : integer) : real; VAR n : integer; z : real; w : arr; Compiles to: .method private static func(IIFFZC[FI)F .var 5 is ch C .var 0 is i I .var 1 is j I .var 7 is length I .var 8 is n I .var 4 is p Z .var 6 is vector [F .var 10 is w [F .var 2 is x F .var 3 is y F .var 9 is z F .var 11 is func F SymTabImpl - add a slot number to each variable’s the symbol table entry for the local variables array. DeclaredRoutineParser – parse() VariableDeclarationParser – parseIdentifier() 4/6/2019

31 Generating Code for Expressions
alpha + 3/(beta - gamma) + 5 Recall that in our Pascal interpreter, the expression executor does a postorder traversal of the expression parse tree. Pascal’s operator precedence rules are encoded in the structure of the parse tree. 4/6/2019

32 Generating Code for Expressions, cont’d
A compiler’s expression code generator also does a postorder traversal to generate code. Assume that alpha, beta, and gamma are local real variables alpha  local variable slot #0 beta  local variable slot #1 gamma  local variable slot #2 Generated code: 1 fload_0 2 ldc 3.0 3 fload_1 4 fload_2 5 fsub 6 fdiv 7 fadd 8 ldc 5.0 9 fadd alpha + 3/(beta - gamma) + 5 4/6/2019

33 Comparing Integer Values
Jasmin has a set of instructions each of which compares the top two integer values on the operand stack and then branches if the comparison is true. The two values are popped off the operand stack. [TOS] is the value at the top of the stack. [TOS-1] is the value just under the one at the top of the stack. Instruction Action if_icmpeq label Branch to label if [TOS-1] == [TOS] if_icmpne label Branch to label if [TOS-1] != [TOS] if_icmpgt label Branch to label if [TOS-1] > [TOS] if_icmpge label Branch to label if [TOS-1] >= [TOS] if_icmplt label Branch to label if [TOS-1] < [TOS] if_icmple label Branch to label if [TOS-1] <= [TOS] 4/6/2019

34 Comparing Integer Values, cont’d
You can also simply compare the single integer value at the top of the operand stack to 0 and then branch if the comparison is true. The top value is popped off the stack. _ Instruction Action ifeq label Branch to label if [TOS] == 0 ifne label Branch to label if [TOS] != 0 ifgt label Branch to label if [TOS] > 0 ifge label Branch to label if [TOS] >= 0 iflt label Branch to label if [TOS1] < 0 ifle label Branch to label if [TOS] <= 0 4/6/2019

35 Comparing Other Values
Instructions lcmp, fcmp, and dcmp compare two long, float, or double values at the top of the operand stack. Each pops the top two values off the operand stack and then pushes the integer value -1, 0, or 1 onto the stack. If [TOS-1] < [TOS], push -1 onto the stack. If [TOS-1] = [TOS], push 0 onto the stack. If [TOS-1] > [TOS], push 1 onto the stack. Use instructions iflt, ifeq, or ifgt to test for the -1, 0, or 1. _ 4/6/2019

36 Relational Expressions
Suppose i and j are local integer variables, and that: i  slot #0 j  slot #1 0 represents false and 1 represents true. For the expression i < j leave either 0 or 1 on top of the operand stack: iload_ ; push the value of i (slot #0) iload_ ; push the value of j (slot #1) if_icmplt L003 ; branch if i < j iconst_ ; push false goto L ; go to next statement L003: iconst_ ; push true L004: The code in red are the only parts that change based on the expression. Your code generator also needs to emit labels. 4/6/2019

37 Relational Expression Code Template
iload_0 iload_1 if_icmplt L003 iconst_0 goto L004 L003: iconst_1 L004: 4/6/2019

38 Assignment Statement Code Template
The code template for an assignment statement to a local variable <variable> := <expression> code for <expression> xstore n Where x is i, l, f, or d depending on the type of the computed value of <expression>. You can generate a shortcut store instruction such as istore_3 (3 is a slot number) whenever possible. _ 4/6/2019

39 Pascal Procedures and Functions
Analogous to Java methods. Two major simplifications for our Pascal compiler: Standard Pascal is not object-oriented. Therefore, Pascal procedures and functions are more like the private static methods of a Java class. Java does not have nested methods. The JVM does not easily implement nested methods. Therefore, we will compile only “top level” (level 1) Pascal procedures and functions. _ 4/6/2019

40 Procedures and Functions, cont’d
A Pascal program: The roughly equivalent Java class: Fields and methods are private static. PROGRAM ADDER; VAR i, j, sum : integer; FUNCTION add(n1, n2 : integer) : integer; s : integer; BEGIN s := i + j + n1 + n2; add := s; END; i := 10; j := 20; sum := add(100, 200); writeln('Sum = ', sum) END. public class Adder { private static int i, j, sum; private static int add(int n1, int n2) int s = i + j + n1 + n2; return s; } public static void main(String args[]) i = 10; j = 20; sum = add(100, 200); System.out.println("Sum = " + sum); 4/6/2019

41 Code for a Pascal Main Program
PROGRAM ADDER; VAR i, j, sum : integer; FUNCTION add(n1, n2 : integer) : integer; s : integer; BEGIN s := i + j + n1 + n2; add := s; END; i := 10; j := 20; sum := add(100, 200); writeln('Sum = ', sum) END. .class public super Adder .super java/lang/Object .private field static i I .private field static j I .private field static sum I .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return .limit stack 1 .limit locals 1 .end method ... Private static class fields. Void method. No parameters. Each Jasmin class must have a constructor named <init>. The local variable in slot #0 contains the value of “this”. Each constructor must call the superclass constructor. 4/6/2019

42 Code for a Pascal Function
PROGRAM ADDER; VAR i, j, sum : integer; FUNCTION add(n1, n2 : integer) : integer; s : integer; BEGIN s := i + j + n1 + n2; add := s; END; i := 10; j := 20; sum := add(100, 200); writeln('Sum = ', sum) END. .method static add(II)I .var 0 is n1 I .var 1 is n2 I .var 2 is s I .var 3 is add I getstatic Adder/i I getstatic Adder/j I iadd iload_0 ; n1 (slot #0) iload_1 ; n2 (slot #1) istore_2 ; s (slot #2) iload_2 ; load s to stack top ireturn ; (see below) .limit stack 2 .limit locals 3 .end method getstatic with a fully qualified name and type to push the value of a static field onto the operand stack. ireturn pops an integer from the top of the callee’s stack and pushes it onto the caller’s stack 4/6/2019

43 Code to Call a Function (Static Method)
PROGRAM ADDER; VAR i, j, sum : integer; FUNCTION add(n1, n2 : integer) : integer; s : integer; BEGIN s := i + j + n1 + n2; add := s; END; i := 10; j := 20; sum := add(100, 200); writeln('Sum = ', sum) END. .method public static main([Ljava/lang/String;)V .limit stack 4 .limit locals 1 bipush 10 putstatic Adder/i I bipush 20 putstatic Adder/j I bipush 100 sipush 200 invokestatic Adder/add(II)I putstatic Adder/sum I ... A function call leaves its return value on top of the operand stack of the caller. Use putstatic with a fully qualified field name and type signature to pop a value off the operand stack and store it into a static field. Use invokestatic with a fully-qualified method name and a type signature to call a static method. 4/6/2019

44 Code to Call a Function (Static Method)
PROGRAM ADDER; VAR i, j, sum : integer; FUNCTION add(n1, n2 : integer) : integer; s : integer; BEGIN s := i + j + n1 + n2; add := s; END; i := 10; j := 20; sum := add(100, 200); writeln('Sum = ', sum) END. .method public static main([Ljava/lang/String;)V .limit stack 4 .limit locals 1 bipush 10 putstatic Adder/i I bipush 20 putstatic Adder/j I bipush 100 sipush 200 invokestatic Adder/add(II)I putstatic Adder/sum I ... Use putstatic with a fully qualified field name and type signature to pop a value off the operand stack and store it into a static field. Use invokestatic with a fully-qualified method name and a type signature to call a static method. 4/6/2019

45 Code to Call System.out.println()
What does the method call System.out.println("Hello, world!") require on the operand stack? A reference to the java.io.PrintStream object System.out. A reference to the java.lang.String object "Hello, world!" object type descriptor of object getstatic java/lang/System/out Ljava/io/PrintStream; ldc "Hello, world!" invokevirtual java/io/PrintStream.println(Ljava/lang/String;)V method parm type descriptor no return type (void) 4/6/2019

46 System.out.println(), cont’d
Compile the Pascal call writeln('Sum = ', sum) as if it were the Java System.out.println( new StringBuilder(" Sum = ") append(sum) toString() ); Each call to invokevirtual requires an object reference and then any required actual parameter values on the operand stack. getstatic java/lang/System/out Ljava/io/PrintStream; new java/lang/StringBuilder dup ldc "Sum = " invokenonvirtual java/lang/StringBuilder/<init>(Ljava/lang/String;)V getstatic Adder/sum I invokevirtual java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder; invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String; invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V Why do we need this dup instruction? 4/6/2019

47 A call to the static format() method of the Java String class has two parameters, the format string and an array of object values and it returns a string value String.format(“The square root of %4d is %8.4f”, n, root) would compile to the Jasmin instruction invokestatic java/lang/String/format(Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/String; This instruction requires that the address of the string constant “The square …. “ and the address of the array containing the values of n, root be at the top of the operand stack. It pops off the string and array addresses to be used as parameters of the call and the call pushes the string value result onto the operand stack 4/6/2019

48 String.format() A more elegant way to compile a call to Pascal’s standard writeln() procedure is to use Java’s String.format() method. Compile Pascal writeln('The square root of ', n:4, ' is ', root:8:4); as if it were the Java System.out.print( String.format( "The square root of %4d is %8.4f\n", n, root) ); 4/6/2019

49 String.format(), cont’d
The Java String.format() method has a variable-length parameter list. The first parameter is the format string. Similar to C’s format strings for printf(). The code generator must construct the format string. Pascal: ('The square root of ', n:4, ' is ', root:8:4) Equivalent Java: ("The square root of %4d is %8.4f\n", n, root) The remaining parameters are the values to be formatted, one for each format specification in the format string. Jasmin passes these remaining parameters as a one-dimensional array of objects. Therefore, we must emit code to create and initialize the array and leave its reference on the operand stack. 4/6/2019

50 String.format(), cont’d
Instruction aastore operands on the stack: Array reference Index value Element value (object reference) s = String.format( "The square root of %4d is %8.4f\n", n, root); ldc "The square root of %4d is %8.4f\n" iconst_2 anewarray java/lang/Object dup iconst_0 getstatic FormatTest/n I invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer; aastore iconst_1 getstatic FormatTest/root F invokestatic java/lang/Float.valueOf(F)Ljava/lang/Float; invokestatic java/lang/String.format(Ljava/lang/String;[Ljava/lang/Object;) Ljava/lang/String; putstatic FormatTest/s Ljava/lang/String; Create an array of size 2 and leave the array reference on the operand stack. Store element 0: The value of n. Why the dup instructions? Store element 1: The value of root. 4/6/2019

51 String.format(), cont’d
System.out.print( String.format("The square root of %4d is 8.4f\n", n, root); ); getstatic java/lang/System/out Ljava/io/PrintStream; ldc "The square root of %4d is %8.4f\n" iconst_2 anewarray java/lang/Object dup iconst_0 getstatic FormatTest/n I invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer; aastore iconst_1 getstatic FormatTest/root F invokestatic java/lang/Float.valueOf(F)Ljava/lang/Float; invokestatic java/lang/String.format(Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/String; invokevirtual java/io/PrintStream.print(Ljava/lang/String;)V 4/6/2019

52 Parameter Passing Java (and Jasmin) always passes parameters by value.
For scalar data type, they are passed by value. For structured data types (string, array, object), their address are passed by value (hence indirectly by reference) Strategies for compiling Pascal parameter passing If a parameter is scalar (integer, real, bool, subrange, enum) without VAR, follow default rule for Java parameter passing. If a parameter is structured data type with VAR, follow default rule for Java parameter passing. If a parameter is scalar (integer, real, bool, subrange, enum) with VAR, convert this into a wrapper class object. If a parameter is structured data type without VAR, we create a clone of the parameter object and pass the clone at the actual parameter _ 4/6/2019

53 Passing Parameters Pascal can pass parameters by value and by reference. VAR parameters = pass by reference Java and Jasmin pass scalar values by value. To pass a scalar value by reference, you must first wrap the value inside an object. Pass the object reference (by value) to the routine. The routine can modify the wrapped value. Upon return, the caller must unwrap the changed value. _ 4/6/2019

54 Passing Parameters, cont’d
Java and Jasmin pass references to objects by value. To pass an array or record by value as in Pascal, first clone the array or record value and then pass the reference to the clone. When a formal parameter to a method is a reference to an object, the method can change the value of the object (such as by modifying the values of the object fields). But the method cannot change the parameter’s value to refer to another object and have the method’s caller see that change. 4/6/2019

55 Passing Parameters, cont’d
The Pascal Runtime Library contains classes for passing parameters by value or by reference. Classes BWrap, CWrap, IWrap, and RWrap wrap a boolean, character, integer, and real scalar value, respectively, to be passed by reference. Class Cloner clones an array or reference to be passed by value. _ public class IWrap { public int value; public IWrap(int value) this.value = value; } 4/6/2019

56 Example: Passing Scalars by Reference
PROGRAM parmswrap; VAR i, j : integer; PROCEDURE swap(VAR parm1, parm : integer); temp : integer; BEGIN temp := parm1; parm1 := parm2; parm2 := temp; END; i := 10; j := 20; swap(i, j); writeln('Result: i = ', i:0, ', j = ', j:0); END. .method public static main([Ljava/lang/String;)V ... new IWrap dup getstatic parmswrap/i I invokenonvirtual IWrap/<init>(I)V astore_1 new IWrap getstatic parmswrap/j I astore_2 invokestatic parmswrap/swap(LIWrap;LIWrap;)V aload_1 getfield IWrap/value I putstatic parmswrap/i I aload_2 putstatic parmswrap/j I Wrap i. Allocate slots #1 and #2 as temporaries to store the wrapped i and j. Wrap j. Call method. Unwrap i. Unwrap j. 4/6/2019

57 Example: Passing Scalars by Reference, cont’d
PROGRAM parmswrap; VAR i, j : integer; PROCEDURE swap(VAR parm1, parm : integer); temp : integer; BEGIN temp := parm1; parm1 := parm2; parm2 := temp; END; i := 10; j := 20; swap(i, j); writeln('Result: i = ', i:0, ', j = ', j:0); END. .method private static swap(LIWrap;LIWrap;)V .var 2 is temp I .var 0 is parm1 LIWrap; .var 1 is parm2 LIWrap; aload_0 getfield IWrap/value I istore_2 aload_1 putfield IWrap/value I iload_2 return .limit locals 3 .limit stack 2 .end method #0 #1 #2 Access the wrapped values of parm1 and parm2 and swap them. 4/6/2019

58 Example: Passing an Array by Value
PROGRAM parmsclone; TYPE cube = ARRAY [0..1, 0..2, 0..3] OF integer; VAR vvv : cube; PROCEDURE printCube(VAR c : cube); ... PROCEDURE doCubeValue(c : cube); i, j, k : integer; BEGIN FOR i := 0 TO 1 DO BEGIN FOR j := 0 TO 2 DO BEGIN FOR k := 0 TO 3 DO BEGIN c[i,j][k] := 200*i + 10*j +k; END; writeln('In doCubeValue:'); printCube(c); PROCEDURE doCubeRef(VAR c : cube); ... BEGIN c[i,j][k] := 100*i + 10*j +k; END; doCubeRef(vvv); writeln('In main:'); printCube(vvv); doCubeValue(vvv); END. getstatic parmsclone/vvv [[[I invokestatic Cloner.deepClone(Ljava/lang/Object;) Ljava/lang/Object; checkcast [[[I invokestatic parmsclone/docubevalue([[[I)V 4/6/2019

59 Class Cloner In the Pascal Runtime Library: Write the original
public class Cloner { public static Object deepClone(Object original) throws PascalRuntimeException try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(original); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } catch (Exception ex) { throw new PascalRuntimeException("Deep clone failed."); Write the original object to a byte array stream. Construct a copy from the stream. Return the copy as the deep clone. 4/6/2019

60 Arrays and Subscripted Variables
Code generation for arrays: Code to allocate memory for an array variable. Code to allocate memory for each non-scalar array element. Code for a subscripted variable in an expression. Code for a subscripted variable that is an assignment target. Allocate memory for single-dimensional arrays Instruction newarray for scalar elements. Instruction anewarray for non-scalar elements. Allocate memory for multidimensional arrays. Instruction multianewarray. _ 4/6/2019

61 Allocating Memory for Arrays
Recall the code template for a Jasmin method. Code to allocate arrays here! Pascal automatically allocates memory for arrays declared in the main program or locally in a procedure or function. The memory allocation occurs whenever the routine is called. This is separate from dynamically allocated data using pointers and new. Therefore, our generated Jasmin code must implement this automatic runtime behavior. 4/6/2019

62 Example: Allocate Memory for Scalar Arrays
PROGRAM ArrayTest; TYPE vector = ARRAY[0..9] OF integer; matrix = ARRAY[0..4, 0..4] OF integer; cube = ARRAY[0..1, 0..2, 0..3] OF integer; VAR i, j, k, n : integer; a : vector; a : matrix; a : cube; BEGIN ... END. bipush 10 newarray int putstatic arraytest/a1 [I iconst_5 multianewarray [[I 2 putstatic arraytest/a2 [[I iconst_2 iconst_3 iconst_4 multianewarray [[[I 3 putstatic arraytest/a3 [[[I 4/6/2019

63 Access an Array Element of a 2-D Array
PROGRAM ArrayTest; TYPE matrix = ARRAY[0..2, 0..3] OF integer; VAR i, j, k : integer; a : matrix; BEGIN ... i := 1; j := 2; k := a2[i, j]; END. a2 1 2 3 1 2 3 4 1 5 6 8 7 2 9 10 11 12 k 7 getstatic arraytest/a2 [[I getstatic arraytest/i I aaload getstatic arraytest/j I iaload putstatic arraytest/k I 1 2 3 4 5 6 7 8 9 10 11 12 4/6/2019

64 Subscripted Variables in Expressions
PROGRAM ArrayTest; TYPE vector = ARRAY[0..9] OF integer; matrix = ARRAY[0..4, 0..4] OF integer; cube = ARRAY[0..1, 0..2, 0..3] OF integer; VAR i, j, k, n : integer; a : vector; a : matrix; a : cube; BEGIN ... j := a1[i]; k := a2[i, j]; n := a3[i, j, k]; END. getstatic arraytest/a1 [I getstatic arraytest/i I iaload putstatic arraytest/j I getstatic arraytest/a2 [[I aaload getstatic arraytest/j I putstatic arraytest/k I getstatic arraytest/a3 [[[I getstatic arraytest/k I putstatic arraytest/n I Instructions iaload (push a scalar value from an array element value) and aaload (push an array element address) 4/6/2019

65 Set an Array Element of a 2-D Array
PROGRAM ArrayTest; TYPE matrix = ARRAY[0..2, 0..3] OF integer; VAR i, j, k : integer; a : matrix; BEGIN ... i := 1; j := 2; k := 0; a2[i, j] := k; END. a2 1 2 3 1 2 3 4 1 5 6 8 7 2 9 10 11 12 k getstatic arraytest/a2 [[I getstatic arraytest/i I aaload getstatic arraytest/j I getstatic arraytest/k I iastore 1 2 3 4 5 6 7 8 9 10 11 12 4/6/2019

66 Subscripted Variables as Assignment Targets
PROGRAM ArrayTest; TYPE vector = ARRAY[0..9] OF integer; matrix = ARRAY[0..4, 0..4] OF integer; cube = ARRAY[0..1, 0..2, 0..3] OF integer; VAR i, j, k, n : integer; a : vector; a : matrix; a : cube; BEGIN ... a1[i] := j; a2[i, j] := k; a3[i, j, k] := n; END. getstatic arraytest/a1 [I getstatic arraytest/i I getstatic arraytest/j I iastore getstatic arraytest/a2 [[I aaload getstatic arraytest/k I getstatic arraytest/a3 [[[I getstatic arraytest/n I Instructions iastore (pop and store a scalar value into an array element) and aaload (push an array element address) 4/6/2019

67 More Subscripted Variables
getstatic arraytest/a3 [[[I getstatic arraytest/i I aaload getstatic arraytest/a1 [I getstatic arraytest/j I iaload getstatic arraytest/k I getstatic arraytest/a2 [[I iconst_2 getstatic arraytest/n I imul iconst_1 iadd isub iastore PROGRAM ArrayTest; TYPE vector = ARRAY[0..9] OF integer; matrix = ARRAY[0..4, 0..4] OF integer; cube = ARRAY[0..1, 0..2, 0..3] OF integer; VAR i, j, k, n : integer; a : vector; a : matrix; a : cube; BEGIN ... a3[i][a1[j]][k] := a2[i][j] - a3[k, 2*n][k+1]; END. Instruction aaload pushes the address of one dimension of an array. Instruction iaload pushes the integer value of an array element. What’s on the stack after this instruction? 4/6/2019

68 Allocate Memory for Non-Scalar Arrays
For a non-scalar array, we must generate code to : Allocate memory for the array itself. Similar to a scalar array, except that each element will contain a reference to its data. Allocate memory for the data of each array element and initialize each element. _ 4/6/2019

69 Allocate Memory for a 1-D String Array
PROGRAM AllocArrayTest2; TYPE string = ARRAY[1..5] OF char; vector = ARRAY[0..9] OF string; VAR a1 : vector; BEGIN END. " " a1 Each array element should contain a reference to a string object. _ 4/6/2019

70 Memory for a 1-D String Array, con’d
PROGRAM AllocArrayTest2; TYPE string = ARRAY[1..5] OF char; vector = ARRAY[0..9] OF string; VAR a1 : vector; BEGIN END. a1 " " " " " " bipush anewarray java/lang/StringBuilder iconst_0 istore_1 L001: iload_1 if_icmpge L002 dup iconst_5 invokestatic PaddedString.create(I) Ljava/lang/StringBuilder; aastore iinc 1 1 goto L001 L002: putstatic allocarraytest2/a [Ljava/lang/StringBuilder; " " " " Allocate slot #1 as the temporary variable i. " " " " Like the Java code: for (int i = 0; i < 10; ++i) { a1[i] = PaddedString.create(5); } " " " " What are we duplicating? " " PaddedString is a class in the Pascal Runtime Library. 4/6/2019

71 Code Template: 1-D Non-Scalar Array
bipush anewarray java/lang/StringBuilder iconst_0 istore_1 L001: iload_1 if_icmpge L002 dup iconst_5 invokestatic PaddedString.create(I)Ljava/lang/StringBuilder; aastore iinc 1 1 goto L001 L002: putstatic allocarraytest2/a1 [Ljava/lang/StringBuilder; 4/6/2019

72 Allocate Memory for a 2-D String Array
" " " " " " PROGRAM AllocArrayTest2; TYPE string = ARRAY[1..5] OF char; matrix = ARRAY[0..2, 0..3] OF string; VAR a2 : matrix; BEGIN END. 4/6/2019

73 Memory for a 2-D String Array, cont’d
iconst_3 iconst_4 multianewarray [[Ljava/lang/StringBuilder; 2 iconst_0 istore_1 L003: iload_1 if_icmpge L004 dup aaload istore_2 L005: iload_2 if_icmpge L006 iconst_5 invokestatic PaddedString.create(I)Ljava/lang/StringBuilder; aastore iinc 2 1 goto L005 L006: pop iinc 1 1 goto L003 L004: putstatic allocarraytest2/a2 [[Ljava/lang/StringBuilder; PROGRAM AllocArrayTest2; TYPE string = ARRAY[1..5] OF char; matrix = ARRAY[0..2, 0..3] OF string; VAR a2 : matrix; BEGIN END. " " Allocate slots #1 and #2 as the temporary variables i and j. a2 ditto ditto Like the Java code: for (int i = 0; i < 3; ++i) { for (int j = 0; j < 4; ++j) a2[i][j] = PaddedString.create(5); } 4/6/2019

74 Code Template: n-D Non-Scalar Array
iconst_5 iconst_4 multianewarray [[Ljava/lang/StringBuilder; 2 iconst_0 istore_1 L003: iload_1 iconst_3 if_icmpge L004 dup aaload istore_2 L005: iload_2 if_icmpge L006 invokestatic PaddedString.create(I)Ljava/lang/StringBuilder; aastore iinc 2 1 goto L005 L006: pop iinc 1 1 goto L003 L004: putstatic allocarraytest2/a2 [[Ljava/lang/StringBuilder; 4/6/2019

75 Code to allocate records here!
Records and Fields Recall the code template for a Jasmin method. Code to allocate records here! Implement the value of each Pascal record variable as a java.util.HashMap object. Keys: Field names (as strings) Values: Field values (as objects) _ 4/6/2019

76 Pascal Records in the JVM
Each record value is a separate hash table. Keys: field names Values: field values Allocate and initialize each value. john "age" "firstname" " " PROGRAM RecordTest2; TYPE String16 = ARRAY [1..16] OF char; PersonRec = RECORD firstName : String16; age : integer; END; VAR john : PersonRec; BEGIN ... END. new java/util/HashMap dup invokenonvirtual java/util/HashMap/<init>()V ldc "age" iconst_0 invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer; invokevirtual java/util/HashMap.put(Ljava/lang/Object; Ljava/lang/Object;)Ljava/lang/Object; pop ldc "firstname" bipush 16 invokestatic PaddedString.create(I)Ljava/lang/StringBuilder; putstatic recordtest2/john Ljava/util/HashMap; Convert the int value 0 to an Integer object. Why pop? 4/6/2019

77 Set the Values of Record Fields
john "age" 24 "firstname" " " "John" "John " "" PROGRAM RecordTest2; TYPE String16 = ARRAY [1..16] OF char; PersonRec = RECORD firstName : String16; age : integer; END; VAR john : PersonRec; age : integer; BEGIN john.age := 24; john.firstName := 'John'; age := john.age; END. getstatic recordtest2/john Ljava/util/HashMap; ldc "age" bipush invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer; invokevirtual java/util/HashMap.put(Ljava/lang/Object; Ljava/lang/Object;)Ljava/lang/Object; pop getstatic recordtest2/john Ljava/util/HashMap; ldc "firstname" invokevirtual java/util/HashMap.get(Ljava/lang/Object;)Ljava/lang/Object; checkcast java/lang/StringBuilder dup iconst_0 invokevirtual java/lang/StringBuilder.setLength(I)V ldc "John" invokevirtual java/lang/StringBuilder.append( Ljava/lang/String;)Ljava/lang/StringBuilder; bipush iconst_4 invokestatic PaddedString.blanks(II)Ljava/lang/StringBuilder; invokevirtual java/lang/StringBuilder.append( Ljava/lang/CharSequence;)Ljava/lang/StringBuilder; 4/6/2019

78 Access Values of Record Fields
PROGRAM RecordTest2; TYPE String16 = ARRAY [1..16] OF char; PersonRec = RECORD firstName : String16; age : integer; END; VAR john : PersonRec; age : integer; BEGIN john.age := 24; john.firstName := 'John'; age := john.age; END. john "age" 24 "firstname" "John " age 24 getstatic recordtest2/john Ljava/util/HashMap; ldc "age" invokevirtual java/util/HashMap.get(Ljava/lang/Object;) Ljava/lang/Object; checkcast java/lang/Integer invokevirtual java/lang/Integer.intValue()I putstatic recordtest2/age I 4/6/2019

79 IF Statement Code Templates
The code that evaluates the boolean expression leaves either 0 (false) or 1 (true) on top of the operand stack. ifeq branches if [TOS] is 0 (the expression is false) 4/6/2019

80 Example: IF Statement PROGRAM IfTest; VAR i, j, t, f : integer;
getstatic iftest/i I getstatic iftest/j I if_icmplt L002 iconst_0 goto L003 L002: iconst_1 L003: ifeq L001 sipush 300 putstatic iftest/t I L001: if_icmpeq L005 goto L006 L005: L006: ifeq L007 sipush 200 goto L004 L007: ineg putstatic iftest/f I L004: PROGRAM IfTest; VAR i, j, t, f : integer; BEGIN {IF statements} ... IF i < j THEN t := 300; IF i = j THEN t := 200 ELSE f := -200; END. 4/6/2019

81 Looping Statement Code Template
The code that evaluates the boolean expression leaves either 0 (false) or 1 (true) on top of the operand stack. ifne branches if [TOS] is not 0 (the expression value is true) There might not be any code before or after the test. _ 4/6/2019

82 Example: Newton’s Square Root Function
iconst_0 istore_1 ; i := 0 fload_0 fstore_2 ; root := x L000: fload_0 ; x fload_2 ; root fdiv ; / fadd ; + fconst_2 ; 2.0 fstore_2 ; ==> root iinc ; i := i + 1; iload_1 ; i bipush 10 ; 10 if_icmpgt L001 ; if i > 10 goto L001 iconst_ ; false goto L002 L001: iconst_ ; true L002: ifne L001 ; if true goto L003 goto L000 L003: fload_2 freturn ; return root #0 FUNCTION sqrt(x : real) : real; VAR i : integer; root : real; BEGIN i := 0; root := x; REPEAT root := (x/root + root)/2; i := i + 1; UNTIL i > 10; sqrt := root; END; #1 #2 4/6/2019

83 Example: FOR Statement
PROGRAM ForTest; VAR j, k, n : integer; BEGIN {FOR statements} ... FOR k := j TO 5 DO BEGIN n := k; END; END. getstatic fortest/j I putstatic fortest/k I L001: getstatic fortest/k I iconst_5 if_icmpgt L003 iconst_0 goto L004 L003: iconst_1 L004: ifne L002 putstatic fortest/n I iadd goto L001 L002: This is code emitted for a general > test. It can be improved! Remember that program variables are translated into Jasmin static fields, and so they have names, not slot numbers. 4/6/2019

84 SELECT Statement 4/6/2019

85 Example: CASE Statement
#0 #1 iload_0 ; i lookupswitch 100: L010 105: L010 200: L020 256: L020 282: L020 default: L099 L010: sipush 1000 istore_1 ; j := 1000 goto L099 L020: sipush 2000 istore_1 ; j := 2000 L099: VAR i, j : integer; ... CASE i OF 100,105: j := 1000; 200,256,282: j := 2000; END 4/6/2019

86 Using Java Because your compilers will generate .class files to run on the Java Virtual Machine (JVM) … You can write Java classes whose methods invoke methods in your compiled code. Your compiled code can invoke methods in classes that you write in Java. Create a runtime library. Example: You invent a new source language with statements that do regular expression searches on strings. You can write the RE algorithms in Java and call them from your compiled code. 4/6/2019

87 The Pascal Runtime Library
Useful utility classes written in Java that contain methods your compiled Jasmin code can call. Create an archive file PascalRTL.jar. Some utility classes: PascalTextIn Runtime text input based on the scanner. RunTimer Time the execution of compiled programs and print the elapsed run time. RangeChecker Perform runtime range checking. PascalRuntimeException Error exception thrown while executing compiled code. PaddedString Pascal string implementation with blank-padding 4/6/2019

88 The Pascal Runtime Library, cont’d
The Pascal Runtime Library can reuse some classes from the front end. When a Pascal program calls the standard procedure read to input values at run time, read must scan the input text for values of various data types (integer, real, string, etc.). Therefore, reuse the scanner and token classes by including them in the library. Include the runtime library on your class path when you run your compiled program. java –cp .;PascalRTL.jar ... Your generated code can call routines in the library. 4/6/2019

89 The Pascal Runtime Library, cont’d
Cloner.class PaddedString.class PascalRuntimeException.class PascalTextIn.class RangeChecker.class RunTimer.class BWrap.class CWrap.class IWrap.class RWrap.class 4/6/2019

90 The Pascal Runtime Library, cont’d
wci/frontend/EofToken.class wci/frontend/Scanner.class wci/frontend/Source.class wci/frontend/Token.class wci/frontend/TokenType.class wci/frontend/pascal/PascalScanner.class wci/frontend/pascal/PascalToken.class wci/frontend/pascal/PascalTokenType.class wci/frontend/pascal/tokens/PascalErrorToken.class wci/frontend/pascal/tokens/PascalNumberToken.class wci/frontend/pascal/tokens/PascalSpecialSymbolToken.class wci/frontend/pascal/tokens/PascalStringToken.class wci/frontend/pascal/tokens/PascalWordToken.class wci/message/Message.class wci/message/MessageHandler.class wci/message/MessageListener.class wci/message/MessageProducer.class wci/message/MessageType.class 4/6/2019


Download ppt "CS 432: Compiler Construction Lecture 16"

Similar presentations


Ads by Google