diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala | 212 |
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 |