diff options
Diffstat (limited to 'src/msil')
7 files changed, 104 insertions, 42 deletions
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java index 99e5c5fe69..69f5d6d32a 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java +++ b/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java @@ -24,23 +24,23 @@ public class ConstructorInfo extends MethodBase { protected static final String CTOR = ".ctor"; protected static final String CCTOR = ".cctor"; - protected static final ConstructorInfo[] EMPTY_ARRAY = - new ConstructorInfo[0]; + protected static final ConstructorInfo[] EMPTY_ARRAY = new ConstructorInfo[0]; protected static String getName(int attrs) { - return (attrs & MethodAttributes.Static) == 0 ? CTOR : CCTOR; + return (attrs & MethodAttributes.Static) == 0 ? CTOR : CCTOR; } - /** Protected constructor */ - protected ConstructorInfo(Type declType, int attrs, Type[] paramTypes) { - super(getName(attrs), declType, attrs, paramTypes); - assert declType != null : "Owner can't be 'null' for a constructor!"; + /** Public constructors */ + + public ConstructorInfo(Type declType, int attrs, Type[] paramTypes) { + super(getName(attrs), declType, attrs, paramTypes); + assert declType != null : "Owner can't be 'null' for a constructor!"; } - protected ConstructorInfo(Type declType, int attrs, ParameterInfo[] params) + public ConstructorInfo(Type declType, int attrs, ParameterInfo[] params) { - super(getName(attrs), declType, attrs, params); - assert declType != null : "Owner can't be 'null' for a constructor!"; + super(getName(attrs), declType, attrs, params); + assert declType != null : "Owner can't be 'null' for a constructor!"; } diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java index 793ee362e9..fe6404346e 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java +++ b/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java @@ -5,6 +5,8 @@ package ch.epfl.lamp.compiler.msil; +import java.util.Iterator; + /** * The common superclass of MemberInfo and ConstructorInfo * @@ -16,6 +18,34 @@ public abstract class MethodBase extends MemberInfo { //########################################################################## // public interface + private java.util.List /* GenericParamAndConstraints */ mVars = new java.util.LinkedList(); + private GenericParamAndConstraints[] sortedMVars = null; + + public void addMVar(GenericParamAndConstraints tvarAndConstraints) { + sortedMVars = null; + mVars.add(tvarAndConstraints); + } + + public GenericParamAndConstraints[] getSortedMVars() { + if(sortedMVars == null) { + sortedMVars = new GenericParamAndConstraints[mVars.size()]; + for (int i = 0; i < sortedMVars.length; i ++){ + Iterator iter = mVars.iterator(); + while(iter.hasNext()) { + GenericParamAndConstraints tvC = (GenericParamAndConstraints)iter.next(); + if(tvC.Number == i) { + sortedMVars[i] = tvC; + } + } + } + } + return sortedMVars; + } + + public final boolean IsGeneric() { + return mVars.size() > 0; + } + /** The attributes associated with this method/constructor. */ public final short Attributes; @@ -36,6 +66,10 @@ public abstract class MethodBase extends MemberInfo { return (Attributes& MethodAttributes.Virtual) != 0; } + public final boolean IsInstance() { + return !IsStatic() && !IsVirtual(); + } + public final boolean IsStatic() { return (Attributes & MethodAttributes.Static) != 0; } @@ -79,6 +113,26 @@ public abstract class MethodBase extends MemberInfo { == MethodAttributes.FamANDAssem; } + public boolean HasPtrParamOrRetType() { + // the override in MethodInfo checks the return type + ParameterInfo[] ps = GetParameters(); + for (int i = 0; i < ps.length; i++) { + Type pT = ps[i].ParameterType; + if(pT.IsPointer()) { + // Type.mkPtr creates a msil.Type for a pointer type + return true; + } + if(pT.IsByRef() && !pT.GetElementType().CanBeTakenAddressOf()) { + /* TODO Cases where GenMSIL (so far) con't emit good bytecode: + the type being taken address of IsArray(), IsGeneric(), or IsTMVarUsage. + For example, System.Enum declares + public static bool TryParse<TEnum>(string value, out TEnum result) where TEnum : struct, new(); + */ + return true; + } + } + return false; + } /** Returns the parameters of the method/constructor. */ public ParameterInfo[] GetParameters() { diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java index 8c53a768fc..a415e7551f 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java +++ b/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java @@ -15,32 +15,17 @@ import java.util.Iterator; */ public class MethodInfo extends MethodBase { - private java.util.List /* GenericParamAndConstraints */ mVars = new java.util.LinkedList(); - private GenericParamAndConstraints[] sortedMVars = null; - - public void addMVar(GenericParamAndConstraints tvarAndConstraints) { - sortedMVars = null; - mVars.add(tvarAndConstraints); - } - - public GenericParamAndConstraints[] getSortedMVars() { - if(sortedMVars == null) { - sortedMVars = new GenericParamAndConstraints[mVars.size()]; - for (int i = 0; i < sortedMVars.length; i ++){ - Iterator iter = mVars.iterator(); - while(iter.hasNext()) { - GenericParamAndConstraints tvC = (GenericParamAndConstraints)iter.next(); - if(tvC.Number == i) { - sortedMVars[i] = tvC; - } - } - } + public boolean HasPtrParamOrRetType() { + if(ReturnType.IsByRef() && !(ReturnType.GetElementType().IsValueType())) { + /* A method returning ByRef won't pass peverify, so I guess this is dead code. */ + return true; } - return sortedMVars; + if(ReturnType.IsPointer()) { + return true; + } + return super.HasPtrParamOrRetType(); } - - //########################################################################## // public members diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Type.java b/src/msil/ch/epfl/lamp/compiler/msil/Type.java index 78704062b7..a4de4ae11b 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/Type.java +++ b/src/msil/ch/epfl/lamp/compiler/msil/Type.java @@ -285,6 +285,19 @@ public abstract class Type extends MemberInfo { public final boolean IsEnum() { return BaseType() == ENUM(); } + public boolean CanBeTakenAddressOf() { + /* TODO should be overridden in TMVarUsage, + but there's currently no way to bind a TMVarUsage to its GenericParamAndConstraints definition. Why? + Because of the way the msil library is organized (e.g., mkArray() returns the same !0[] representation + for all !0[] usages, irrespective of the scope of the !0 type-param) + This in turn is so because without generics there's no harm in using a type-def instance + where a type-ref should go (e.g., the ParameterType of a ParameterInfo nowadays may point to a PEType). + The net effect is that this method (CanBeTakenAddressOf) is conservative, it will answer "no" + for example for !0 where !0 refers to a type-param with the isValuetype constraint set. + The whole thing is ok at this point in time, where generics are not supported at the backend. */ + return IsValueType() && (this != ENUM()); + /* ENUM() is a singleton, i.e. System.Enum is not generic */ + } /** IsGeneric, true for a PEType or TypeBuilder (i.e., a type definition) * containing one or more type params. Not to be called on a reference @@ -325,7 +338,8 @@ public abstract class Type extends MemberInfo { public final int Number; public final boolean isTVar; - /** Non-defining reference to either a TVar or an MVar */ + /** Non-defining reference to either a TVar or an MVar. + * An instance of GenericParamAndConstraints represents a TVar or an MVar definition. */ public TMVarUsage(int Number, boolean isTVar) { super(null, 0, ((isTVar ? "!" : "!!") + Number), null, null, null, AuxAttr.None, null); this.Number = Number; @@ -378,7 +392,7 @@ public abstract class Type extends MemberInfo { if (array != null) return array; array = new PrimitiveType(elemType.Module, - TypeAttributes.Public + elemType.Attributes | TypeAttributes.Sealed | TypeAttributes.Serializable, elemType.FullName + arrSig, @@ -393,7 +407,7 @@ public abstract class Type extends MemberInfo { Type type = getType(name); if (type != null) return type; type = new PrimitiveType(elemType.Module, - TypeAttributes.NotPublic, + elemType.Attributes, name, null, EmptyTypes, null, AuxAttr.Pointer, elemType); return addType(type); @@ -405,7 +419,7 @@ public abstract class Type extends MemberInfo { Type type = getType(name); if (type != null) return type; type = new PrimitiveType(elemType.Module, - TypeAttributes.NotPublic, + elemType.Attributes, name, null, EmptyTypes, null, AuxAttr.ByRef, elemType); return addType(type); diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala index cc359b813f..66f53b8132 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala @@ -450,7 +450,7 @@ abstract class ILPrinterVisitor extends Visitor { def caseOpCode(opCode: OpCode) { var opString = opCode.toString() print(opString) - pad(12 - opString.length()) + pad(14 - opString.length()) // switch opcode if (opCode == OpCode.Ldstr) { @@ -484,9 +484,8 @@ abstract class ILPrinterVisitor extends Visitor { print(" \'"); print(loc.name); print("\'") //print("'") print(((LocalBuilder)argument).name) print("'") } else if (opCode == OpCode.Readonly) { - println("readonly. ") + // nothing to do } else if (opCode == OpCode.Constrained) { - print("constrained. ") printReference(argument.asInstanceOf[Type]) } else if (opCode == OpCode.Ldelema) { printReference(argument.asInstanceOf[Type]) diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala index bfccc42214..fbcdbf893f 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala @@ -805,13 +805,13 @@ object OpCode { * constrained prefix */ final val Constrained = new OpCode() -opcode(Constrained, CEE_CONSTRAINED , "constrained" , 0xFFFFFE16, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT) +opcode(Constrained, CEE_CONSTRAINED , "constrained." , 0xFFFFFE16, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT) /** * readonly prefix */ final val Readonly = new OpCode() -opcode(Readonly, CEE_READONLY , "readonly" , 0xFFFFFE1E, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT) +opcode(Readonly, CEE_READONLY , "readonly." , 0xFFFFFE1E, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT) /** * Calls the method indicated on the evaluation stack (as a pointer to an entry point) diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala index db2a6fedc7..d486c31af0 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala @@ -235,6 +235,16 @@ object OpCodes { final val Call = OpCode.Call /** + * constrained. prefix + */ + final val Constrained = OpCode.Constrained + + /** + * readonly. prefix + */ + final val Readonly = OpCode.Readonly + + /** * Calls the method indicated on the evaluation stack (as a pointer to an entry point) * with arguments described by a calling convention. */ |