summaryrefslogtreecommitdiff
path: root/src/msil
diff options
context:
space:
mode:
authorMiguel Garcia <magarcia@epfl.ch>2010-11-18 15:30:51 +0000
committerMiguel Garcia <magarcia@epfl.ch>2010-11-18 15:30:51 +0000
commit13a20ba71ae1805c7361e95d66360bd0a9a7f3d8 (patch)
tree02b643e8a58e74e0572d6564b81824982a7e33e2 /src/msil
parenta86453a5eed21abf5dfa5fd1d0321c8eb0298302 (diff)
downloadscala-13a20ba71ae1805c7361e95d66360bd0a9a7f3d8.tar.gz
scala-13a20ba71ae1805c7361e95d66360bd0a9a7f3d8.tar.bz2
scala-13a20ba71ae1805c7361e95d66360bd0a9a7f3d8.zip
Improvements forMSIL:
(1) the Scala types in ch.epfl.lamp.compiler.msil.emit now use Scala collections instead of Java's, (2) a few bug fixes regarding metadata parsing, (3) GenMSIL emits output useful for IDE debugging, (4) TypeParser now enters symbols for generics in case the assemblies being linked sport them, (5) a few fixes for bytecode verif in GenMSIL. review by rytz
Diffstat (limited to 'src/msil')
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java2
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEFile.java15
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEModule.java6
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Type.java2
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala25
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala64
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala139
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala19
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala7
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala4
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala64
11 files changed, 195 insertions, 152 deletions
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java b/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java
index dee67fda43..8c82cb4876 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java
@@ -11,7 +11,7 @@ public class ConstructedType extends Type {
public final Type[] typeArgs;
public ConstructedType(Type instantiatedType, Type[] typeArgs) {
- super (null, instantiatedType.Attributes, "", null, null, null, instantiatedType.auxAttr /*AuxAttr.None*/ , null);
+ super(instantiatedType.Module, instantiatedType.Attributes, "", null, null, null, instantiatedType.auxAttr /*AuxAttr.None*/ , null);
this.instantiatedType = instantiatedType;
this.typeArgs = typeArgs;
}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
index 3ac90291b4..d6d12c8b4a 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
@@ -911,20 +911,17 @@ public class PEFile {
while (getByte() == ELEMENT_TYPE_CMOD_OPT
|| getByte() == ELEMENT_TYPE_CMOD_REQD)
{
+ boolean isREQD = (getByte() == ELEMENT_TYPE_CMOD_REQD);
// skip the tag 23.2.7
readByte();
// skip the TypeDefOrRefEncoded (23.2.8)
- readByte();
- readByte();
-
- // @FIXME: could be 4 bytes, not always 2...
-
- //Type t = decodeType();
- //System.err.println("CMOD: " + t);
- //if (getByte() == ELEMENT_TYPE_CMOD_REQD)
- //throw new RuntimeException("Reqired CMOD: " + t);
+ Type ignored = pemodule.getTypeDefOrRef(decodeInt());
+ if(isREQD) {
+ // System.err.println("ELEMENT_TYPE_CMOD_REQD: " + ignored);
+ // throw new RuntimeException("Reqired CMOD: " + ignored);
}
}
+ }
//######################################################################
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java b/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
index 5cf3e964a7..cb8cd8f098 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
@@ -161,7 +161,7 @@ final class PEModule extends Module {
int tableId = Table.getTableId(Table._ResolutionScope,
tr.ResolutionScope);
int refRow = tr.ResolutionScope >> Table.NoBits[Table._ResolutionScope];
- String typeName = tr.getFullName();
+ final String typeName = tr.getFullName();
pefile.getTable(tableId).readRow(refRow);
switch (tableId) {
case AssemblyRef.ID:
@@ -190,7 +190,9 @@ final class PEModule extends Module {
//assert type != null;
break;
case TypeRef.ID:
- type = getTypeRef(refRow);
+ Type nestingType = getTypeRef(refRow);
+ String nestedName = typeName;
+ type = nestingType.GetNestedType(nestedName);
break;
case ModuleRef.ID:
type = getAssembly(pefile.ModuleRef.getName()).GetType(typeName);
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Type.java b/src/msil/ch/epfl/lamp/compiler/msil/Type.java
index a4de4ae11b..b2489ab66e 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/Type.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Type.java
@@ -154,7 +154,7 @@ public abstract class Type extends MemberInfo {
fullName.length()),
declType);
- Module = module;
+ Module = module; // null only for TMVarUsage and for PrimitiveType
Attributes = attr;
this.baseType = baseType;
if (DeclaringType == null) {
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
index 2c4011eeb0..3110ccd1ce 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
@@ -6,9 +6,6 @@
package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
-import java.util.HashMap
-import java.util.HashSet
-import java.util.ArrayList
import java.io.IOException
/**
@@ -50,19 +47,19 @@ class AssemblyBuilder(name: AssemblyName)
/** Saves this dynamic assembly to disk. */
@throws(classOf[IOException])
def Save(fileName: String) {
- generatedFiles = new ArrayList()
+ generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String]
ILPrinterVisitor.printAssembly(this, fileName)
}
@throws(classOf[IOException])
def Save(destPath: String, sourceFilesPath: String) {
- generatedFiles = new ArrayList()
+ generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String]
ILPrinterVisitor.printAssembly(this, destPath, sourceFilesPath)
}
/** Returns the list of generated files from calling Save(). */
def GetGeneratedFiles(): Array[String] = {
- return generatedFiles.toArray(new Array[String](generatedFiles.size())).asInstanceOf[Array[String]]
+ return generatedFiles.toArray // (new Array[String](generatedFiles.size())).asInstanceOf[Array[String]]
}
/** Sets the entry point for this dynamic assembly. */
@@ -82,24 +79,28 @@ class AssemblyBuilder(name: AssemblyName)
private var access : Int = _
// all extern assemblies used in this assembly builder
- protected var externAssemblies = new HashSet[Assembly]()
+ protected var externAssemblies = scala.collection.mutable.Set.empty[Assembly]
// register an extern assembly
protected def registerExternAssembly(assembly: Assembly) {
- externAssemblies.add(assembly)
+ externAssemblies += assembly
}
// get all extern Assemblies used in this Assembly Builder
def getExternAssemblies(): Array[Assembly] = {
- externAssemblies = new HashSet[Assembly](Assembly.assemblies.values().asInstanceOf[java.util.Collection[Assembly]])
- externAssemblies.remove(this)
- return externAssemblies.toArray(new Array[Assembly](0)).asInstanceOf[Array[Assembly]]
+ externAssemblies = scala.collection.mutable.Set[Assembly]()
+ val iter = Assembly.assemblies.values().iterator
+ while (iter.hasNext) {
+ externAssemblies += iter.next.asInstanceOf[Assembly]
+ }
+ externAssemblies -= this
+ return externAssemblies.toArray
}
def loadModules() {}
// contains list of generated .msil files after calling Save()
- var generatedFiles: ArrayList[String] = new ArrayList[String]()
+ var generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String]
//##########################################################################
//##########################################################################
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
index 40888a9b83..c7899c7f54 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
@@ -7,11 +7,7 @@ package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
import ch.epfl.lamp.compiler.msil.util.Table
-import java.util.ArrayList
import java.util.Stack
-import java.util.Iterator
-import java.util.Map
-import java.util.HashMap
import java.io.IOException
import ILGenerator._
@@ -293,7 +289,7 @@ import ILGenerator._
def DeclareLocal(localType: Type): LocalBuilder = {
val l: LocalBuilder = new LocalBuilder(locals, localType)
locals = locals + 1
- localList.add(l)
+ localList += l
return l
}
@@ -415,19 +411,13 @@ import ILGenerator._
lineNums.put(lastLabel, line + " '" + filename + "'")
}
- def getLocals(): Array[LocalBuilder] = {
- localList.toArray(new Array[LocalBuilder](0)).asInstanceOf[Array[LocalBuilder]]
- }
+ def getLocals(): Array[LocalBuilder] = localList.toArray
- def getLabelIterator(): Iterator[Label] = {
- labelList.iterator()
- }
- def getOpcodeIterator(): Iterator[OpCode] = {
- opcodeList.iterator()
- }
- def getArgumentIterator(): Iterator[Object] = {
- argumentList.iterator()
- }
+ def getLabelIterator() = labelList.iterator
+
+ def getOpcodeIterator() = opcodeList.iterator
+
+ def getArgumentIterator() = argumentList.iterator
//##########################################################################
// private implementation details
@@ -435,15 +425,15 @@ import ILGenerator._
// the local variable list
- private final val localList: ArrayList[LocalBuilder] = new ArrayList[LocalBuilder]()
+ private final val localList = scala.collection.mutable.ArrayBuffer.empty[LocalBuilder]
// the label list, the opcode list and the opcode argument list
// labelList is an array of Label
// opcodeList is an array of OpCode
// argumentList is an array of Object (null if no argument)
- private final val labelList: ArrayList[Label] = new ArrayList[Label]()
- private final val opcodeList: ArrayList[OpCode] = new ArrayList[OpCode]()
- private final val argumentList: ArrayList[Object] = new ArrayList[Object]()
+ private final val labelList = scala.collection.mutable.ArrayBuffer.empty[Label]
+ private final val opcodeList = scala.collection.mutable.ArrayBuffer.empty[OpCode]
+ private final val argumentList = scala.collection.mutable.ArrayBuffer.empty[Object]
// the program counter (pc)
// also called the stream's current position
@@ -464,7 +454,7 @@ import ILGenerator._
// the method info owner of this ILGenerator
var owner: MethodBase = _owner
- val lineNums: Map[Label, String] = new HashMap[Label, String]()
+ val lineNums = scala.collection.mutable.Map.empty[Label, String]
def getMaxStacksize(): Int = { this.maxstack }
@@ -477,13 +467,15 @@ import ILGenerator._
// private emit with Object Argument and override POPUSH
private def emit(opcode: OpCode, arg: Object, overridePOPUSH: Int) {
// add label, opcode and argument
- labelList.add(lastLabel)
- opcodeList.add(opcode)
- argumentList.add(arg)
+ labelList += lastLabel
+ opcodeList += opcode
+ argumentList += arg
// compute new lastLabel (next label)
val stackSize: Int = lastLabel.getStacksize() + overridePOPUSH
if (stackSize < 0) {
- throw new RuntimeException("ILGenerator.emit(): Stack underflow in method: " + owner)
+ val msg = "ILGenerator.emit(): Stack underflow in method: " + owner
+ scala.Console.println(msg)
+ // throw new RuntimeException(msg)
}
if (stackSize > maxstack)
maxstack = stackSize
@@ -498,7 +490,7 @@ import ILGenerator._
def Ldarg0WasJustEmitted() : Boolean = {
if(opcodeList.isEmpty)
return false
- val lastEmitted = opcodeList.get(opcodeList.size - 1)
+ val lastEmitted = opcodeList(opcodeList.size - 1)
lastEmitted eq OpCode.Ldarg_0
}
@@ -506,9 +498,9 @@ import ILGenerator._
emitSpecialLabel(l, null)
}
private def emitSpecialLabel(l: Label, catchType: Type) {
- labelList.add(l)
- opcodeList.add(null)
- argumentList.add(catchType)
+ labelList += l
+ opcodeList += null
+ argumentList += catchType
}
//##########################################################################
@@ -528,16 +520,16 @@ object ILGenerator {
val NO_LABEL: String = ""
private final class ExceptionStack {
- private val labels: Stack[Label] = new Stack[Label]()
- private val kinds: Stack[Label] = new Stack[Label]()
+ private val labels = new scala.collection.mutable.Stack[Label]()
+ private val kinds = new scala.collection.mutable.Stack[Label]()
def ExceptionStack() {}
- def pop() { labels.pop(); kinds.pop() }
+ def pop() { labels.pop; kinds.pop }
def push(kind: Label, label: Label) {
kinds.push(kind); labels.push(label)
}
- def peekKind(): Label.Kind = {kinds.peek().asInstanceOf[Label].getKind() }
- def peekLabel(): Label = { labels.peek().asInstanceOf[Label] }
- def popLabel(): Label = { kinds.pop(); labels.pop().asInstanceOf[Label]}
+ def peekKind(): Label.Kind = kinds.top.getKind
+ def peekLabel(): Label = labels.top
+ def popLabel(): Label = { kinds.pop(); labels.pop() }
}
}
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 66f53b8132..73bc0f435c 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
@@ -10,9 +10,6 @@ import java.io.FileWriter
import java.io.BufferedWriter
import java.io.PrintWriter
import java.io.IOException
-import java.util.Iterator
-import java.util.HashMap
-import java.util.Arrays
import java.util.Comparator
import ch.epfl.lamp.compiler.msil._
@@ -33,8 +30,8 @@ abstract class ILPrinterVisitor extends Visitor {
//##########################################################################
protected final val assemblyNameComparator =
- new Comparator[Assembly]() {
- def compare(o1: Assembly, o2: Assembly): Int = {
+ new scala.math.Ordering[Assembly]() {
+ override def compare(o1: Assembly, o2: Assembly): Int = {
val a1 = o1.asInstanceOf[Assembly]
val a2 = o2.asInstanceOf[Assembly]
return a1.GetName().Name.compareTo(a2.GetName().Name)
@@ -101,7 +98,7 @@ abstract class ILPrinterVisitor extends Visitor {
protected def printName(name: String) {
var ch = name.charAt(0)
//if (Character.isLetter(ch) && Character.isLowerCase(ch)) {
- if (ch != '.') {
+ if ((ch != '.') && (ch != '!')) {
print('\''); print(name); print('\'')
} else
print(name)
@@ -236,23 +233,23 @@ abstract class ILPrinterVisitor extends Visitor {
printAttributes(`type`)
}
// print nested classes
- val nested = `type`.nestedTypeBuilders.iterator()
- while(nested.hasNext())
+ val nested = `type`.nestedTypeBuilders.iterator
+ while(nested.hasNext)
print(nested.next().asInstanceOf[TypeBuilder])
// print each field
- val fields = `type`.fieldBuilders.iterator()
- while(fields.hasNext())
+ val fields = `type`.fieldBuilders.iterator
+ while(fields.hasNext)
print(fields.next().asInstanceOf[FieldBuilder])
// print each constructor
- val constrs = `type`.constructorBuilders.iterator()
- while (constrs.hasNext())
+ val constrs = `type`.constructorBuilders.iterator
+ while (constrs.hasNext)
print(constrs.next().asInstanceOf[ConstructorBuilder])
// print each method
- val methods = `type`.methodBuilders.iterator()
- while (methods.hasNext()) {
+ val methods = `type`.methodBuilders.iterator
+ while (methods.hasNext) {
val method = methods.next().asInstanceOf[MethodBuilder]
assert(method.DeclaringType == `type`)
print(method)
@@ -308,29 +305,9 @@ abstract class ILPrinterVisitor extends Visitor {
print((value.asInstanceOf[Long]).longValue())
print(")")
} else if (value.isInstanceOf[Float]) {
- // !!! check if encoding is correct
- val bits = java.lang.Float.floatToRawIntBits((value.asInstanceOf[Float]).floatValue())
- // float32(float32(...)) != float32(...)
- print("float32 (float32 (")
- /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
- val valFlo = value.asInstanceOf[Float]
- if (java.lang.Float.NaN == valFlo) print("0xFFC00000 /* NaN */ ") /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
- else if (java.lang.Float.NEGATIVE_INFINITY == valFlo) print("0xFF800000 /* NEGATIVE_INFINITY */ ")
- else if (java.lang.Float.POSITIVE_INFINITY == valFlo) print("0x7F800000 /* POSITIVE_INFINITY */ ")
- else print(bits)
- print("))")
+ print(msilSyntaxFloat(value.asInstanceOf[Float]))
} else if (value.isInstanceOf[Double]) {
- // !!! check if encoding is correct
- var bits = java.lang.Double.doubleToRawLongBits((value.asInstanceOf[Double]).doubleValue())
- // float64(float64(...)) != float64(...)
- print("float64 (float64 (")
- /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
- val valDou = value.asInstanceOf[Double]
- if (java.lang.Double.NaN == valDou) print("0xffffffffffffffff /* NaN */ ") /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
- else if (java.lang.Double.NEGATIVE_INFINITY == valDou) print("0xfff0000000000000 /* NEGATIVE_INFINITY */ ")
- else if (java.lang.Double.POSITIVE_INFINITY == valDou) print("0x7ff0000000000000 /* POSITIVE_INFINITY */ ")
- else print(bits)
- print("))")
+ print(msilSyntaxDouble(value.asInstanceOf[Double]))
} else {
throw new Error("ILPrinterVisitor: Illegal default value: "
+ value.getClass())
@@ -340,6 +317,31 @@ abstract class ILPrinterVisitor extends Visitor {
printAttributes(field)
}
+ def msilSyntaxFloat(valFlo: java.lang.Float) : String = {
+ // !!! check if encoding is correct
+ val bits = java.lang.Float.floatToRawIntBits(valFlo.floatValue())
+ /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
+ /* Note: no value is equal to Nan, including NaN. Thus, x == Float.NaN always evaluates to false. */
+ val res = if (valFlo.isNaN) "0xFFC00000 /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
+ else if (java.lang.Float.NEGATIVE_INFINITY == valFlo.floatValue) "0xFF800000 /* NEGATIVE_INFINITY */ "
+ else if (java.lang.Float.POSITIVE_INFINITY == valFlo.floatValue) "0x7F800000 /* POSITIVE_INFINITY */ "
+ else bits
+ "float32 (" + res + ")"
+ }
+
+ def msilSyntaxDouble(valDou: java.lang.Double) : String = {
+ // !!! check if encoding is correct
+ var bits = java.lang.Double.doubleToRawLongBits(valDou.doubleValue())
+ /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
+ /* Note: no value is equal to Nan, including NaN. Thus, x == Double.NaN always evaluates to false. */
+ val res = if (valDou.isNaN) "0xffffffffffffffff /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
+ else if (java.lang.Double.NEGATIVE_INFINITY == valDou.doubleValue) "0xfff0000000000000 /* NEGATIVE_INFINITY */ "
+ else if (java.lang.Double.POSITIVE_INFINITY == valDou.doubleValue) "0x7ff0000000000000 /* POSITIVE_INFINITY */ "
+ else bits
+ // float64(float64(...)) != float64(...)
+ "float64 (" + res + ")"
+ }
+
/**
* Visit a ConstructorBuilder
*/
@@ -402,6 +404,7 @@ abstract class ILPrinterVisitor extends Visitor {
print(' '); printName(param.Name)
}
+ var locals: Array[LocalBuilder] = null
/**
* Visit an ILGenerator
*/
@@ -410,7 +413,7 @@ abstract class ILPrinterVisitor extends Visitor {
// print maxstack
println(".maxstack " + code.getMaxStacksize())
// get the local variables
- var locals: Array[LocalBuilder] = code.getLocals()
+ locals = code.getLocals()
if (locals.length > 0) {
println(".locals init (")
indent()
@@ -426,15 +429,16 @@ abstract class ILPrinterVisitor extends Visitor {
val itO = code.getOpcodeIterator()
val itA = code.getArgumentIterator()
// iterate over each opcode
- while (itO.hasNext()) {
+ while (itO.hasNext) {
// first print label
- val label = itL.next().asInstanceOf[Label]
- var o = code.lineNums.get(label)
- if (o != null)
- println(".line " + o)
- argument = itA.next().asInstanceOf[Object]
+ val label = itL.next
+ val oOpt = code.lineNums.get(label)
+ if (oOpt.isDefined) {
+ println(".line " + oOpt.get)
+ }
+ argument = itA.next.asInstanceOf[Object]
printLabel(label)
- val o2 = itO.next()
+ val o2 = itO.next
if (o2 != null) {
print(" ")
print(o2.asInstanceOf[OpCode])
@@ -483,6 +487,14 @@ abstract class ILPrinterVisitor extends Visitor {
print(loc.slot); print("\t// "); printSignature(loc.LocalType)
print(" \'"); print(loc.name); print("\'")
//print("'") print(((LocalBuilder)argument).name) print("'")
+ } else if (opCode == OpCode.Ldloc_0 || opCode == OpCode.Ldloc_1 || opCode == OpCode.Ldloc_2 || opCode == OpCode.Ldloc_3 ) {
+ val loc = locals(opCode.CEE_opcode - OpCode.CEE_LDLOC_0)
+ print("\t// "); printSignature(loc.LocalType)
+ print(" \'"); print(loc.name); print("\'")
+ } else if (opCode == OpCode.Stloc_0 || opCode == OpCode.Stloc_1 || opCode == OpCode.Stloc_2 || opCode == OpCode.Stloc_3 ) {
+ val loc = locals(opCode.CEE_opcode - OpCode.CEE_STLOC_0)
+ print("\t// "); printSignature(loc.LocalType)
+ print(" \'"); print(loc.name); print("\'")
} else if (opCode == OpCode.Readonly) {
// nothing to do
} else if (opCode == OpCode.Constrained) {
@@ -491,8 +503,21 @@ abstract class ILPrinterVisitor extends Visitor {
printReference(argument.asInstanceOf[Type])
} else {
// by default print toString argument if any
- if (argument != null)
- print(argument)
+ if (argument != null) {
+ val strArgument = java.lang.String.valueOf(argument)
+ if ( argument.isInstanceOf[java.lang.Float]
+ && ( strArgument.equals("NaN")
+ || strArgument.equals("-Infinity")
+ || strArgument.equals("Infinity")))
+ print(msilSyntaxFloat(argument.asInstanceOf[java.lang.Float]))
+ else if ( argument.isInstanceOf[java.lang.Double]
+ && ( strArgument.equals("NaN")
+ || strArgument.equals("-Infinity")
+ || strArgument.equals("Infinity")))
+ print(msilSyntaxDouble(argument.asInstanceOf[java.lang.Double]))
+ else print(strArgument)
+ }
+
} // end switch
}
@@ -646,12 +671,11 @@ abstract class ILPrinterVisitor extends Visitor {
}
def printSignature(`type`: Type) {
- val sig : Object = primitive.get(`type`)
- if (sig != null) {
- print(sig)
+ val sigOpt = primitive.get(`type`)
+ if (sigOpt.isDefined) {
+ print(sigOpt.get)
return
}
-
if (`type`.HasElementType()) {
printSignature(`type`.GetElementType())
if (`type`.IsArray())
@@ -661,29 +685,36 @@ abstract class ILPrinterVisitor extends Visitor {
else if (`type`.IsByRef())
print('&')
} else {
- print(if(`type`.IsValueType()) "valuetype " else "class ")
+ val preref = if (`type`.isInstanceOf[Type.TMVarUsage]) ""
+ else if(`type`.IsValueType()) "valuetype "
+ else "class "
+ print(preref)
printReference(`type`)
}
}
def printReference(`type`: Type) {
+ if (`type`.Module != null) { // i.e. not PrimitiveType and not TMVarUsage
if (`type`.Assembly() != currentModule.Assembly) {
print('['); print(`type`.Assembly().GetName().Name); print("]")
} else if (`type`.Module != currentModule) {
print("[.module "); print(`type`.Module.Name); print("]")
}
+ }
printTypeName(`type`)
}
def printTypeName(`type`: Type) {
if (`type`.isInstanceOf[ConstructedType]) {
val ct = `type`.asInstanceOf[ConstructedType]
- printSignature(ct.instantiatedType)
+ printTypeName(ct.instantiatedType)
print("<")
var i = 0
while (i < ct.typeArgs.length) {
val ta = ct.typeArgs(i)
- printTypeName(ta); /* should be printSignature, but don't want `class' or `valuetype'
+ val sigOpt = primitive.get(ta)
+ if (sigOpt.isDefined) print(sigOpt.get)
+ else printTypeName(ta); /* should be printSignature, but don't want `class' or `valuetype'
appearing before a type param usage. */
i = i + 1;
if (i < ct.typeArgs.length) {
@@ -789,7 +820,7 @@ object ILPrinterVisitor {
/** The current assembly */
var currAssembly: Assembly = _
- final var primitive = new HashMap[Type, String]()
+ final var primitive = scala.collection.mutable.Map.empty[Type, String]
def addPrimitive(name: String, sig: String) {
var `type` =
Type.GetType(name)
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
index a2d284865f..981e855e0e 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
@@ -6,8 +6,6 @@
package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
-import java.util.HashMap
-import java.util.ArrayList
import java.io.IOException
/**
@@ -36,8 +34,8 @@ class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly:
def CreateGlobalFunctions() {
if (globalsCreated)
throw new RuntimeException("Global functions are already created")
- this.fields = fieldBuilders.toArray(fields).asInstanceOf[Array[FieldInfo]]
- this.methods = methodBuilders.toArray(methods).asInstanceOf[Array[MethodInfo]]
+ this.fields = fieldBuilders.toArray // (fields).asInstanceOf[Array[FieldInfo]]
+ this.methods = methodBuilders.toArray // (methods).asInstanceOf[Array[MethodInfo]]
globalsCreated = true
}
@@ -94,13 +92,18 @@ class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly:
{
val method =
new MethodBuilder(name, null, attributes, returnType, paramTypes)
- methodBuilders.add(method)
+ methodBuilders += method
return method
}
override def GetTypes(): Array[Type] = {
- return typesMap.values().toArray(Type.EmptyTypes).asInstanceOf[Array[Type]]
+ val res = scala.collection.mutable.ArrayBuffer.empty[Type]
+ val iter = typesMap.values().iterator
+ while (iter.hasNext) {
+ res += iter.next.asInstanceOf[Type]
+ }
+ return res.toArray
}
/** Sets a custom attribute. */
@@ -112,8 +115,8 @@ class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly:
// internal members
var globalsCreated = false
- protected var fieldBuilders = new ArrayList[FieldInfo]()
- protected var methodBuilders = new ArrayList[MethodInfo]()
+ protected var fieldBuilders = scala.collection.mutable.ArrayBuffer.empty[FieldInfo]
+ protected var methodBuilders = scala.collection.mutable.ArrayBuffer.empty[MethodInfo]
override def addType(t: Type): Type = {
return super.addType(t)
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
index afd2d5d556..43333ef825 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
@@ -11,7 +11,6 @@ import java.io.BufferedWriter
import java.io.PrintWriter
import java.io.IOException
import java.util.Iterator
-import java.util.HashMap
import java.util.Arrays
import ch.epfl.lamp.compiler.msil._
@@ -39,7 +38,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str
// all external assemblies
as = assemblyBuilder.getExternAssemblies()
- Arrays.sort(as, assemblyNameComparator)
+ scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator)
// print each module
var m: Array[Module] = assemblyBuilder.GetModules()
@@ -91,7 +90,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str
append = true
} else {
fileName.getParentFile().mkdirs()
- assemblyBuilder.generatedFiles.add(fileName.getPath)
+ assemblyBuilder.generatedFiles += (fileName.getPath)
}
out = new PrintWriter(new BufferedWriter(new FileWriter(fileName, append)))
@@ -115,7 +114,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str
out = new PrintWriter(new BufferedWriter(new FileWriter(globalMethods, append)))
// make sure we're the first in the list (ilasm uses the first file name to guess the output file name)
- assemblyBuilder.generatedFiles.add(0, globalMethods.getPath)
+ assemblyBuilder.generatedFiles.insert(0, globalMethods.getPath)
// if this file hasn't been created by one of the classes, write boilerplate
if(!append) {
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
index d1b13054bc..0f2e7d7ecf 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
@@ -42,9 +42,9 @@ final class SingleFileILPrinterVisitor(_fileName: String) extends ILPrinterVisit
// all external assemblies
as = assemblyBuilder.getExternAssemblies()
- Arrays.sort(as, assemblyNameComparator)
+ scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator)
- assemblyBuilder.generatedFiles.add(fileName)
+ assemblyBuilder.generatedFiles += fileName
printAssemblyBoilerplate()
// print each module
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 8667098cdb..663b2c5cb0 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
@@ -6,9 +6,6 @@
package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
-import java.util.HashMap
-import java.util.ArrayList
-import java.util.Iterator
import java.io.IOException
/**
@@ -29,10 +26,10 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
/** 'Bakes' the type. */
def CreateType(): Type = {
- fields = fieldBuilders.toArray(new Array[FieldInfo](fieldBuilders.size())).asInstanceOf[Array[FieldInfo]]
- methods = methodBuilders.toArray(new Array[MethodInfo](methodBuilders.size())).asInstanceOf[Array[MethodInfo]]
- constructors = constructorBuilders.toArray(new Array[ConstructorInfo](constructorBuilders.size())).asInstanceOf[Array[ConstructorInfo]]
- nestedTypes = nestedTypeBuilders.toArray(new Array[Type](nestedTypeBuilders.size())).asInstanceOf[Array[Type]]
+ fields = fieldBuilders.toArray // (new Array[FieldInfo](fieldBuilders.size())).asInstanceOf[Array[FieldInfo]]
+ methods = methodBuilders.toArray // (new Array[MethodInfo](methodBuilders.size())).asInstanceOf[Array[MethodInfo]]
+ constructors = constructorBuilders.toArray // (new Array[ConstructorInfo](constructorBuilders.size())).asInstanceOf[Array[ConstructorInfo]]
+ nestedTypes = nestedTypeBuilders.toArray // (new Array[Type](nestedTypeBuilders.size())).asInstanceOf[Array[Type]]
raw = false
if (DeclaringType == null)
@@ -46,7 +43,7 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
*/
def DefineField(name: String, `type`: Type, attrs: Short): FieldBuilder = {
val field: FieldBuilder = new FieldBuilder(name, this, attrs, `type`)
- fieldBuilders.add(field)
+ fieldBuilders += field
return field
}
@@ -56,14 +53,14 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
*/
def DefineMethod(name: String, attrs: Short, returnType: Type, paramTypes: Array[Type]): MethodBuilder = {
val method = new MethodBuilder(name, this, attrs, returnType, paramTypes)
- val methods = methodBuilders.iterator()
- while(methods.hasNext()) {
+ val methods = methodBuilders.iterator
+ while(methods.hasNext) {
val m = methods.next().asInstanceOf[MethodInfo]
- if (methodsEqual(m, method))
- throw new RuntimeException("["+ Assembly() +
- "] Method has already been defined: " + m)
+ if (methodsEqual(m, method)) {
+ throw new RuntimeException("["+ Assembly() + "] Method has already been defined: " + m)
}
- methodBuilders.add(method)
+ }
+ methodBuilders += method
return method
}
@@ -73,7 +70,14 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
*/
def DefineConstructor(attrs: Short, callingConvention: Short, paramTypes: Array[Type]): ConstructorBuilder = {
val constr = new ConstructorBuilder(this, attrs, paramTypes)
- constructorBuilders.add(constr)
+ val iter = constructorBuilders.iterator
+ while(iter.hasNext) {
+ val c = iter.next().asInstanceOf[ConstructorInfo]
+ if (constructorsEqual(c, constr)) {
+ throw new RuntimeException("["+ Assembly() + "] Constructor has already been defined: " + c)
+ }
+ }
+ constructorBuilders += constr
return constr
}
@@ -81,16 +85,16 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
* Defines a nested type given its name.
*/
def DefineNestedType(name: String, attributes: Int, baseType: Type, interfaces: Array[Type]): TypeBuilder = {
- val nested = nestedTypeBuilders.iterator()
- while(nested.hasNext()) {
- val nt = nested.next().asInstanceOf[TypeBuilder]
+ val nested = nestedTypeBuilders.iterator
+ while(nested.hasNext) {
+ val nt = nested.next
if (nt.Name.equals(name)) {
val message = "Nested type " + name + " has already been defined: " + nt
throw new RuntimeException(message)
}
}
val t = new TypeBuilder(Module, attributes, name, baseType, interfaces, this)
- nestedTypeBuilders.add(t)
+ nestedTypeBuilders += t
return t
}
@@ -176,10 +180,10 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
var sourceFilename: String = _
var sourceFilepath: String = _
- var fieldBuilders = new ArrayList[FieldBuilder]()
- var methodBuilders = new ArrayList[MethodBuilder]()
- var constructorBuilders = new ArrayList[ConstructorBuilder]()
- var nestedTypeBuilders = new ArrayList[TypeBuilder]()
+ var fieldBuilders = scala.collection.mutable.ArrayBuffer.empty[FieldBuilder]
+ var methodBuilders = scala.collection.mutable.ArrayBuffer.empty[MethodBuilder]
+ var constructorBuilders = scala.collection.mutable.ArrayBuffer.empty[ConstructorBuilder]
+ var nestedTypeBuilders = scala.collection.mutable.ArrayBuffer.empty[TypeBuilder]
// shows if the type is 'raw', i.e. still subject to changes
private var raw = true
@@ -230,4 +234,18 @@ object TypeBuilder {
return false
return true
}
+
+ def constructorsEqual(c1: ConstructorInfo, c2: ConstructorInfo): Boolean = {
+ if (c1.IsStatic != c2.IsStatic)
+ return false
+ val p1 = c1.GetParameters()
+ val p2 = c2.GetParameters()
+ if (p1.length != p2.length)
+ return false
+ for(val i <- 0 until p1.length)
+ if (p1(i).ParameterType != p2(i).ParameterType)
+ return false
+ return true
+}
+
}