From 13a20ba71ae1805c7361e95d66360bd0a9a7f3d8 Mon Sep 17 00:00:00 2001 From: Miguel Garcia Date: Thu, 18 Nov 2010 15:30:51 +0000 Subject: 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 --- .../epfl/lamp/compiler/msil/ConstructedType.java | 2 +- src/msil/ch/epfl/lamp/compiler/msil/PEFile.java | 15 +-- src/msil/ch/epfl/lamp/compiler/msil/PEModule.java | 6 +- src/msil/ch/epfl/lamp/compiler/msil/Type.java | 2 +- .../lamp/compiler/msil/emit/AssemblyBuilder.scala | 25 ++-- .../epfl/lamp/compiler/msil/emit/ILGenerator.scala | 64 +++++----- .../lamp/compiler/msil/emit/ILPrinterVisitor.scala | 139 +++++++++++++-------- .../lamp/compiler/msil/emit/ModuleBuilder.scala | 19 +-- .../msil/emit/MultipleFilesILPrinterVisitor.scala | 7 +- .../msil/emit/SingleFileILPrinterVisitor.scala | 4 +- .../epfl/lamp/compiler/msil/emit/TypeBuilder.scala | 64 ++++++---- 11 files changed, 195 insertions(+), 152 deletions(-) (limited to 'src/msil/ch/epfl') 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 +} + } -- cgit v1.2.3