summaryrefslogtreecommitdiff
path: root/src/msil/ch/epfl
diff options
context:
space:
mode:
authorMiguel Garcia <magarcia@epfl.ch>2011-04-08 11:38:48 +0000
committerMiguel Garcia <magarcia@epfl.ch>2011-04-08 11:38:48 +0000
commit4cf60d65bc8f71969d6012182738c6bb31a4c49b (patch)
tree8f8dc7d307829d82d7f8a32934ce58f12bab3dca /src/msil/ch/epfl
parentcaee04079fb8ed40a1458cf24649fad9d80a85c1 (diff)
downloadscala-4cf60d65bc8f71969d6012182738c6bb31a4c49b.tar.gz
scala-4cf60d65bc8f71969d6012182738c6bb31a4c49b.tar.bz2
scala-4cf60d65bc8f71969d6012182738c6bb31a4c49b.zip
[MSIL] handling of volatile fields.
Diffstat (limited to 'src/msil/ch/epfl')
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Attribute.java6
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java45
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java49
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java9
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEFile.java32
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEType.java16
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java5
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala7
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala36
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala22
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java23
11 files changed, 198 insertions, 52 deletions
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java b/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java
index cdcf6a64f1..0f2c4e6764 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java
@@ -372,10 +372,8 @@ public class Attribute {
private Type getTypeFromSerString() {
String typename = parseString();
int i = typename.indexOf(',');
- // fully qualified assembly name follows
- // just strip it on the assumtion theat the
- // assembly is referenced in the externs and the
- // type will be found
+ /* fully qualified assembly name follows. Just strip it on the assumption that
+ the assembly is referenced in the externs and the type will be found. */
String name = (i < 0) ? typename : typename.substring(0, i);
Type t = Type.GetType(name);
if (t == null && i > 0) {
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java b/src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java
new file mode 100644
index 0000000000..cf30008c60
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java
@@ -0,0 +1,45 @@
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Quoting from the CIL spec, Partition II, Sec. 7.1.1:
+ *
+ * Custom modifiers, defined using `modreq` (required modifier) and `modopt` (optional modifier), are
+ * similar to custom attributes (Sec. 21) except that modifiers are part of a signature rather than being attached to a
+ * declaration. Each modifer associates a type reference with an item in the signature.
+ *
+ */
+public class CustomModifier {
+
+ public boolean isReqd;
+ public Type marker;
+
+ public CustomModifier(boolean isReqd, Type marker) {
+ this.isReqd = isReqd;
+ this.marker = marker;
+ }
+
+ public String toString() {
+ String res = (isReqd ? "modreq( " : "modopt( ") + marker.toString() + " )";
+ return res;
+ }
+
+ public static Type[] helperCustomMods(boolean isReqd, CustomModifier[] cmods) {
+ if(cmods == null) return null;
+ int count = 0;
+ for (int idx = 0; idx < cmods.length; idx++) {
+ if(cmods[idx].isReqd == isReqd) count++;
+ }
+ Type[] res = new Type[count];
+ int residx = 0;
+ for (int idx = 0; idx < cmods.length; idx++) {
+ res[residx] = cmods[idx].marker;
+ residx++;
+ }
+ return res;
+ }
+
+ public static Type VolatileMarker() {
+ return Type.GetType("System.Runtime.CompilerServices.IsVolatile");
+ }
+
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java
index 9649dabd4e..536a67e9a8 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java
@@ -5,13 +5,15 @@
package ch.epfl.lamp.compiler.msil;
+import ch.epfl.lamp.compiler.msil.util.PECustomMod;
+
/**
* Discovers the attributes of a field and provides access to field metadata.
*
* @author Nikolay Mihaylov
* @version 1.0
*/
-public class FieldInfo extends MemberInfo {
+public class FieldInfo extends MemberInfo implements HasCustomModifiers {
//##########################################################################
// public interface
@@ -24,6 +26,9 @@ public class FieldInfo extends MemberInfo {
/** Type of the field represented by this FieldInfo object. */
public final Type FieldType;
+ /** can be null */
+ public final CustomModifier[] cmods;
+
protected final Object value;
public final boolean IsStatic() {
@@ -80,6 +85,33 @@ public class FieldInfo extends MemberInfo {
return (Attributes & FieldAttributes.NotSerialized) != 0;
}
+ private boolean knownVolatile = false;
+ private boolean cachedVolatile = false;
+ public final boolean IsVolatile() {
+ if(knownVolatile) return cachedVolatile;
+ knownVolatile = true;
+ if(cmods == null) {
+ cachedVolatile = false;
+ return cachedVolatile;
+ }
+ for (int idx = 0; idx < cmods.length; idx++) {
+ if(cmods[idx].marker == CustomModifier.VolatileMarker()) {
+ cachedVolatile = true;
+ return cachedVolatile;
+ }
+ }
+ cachedVolatile = false;
+ return cachedVolatile;
+ }
+
+ public final Type[] GetOptionalCustomModifiers () {
+ return CustomModifier.helperCustomMods(false, cmods);
+ }
+
+ public final Type[] GetRequiredCustomModifiers() {
+ return CustomModifier.helperCustomMods(true, cmods);
+ }
+
public String toString() {
return FieldAttributes.toString(Attributes) + " " +
FieldType + " " + DeclaringType.FullName + "::" + Name;
@@ -90,17 +122,14 @@ public class FieldInfo extends MemberInfo {
protected static final FieldInfo[] EMPTY_ARRAY = new FieldInfo[0];
/** Initializes a new instance of the FieldInfo class. */
- protected FieldInfo(String name, Type declType, int attrs, Type fieldType) {
- this(name, declType, attrs, fieldType, null);
- }
-
protected FieldInfo(String name, Type declType,
- int attrs, Type fieldType, Object value)
+ int attrs, PECustomMod fieldTypeWithMods, Object value)
{
- super(name, declType);
- FieldType = fieldType;
- Attributes = (short) attrs;
- this.value = value;
+ super(name, declType);
+ FieldType = fieldTypeWithMods.marked;
+ cmods = fieldTypeWithMods.cmods;
+ Attributes = (short) attrs;
+ this.value = value;
}
/**
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java b/src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java
new file mode 100644
index 0000000000..5ead087350
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java
@@ -0,0 +1,9 @@
+package ch.epfl.lamp.compiler.msil;
+
+public interface HasCustomModifiers {
+
+ public Type[] GetOptionalCustomModifiers();
+
+ public Type[] GetRequiredCustomModifiers();
+
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
index d6d12c8b4a..481d5f2116 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
@@ -873,10 +873,11 @@ public class PEFile {
return type;
} // decodeType0()
- public Type decodeFieldType() {
- skipByte(FIELD);
- skipCustomMods();
- return decodeType();
+ public PECustomMod decodeFieldType() {
+ skipByte(FIELD); // 0x06
+ CustomModifier[] cmods = getCustomMods();
+ Type fieldType = decodeType();
+ return new PECustomMod(fieldType, cmods);
}
/** decodes the return type of a method signature (22.2.11). */
@@ -908,10 +909,10 @@ public class PEFile {
}
public void skipCustomMods() {
- while (getByte() == ELEMENT_TYPE_CMOD_OPT
- || getByte() == ELEMENT_TYPE_CMOD_REQD)
+ while (getByte() == ELEMENT_TYPE_CMOD_OPT /* 0x20 */
+ || getByte() == ELEMENT_TYPE_CMOD_REQD /* 0x1f */ )
{
- boolean isREQD = (getByte() == ELEMENT_TYPE_CMOD_REQD);
+ boolean isREQD = (getByte() == ELEMENT_TYPE_CMOD_REQD); // 0x1f
// skip the tag 23.2.7
readByte();
// skip the TypeDefOrRefEncoded (23.2.8)
@@ -923,7 +924,22 @@ public class PEFile {
}
}
- //######################################################################
+ /**
+ * @see CustomModifier
+ */
+ public CustomModifier[] getCustomMods() {
+ java.util.List/*<CustomModifier>*/ cmods = new java.util.LinkedList();
+ while (getByte() == ELEMENT_TYPE_CMOD_OPT || getByte() == ELEMENT_TYPE_CMOD_REQD) {
+ boolean isReqd = (getByte() == ELEMENT_TYPE_CMOD_REQD);
+ readByte(); // tag 23.2.7
+ Type t = pemodule.getTypeDefOrRef(decodeInt()); // TypeDefOrRefEncoded (23.2.8)
+ cmods.add(new CustomModifier(isReqd, t));
+ }
+ CustomModifier[] res = (CustomModifier[])cmods.toArray(new CustomModifier[0]);
+ return res;
+ }
+
+ //######################################################################
} // class Sig
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEType.java b/src/msil/ch/epfl/lamp/compiler/msil/PEType.java
index 25e5373df1..418c6603b3 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PEType.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEType.java
@@ -10,6 +10,7 @@ import ch.epfl.lamp.compiler.msil.PEFile.Sig;
import ch.epfl.lamp.compiler.msil.util.Table;
import ch.epfl.lamp.compiler.msil.util.Table.*;
import ch.epfl.lamp.compiler.msil.util.Signature;
+import ch.epfl.lamp.compiler.msil.util.PECustomMod;
import java.util.ArrayList;
@@ -83,7 +84,7 @@ final class PEType extends Type implements Signature {
String name = file.FieldDef.getName();
//System.out.println("\t-->Loading field: " + name);
Sig sig = file.FieldDef.getSignature();
- Type fieldType = sig.decodeFieldType();
+ PECustomMod pecmod = sig.decodeFieldType();
Object val = null;
Table.Constant consts = file.Constant;
for (int i = 1; i <= consts.rows; i++) {
@@ -93,10 +94,8 @@ final class PEType extends Type implements Signature {
if (tableId == Table.FieldDef.ID && refRow == frow)
val = consts.getValue();
}
- FieldInfo field =
- new PEFieldInfo(row, name, attrs, fieldType, val);
- if (field.Name.equals("value__") && field.IsSpecialName())
- {
+ FieldInfo field = new PEFieldInfo(row, name, attrs, pecmod, val);
+ if (field.Name.equals("value__") && field.IsSpecialName()) {
assert underlyingType == null : underlyingType.toString();
underlyingType = field.FieldType;
}
@@ -158,8 +157,7 @@ final class PEType extends Type implements Signature {
//System.out.println("Retval attributes 0x" +
// PEFile.short2hex(pattr));
} else {
- params[seq - 1] = new ParameterInfo
- (paramName, paramType[seq - 1], pattr, seq - 1);
+ params[seq - 1] = new ParameterInfo(paramName, paramType[seq - 1], pattr, seq - 1);
}
}
for (int i = 0; i < params.length; i++) {
@@ -351,9 +349,9 @@ final class PEType extends Type implements Signature {
private class PEFieldInfo extends FieldInfo {
private final int definingRow;
public PEFieldInfo(int definingRow, String name,
- int attrs, Type fieldType, Object value)
+ int attrs, PECustomMod pecmod, Object value)
{
- super(name, PEType.this, attrs, fieldType, value);
+ super(name, PEType.this, attrs, pecmod, value);
this.definingRow = definingRow;
}
protected void loadCustomAttributes(Type attributeType) {
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java b/src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java
index ccca52edba..b19fe29869 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java
@@ -1,5 +1,7 @@
package ch.epfl.lamp.compiler.msil;
+import ch.epfl.lamp.compiler.msil.util.PECustomMod;
+
public final class PrimitiveType extends Type {
public PrimitiveType(Module module,
int attributes,
@@ -31,7 +33,8 @@ public final class PrimitiveType extends Type {
}
public FieldInfo addField(String name, int attrs, Type fieldType) {
- FieldInfo res = new FieldInfo(name, this, attrs, fieldType);
+ PECustomMod fieldTypeWithMods = new PECustomMod(fieldType, null);
+ FieldInfo res = new FieldInfo(name, this, attrs, fieldTypeWithMods, null);
FieldInfo[] ms = new FieldInfo[fields.length + 1];
System.arraycopy(fields, 0, ms, 0, fields.length);
ms[ms.length - 1] = res;
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala
index 3ea06382e5..7ef9dc7a5b 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala
@@ -9,6 +9,9 @@ import ch.epfl.lamp.compiler.msil.FieldInfo
import ch.epfl.lamp.compiler.msil.Type
import ch.epfl.lamp.compiler.msil.FieldAttributes
import ch.epfl.lamp.compiler.msil.ConstructorInfo
+
+import ch.epfl.lamp.compiler.msil.util.PECustomMod
+
import java.io.IOException
/**
@@ -17,8 +20,8 @@ import java.io.IOException
* @author Nikolay Mihaylov
* @version 1.0
*/
-class FieldBuilder(name: String, declType: Type, attrs: Int, fieldType: Type)
- extends FieldInfo(name, declType, attrs, fieldType)
+class FieldBuilder(name: String, declType: Type, attrs: Int, fieldTypeWithMods: PECustomMod)
+ extends FieldInfo(name, declType, attrs, fieldTypeWithMods, null)
with ICustomAttributeSetter
with Visitable
{
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 73bc0f435c..d3a57194da 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
@@ -271,7 +271,7 @@ abstract class ILPrinterVisitor extends Visitor {
// [[int32]] <fieldAttr>* <type> <id> [= <fieldInit> | at <dataLabel>]
print(".field ")
print(FieldAttributes.toString(field.Attributes))
- print(" "); printSignature(field.FieldType)
+ print(" "); printSignature(field.FieldType, field.cmods)
print(" \'"); print(field.Name); print("\'")
if (field.IsLiteral()) {
print(" = ")
@@ -608,16 +608,16 @@ abstract class ILPrinterVisitor extends Visitor {
}
- def printSignature(field: FieldInfo) {
- printSignature(field.FieldType)
- //print(' ') print(owner)
- print(' ')
- //if (field.IsStatic && field.DeclaringType != currentType) {
- printReference(field.DeclaringType)
- print("::")
- //}
- printName(field.Name)
- }
+ def printSignature(field: FieldInfo) {
+ printSignature(field.FieldType, field.cmods)
+ //print(' ') print(owner)
+ print(' ')
+ //if (field.IsStatic && field.DeclaringType != currentType) {
+ printReference(field.DeclaringType)
+ print("::")
+ //}
+ printName(field.Name)
+ }
// print method head
@throws(classOf[IOException])
@@ -670,7 +670,19 @@ abstract class ILPrinterVisitor extends Visitor {
print(")")
}
- def printSignature(`type`: Type) {
+ def printSignature(marked: Type, cmods: Array[CustomModifier]) {
+ printSignature(marked)
+ if( (cmods != null) && !cmods.isEmpty ) {
+ print(" ")
+ for(cm <- cmods) {
+ print(if (cm.isReqd) "modreq( " else "modopt( ")
+ printReference(cm.marker)
+ print(" ) ")
+ }
+ }
+ }
+
+ def printSignature(`type`: Type) {
val sigOpt = primitive.get(`type`)
if (sigOpt.isDefined) {
print(sigOpt.get)
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
index 663b2c5cb0..5126a0c34d 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
@@ -6,6 +6,9 @@
package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
+
+import ch.epfl.lamp.compiler.msil.util.PECustomMod
+
import java.io.IOException
/**
@@ -38,15 +41,22 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
}
/**
- * Adds a new field to the class, with the given name,
- * attributes and field type.
+ * Adds a new field to the class, with the given name, attributes and field type. The location has no custom mods.
*/
- def DefineField(name: String, `type`: Type, attrs: Short): FieldBuilder = {
- val field: FieldBuilder = new FieldBuilder(name, this, attrs, `type`)
- fieldBuilders += field
- return field
+ def DefineField(name: String, fieldType: Type, attrs: Short): FieldBuilder = {
+ val fieldTypeWithCustomMods = new PECustomMod(fieldType, null)
+ DefineField(name, fieldTypeWithCustomMods, attrs)
}
+ /**
+ * Adds a new field to the class, with the given name, attributes and (field type , custom mods) combination.
+ */
+ def DefineField(name: String, fieldTypeWithMods: PECustomMod, attrs: Short): FieldBuilder = {
+ val field: FieldBuilder = new FieldBuilder(name, this, attrs, fieldTypeWithMods)
+ fieldBuilders += field
+ return field
+ }
+
/**
* Adds a new method to the class, with the given name and
* method signature.
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java b/src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java
new file mode 100644
index 0000000000..56519e8487
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java
@@ -0,0 +1,23 @@
+package ch.epfl.lamp.compiler.msil.util;
+
+import ch.epfl.lamp.compiler.msil.Type;
+import ch.epfl.lamp.compiler.msil.CustomModifier;
+
+/**
+ * A PECustomMod holds the info parsed from metadata per the CustomMod production in Sec. 23.2.7, Partition II.
+ * */
+public final class PECustomMod {
+
+ public final Type marked;
+ public final CustomModifier[] cmods;
+
+ /** Terminology:
+ the CustomModifier(s) are markers,
+ and the msil.Type is a type marked by those markers. */
+ public PECustomMod(Type marked, CustomModifier[] cmods) {
+ this.marked = marked;
+ this.cmods = cmods;
+ }
+
+}
+