From 4cf60d65bc8f71969d6012182738c6bb31a4c49b Mon Sep 17 00:00:00 2001 From: Miguel Garcia Date: Fri, 8 Apr 2011 11:38:48 +0000 Subject: [MSIL] handling of volatile fields. --- src/msil/ch/epfl/lamp/compiler/msil/Attribute.java | 6 +-- .../ch/epfl/lamp/compiler/msil/CustomModifier.java | 45 ++++++++++++++++++++ src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java | 49 +++++++++++++++++----- .../lamp/compiler/msil/HasCustomModifiers.java | 9 ++++ src/msil/ch/epfl/lamp/compiler/msil/PEFile.java | 32 ++++++++++---- src/msil/ch/epfl/lamp/compiler/msil/PEType.java | 16 ++++--- .../ch/epfl/lamp/compiler/msil/PrimitiveType.java | 5 ++- .../lamp/compiler/msil/emit/FieldBuilder.scala | 7 +++- .../lamp/compiler/msil/emit/ILPrinterVisitor.scala | 36 ++++++++++------ .../epfl/lamp/compiler/msil/emit/TypeBuilder.scala | 22 +++++++--- .../epfl/lamp/compiler/msil/util/PECustomMod.java | 23 ++++++++++ 11 files changed, 198 insertions(+), 52 deletions(-) create mode 100644 src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java create mode 100644 src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java create mode 100644 src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java (limited to 'src/msil/ch/epfl') 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/**/ 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]] * [= | at ] 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; + } + +} + -- cgit v1.2.3