/* * Copyright 2012 Phil Pratt-Szeliga and other contributors * http://chirrup.org/ * * See the file LICENSE for copying permission. */ package org.trifort.rootbeer.generate.opencl; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.trifort.rootbeer.generate.opencl.tweaks.Tweaks; import soot.RefType; import soot.SootClass; import soot.Type; import soot.jimple.InstanceOfExpr; import soot.rbclassload.ClassHierarchy; import soot.rbclassload.HierarchyGraph; import soot.rbclassload.NumberedType; import soot.rbclassload.RootbeerClassLoader; import soot.rbclassload.StringNumbers; public class OpenCLInstanceof { private Type m_type; private OpenCLType m_oclType; public OpenCLInstanceof(Type type) { m_type = type; m_oclType = new OpenCLType(m_type); } public String getPrototype() { return getDecl()+";\n"; } private String getDecl(){ String device = Tweaks.v().getDeviceFunctionQualifier(); String global = Tweaks.v().getGlobalAddressSpaceQualifier(); String ret = device+" char "+getMethodName(); ret += "(int thisref, int * exception)"; return ret; } private String getMethodName(){ return "org_trifort_rootbeer_instanceof_"+m_oclType.getDerefString(); } public String getBody() { if(m_type instanceof RefType == false){ throw new RuntimeException("not supported yet"); } RefType ref_type = (RefType) m_type; List<NumberedType> type_list = getTypeList(ref_type.getSootClass()); String ret = getDecl(); ret += "{\n"; ret += " char * thisref_deref;\n"; ret += " GC_OBJ_TYPE_TYPE type;\n"; ret += " if(thisref == -1){\n"; ret += " return 0;\n"; ret += " }\n"; ret += " thisref_deref = org_trifort_gc_deref(thisref);\n"; ret += " type = org_trifort_gc_get_type(thisref_deref);\n"; ret += " switch(type){\n"; for(NumberedType ntype : type_list){ ret += " case "+ntype.getNumber()+":\n"; } ret += " return 1;\n"; ret += " }\n"; ret += " return 0;\n"; ret += "}\n"; return ret; } public String invokeExpr(InstanceOfExpr arg0){ String ret = getMethodName(); ret += "("+arg0.getOp().toString()+", exception)"; return ret; } @Override public boolean equals(Object other){ if(other == null){ return false; } if(other instanceof OpenCLInstanceof){ OpenCLInstanceof rhs = (OpenCLInstanceof) other; return m_type.equals(rhs.m_type); } else { return false; } } @Override public int hashCode() { int hash = 5; hash = 29 * hash + (this.m_type != null ? this.m_type.hashCode() : 0); return hash; } private List<NumberedType> getTypeList(SootClass soot_class) { ClassHierarchy class_hierarchy = RootbeerClassLoader.v().getClassHierarchy(); HierarchyGraph hgraph = class_hierarchy.getHierarchyGraph(); Set<Integer> visited = new TreeSet<Integer>(); visited.add(StringNumbers.v().addString(soot_class.getName())); LinkedList<String> queue = new LinkedList<String>(); queue.add(soot_class.getName()); Set<Integer> new_invokes = RootbeerClassLoader.v().getNewInvokes(); List<NumberedType> ret = new ArrayList<NumberedType>(); while(queue.isEmpty() == false){ String entry = queue.removeFirst(); Integer num = StringNumbers.v().addString(entry); if(new_invokes.contains(num)){ NumberedType ntype = class_hierarchy.getNumberedType(entry); ret.add(ntype); } Set<Integer> children = hgraph.getChildren(num); for(Integer child : children){ if(visited.contains(child)){ continue; } visited.add(child); queue.add(StringNumbers.v().getString(child)); } } return ret; } }