summaryrefslogtreecommitdiff
path: root/src/msil/ch
diff options
context:
space:
mode:
Diffstat (limited to 'src/msil/ch')
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java20
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java54
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java31
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Type.java22
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala5
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala4
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala10
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.
*/