X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FIR%2FTypeUtil.java;h=df68f021a110519cfc955cad11ac026793945743;hb=937867fd8d958d7ce7dadc3e4aab8ff03084eb51;hp=2cb7396803524c5d9ed4d1ba92c9fa08728b763e;hpb=19bab0abfb85ab12604a7ddda3253894b0933938;p=IRC.git diff --git a/Robust/src/IR/TypeUtil.java b/Robust/src/IR/TypeUtil.java index 2cb73968..df68f021 100644 --- a/Robust/src/IR/TypeUtil.java +++ b/Robust/src/IR/TypeUtil.java @@ -1,110 +1,561 @@ package IR; import java.util.*; +import IR.Flat.FlatNode; +import IR.Tree.*; +import java.io.File; +import Main.Main; + public class TypeUtil { - public static final String StringClass="String"; - State state; - Hashtable supertable; - Hashtable subclasstable; + public static String StringClass; + public static String StringClassValueField; + public static String ObjectClass; + public static String StartupClass; + public static String TagClass; + public static String ThreadClass; + public static String TaskClass; + State state; + Hashtable supertable; + Hashtable subclasstable; + Hashtable directSubClassTable; + BuildIR bir; + + // for interfaces + Hashtable> superIFtbl; + + public TypeUtil(State state, BuildIR bir) { + this.state=state; + this.bir=bir; + if (state.JNI) { + StringClass="java.lang.String"; + StringClassValueField="value"; + ObjectClass="java.lang.Object"; + StartupClass="StartupObject"; + TagClass="TagDescriptor"; + ThreadClass="java.lang.Thread"; + TaskClass="Task"; + } else { + StringClass="String"; + StringClassValueField="value"; + ObjectClass="Object"; + StartupClass="StartupObject"; + TagClass="TagDescriptor"; + ThreadClass="Thread"; + TaskClass="Task"; + } + createTables(); + } + + public void addNewClass(String cl, Set todo) { + //search through the default locations for the file. + if(state.MGC) { + // do not consider package or import when compiling MGC version + cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1); + } + for (int i = 0; i < state.classpath.size(); i++) { + String path = (String) state.classpath.get(i); + File f = new File(path, cl.replace('.', '/') + ".java"); + if (f.exists()) { + try { + ParseNode pn = Main.readSourceFile(state, f.getCanonicalPath()); + bir.buildtree(pn, todo, f.getCanonicalPath()); + return; + } catch (Exception e) { + throw new Error(e); + } + } + } + } + - public TypeUtil(State state) { - this.state=state; - createTables(); + + public ClassDescriptor getClass(String classname) { + String cl = classname; + if(state.MGC) { + // do not consider package or import when compiling MGC version + cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1); } + ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(cl); + return cd; + } + + public ClassDescriptor getClass(ClassDescriptor context, String classnameIn, HashSet todo) { + int fileindex=0; + do { + int dotindex=classnameIn.indexOf('.',fileindex); + fileindex=dotindex+1; - public ClassDescriptor getClass(String classname) { - ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname); + if(dotindex==-1) { + //get entire class name + dotindex=classnameIn.length(); + } + + String classnamestr = classnameIn.substring(0, dotindex); + String remainder = classnameIn.substring(dotindex, classnameIn.length()); + + if (context!=null) { + classnamestr = context.getCanonicalImportMapName(classnamestr); + } + ClassDescriptor cd=helperGetClass(classnamestr, remainder, todo); + + if (cd!=null) { return cd; + } + } while(fileindex!=0); + throw new Error("Cannot find class: "+classnameIn); + } + + private ClassDescriptor helperGetClass(String classname, String remainder, HashSet todo) { + String cl = classname; + if(state.MGC) { + // do not consider package or import when compiling MGC version + cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1); + } + + ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(cl); + if (cd==null) { + //have to find class + addNewClass(cl, todo); + String cl2=cl+remainder.replace('.','$'); + cd=(ClassDescriptor)state.getClassSymbolTable().get(cl2); + if (cd==null) + return null; + System.out.println("Build class:"+cd); + todo.add(cd); + } else { + String cl2=cl+remainder.replace('.','$'); + cd=(ClassDescriptor)state.getClassSymbolTable().get(cl2); + if (cd==null) + return null; + } + if (!supertable.containsKey(cd)) { + String superc=cd.getSuper(); + if (superc!=null) { + ClassDescriptor cd_super=getClass(cd, superc, todo); + supertable.put(cd,cd_super); + } + } + if (!superIFtbl.containsKey(cd)) { + // add inherited interfaces + superIFtbl.put(cd,new HashSet()); + HashSet hs=(HashSet)superIFtbl.get(cd); + Vector superifv = cd.getSuperInterface(); + for(int i = 0; i < superifv.size(); i++) { + String superif = superifv.elementAt(i); + ClassDescriptor if_super = getClass(cd, superif, todo); + hs.add(if_super); + } + } + return cd; + } + + private void createTables() { + supertable=new Hashtable(); + superIFtbl = new Hashtable>(); + } + + public ClassDescriptor getMainClass() { + return getClass(state.main); + } + + public MethodDescriptor getRun() { + ClassDescriptor cd=getClass(TypeUtil.ThreadClass); + for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext(); ) { + MethodDescriptor md=(MethodDescriptor) methodit.next(); + if (md.numParameters()!=0||md.getModifiers().isStatic()) + continue; + return md; + } + throw new Error("Can't find Thread.run"); + } + + public MethodDescriptor getStaticStart() { + ClassDescriptor cd=getClass(TypeUtil.ThreadClass); + for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit.hasNext(); ) { + MethodDescriptor md=(MethodDescriptor) methodit.next(); + if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).isClass()||md.getParamType(0).getClassDesc()!=cd) + continue; + return md; + } + throw new Error("Can't find Thread.run"); + } + + public MethodDescriptor getExecute() { + ClassDescriptor cd = getClass(TypeUtil.TaskClass); + + if(cd == null && state.DSMTASK) + throw new Error("Task.java is not included"); + + for(Iterator methodit = cd.getMethodTable().getSet("execute").iterator(); methodit.hasNext(); ) { + MethodDescriptor md = (MethodDescriptor) methodit.next(); + if (md.numParameters()!=0 || md.getModifiers().isStatic()) + continue; + return md; + } + throw new Error("Can't find Task.execute"); + } + + + public MethodDescriptor getMain() { + ClassDescriptor cd=getMainClass(); + Set mainset=cd.getMethodTable().getSet("main"); + + for(Iterator mainit=mainset.iterator(); mainit.hasNext(); ) { + MethodDescriptor md=(MethodDescriptor)mainit.next(); + if (md.numParameters()!=1) + continue; + Descriptor pd=md.getParameter(0); + TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd) + .getType(); + if (tpd.getArrayCount()!=1) + continue; + if (!tpd.getSymbol().equals(StringClass)) + continue; + if (!md.getModifiers().isStatic()) + throw new Error("Error: Non static main"); + return md; + } + throw new Error(cd+" has no main"); + } + + /** Check to see if md1 is more specific than md2... Informally + if md2 could always be called given the arguments passed into + md1 */ + + public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2, boolean checkReturnType) { + /* Checks if md1 is more specific than md2 */ + if (md1.numParameters()!=md2.numParameters()) + throw new Error(); + for(int i=0; i getSuperIFs(ClassDescriptor cd) { + return superIFtbl.get(cd); + } + + public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) { + if (original.isChar()&& + (casttype.isByte()|| + casttype.isShort())) + return true; + + if (casttype.isChar()&& + (original.isByte()|| + original.isShort()|| + original.isInt()|| + original.isLong()|| + original.isFloat()|| + original.isDouble())) + return true; + + return false; + } + + public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) { + if (possiblesuper.isOffset() || cd2.isOffset()) return true; + //Matching type are always okay + if (possiblesuper.equals(cd2)) + return true; + + if ((possiblesuper.isTag() && !cd2.isTag())|| + (!possiblesuper.isTag() && cd2.isTag())) + return false; + + //Handle arrays + if (cd2.isArray()||possiblesuper.isArray()) { + // Object is super class of all arrays + if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray()) + return true; + + // If we have the same dimensionality of arrays & both are classes, we can default to the normal test + if (cd2.isClass()&&possiblesuper.isClass() + &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&& + isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc())) + return true; + + // Object is superclass of all array classes + if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass() + &&(possiblesuper.getArrayCount() it_sifs = getSuperIFs(cd2).iterator(); + while(it_sifs.hasNext()) { + ClassDescriptor cd = it_sifs.next(); + if(cd == possiblesuper) { + return true; + } else if(!tovisit.contains(cd)) { + tovisit.add(cd); + } + } + } + + while(cd2!=null) { + cd2=getSuper(cd2); + if (cd2==possiblesuper) + return true; + + // check cd2's interface ancestors + if(cd2 != null) { + Iterator it_sifs = getSuperIFs(cd2).iterator(); + while(it_sifs.hasNext()) { + ClassDescriptor cd = (ClassDescriptor)it_sifs.next(); + if(cd == possiblesuper) { + return true; + } else if(!tovisit.contains(cd)) { + tovisit.add(cd); + } + } + } + } + + while(!tovisit.isEmpty()) { + ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next(); + tovisit.remove(cd); - private void createTables() { - supertable=new Hashtable(); - subclasstable=new Hashtable(); - - Iterator classit=state.getClassSymbolTable().getDescriptorsIterator(); - while(classit.hasNext()) { - ClassDescriptor cd=(ClassDescriptor)classit.next(); - String superc=cd.getSuper(); - if (superc!=null) { - ClassDescriptor cd_super=getClass(superc); - supertable.put(cd,cd_super); - } - - ClassDescriptor tmp=cd.getSuperDesc(); - while(tmp!=null) { - if (!subclasstable.containsKey(tmp)) - subclasstable.put(tmp,new HashSet()); - HashSet hs=(HashSet)subclasstable.get(tmp); - hs.add(cd); - tmp=tmp.getSuperDesc(); - } - } - } - - public Set getSubClasses(ClassDescriptor cd) { - return (Set)subclasstable.get(cd); - } - - public ClassDescriptor getSuper(ClassDescriptor cd) { - return (ClassDescriptor)supertable.get(cd); - } - - public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) { - if (possiblesuper.isClass()&& - cd2.isClass()) - return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()); - else if (possiblesuper.isClass()&& - cd2.isNull()) - return true; - else if (possiblesuper.isNull()) - throw new Error(); //not sure when this case would occur - else if (possiblesuper.isPrimitive()&& - cd2.isPrimitive()) { - ///Primitive widenings from 5.1.2 - if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()|| - possiblesuper.isInt()||possiblesuper.isLong()|| - possiblesuper.isFloat()||possiblesuper.isDouble())) - return true; - if (cd2.isShort()&&(possiblesuper.isShort()|| - possiblesuper.isInt()||possiblesuper.isLong()|| - possiblesuper.isFloat()||possiblesuper.isDouble())) - return true; - if (cd2.isChar()&&(possiblesuper.isChar()|| - possiblesuper.isInt()||possiblesuper.isLong()|| - possiblesuper.isFloat()||possiblesuper.isDouble())) - return true; - if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()|| - possiblesuper.isFloat()||possiblesuper.isDouble())) - return true; - if (cd2.isLong()&&(possiblesuper.isLong()|| - possiblesuper.isFloat()||possiblesuper.isDouble())) - return true; - if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble())) - return true; - if (cd2.isDouble()&&possiblesuper.isDouble()) - - return true; - if (cd2.isBoolean()&&possiblesuper.isBoolean()) - return true; - - return false; - } else throw new Error(); - } - - - public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) { - if (possiblesuper==cd2) - return true; - else - return isSuper(possiblesuper, cd2); - } - - public boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) { - while(cd2!=null) { - cd2=getSuper(cd2); - if (cd2==possiblesuper) - return true; - } - return false; + if(!visited.contains(cd)) { + Iterator it_sifs = getSuperIFs(cd).iterator(); + while(it_sifs.hasNext()) { + ClassDescriptor cdt = (ClassDescriptor)it_sifs.next(); + if(cdt == possiblesuper) { + return true; + } else if(!tovisit.contains(cdt)) { + tovisit.add(cdt); + } + } + visited.add(cd); + } } + return false; + } }