package IR;
import java.util.*;
+
+import IR.Flat.FlatNode;
import IR.Tree.*;
import java.io.File;
import Main.Main;
Hashtable supertable;
Hashtable subclasstable;
BuildIR bir;
+
+ // for interfaces
+ Hashtable superIFtbl;
public TypeUtil(State state, BuildIR bir) {
this.state=state;
supertable.put(cd,cd_super);
}
}
+ if (!this.superIFtbl.containsKey(cd)) {
+ // add inherited interfaces
+ superIFtbl.put(cd,new HashSet());
+ HashSet hs=(HashSet)superIFtbl.get(cd);
+ Vector<String> superifv = cd.getSuperInterface();
+ for(int i = 0; i < superifv.size(); i++) {
+ String superif = superifv.elementAt(i);
+ ClassDescriptor if_super = getClass(superif, todo);
+ hs.add(if_super);
+ }
+ }
return cd;
}
private void createTables() {
supertable=new Hashtable();
+ superIFtbl = new Hashtable();
}
public ClassDescriptor getMainClass() {
if (md1.numParameters()!=md2.numParameters())
throw new Error();
for(int i=0; i<md1.numParameters(); i++) {
- if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
- return false;
+ if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i))) {
+ if(state.MGC && ((!md1.getParamType(i).isArray() &&
+ (md1.getParamType(i).isInt() || md1.getParamType(i).isLong() || md1.getParamType(i).isDouble() || md1.getParamType(i).isFloat()))
+ && md2.getParamType(i).isClass() && md2.getParamType(i).getClassDesc().getSymbol().equals("Object"))) {
+ // primitive parameters vs Object
+ } else {
+ return false;
+ }
+ }
}
if (md1.getReturnType()==null||md2.getReturnType()==null) {
if (md1.getReturnType()!=md2.getReturnType())
public void createFullTable() {
subclasstable=new Hashtable();
+ //subIFclasstable = new Hashtable();
+ HashSet tovisit=new HashSet();
+ HashSet visited=new HashSet();
Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
while(classit.hasNext()) {
ClassDescriptor cd=(ClassDescriptor)classit.next();
ClassDescriptor tmp=cd.getSuperDesc();
+
+ if(state.MGC) {
+ // TODO add version for normal Java later
+ // check tmp's interface ancestors
+ Iterator it_sifs = cd.getSuperInterfaces();
+ while(it_sifs.hasNext()) {
+ ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
+ if(!tovisit.contains(cdt)){
+ tovisit.add(cdt);
+ }
+ }
+ }
while(tmp!=null) {
- if (!subclasstable.containsKey(tmp))
- subclasstable.put(tmp,new HashSet());
- HashSet hs=(HashSet)subclasstable.get(tmp);
- hs.add(cd);
- tmp=tmp.getSuperDesc();
+ if (!subclasstable.containsKey(tmp))
+ subclasstable.put(tmp,new HashSet());
+ HashSet hs=(HashSet)subclasstable.get(tmp);
+ hs.add(cd);
+ if(state.MGC) {
+ // TODO add version for normal Java later
+ // check tmp's interface ancestors
+ Iterator it_sifs = tmp.getSuperInterfaces();
+ while(it_sifs.hasNext()) {
+ ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
+ if(!tovisit.contains(cdt)){
+ tovisit.add(cdt);
+ }
+ }
+ }
+ tmp=tmp.getSuperDesc();
+ }
+
+ if(state.MGC) {
+ // TODO add version for normal Java later
+ while(!tovisit.isEmpty()) {
+ ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next();
+ tovisit.remove(sif);
+
+ if(!visited.contains(sif)) {
+ if(!this.subclasstable.containsKey(sif)) {
+ this.subclasstable.put(sif, new HashSet());
+ }
+ HashSet hs = (HashSet)this.subclasstable/*subIFclasstable*/.get(sif);
+ hs.add(cd);
+
+ Iterator it_sifs = sif.getSuperInterfaces();
+ while(it_sifs.hasNext()) {
+ ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next();
+ if(!tovisit.contains(siftmp)){
+ tovisit.add(siftmp);
+ }
+ }
+ visited.add(sif);
+ }
+ }
}
}
}
public ClassDescriptor getSuper(ClassDescriptor cd) {
return (ClassDescriptor)supertable.get(cd);
}
+
+ public Set getSuperIFs(ClassDescriptor cd) {
+ return (Set)this.superIFtbl.get(cd);
+ }
public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
if (original.isChar()&&
}
public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
+ if(state.MGC) {
+ if(possiblesuper.isClass() && possiblesuper.class_desc.isEnum() && cd2.isInt()) {
+ return true;
+ }
+ }
if (possiblesuper.isOffset() || cd2.isOffset()) return true;
//Matching type are always okay
if (possiblesuper.equals(cd2))
throw new Error("Case not handled:"+possiblesuper+" "+cd2);
}
+ public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
+ if( isSuperorType( td1, td2 ) ) {
+ return td2;
+ }
+ if( isSuperorType( td2, td1 ) ) {
+ return td1;
+ }
+ throw new Error( td1+" and "+td2+" have no superclass relationship" );
+ }
+
+ public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
+ return mostSpecific( td1, mostSpecific( td2, td3 ) );
+ }
public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
if (possiblesuper==cd2)
}
private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
+ HashSet tovisit=new HashSet();
+ HashSet visited=new HashSet();
+
+ if(state.MGC) {
+ // TODO add version for normal Java later
+ // check cd2's interface ancestors
+ 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(cd2!=null) {
cd2=getSuper(cd2);
if (cd2==possiblesuper)
return true;
+
+ if(state.MGC) {
+ // TODO add version for normal Java later
+ // 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);
+ }
+ }
+ }
+ }
+ }
+
+ if(state.MGC) {
+ // TODO add version for normal Java later
+ while(!tovisit.isEmpty()) {
+ ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
+ tovisit.remove(cd);
+
+ 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;
}