Commits

Shashank Bharadwaj committed b0ecff2

current progress

Comments (0)

Files changed (1)

fix-asm-via-cfg.patch

 new file mode 100644
 --- /dev/null
 +++ b/src/org/python/antlr/ast/BasicBlock.java
-@@ -0,0 +1,23 @@
+@@ -0,0 +1,43 @@
 +package org.python.antlr.ast;
 +
++import java.util.ArrayList;
 +import java.util.List;
 +
 +import org.python.antlr.base.stmt;
++import org.python.compiler.cfg.Edge;
 +
 +public class BasicBlock extends stmt {
-+	
-+	public List<stmt> stmts = null;
 +
-+	public BasicBlock(List<stmt> suite) {
-+		this.stmts = suite;
++	public List<stmt> stmts;
++	public List<Edge> inEdges;
++	public List<Edge> outEdges;
++
++	public Object start;
++	public Object end;
++
++	public BasicBlock() {
++		this.stmts = new ArrayList<>();
++		this.inEdges = new ArrayList<>();
++		this.outEdges = new ArrayList<>();
 +	}
 +
 +	public <R> R accept(VisitorIF<R> visitor) throws Exception {
 +	}
 +
 +	public void traverse(VisitorIF<?> visitor) throws Exception {
-+		// TODO: nothing here for now
++		// visitor.visitSuite(new Suite(getToken(), stmts));
++	}
++
++	@Override
++	public String toString() {
++		if (outEdges.size() == 1) {
++			return "BasicBlock with 1 out edge and handler block with: "
++					+ outEdges.get(0).getDestination().inEdges.size()
++					+ " incoming edges";
++		}
++		return "BasicBlock with: " + outEdges.size() + " out edges and "
++				+ inEdges.size() + " in edges";
 +	}
 +
 +}
      public R visitExceptHandler(ExceptHandler node) throws Exception;
 +    public R visitBasicBlock(BasicBlock basicBlock) throws Exception;
  }
-diff --git a/src/org/python/compiler/CFGBuilder.java b/src/org/python/compiler/CFGBuilder.java
+diff --git a/src/org/python/compiler/ClassFile.java b/src/org/python/compiler/ClassFile.java
+--- a/src/org/python/compiler/ClassFile.java
++++ b/src/org/python/compiler/ClassFile.java
+@@ -2,6 +2,7 @@
+ package org.python.compiler;
+ 
+ import java.io.ByteArrayOutputStream;
++import java.io.FileOutputStream;
+ import java.io.IOException;
+ import java.io.OutputStream;
+ import java.util.ArrayList;
+@@ -13,7 +14,6 @@
+ import org.objectweb.asm.FieldVisitor;
+ import org.objectweb.asm.MethodVisitor;
+ import org.objectweb.asm.Opcodes;
+-
+ import org.python.core.imp;
+ 
+ public class ClassFile
+@@ -104,7 +104,7 @@
+     }
+ 
+     public void write(OutputStream stream) throws IOException {
+-        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, this.name, null, this.superclass, interfaces);
++        cw.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, this.name, null, this.superclass, interfaces);
+         AnnotationVisitor av = cw.visitAnnotation("Lorg/python/compiler/APIVersion;", true);
+         // XXX: should imp.java really house this value or should imp.java point into
+         // org.python.compiler?
+@@ -126,7 +126,18 @@
+         ByteArrayOutputStream baos = new ByteArrayOutputStream(ba.length);
+         baos.write(ba, 0, ba.length);
+         baos.writeTo(stream);
+-        //debug(baos);
++        debug(baos);
+         baos.close();
+     }
++    
++	private void debug(ByteArrayOutputStream baos) {
++		FileOutputStream fos = null;
++		try {
++			fos = new FileOutputStream(this.sfilename + ".class");
++			baos.writeTo(fos);
++		} catch (IOException e) {
++			// TODO Auto-generated catch block
++			e.printStackTrace();
++		}
++	}
+ }
+diff --git a/src/org/python/compiler/CodeCompiler.java b/src/org/python/compiler/CodeCompiler.java
+--- a/src/org/python/compiler/CodeCompiler.java
++++ b/src/org/python/compiler/CodeCompiler.java
+@@ -17,6 +17,7 @@
+ import org.python.antlr.ast.Assign;
+ import org.python.antlr.ast.Attribute;
+ import org.python.antlr.ast.AugAssign;
++import org.python.antlr.ast.BasicBlock;
+ import org.python.antlr.ast.BinOp;
+ import org.python.antlr.ast.BoolOp;
+ import org.python.antlr.ast.Break;
+@@ -75,6 +76,7 @@
+ import org.python.antlr.base.expr;
+ import org.python.antlr.base.mod;
+ import org.python.antlr.base.stmt;
++import org.python.compiler.cfg.Edge;
+ import org.python.core.CompilerFlags;
+ import org.python.core.ContextGuard;
+ import org.python.core.ContextManager;
+@@ -1393,21 +1395,27 @@
+     }
+ 
+     @Override
++    public Object visitBasicBlock(BasicBlock node) throws Exception {
++    	System.out.println("Codecompiler::visiting basicblock: " + node + node.stmts);
++    	return suite(node.stmts);
++    }
++    
++    @Override
+     public Object visitTryExcept(TryExcept node) throws Exception {
+-        Label start = new Label();
+-        Label end = new Label();
+-        Label handler_start = new Label();
++    	BasicBlock body = (BasicBlock) node.getInternalBody().get(0);
++    	System.out.println("body: " + body);
++    	java.util.List<Edge> out = body.outEdges;
++    	Edge one = out.get(0);
++        Label start = one.getStart();
++        Label end = one.getEnd();
++        Label handler_start = one.getHandlerStart();
+         Label handler_end = new Label();
+-        ExceptionHandler handler = new ExceptionHandler();
++        code.visitTryCatchBlock(start, end, handler_start, p(Throwable.class));
+ 
+         code.label(start);
+-        handler.exceptionStarts.addElement(start);
+-        exceptionHandlers.push(handler);
+         //Do suite
+         Object exit = suite(node.getInternalBody());
+-        exceptionHandlers.pop();
+         code.label(end);
+-        handler.exceptionEnds.addElement(end);
+ 
+         if (exit == null) {
+             code.goto_(handler_end);
+@@ -1439,7 +1447,6 @@
+         }
+ 
+         code.freeFinallyLocal(exc);
+-        handler.addExceptionHandlers(handler_start);
+         return null;
+     }
+ 
+diff --git a/src/org/python/compiler/Module.java b/src/org/python/compiler/Module.java
+--- a/src/org/python/compiler/Module.java
++++ b/src/org/python/compiler/Module.java
+@@ -10,6 +10,7 @@
+ 
+ import org.objectweb.asm.Label;
+ import org.objectweb.asm.Opcodes;
++import org.python.compiler.cfg.CFGBuilder;
+ import org.python.core.CodeBootstrap;
+ import org.python.core.CodeFlag;
+ import org.python.core.CodeLoader;
+@@ -657,6 +658,8 @@
+     public static void compile(mod node, OutputStream ostream, String name, String filename,
+             boolean linenumbers, boolean printResults, CompilerFlags cflags, long mtime)
+             throws Exception {
++    	node = (mod) new CFGBuilder().visit(node);
++    	
+         Module module = new Module(name, filename, linenumbers, mtime);
+         if (cflags == null) {
+             cflags = new CompilerFlags();
+diff --git a/src/org/python/compiler/ScopesCompiler.java b/src/org/python/compiler/ScopesCompiler.java
+--- a/src/org/python/compiler/ScopesCompiler.java
++++ b/src/org/python/compiler/ScopesCompiler.java
+@@ -4,6 +4,7 @@
+ 
+ import org.python.antlr.Visitor;
+ import org.python.antlr.PythonTree;
++import org.python.antlr.ast.BasicBlock;
+ import org.python.antlr.ast.ClassDef;
+ import org.python.antlr.ast.DictComp;
+ import org.python.antlr.ast.Exec;
+@@ -374,5 +375,11 @@
+ 
+         return null;
+     }
++    
++    @Override
++    public Object visitBasicBlock(BasicBlock node) throws Exception {
++    	suite(node.stmts);
++    	return null;
++    }
+ 
+ }
+diff --git a/src/org/python/compiler/cfg/CFGBuilder.java b/src/org/python/compiler/cfg/CFGBuilder.java
 new file mode 100644
 --- /dev/null
-+++ b/src/org/python/compiler/CFGBuilder.java
-@@ -0,0 +1,18 @@
-+package org.python.compiler;
++++ b/src/org/python/compiler/cfg/CFGBuilder.java
+@@ -0,0 +1,108 @@
++package org.python.compiler.cfg;
 +
 +import java.util.ArrayList;
 +import java.util.List;
++import java.util.Stack;
 +
 +import org.python.antlr.ast.BasicBlock;
++import org.python.antlr.ast.FunctionDef;
++import org.python.antlr.ast.TryExcept;
++import org.python.antlr.base.excepthandler;
 +import org.python.antlr.base.stmt;
 +
 +public class CFGBuilder extends TransitiveVisitor {
++
++	public static class CFGBuilderData {
++		public List<stmt> blocks;
++		public stmt currBlock;
++
++		public CFGBuilderData() {
++			blocks = new ArrayList<stmt>();
++			currBlock = new BasicBlock();
++		}
++	}
++
++	Stack<CFGBuilderData> stack = new Stack<>();
++
++	CFGBuilderData data;
++
++	private void beginBlock(BasicBlock end) {
++		System.out.println("starting new block with an edge to: " + end);
++		data = new CFGBuilderData();
++		if (end != null) {
++			new Edge((BasicBlock) data.currBlock, end);
++		}
++	}
++
++	private void endBlock() {
++		data.blocks.add(data.currBlock);
++		data.currBlock = null;
++	}
++
++	private void pauseBlock() {
++		if (data != null) {
++			System.out.println("pausing block");
++			endBlock();
++			stack.push(data);
++		} else {
++			System.out.println("no block to pause");
++		}
++	}
++
++	private void restartBlock() {
++		if (!stack.isEmpty()) {
++			System.out.println("Restarting old block");
++			data = stack.pop();
++			data.currBlock = new BasicBlock();
++			data.blocks.add(data.currBlock);
++		}
++	}
++
++	@Override
++	public List<stmt> suite(List<stmt> stmts) throws Exception {
++		beginBlock(null);
++		doSuite(stmts);
++		endBlock();
++		System.out.println("Finished scope: " + data.blocks.size());
++		return data.blocks;
++	}
++
++	private void doSuite(List<stmt> stmts) throws Exception {
++		for (stmt s : stmts) {
++			((BasicBlock)data.currBlock).stmts.add((stmt) visit(s));
++		}
++	}
 +	
 +	@Override
-+	public List<stmt> suite(List<stmt> stmts) throws Exception {
-+		List<stmt> new_stmt = new ArrayList<stmt>();
-+		new_stmt.add(new BasicBlock(super.suite(stmts)));
-+        return new_stmt;
++	public Object visitFunctionDef(FunctionDef node) throws Exception {
++		return super.visitFunctionDef(node);
++	}
++
++	public List<stmt> suite(List<stmt> stmts, BasicBlock end) throws Exception {
++		beginBlock(end);
++		doSuite(stmts);
++		endBlock();
++		return data.blocks;
++	}
++
++	@Override
++	public Object visitTryExcept(TryExcept node) throws Exception {
++		pauseBlock();
++		System.out.println("::Starting try except");
++		BasicBlock handler = new BasicBlock();
++		List<stmt> body = suite(node.getInternalBody(), handler);
++//		List<stmt> orelse = suite(node.getInternalOrelse(), handler);
++		List<stmt> orelse = node.getInternalOrelse();
++
++		List<excepthandler> handlers = new ArrayList<excepthandler>();
++		for (excepthandler target : node.getInternalHandlers()) {
++			handlers.add((excepthandler) visit(target));
++		}
++		System.out.println("::end try-except::basic block: " + handler);
++		TryExcept new_node = new TryExcept(node.getToken(), body, handlers, orelse);
++		restartBlock();
++
++		return new_node;
 +	}
 +
 +}
-diff --git a/src/org/python/compiler/TransitiveVisitor.java b/src/org/python/compiler/TransitiveVisitor.java
+diff --git a/src/org/python/compiler/cfg/Edge.java b/src/org/python/compiler/cfg/Edge.java
 new file mode 100644
 --- /dev/null
-+++ b/src/org/python/compiler/TransitiveVisitor.java
-@@ -0,0 +1,593 @@
-+package org.python.compiler;
++++ b/src/org/python/compiler/cfg/Edge.java
+@@ -0,0 +1,54 @@
++package org.python.compiler.cfg;
++
++import org.objectweb.asm.Label;
++import org.python.antlr.ast.BasicBlock;
++
++/**
++ * A class which represents an edge between two basic blocks
++ */
++public class Edge {
++	private BasicBlock source;
++	private BasicBlock destination;
++
++	/**
++	 * Create a new edge from source to destination. This constructor also takes
++	 * care of updating those nodes to maintain links to this edge
++	 * 
++	 * @param source
++	 * @param destination
++	 */
++	public Edge(BasicBlock source, BasicBlock destination) {
++		this.source = source;
++		this.destination = destination;
++		source.outEdges.add(this);
++		source.start = new Label();
++		source.end = new Label();
++		destination.inEdges.add(this);
++		destination.start = new Label();
++	}
++
++	public BasicBlock getDestination() {
++		return destination;
++	}
++
++	public BasicBlock getSource() {
++		return source;
++	}
++
++	public Label getStart() {
++		return (Label) source.start;
++	}
++
++	public Label getEnd() {
++		return (Label) source.end;
++	}
++
++	public Label getHandlerStart() {
++		return (Label) destination.start;
++	}
++
++	@Override
++	public String toString() {
++		return "<" + source + " --> " + destination + "> ";
++	}
++}
+diff --git a/src/org/python/compiler/cfg/TransitiveVisitor.java b/src/org/python/compiler/cfg/TransitiveVisitor.java
+new file mode 100644
+--- /dev/null
++++ b/src/org/python/compiler/cfg/TransitiveVisitor.java
+@@ -0,0 +1,591 @@
++package org.python.compiler.cfg;
 +
 +import java.util.ArrayList;
 +import java.util.Iterator;
 +        List<excepthandler> old_handlers = node.getInternalHandlers();
 +
 +        List<excepthandler> handlers = new ArrayList<excepthandler>();
-+        for (Iterator<excepthandler> iterator = old_handlers.iterator(); iterator.hasNext();) {
-+            excepthandler target = iterator.next();
++        for (excepthandler target : old_handlers) {
 +            handlers.add((excepthandler)visit(target));
 +        }
 +
 +        TryExcept new_node = new TryExcept(node.getToken(), body, handlers, orelse);
-+        
 +        return new_node;
 +    }
 +
 +    }
 +}
 \ No newline at end of file
+diff --git a/tmp/test.py b/tmp/test.py
+new file mode 100644
+--- /dev/null
++++ b/tmp/test.py
+@@ -0,0 +1,23 @@
++def openfile():
++    foo = "ha"
++    try:
++        f = 42
++        yield 42
++        try:
++            yield 24
++            raise IOError()
++        except IOError:
++            yield 22
++            
++    except IOError:
++        print "hi there"
++        yield 12
++#        return
++    print foo
++#    return f
++    yield 32
++
++#openfile()
++
++for _ in openfile():
++    print _
+\ No newline at end of file