Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CMPE 152: Compiler Design April 11 Lab Department of Computer Engineering San Jose State University Spring 2017 Instructor: Ron Mak www.cs.sjsu.edu/~mak 1 Today’s Lab More Jasmin assembly language Testing Jasmin programs Hybrid Java + Jasmin programs Code templates and code generation Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 2 Using Java 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. Create wrappers and test harnesses. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 3 Using Java, cont’d 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. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 4 Testing Jasmin Programs Jasmin multiply engine: .class public engines/MultiplyEngine .super java/lang/Object .method public static multiply(II)I .limit stack 2 .limit locals 2 iload_0 iload_1 imul ireturn ; ; ; ; Method engines.multiply takes two integer parameters and returns an integer value. Locals #0: first parameter value #1: second parameter value push the local variable in slot #0 (1st parm) push the local variable in slot #1 (2nd parm) multiply return the product on the stack .end method Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 5 Testing Jasmin Programs, cont’d Java test harness: package test; public class MultiplyTester { public static void main(String args[]) { int op0 = Integer.parseInt(args[0]); int op1 = Integer.parseInt(args[1]); int prod = MultiplyEngine.multiply(op0, op1); System.out.println(op0 + " times " + op1 + " equals " + prod); } } Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak Demo 6 Building Hybrid Java + Jasmin in Eclipse Put your .j files inside the src subdirectory with your .java files. Create a jbin subdirectory in your project directory that will contain the .class files generated from your .j files. Right-click the project name in Eclipse. Create a jasmin.bat or jasmin.sh script: java -jar G:\jasmin-2.3\jasmin.jar %1 %2 %3 %4 %5 java -jar /jasmin-2.3/jasmin.jar $1 $2 $3 $4 $5 Select Run External Tools External Tools Configuration ... Select Build Path Configure Build Path ... Select the Libraries tab. Click the Add External Class Folder ... button. Navigate to your jbin directory and click the OK button. Click the OK button. Your jbin directory should now appear under Referenced Libraries in the project tree. Name: jasmin Location: path to your jasmin.bat or jasmin.sh script Working directory: ${project_loc}\jbin Arguments: ${selected_resource_loc} Select a .j file in the project tree. Select Run External Tools Jasmin to assemble the .j file into a .class file under the jbin subdirectory. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 7 Code Templates Syntax diagrams Specify the source language grammar Help us write the parsers Code templates Specify what object code to generate Help us write the code emitters Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 8 Code Template for a Pascal Program Computer Engineering Dept. Spring 2017: April 11 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. CMPE 152: Compiler Design Lab © R. Mak 9 Compilation Strategy We’ll compile a Pascal program 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 Java class. We’ll compile each program variable as if it were a field of the class. Fields do have names in a Jasmin program. Recall that local variables and parameters are referred to only by their slot numbers. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 10 Compilation Strategy, cont’d We’ll compile each Pascal procedure or function 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. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 11 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; Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 12 Program Fields Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 13 Program Fields, cont’d For example: PROGRAM test; VAR i, j, k : x, y : p, q : ch : index : integer; real; boolean; char; 1..10; Pascal program variables Compiles to: .field .field .field .field .field .field .field .field .field .field .field private private private private private private private private private private private Computer Engineering Dept. Spring 2017: April 11 static static static static static static static static static static static _runTimer LRunTimer; _standardIn LPascalTextIn; ch C i I Classes RunTimer and PascalTextIn index I are defined in the Pascal Runtime Library j I PascalRTL.jar which contains runtime k I routines written in Java. p Z q Z x F y F CMPE 152: Compiler Design Lab © R. Mak 14 Code Template for the Main Method, cont’d Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 15 Code Template for the Main Method, cont’d Computer Engineering Dept. Spring 2017: April 11 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. CMPE 152: Compiler Design Lab © R. Mak 16 Loading a Program Variable’s Value To load (push) a program variable’s value onto the operand stack: getstatic Examples: program-name/variable-name type-descriptor getstatic getstatic Java Scalar type Test/count I Test/radius F Jasmin Type Descriptor int I float F boolean Z char C Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 17 Storing a Program Variable’s Value To store (pop) a value from the operand stack into a program variable: putstatic Examples: program-name/variable-name type-descriptor putstatic putstatic Java Scalar type Test/count I Test/radius F Jasmin Type Descriptor int I float F boolean Z char C Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 18 Recall: Operating Calculator SimpleNode Expression() : {} { Operator() { calculator_calculating.jjt SimpleNode operator = (SimpleNode) jjtThis.jjtGetChild(0); SimpleNode first = (SimpleNode) operator.jjtGetChild(0); int firstValue = (Integer) first.jjtGetValue(); First child SimpleNode second = (SimpleNode) operator.jjtGetChild(1); int secondValue = (Integer) second.jjtGetValue(); Second child if (((String) operator.jjtGetValue()).equals("+")) { jjtThis.jjtSetValue(firstValue + secondValue); } else { System.out.println("Unknown operator"); } return jjtThis; } } Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 19 The Visitor Design Pattern Purpose: The visitor interface declares a visit() method for each node type that wants to be visited. Visit the different node types of a tree structure. Perform operations on the nodes without needing to modify the nodes. visit(NodeTypeA node) visit(NodeTypeB node) Each tree node has an accept() method to accept a visitor. accept(Visitor v) Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 20 The Visitor Design Pattern A tree node’s accept() method calls the visitor’s visit() method that’s appropriate for the node type, passing itself as an argument. Accept a visitor call the visitor’s visit() method “Here’s the house key. Go visit my house now.” In order to perform its operation, the visitor’s visit() method uses the node argument (the house key) to access the node’s public data and to call the node’s public methods. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 21 Calculator and the Visitor Design Pattern The visitor interface declares an overloaded visit() method for each node type. Each tree node has an accept() method to accept a visitor. A tree node’s accept() method calls the visitor’s visit() method that’s appropriate for the node type, passing itself as an argument. The visitor’s visit() method uses the node argument to access the node’s public data and to call the node’s public methods in order to perform its operation. JJTree generates the black classes. You write the blue classes. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 22 Calculator and the Visitor Design Pattern First create a visitor object from class SumVisitor. Tell the root node of the expression parse tree to accept the visitor. Reader sr = new StringReader(args[0]); Calculator calc = new Calculator(sr); SimpleNode root = calc.Expression(); SumVisitor visitor = new SumVisitor(); Call the root node’s accept() method and pass the visitor object that will visit the root node. The root node’s accept() method makes the visit happen by calling the visitor’s overloaded visit() method and passing itself (the node = house key) as a parameter. root.jjtAccept(visitor, null); System.out.println("Sum is " + visitor.sum); Computer Engineering Dept. Spring 2017: April 11 There is only one visitor object! CMPE 152: Compiler Design Lab © R. Mak The parameter’s node type determines which visit() method of the visitor is called. 23 Calculator and the Visitor Design Pattern public class CalculatorVisitorAdapter implements CalculatorVisitor { JJTree generates the public Object visit(SimpleNode node, Object data) CalculatorVisitor { return node.childrenAccept(this, data); interface. } One visit() method public Object visit(ASTExpression node, Object data) for each tree node type { that can accept visitors. return node.childrenAccept(this, data); } public Object visit(ASTOperator node, Object data) { return node.childrenAccept(this, data); } public Object visit(ASTOperand node, Object data) { return node.childrenAccept(this, data); } } Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak The default action when visiting each type of tree node is to tell each of the node’s children to accept the visitor. (In other words, recursively walk down the tree.) This action can be overridden by subclasses. 24 Calculator and the Visitor Design Pattern, cont’d public class SumVisitor extends CalculatorVisitorAdapter { public int sum = 0; Only override the visit method of the ASTOperand node. public Object visit(ASTOperand operand, Object data) { sum += (Integer) operand.jjtGetValue(); return super.visit(operand, data); } After summing, do the default action (super.visit) } for any children. (This is a preorder traversal.) SumVisitor’s visit() method is called whenever the tree node is an ASTOperand (i.e., an ASTOperand node is being visited). The SumVisitor object simply adds the value stored in the operand node to its running sum . Then it performs the default action for any children. SumVisitor is a subclass of CalculatorVisitorAdaptor. The adaptor implements visit() methods for the other node types. Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 25 Pcl2 Pcl2 has a .jjt grammar file to generate a parse tree. The process() method of the backend CodeGenerator class generates the Jasmin object code for an entire Pascal program. program header program fields (variables) class constructor main method header main method prologue main method’s compound statement (using the visitor pattern) main method epilogue Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 26 Pcl2 Code Generator You can use the visitor design pattern to generate Jasmin object code for the main program’s compound statement: CodeGeneratorVisitor codeVisitor = new CodeGeneratorVisitor(); Node rootNode = iCode.getRoot(); rootNode.jjtAccept(codeVisitor, programName); Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 27 Pcl2 Code Generator The visit() methods emit the appropriate Jasmin code for various types of tree nodes: public class CodeGeneratorVisitor extends PclParserVisitorAdapter implements PclParserTreeConstants { public Object visit(ASTintegerConstant node, Object data) { int value = (Integer) node.getAttribute(VALUE); // Emit a load constant instruction. CodeGenerator.objectFile.println(" CodeGenerator.objectFile.flush(); return data; ldc " + value); You should check whether to use a shortcut instruction } public public public public Object Object Object Object visit(ASTrealConstant node, Object data) ... visit(ASTassignmentStatement node, Object data) ... visit(ASTadd node, Object data) ... visit(ASTvariable node, Object data) ... } Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak Demo 28 Code for Procedures and Functions Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 29 Code for Procedures and Functions Each a private static method. Method signature: Routine’s name Type descriptors of the formal parameters. Example: TYPE arr = ARRAY [1..5] OF real; FUNCTION func(i, j : integer; x, y : real; p : boolean; ch : char; vector : arr; length : integer) : real; Compiles to: .method private static func(IIFFZC[FI)F Computer Engineering Dept. Spring 2017: April 11 CMPE 152: Compiler Design Lab © R. Mak 30