summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMiguel Garcia <magarcia@epfl.ch>2011-03-20 14:08:34 +0000
committerMiguel Garcia <magarcia@epfl.ch>2011-03-20 14:08:34 +0000
commit72a0e8be61df92b15c9991d023b783e019a58916 (patch)
tree7b2643b56132d977743a0d344dfa7df5965b03eb /src/compiler
parent6eb6e8ca22ce4c5f3f41cd12139ad57354f82eb2 (diff)
downloadscala-72a0e8be61df92b15c9991d023b783e019a58916.tar.gz
scala-72a0e8be61df92b15c9991d023b783e019a58916.tar.bz2
scala-72a0e8be61df92b15c9991d023b783e019a58916.zip
The last checkin caused a test to time-out, but...
The last checkin caused a test to time-out, but that test runs fine locally. I'm giving Jenkins another chance. Like the previous changeset, this one has to do with .NET bootstrapping. review by rytz.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala212
1 files changed, 71 insertions, 141 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index a934d569d5..076a59ce46 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -42,14 +42,19 @@ abstract class GenMSIL extends SubComponent {
//classes is ICodes.classes, a HashMap[Symbol, IClass]
classes.values foreach codeGenerator.findEntryPoint
+ if( opt.showClass.isDefined && (codeGenerator.entryPoint == null) ) { // TODO introduce dedicated setting instead
+ val entryclass = opt.showClass.get.toString
+ warning("Couldn't find entry class " + entryclass)
+ }
codeGenerator.initAssembly
- classes.values foreach codeGenerator.createTypeBuilder
- classes.values foreach codeGenerator.createClassMembers
+ val classesSorted = classes.values.toList.sortBy(c => c.symbol.id) // simplifies comparing cross-compiler vs. .exe output
+ classesSorted foreach codeGenerator.createTypeBuilder
+ classesSorted foreach codeGenerator.createClassMembers
try {
- classes.values foreach codeGenerator.genClass
+ classesSorted foreach codeGenerator.genClass
} finally {
codeGenerator.writeAssembly
}
@@ -68,7 +73,7 @@ abstract class GenMSIL extends SubComponent {
val MODULE_INSTANCE_NAME = "MODULE$"
- import clrTypes.{VOID => MVOID, BOOLEAN => MBOOL, UBYTE => MBYTE, SHORT => MSHORT,
+ import clrTypes.{VOID => MVOID, BOOLEAN => MBOOL, BYTE => MBYTE, SHORT => MSHORT,
CHAR => MCHAR, INT => MINT, LONG => MLONG, FLOAT => MFLOAT,
DOUBLE => MDOUBLE, OBJECT => MOBJECT, STRING => MSTRING,
STRING_ARRAY => MSTRING_ARRAY,
@@ -98,18 +103,16 @@ abstract class GenMSIL extends SubComponent {
val JOBJECT = definitions.ObjectClass
val JSTRING = definitions.StringClass
- var JSTRING_SUBSTRING_INT_INT: Symbol = _
-
val SystemConvert = clrTypes.getType("System.Convert")
val objParam = Array(MOBJECT)
// val toBool: MethodInfo = SystemConvert.GetMethod("ToBoolean", objParam)
- val toByte: MethodInfo = SystemConvert.GetMethod("ToByte", objParam)
- val toShort: MethodInfo = SystemConvert.GetMethod("ToInt16", objParam)
- val toChar: MethodInfo = SystemConvert.GetMethod("ToChar", objParam)
- val toInt: MethodInfo = SystemConvert.GetMethod("ToInt32", objParam)
- val toLong: MethodInfo = SystemConvert.GetMethod("ToInt64", objParam)
+ val toSByte: MethodInfo = SystemConvert.GetMethod("ToSByte", objParam)
+ val toShort: MethodInfo = SystemConvert.GetMethod("ToInt16", objParam)
+ val toChar: MethodInfo = SystemConvert.GetMethod("ToChar", objParam)
+ val toInt: MethodInfo = SystemConvert.GetMethod("ToInt32", objParam)
+ val toLong: MethodInfo = SystemConvert.GetMethod("ToInt64", objParam)
val toFloat: MethodInfo = SystemConvert.GetMethod("ToSingle", objParam)
val toDouble: MethodInfo = SystemConvert.GetMethod("ToDouble", objParam)
@@ -140,58 +143,6 @@ abstract class GenMSIL extends SubComponent {
mapType(definitions.NullClass, EXCEPTION)
mapType(definitions.NothingClass, EXCEPTION)
- val jEmpty = new Array[Type](0)
- val jString1 = Array(JSTRING.tpe)
- val jInt1 = Array(definitions.IntClass.tpe)
- val jInt2 = Array(definitions.IntClass.tpe, definitions.IntClass.tpe)
- val jLong1 = Array(definitions.LongClass.tpe)
- val jStringInt = Array(JSTRING.tpe, definitions.IntClass.tpe)
- val jChar2 = Array(definitions.CharClass.tpe, definitions.CharClass.tpe)
-
- val mObject1 = Array(MOBJECT)
- val mString1 = Array(MSTRING)
- val mString2 = Array(MSTRING, MSTRING)
- val mChar1 = Array(MCHAR)
- val mCharInt = Array(MCHAR, MINT)
-
- JSTRING_SUBSTRING_INT_INT = lookupMethod(JSTRING, "substring", jInt2)
-
- mapMethod(JOBJECT, "clone", MOBJECT, "MemberwiseClone")
- mapMethod(JOBJECT, nme.equals_, MOBJECT, "Equals")
- mapMethod(JOBJECT, nme.hashCode_, MOBJECT, "GetHashCode")
- mapMethod(JOBJECT, nme.toString_, MOBJECT, "ToString")
- mapMethod(JOBJECT, nme.finalize_, MOBJECT, "Finalize")
- mapMethod(JOBJECT, nme.wait_, jEmpty, MMONITOR, "Wait", mObject1)
- mapMethod(JOBJECT, nme.wait_, jLong1, MMONITOR, "Wait", Array(MOBJECT, MINT))
- mapMethod(JOBJECT, nme.notify_, jEmpty, MMONITOR, "Pulse", mObject1)
- mapMethod(JOBJECT, nme.notifyAll_, jEmpty, MMONITOR, "PulseAll", mObject1)
-
- mapMethod(JSTRING, "compareTo",MSTRING, "CompareTo")
- mapMethod(JSTRING, "length", MSTRING, "get_Length")
- mapMethod(JSTRING, "charAt", MSTRING, "get_Chars")
-
- mapMethod(JSTRING, "concat", jString1, MSTRING, "Concat", mString2)
- mapMethod(JSTRING, "indexOf", jInt1, MSTRING, "IndexOf", mChar1)
- mapMethod(JSTRING, "indexOf", jInt2, MSTRING, "IndexOf", mCharInt)
-
- mapMethod(JSTRING, "indexOf", jString1, MSTRING, "IndexOf")
- mapMethod(JSTRING, "indexOf", jStringInt, MSTRING, "IndexOf")
- mapMethod(JSTRING, "lastIndexOf", jInt1, MSTRING, "LastIndexOf", mChar1)
- mapMethod(JSTRING, "lastIndexOf", jInt2, MSTRING, "LastIndexOf", mCharInt)
- mapMethod(JSTRING, "lastIndexOf", jString1, MSTRING, "LastIndexOf")
- mapMethod(JSTRING, "lastIndexOf", jStringInt, MSTRING, "LastIndexOf")
-
- mapMethod(JSTRING, "toLowerCase", jEmpty, MSTRING, "ToLower")
- mapMethod(JSTRING, "toUpperCase", jEmpty, MSTRING, "ToUpper")
- mapMethod(JSTRING, "startsWith", jString1, MSTRING, "StartsWith")
- mapMethod(JSTRING, "endsWith", jString1, MSTRING, "EndsWith")
- mapMethod(JSTRING, "substring", jInt1, MSTRING, "Substring")
- mapMethod(JSTRING, "substring", jInt2, MSTRING, "Substring")
- mapMethod(JSTRING, "trim", jEmpty, MSTRING, "Trim")
- mapMethod(JSTRING, "intern", jEmpty, MSTRING, "Intern", mString1)
- mapMethod(JSTRING, "replace", jChar2, MSTRING, "Replace")
- mapMethod(JSTRING, "toCharArray", MSTRING, "ToCharArray")
-
mapType(definitions.BooleanClass, MBOOL)
mapType(definitions.ByteClass, MBYTE)
mapType(definitions.ShortClass, MSHORT)
@@ -457,14 +408,17 @@ abstract class GenMSIL extends SubComponent {
code.Emit(OpCodes.Ret)
}
createTypes()
- val filename = outDir.getPath()
- if (settings.debug.value)
- log("Output path: " + filename)
+ var outDirName: String = null
try {
- // massembly.Save(filename + "\\" + assemName + ".msil") /* use SingleFileILPrinterVisitor */
- massembly.Save(filename, srcPath.getPath()) /* use MultipleFilesILPrinterVisitor */
+ if (settings.Ygenjavap.isDefault) { // we reuse the JVM-sounding setting because it's conceptually similar
+ outDirName = outDir.getPath()
+ massembly.Save(outDirName + "\\" + assemName + ".msil") /* use SingleFileILPrinterVisitor */
+ } else {
+ outDirName = srcPath.getPath()
+ massembly.Save(settings.Ygenjavap.value, outDirName) /* use MultipleFilesILPrinterVisitor */
+ }
} catch {
- case e:IOException => abort("Could not write to " + filename + ": " + e.getMessage())
+ case e:IOException => abort("Could not write to " + outDirName + ": " + e.getMessage())
}
}
@@ -596,14 +550,19 @@ abstract class GenMSIL extends SubComponent {
labels.clear
- var linearization = if(m.exh != Nil) msilLinearizer.linearize(m)
+ var linearization = if(!m.exh.isEmpty) msilLinearizer.linearize(m)
else linearizer.linearize(m)
- if (m.exh != Nil)
+ if (!m.exh.isEmpty)
linearization = computeExceptionMaps(linearization, m)
makeLabels(linearization)
+ // debug val blocksInM = m.code.blocks.toList.sortBy(bb => bb.label)
+ // debug val blocksInL = linearization.sortBy(bb => bb.label)
+ // debug val MButNotL = (blocksInM.toSet) diff (blocksInL.toSet) // if non-empty, a jump to B fails to find a label for B (case CJUMP, case CZJUMP)
+ // debug if(!MButNotL.isEmpty) { }
+
genBlocks(linearization)
// RETURN inside exception blocks are replaced by Leave. The target of the
@@ -989,7 +948,7 @@ abstract class GenMSIL extends SubComponent {
case LOAD_ARRAY_ITEM(kind) =>
(kind: @unchecked) match {
case BOOL => mcode.Emit(OpCodes.Ldelem_I1)
- case BYTE => mcode.Emit(OpCodes.Ldelem_U1)
+ case BYTE => mcode.Emit(OpCodes.Ldelem_I1) // I1 for System.SByte, i.e. a scala.Byte
case SHORT => mcode.Emit(OpCodes.Ldelem_I2)
case CHAR => mcode.Emit(OpCodes.Ldelem_U2)
case INT => mcode.Emit(OpCodes.Ldelem_I4)
@@ -1113,17 +1072,6 @@ abstract class GenMSIL extends SubComponent {
}
} else {
- // java.lang.String.substring(int start_incl, int end_excl)
- // System.String.Substring(int start_incl, int length)
- if (msym == JSTRING_SUBSTRING_INT_INT) {
- val endLocal = mcode.DeclareLocal(MINT)
- endLocal.SetLocalSymInfo("$substring_end")
- mcode.Emit(OpCodes.Stloc, endLocal)
- mcode.Emit(OpCodes.Dup) // duplicate start_incl
- mcode.Emit(OpCodes.Neg)
- mcode.Emit(OpCodes.Ldloc, endLocal) // load end_excl
- mcode.Emit(OpCodes.Add) // compute length (-start + end)
- }
var doEmit = true
getTypeOpt(msym.owner) match {
@@ -1388,7 +1336,7 @@ abstract class GenMSIL extends SubComponent {
log("Converting from: " + src + " to: " + dst)
dst match {
- case BYTE => mcode.Emit(OpCodes.Conv_U1)
+ case BYTE => mcode.Emit(OpCodes.Conv_I1) // I1 for System.SByte, i.e. a scala.Byte
case SHORT => mcode.Emit(OpCodes.Conv_I2)
case CHAR => mcode.Emit(OpCodes.Conv_U2)
case INT => mcode.Emit(OpCodes.Conv_I4)
@@ -1745,6 +1693,7 @@ abstract class GenMSIL extends SubComponent {
val localBuilders: HashMap[Local, LocalBuilder] = new HashMap()
private[GenMSIL] def findEntryPoint(cls: IClass) {
+
def isEntryPoint(sym: Symbol):Boolean = {
if (isStaticModule(sym.owner) && msilName(sym) == "main")
if (sym.tpe.paramTypes.length == 1) {
@@ -1759,12 +1708,15 @@ abstract class GenMSIL extends SubComponent {
false
}
- for (m <- cls.methods) {
- if (isEntryPoint(m.symbol)) {
- if (entryPoint == null)
- entryPoint = m.symbol
+ if((entryPoint == null) && opt.showClass.isDefined) { // TODO introduce dedicated setting instead
+ val entryclass = opt.showClass.get.toString
+ val cfn = cls.symbol.fullName
+ if(cfn == entryclass) {
+ for (m <- cls.methods; if isEntryPoint(m.symbol)) { entryPoint = m.symbol }
+ if(entryPoint == null) { warning("Couldn't find main method in class " + cfn) }
}
}
+
if (firstSourceName == "")
if (cls.symbol.sourceFile != null) // is null for nested classes
firstSourceName = cls.symbol.sourceFile.name
@@ -1806,22 +1758,25 @@ abstract class GenMSIL extends SubComponent {
* Get an MSIL type from a symbol. First look in the clrTypes.types map, then
* lookup the name using clrTypes.getType
*/
- def getTypeOpt(sym: Symbol): Option[MsilType] = types.get(sym) match {
- case typ @ Some(_) => typ
- case None =>
- def typeString(sym: Symbol): String = {
- val s = if (sym.isNestedClass) typeString(sym.owner) +"+"+ sym.simpleName
- else sym.fullName
- if (sym.isModuleClass && !sym.isTrait) s + "$" else s
- }
- val name = typeString(sym)
- val typ = clrTypes.getType(name)
- if (typ == null)
- None
- else {
- types(sym) = typ
- Some(typ)
- }
+ def getTypeOpt(sym: Symbol): Option[MsilType] = {
+ val tmp = types.get(sym)
+ tmp match {
+ case typ @ Some(_) => typ
+ case None =>
+ def typeString(sym: Symbol): String = {
+ val s = if (sym.isNestedClass) typeString(sym.owner) +"+"+ sym.simpleName
+ else sym.fullName
+ if (sym.isModuleClass && !sym.isTrait) s + "$" else s
+ }
+ val name = typeString(sym)
+ val typ = clrTypes.getType(name)
+ if (typ == null)
+ None
+ else {
+ types(sym) = typ
+ Some(typ)
+ }
+ }
}
def mapType(sym: Symbol, mType: MsilType) {
@@ -1952,7 +1907,7 @@ abstract class GenMSIL extends SubComponent {
} else {
var resType = msilType(m.returnType)
val method =
- ownerType.DefineMethod(getMethodName(sym), attr, resType, paramTypes)
+ ownerType.DefineMethod(msilName(sym), attr, resType, paramTypes)
for (i <- 0.until(paramTypes.length)) {
method.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
}
@@ -2106,7 +2061,7 @@ abstract class GenMSIL extends SubComponent {
paramNames(i) = "x_" + i
// CHECK: verify if getMethodName is better than msilName
- val mirrorMethod = mirrorTypeBuilder.DefineMethod(getMethodName(m),
+ val mirrorMethod = mirrorTypeBuilder.DefineMethod(msilName(m),
(MethodAttributes.Public |
MethodAttributes.Static).toShort,
msilType(m.tpe.resultType),
@@ -2198,25 +2153,29 @@ abstract class GenMSIL extends SubComponent {
case UNIT => code.Emit(OpCodes.Ldsfld, boxedUnit)
case BOOL | BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE =>
code.Emit(OpCodes.Box, msilType(boxType))
- case REFERENCE(cls) if (definitions.boxMethod.contains(cls)) =>
+ case REFERENCE(cls) if clrTypes.isValueType(cls) =>
code.Emit(OpCodes.Box, (msilType(boxType)))
- case REFERENCE(_) | ARRAY(_) => ()
+ case REFERENCE(_) | ARRAY(_) =>
+ warning("Tried to BOX a non-valuetype.")
+ ()
}
def emitUnbox(code: ILGenerator, boxType: TypeKind) = (boxType: @unchecked) match {
case UNIT => code.Emit(OpCodes.Pop)
case BOOL => code.Emit(OpCodes.Unbox, MBOOL); code.Emit(OpCodes.Ldind_I1)
- case BYTE => code.Emit(OpCodes.Call, toByte)
+ case BYTE => code.Emit(OpCodes.Call, toSByte)
case SHORT => code.Emit(OpCodes.Call, toShort)
case CHAR => code.Emit(OpCodes.Call, toChar)
case INT => code.Emit(OpCodes.Call, toInt)
case LONG => code.Emit(OpCodes.Call, toLong)
case FLOAT => code.Emit(OpCodes.Call, toFloat)
case DOUBLE => code.Emit(OpCodes.Call, toDouble)
- case REFERENCE(cls) if (definitions.unboxMethod.contains(cls)) =>
+ case REFERENCE(cls) if clrTypes.isValueType(cls) =>
code.Emit(OpCodes.Unbox, msilType(boxType))
code.Emit(OpCodes.Ldobj, msilType(boxType))
- case REFERENCE(_) | ARRAY(_) => ()
+ case REFERENCE(_) | ARRAY(_) =>
+ warning("Tried to UNBOX a non-valuetype.")
+ ()
}
// #####################################################################
@@ -2243,23 +2202,13 @@ abstract class GenMSIL extends SubComponent {
}
private def getMethod(sym: Symbol): MethodInfo = {
- //private def getMethod(sym: Symbol): MethodInfo = sym match {
-// case SRToInt => toInt
-// case SRToDouble => toDouble
-// case SRToLong => toLong
-// case SRToChar => toChar
-// case SRToFloat => toFloat
-// case SRToBool => toBool
-// case SRToByte => toByte
-// case SRToShort => toShort
-// case _ =>
methods.get(sym) match {
case Some(method) => method
case None =>
val mClass = getType(sym.owner)
try {
- val method = mClass.GetMethod(getMethodName(sym), msilParamTypes(sym),
+ val method = mClass.GetMethod(msilName(sym), msilParamTypes(sym),
msilType(sym.tpe.resultType))
if (method eq null) {
java.lang.System.out.println("Cannot find method " + sym.owner + "::" + msilName(sym))
@@ -2379,25 +2328,6 @@ abstract class GenMSIL extends SubComponent {
}
}
- def getMethodName(methodSym: Symbol): String = {
- val name = methodSym.name
- val params = methodSym.tpe.paramTypes
- if (name == nme.finalize_ && params.length == 0)
- "Finalize"
- else if (name == nme.toString_ && params.length == 0)
- "ToString"
- else if (name == nme.hashCode_ && params.length == 0)
- "GetHashCode"
- else if (name == nme.equals_ && params.length == 1 &&
- params(0) == definitions.ObjectClass.tpe)
- "Equals"
- // FIXME: why is there no nme.clone_ ?
- else if (name.toString() == "clone" && params.length == 0)
- "Clone"
- else
- msilName(methodSym)
- }
-
private def showsym(sym: Symbol): String = (sym.toString +
"\n symbol = " + Flags.flagsToString(sym.flags) + " " + sym +
"\n owner = " + Flags.flagsToString(sym.owner.flags) + " " + sym.owner