summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-02-03 11:57:47 -0800
committerPaul Phillips <paulp@improving.org>2012-02-03 12:47:23 -0800
commitde82b3723271c5ca3655cfd76eea0638f0d18eb1 (patch)
tree140f620159b89706363038661c52e030a6a252a0 /src
parent8c7005fc90008b6874431d318b482c2ad985181a (diff)
downloadscala-de82b3723271c5ca3655cfd76eea0638f0d18eb1.tar.gz
scala-de82b3723271c5ca3655cfd76eea0638f0d18eb1.tar.bz2
scala-de82b3723271c5ca3655cfd76eea0638f0d18eb1.zip
Disabled all things MSIL.
It's a huge drag when making fundamental changes.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala9
-rw-r--r--src/compiler/scala/tools/nsc/backend/MSILPlatform.scala130
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala322
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala114
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala13
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala4714
-rw-r--r--src/compiler/scala/tools/nsc/io/MsilFile.scala36
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala32
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala274
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala1702
-rw-r--r--src/compiler/scala/tools/nsc/util/MsilClassPath.scala338
11 files changed, 3842 insertions, 3842 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 8e5ca2156a..31269829bf 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -27,7 +27,8 @@ import typechecker._
import transform._
import backend.icode.{ ICodes, GenICode, ICodeCheckers }
-import backend.{ ScalaPrimitives, Platform, MSILPlatform, JavaPlatform }
+// import backend.{ ScalaPrimitives, Platform, MSILPlatform, JavaPlatform }
+import backend.{ ScalaPrimitives, Platform, JavaPlatform }
import backend.jvm.GenJVM
import backend.opt.{ Inliners, InlineExceptionHandlers, ClosureElimination, DeadCodeElimination }
import backend.icode.analysis._
@@ -65,9 +66,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
type ThisPlatform = Platform { val global: Global.this.type }
- lazy val platform: ThisPlatform =
- if (forMSIL) new { val global: Global.this.type = Global.this } with MSILPlatform
- else new { val global: Global.this.type = Global.this } with JavaPlatform
+ lazy val platform: ThisPlatform = new { val global: Global.this.type = Global.this } with JavaPlatform
+ // if (forMSIL) new { val global: Global.this.type = Global.this } with MSILPlatform
+ // else new { val global: Global.this.type = Global.this } with JavaPlatform
def classPath: ClassPath[platform.BinaryRepr] = platform.classPath
def rootLoader: LazyType = platform.rootLoader
diff --git a/src/compiler/scala/tools/nsc/backend/MSILPlatform.scala b/src/compiler/scala/tools/nsc/backend/MSILPlatform.scala
index 65b1fbc229..a86528d492 100644
--- a/src/compiler/scala/tools/nsc/backend/MSILPlatform.scala
+++ b/src/compiler/scala/tools/nsc/backend/MSILPlatform.scala
@@ -1,65 +1,65 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package backend
-
-import ch.epfl.lamp.compiler.{ msil => msillib }
-import util.{ ClassPath, MsilClassPath }
-import msil.GenMSIL
-import io.{ AbstractFile, MsilFile }
-
-trait MSILPlatform extends Platform {
- import global._
- import definitions.{ ComparatorClass, BoxedNumberClass, getMember }
-
- type BinaryRepr = MsilFile
-
- if (settings.verbose.value)
- inform("[AssemRefs = " + settings.assemrefs.value + "]")
-
- // phaseName = "msil"
- object genMSIL extends {
- val global: MSILPlatform.this.global.type = MSILPlatform.this.global
- val runsAfter = List[String]("dce")
- val runsRightAfter = None
- } with GenMSIL
-
- lazy val classPath = MsilClassPath.fromSettings(settings)
- def rootLoader = new loaders.PackageLoader(classPath.asInstanceOf[ClassPath[platform.BinaryRepr]])
- // See discussion in JavaPlatForm for why we need a cast here.
-
- def platformPhases = List(
- genMSIL // generate .msil files
- )
-
- lazy val externalEquals = getMember(ComparatorClass.companionModule, nme.equals_)
- def isMaybeBoxed(sym: Symbol) = sym isNonBottomSubClass BoxedNumberClass
-
- def newClassLoader(bin: MsilFile): loaders.SymbolLoader = new loaders.MsilFileLoader(bin)
-
- /**
- * Tells whether a class should be loaded and entered into the package
- * scope. On .NET, this method returns `false` for all synthetic classes
- * (anonymous classes, implementation classes, module classes), their
- * symtab is encoded in the pickle of another class.
- */
- def doLoad(cls: ClassPath[BinaryRepr]#ClassRep): Boolean = {
- if (cls.binary.isDefined) {
- val typ = cls.binary.get.msilType
- if (typ.IsDefined(loaders.clrTypes.SCALA_SYMTAB_ATTR, false)) {
- val attrs = typ.GetCustomAttributes(loaders.clrTypes.SCALA_SYMTAB_ATTR, false)
- assert(attrs.length == 1, attrs.length)
- val a = attrs(0).asInstanceOf[msillib.Attribute]
- // symtab_constr takes a byte array argument (the pickle), i.e. typ has a pickle.
- // otherwise, symtab_default_constr was used, which marks typ as scala-synthetic.
- a.getConstructor() == loaders.clrTypes.SYMTAB_CONSTR
- } else true // always load non-scala types
- } else true // always load source
- }
-
- def needCompile(bin: MsilFile, src: AbstractFile) =
- false // always use compiled file on .net
-}
+// /* NSC -- new Scala compiler
+// * Copyright 2005-2011 LAMP/EPFL
+// * @author Paul Phillips
+// */
+//
+// package scala.tools.nsc
+// package backend
+//
+// import ch.epfl.lamp.compiler.{ msil => msillib }
+// import util.{ ClassPath, MsilClassPath }
+// import msil.GenMSIL
+// import io.{ AbstractFile, MsilFile }
+//
+// trait MSILPlatform extends Platform {
+// import global._
+// import definitions.{ ComparatorClass, BoxedNumberClass, getMember }
+//
+// type BinaryRepr = MsilFile
+//
+// if (settings.verbose.value)
+// inform("[AssemRefs = " + settings.assemrefs.value + "]")
+//
+// // phaseName = "msil"
+// object genMSIL extends {
+// val global: MSILPlatform.this.global.type = MSILPlatform.this.global
+// val runsAfter = List[String]("dce")
+// val runsRightAfter = None
+// } with GenMSIL
+//
+// lazy val classPath = MsilClassPath.fromSettings(settings)
+// def rootLoader = new loaders.PackageLoader(classPath.asInstanceOf[ClassPath[platform.BinaryRepr]])
+// // See discussion in JavaPlatForm for why we need a cast here.
+//
+// def platformPhases = List(
+// genMSIL // generate .msil files
+// )
+//
+// lazy val externalEquals = getMember(ComparatorClass.companionModule, nme.equals_)
+// def isMaybeBoxed(sym: Symbol) = sym isNonBottomSubClass BoxedNumberClass
+//
+// def newClassLoader(bin: MsilFile): loaders.SymbolLoader = new loaders.MsilFileLoader(bin)
+//
+// /**
+// * Tells whether a class should be loaded and entered into the package
+// * scope. On .NET, this method returns `false` for all synthetic classes
+// * (anonymous classes, implementation classes, module classes), their
+// * symtab is encoded in the pickle of another class.
+// */
+// def doLoad(cls: ClassPath[BinaryRepr]#ClassRep): Boolean = {
+// if (cls.binary.isDefined) {
+// val typ = cls.binary.get.msilType
+// if (typ.IsDefined(loaders.clrTypes.SCALA_SYMTAB_ATTR, false)) {
+// val attrs = typ.GetCustomAttributes(loaders.clrTypes.SCALA_SYMTAB_ATTR, false)
+// assert(attrs.length == 1, attrs.length)
+// val a = attrs(0).asInstanceOf[msillib.Attribute]
+// // symtab_constr takes a byte array argument (the pickle), i.e. typ has a pickle.
+// // otherwise, symtab_default_constr was used, which marks typ as scala-synthetic.
+// a.getConstructor() == loaders.clrTypes.SYMTAB_CONSTR
+// } else true // always load non-scala types
+// } else true // always load source
+// }
+//
+// def needCompile(bin: MsilFile, src: AbstractFile) =
+// false // always use compiled file on .net
+// }
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 3baff7da9e..acb20b4627 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -160,8 +160,8 @@ abstract class GenICode extends SubComponent {
case Assign(lhs @ Select(_, _), rhs) =>
val isStatic = lhs.symbol.isStaticMember
var ctx1 = if (isStatic) ctx
- else if (forMSIL && msil_IsValuetypeInstField(lhs.symbol))
- msil_genLoadQualifierAddress(lhs, ctx)
+ // else if (forMSIL && msil_IsValuetypeInstField(lhs.symbol))
+ // msil_genLoadQualifierAddress(lhs, ctx)
else genLoadQualifier(lhs, ctx)
ctx1 = genLoad(rhs, ctx1, toTypeKind(lhs.symbol.info))
@@ -460,132 +460,132 @@ abstract class GenICode extends SubComponent {
fun.symbol.simpleName + ") " + " at: " + (tree.pos)
)
}
-
- /**
- * forMSIL
- */
- private def msil_IsValuetypeInstMethod(msym: Symbol) = (
- loaders.clrTypes.methods get msym exists (mMSIL =>
- mMSIL.IsInstance && mMSIL.DeclaringType.IsValueType
- )
- )
- private def msil_IsValuetypeInstField(fsym: Symbol) = (
- loaders.clrTypes.fields get fsym exists (fMSIL =>
- !fMSIL.IsStatic && fMSIL.DeclaringType.IsValueType
- )
- )
-
- /**
- * forMSIL: Adds a local var, the emitted code requires one more slot on the stack as on entry
- */
- private def msil_genLoadZeroOfNonEnumValuetype(ctx: Context, kind: TypeKind, pos: Position, leaveAddressOnStackInstead: Boolean) {
- val REFERENCE(clssym) = kind
- assert(loaders.clrTypes.isNonEnumValuetype(clssym), clssym)
- val local = ctx.makeLocal(pos, clssym.tpe, "tmp")
- ctx.method.addLocal(local)
- ctx.bb.emit(CIL_LOAD_LOCAL_ADDRESS(local), pos)
- ctx.bb.emit(CIL_INITOBJ(kind), pos)
- val instr = if (leaveAddressOnStackInstead)
- CIL_LOAD_LOCAL_ADDRESS(local)
- else
- LOAD_LOCAL(local)
- ctx.bb.emit(instr, pos)
- }
-
- /**
- * forMSIL
- */
- private def msil_genLoadAddressOf(tree: Tree, ctx: Context, expectedType: TypeKind, butRawValueIsAlsoGoodEnough: Boolean): Context = {
- var generatedType = expectedType
- var addressTaken = false
- debuglog("at line: " + (if (tree.pos.isDefined) tree.pos.line else tree.pos))
-
- var resCtx: Context = tree match {
-
- // emits CIL_LOAD_FIELD_ADDRESS
- case Select(qualifier, selector) if (!tree.symbol.isModule) =>
- addressTaken = true
- val sym = tree.symbol
- generatedType = toTypeKind(sym.info)
-
- if (sym.isStaticMember) {
- ctx.bb.emit(CIL_LOAD_FIELD_ADDRESS(sym, true), tree.pos)
- ctx
- } else {
- val ctx1 = genLoadQualifier(tree, ctx)
- ctx1.bb.emit(CIL_LOAD_FIELD_ADDRESS(sym, false), tree.pos)
- ctx1
- }
-
- // emits CIL_LOAD_LOCAL_ADDRESS
- case Ident(name) if (!tree.symbol.isPackage && !tree.symbol.isModule)=>
- addressTaken = true
- val sym = tree.symbol
- try {
- val Some(l) = ctx.method.lookupLocal(sym)
- ctx.bb.emit(CIL_LOAD_LOCAL_ADDRESS(l), tree.pos)
- generatedType = l.kind // actually, should be "V&" but the callsite is aware of this
- } catch {
- case ex: MatchError =>
- abort("symbol " + sym + " does not exist in " + ctx.method)
- }
- ctx
-
- // emits CIL_LOAD_ARRAY_ITEM_ADDRESS
- case Apply(fun, args) =>
- if (isPrimitive(fun.symbol)) {
-
- val sym = tree.symbol
- val Apply(fun @ Select(receiver, _), args) = tree
- val code = scalaPrimitives.getPrimitive(sym, receiver.tpe)
-
- if (isArrayOp(code)) {
- val arrayObj = receiver
- val k = toTypeKind(arrayObj.tpe)
- val ARRAY(elementType) = k
- if (scalaPrimitives.isArrayGet(code)) {
- var ctx1 = genLoad(arrayObj, ctx, k)
- // load argument on stack
- debugassert(args.length == 1, "Too many arguments for array get operation: " + tree)
- ctx1 = genLoad(args.head, ctx1, INT)
- generatedType = elementType // actually "managed pointer to element type" but the callsite is aware of this
- ctx1.bb.emit(CIL_LOAD_ARRAY_ITEM_ADDRESS(elementType), tree.pos)
- addressTaken = true
- ctx1
- } else null
- } else null
- } else null
-
- case This(qual) =>
- /* TODO: this case handler is a placeholder for the time when Level 2 support for valuetypes is in place,
- in particular when invoking other methods on this where this is a valuetype value (boxed or not).
- As receiver, a managed pointer is expected, and a plain ldarg.0 achieves just that. */
- addressTaken = true
- genLoad(tree, ctx, expectedType)
-
- case _ =>
- null /* A method returning ByRef won't pass peverify, so I guess this case handler is dead code.
- Even if it's not, the code below to handler !addressTaken below. */
- }
-
- if (!addressTaken) {
- resCtx = genLoad(tree, ctx, expectedType)
- if (!butRawValueIsAlsoGoodEnough) {
- // raw value on stack (must be an intermediate result, e.g. returned by method call), take address
- addressTaken = true
- val boxType = expectedType // toTypeKind(expectedType /* TODO FIXME */)
- resCtx.bb.emit(BOX(boxType), tree.pos)
- resCtx.bb.emit(CIL_UNBOX(boxType), tree.pos)
- }
- }
-
- // emit conversion
- if (generatedType != expectedType)
- abort("Unexpected tree in msil_genLoadAddressOf: " + tree + " at: " + tree.pos)
-
- resCtx
- }
-
+ //
+ // /**
+ // * forMSIL
+ // */
+ // private def msil_IsValuetypeInstMethod(msym: Symbol) = (
+ // loaders.clrTypes.methods get msym exists (mMSIL =>
+ // mMSIL.IsInstance && mMSIL.DeclaringType.IsValueType
+ // )
+ // )
+ // private def msil_IsValuetypeInstField(fsym: Symbol) = (
+ // loaders.clrTypes.fields get fsym exists (fMSIL =>
+ // !fMSIL.IsStatic && fMSIL.DeclaringType.IsValueType
+ // )
+ // )
+ //
+ // /**
+ // * forMSIL: Adds a local var, the emitted code requires one more slot on the stack as on entry
+ // */
+ // private def msil_genLoadZeroOfNonEnumValuetype(ctx: Context, kind: TypeKind, pos: Position, leaveAddressOnStackInstead: Boolean) {
+ // val REFERENCE(clssym) = kind
+ // assert(loaders.clrTypes.isNonEnumValuetype(clssym), clssym)
+ // val local = ctx.makeLocal(pos, clssym.tpe, "tmp")
+ // ctx.method.addLocal(local)
+ // ctx.bb.emit(CIL_LOAD_LOCAL_ADDRESS(local), pos)
+ // ctx.bb.emit(CIL_INITOBJ(kind), pos)
+ // val instr = if (leaveAddressOnStackInstead)
+ // CIL_LOAD_LOCAL_ADDRESS(local)
+ // else
+ // LOAD_LOCAL(local)
+ // ctx.bb.emit(instr, pos)
+ // }
+ //
+ // /**
+ // * forMSIL
+ // */
+ // private def msil_genLoadAddressOf(tree: Tree, ctx: Context, expectedType: TypeKind, butRawValueIsAlsoGoodEnough: Boolean): Context = {
+ // var generatedType = expectedType
+ // var addressTaken = false
+ // debuglog("at line: " + (if (tree.pos.isDefined) tree.pos.line else tree.pos))
+ //
+ // var resCtx: Context = tree match {
+ //
+ // // emits CIL_LOAD_FIELD_ADDRESS
+ // case Select(qualifier, selector) if (!tree.symbol.isModule) =>
+ // addressTaken = true
+ // val sym = tree.symbol
+ // generatedType = toTypeKind(sym.info)
+ //
+ // if (sym.isStaticMember) {
+ // ctx.bb.emit(CIL_LOAD_FIELD_ADDRESS(sym, true), tree.pos)
+ // ctx
+ // } else {
+ // val ctx1 = genLoadQualifier(tree, ctx)
+ // ctx1.bb.emit(CIL_LOAD_FIELD_ADDRESS(sym, false), tree.pos)
+ // ctx1
+ // }
+ //
+ // // emits CIL_LOAD_LOCAL_ADDRESS
+ // case Ident(name) if (!tree.symbol.isPackage && !tree.symbol.isModule)=>
+ // addressTaken = true
+ // val sym = tree.symbol
+ // try {
+ // val Some(l) = ctx.method.lookupLocal(sym)
+ // ctx.bb.emit(CIL_LOAD_LOCAL_ADDRESS(l), tree.pos)
+ // generatedType = l.kind // actually, should be "V&" but the callsite is aware of this
+ // } catch {
+ // case ex: MatchError =>
+ // abort("symbol " + sym + " does not exist in " + ctx.method)
+ // }
+ // ctx
+ //
+ // // emits CIL_LOAD_ARRAY_ITEM_ADDRESS
+ // case Apply(fun, args) =>
+ // if (isPrimitive(fun.symbol)) {
+ //
+ // val sym = tree.symbol
+ // val Apply(fun @ Select(receiver, _), args) = tree
+ // val code = scalaPrimitives.getPrimitive(sym, receiver.tpe)
+ //
+ // if (isArrayOp(code)) {
+ // val arrayObj = receiver
+ // val k = toTypeKind(arrayObj.tpe)
+ // val ARRAY(elementType) = k
+ // if (scalaPrimitives.isArrayGet(code)) {
+ // var ctx1 = genLoad(arrayObj, ctx, k)
+ // // load argument on stack
+ // debugassert(args.length == 1, "Too many arguments for array get operation: " + tree)
+ // ctx1 = genLoad(args.head, ctx1, INT)
+ // generatedType = elementType // actually "managed pointer to element type" but the callsite is aware of this
+ // ctx1.bb.emit(CIL_LOAD_ARRAY_ITEM_ADDRESS(elementType), tree.pos)
+ // addressTaken = true
+ // ctx1
+ // } else null
+ // } else null
+ // } else null
+ //
+ // case This(qual) =>
+ // /* TODO: this case handler is a placeholder for the time when Level 2 support for valuetypes is in place,
+ // in particular when invoking other methods on this where this is a valuetype value (boxed or not).
+ // As receiver, a managed pointer is expected, and a plain ldarg.0 achieves just that. */
+ // addressTaken = true
+ // genLoad(tree, ctx, expectedType)
+ //
+ // case _ =>
+ // null /* A method returning ByRef won't pass peverify, so I guess this case handler is dead code.
+ // Even if it's not, the code below to handler !addressTaken below. */
+ // }
+ //
+ // if (!addressTaken) {
+ // resCtx = genLoad(tree, ctx, expectedType)
+ // if (!butRawValueIsAlsoGoodEnough) {
+ // // raw value on stack (must be an intermediate result, e.g. returned by method call), take address
+ // addressTaken = true
+ // val boxType = expectedType // toTypeKind(expectedType /* TODO FIXME */)
+ // resCtx.bb.emit(BOX(boxType), tree.pos)
+ // resCtx.bb.emit(CIL_UNBOX(boxType), tree.pos)
+ // }
+ // }
+ //
+ // // emit conversion
+ // if (generatedType != expectedType)
+ // abort("Unexpected tree in msil_genLoadAddressOf: " + tree + " at: " + tree.pos)
+ //
+ // resCtx
+ // }
+ //
/**
* Generate code for trees that produce values on the stack
@@ -793,19 +793,19 @@ abstract class GenICode extends SubComponent {
debugassert(ctor.owner == cls,
"Symbol " + ctor.owner.fullName + " is different than " + tpt)
- val ctx2 = if (forMSIL && loaders.clrTypes.isNonEnumValuetype(cls)) {
- /* parameterful constructors are the only possible custom constructors,
- a default constructor can't be defined for valuetypes, CLR dixit */
- val isDefaultConstructor = args.isEmpty
- if (isDefaultConstructor) {
- msil_genLoadZeroOfNonEnumValuetype(ctx, rt, tree.pos, leaveAddressOnStackInstead = false)
- ctx
- } else {
- val ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx)
- ctx1.bb.emit(CIL_NEWOBJ(ctor), tree.pos)
- ctx1
- }
- } else {
+ // val ctx2 = if (forMSIL && loaders.clrTypes.isNonEnumValuetype(cls)) {
+ // /* parameterful constructors are the only possible custom constructors,
+ // a default constructor can't be defined for valuetypes, CLR dixit */
+ // val isDefaultConstructor = args.isEmpty
+ // if (isDefaultConstructor) {
+ // msil_genLoadZeroOfNonEnumValuetype(ctx, rt, tree.pos, leaveAddressOnStackInstead = false)
+ // ctx
+ // } else {
+ // val ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx)
+ // ctx1.bb.emit(CIL_NEWOBJ(ctor), tree.pos)
+ // ctx1
+ // }
+ // } else {
val nw = NEW(rt)
ctx.bb.emit(nw, tree.pos)
ctx.bb.emit(DUP(generatedType))
@@ -815,8 +815,8 @@ abstract class GenICode extends SubComponent {
nw.init = init
ctx1.bb.emit(init, tree.pos)
ctx1
- }
- ctx2
+ // }
+ // ctx2
case _ =>
abort("Cannot instantiate " + tpt + "of kind: " + generatedType)
@@ -845,12 +845,12 @@ abstract class GenICode extends SubComponent {
generatedType = boxType
ctx1.bb.emit(UNBOX(boxType), expr.pos)
ctx1
-
- case Apply(fun @ _, List(expr)) if (forMSIL && loaders.clrTypes.isAddressOf(fun.symbol)) =>
- debuglog("ADDRESSOF : " + fun.symbol.fullName);
- val ctx1 = msil_genLoadAddressOf(expr, ctx, toTypeKind(expr.tpe), butRawValueIsAlsoGoodEnough = false)
- generatedType = toTypeKind(fun.symbol.tpe.resultType)
- ctx1
+ //
+ // case Apply(fun @ _, List(expr)) if (forMSIL && loaders.clrTypes.isAddressOf(fun.symbol)) =>
+ // debuglog("ADDRESSOF : " + fun.symbol.fullName);
+ // val ctx1 = msil_genLoadAddressOf(expr, ctx, toTypeKind(expr.tpe), butRawValueIsAlsoGoodEnough = false)
+ // generatedType = toTypeKind(fun.symbol.tpe.resultType)
+ // ctx1
case app @ Apply(fun, args) =>
val sym = fun.symbol
@@ -887,9 +887,9 @@ abstract class GenICode extends SubComponent {
var ctx1 =
if (invokeStyle.hasInstance) {
- if (forMSIL && !(invokeStyle.isInstanceOf[SuperCall]) && msil_IsValuetypeInstMethod(sym))
- msil_genLoadQualifierAddress(fun, ctx)
- else
+ // if (forMSIL && !(invokeStyle.isInstanceOf[SuperCall]) && msil_IsValuetypeInstMethod(sym))
+ // msil_genLoadQualifierAddress(fun, ctx)
+ // else
genLoadQualifier(fun, ctx)
} else ctx
@@ -1150,15 +1150,15 @@ abstract class GenICode extends SubComponent {
case _ =>
abort("Unknown qualifier " + tree)
}
-
- /** forMSIL */
- private def msil_genLoadQualifierAddress(tree: Tree, ctx: Context): Context =
- tree match {
- case Select(qualifier, _) =>
- msil_genLoadAddressOf(qualifier, ctx, toTypeKind(qualifier.tpe), butRawValueIsAlsoGoodEnough = false)
- case _ =>
- abort("Unknown qualifier " + tree)
- }
+ //
+ // /** forMSIL */
+ // private def msil_genLoadQualifierAddress(tree: Tree, ctx: Context): Context =
+ // tree match {
+ // case Select(qualifier, _) =>
+ // msil_genLoadAddressOf(qualifier, ctx, toTypeKind(qualifier.tpe), butRawValueIsAlsoGoodEnough = false)
+ // case _ =>
+ // abort("Unknown qualifier " + tree)
+ // }
/**
* Generate code that loads args into label parameters.
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index 2bcfb9d4a9..bf8580b903 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -636,63 +636,63 @@ trait Opcodes { self: ICodes =>
// CLR backend
-
- case class CIL_LOAD_LOCAL_ADDRESS(local: Local) extends Instruction {
- /** Returns a string representation of this instruction */
- override def toString(): String = "CIL_LOAD_LOCAL_ADDRESS "+local //+isArgument?" (argument)":"";
-
- override def consumed = 0
- override def produced = 1
-
- override def producedTypes = List(msil_mgdptr(local.kind))
- }
-
- case class CIL_LOAD_FIELD_ADDRESS(field: Symbol, isStatic: Boolean) extends Instruction {
- /** Returns a string representation of this instruction */
- override def toString(): String =
- "CIL_LOAD_FIELD_ADDRESS " + (if (isStatic) field.fullName else field.toString)
-
- override def consumed = if (isStatic) 0 else 1
- override def produced = 1
-
- override def consumedTypes = if (isStatic) Nil else List(REFERENCE(field.owner));
- override def producedTypes = List(msil_mgdptr(REFERENCE(field.owner)));
-}
-
- case class CIL_LOAD_ARRAY_ITEM_ADDRESS(kind: TypeKind) extends Instruction {
- /** Returns a string representation of this instruction */
- override def toString(): String = "CIL_LOAD_ARRAY_ITEM_ADDRESS (" + kind + ")"
-
- override def consumed = 2
- override def produced = 1
-
- override def consumedTypes = List(ARRAY(kind), INT)
- override def producedTypes = List(msil_mgdptr(kind))
- }
-
- case class CIL_UNBOX(valueType: TypeKind) extends Instruction {
- override def toString(): String = "CIL_UNBOX " + valueType
- override def consumed = 1
- override def consumedTypes = ObjectReference :: Nil // actually consumes a 'boxed valueType'
- override def produced = 1
- override def producedTypes = List(msil_mgdptr(valueType))
- }
-
- case class CIL_INITOBJ(valueType: TypeKind) extends Instruction {
- override def toString(): String = "CIL_INITOBJ " + valueType
- override def consumed = 1
- override def consumedTypes = ObjectReference :: Nil // actually consumes a managed pointer
- override def produced = 0
- }
-
- case class CIL_NEWOBJ(method: Symbol) extends Instruction {
- override def toString(): String = "CIL_NEWOBJ " + hostClass.fullName + method.fullName
- var hostClass: Symbol = method.owner;
- override def consumed = method.tpe.paramTypes.length
- override def consumedTypes = method.tpe.paramTypes map toTypeKind
- override def produced = 1
- override def producedTypes = List(toTypeKind(method.tpe.resultType))
- }
+//
+// case class CIL_LOAD_LOCAL_ADDRESS(local: Local) extends Instruction {
+// /** Returns a string representation of this instruction */
+// override def toString(): String = "CIL_LOAD_LOCAL_ADDRESS "+local //+isArgument?" (argument)":"";
+//
+// override def consumed = 0
+// override def produced = 1
+//
+// override def producedTypes = List(msil_mgdptr(local.kind))
+// }
+//
+// case class CIL_LOAD_FIELD_ADDRESS(field: Symbol, isStatic: Boolean) extends Instruction {
+// /** Returns a string representation of this instruction */
+// override def toString(): String =
+// "CIL_LOAD_FIELD_ADDRESS " + (if (isStatic) field.fullName else field.toString)
+//
+// override def consumed = if (isStatic) 0 else 1
+// override def produced = 1
+//
+// override def consumedTypes = if (isStatic) Nil else List(REFERENCE(field.owner));
+// override def producedTypes = List(msil_mgdptr(REFERENCE(field.owner)));
+// }
+//
+// case class CIL_LOAD_ARRAY_ITEM_ADDRESS(kind: TypeKind) extends Instruction {
+// /** Returns a string representation of this instruction */
+// override def toString(): String = "CIL_LOAD_ARRAY_ITEM_ADDRESS (" + kind + ")"
+//
+// override def consumed = 2
+// override def produced = 1
+//
+// override def consumedTypes = List(ARRAY(kind), INT)
+// override def producedTypes = List(msil_mgdptr(kind))
+// }
+//
+// case class CIL_UNBOX(valueType: TypeKind) extends Instruction {
+// override def toString(): String = "CIL_UNBOX " + valueType
+// override def consumed = 1
+// override def consumedTypes = ObjectReference :: Nil // actually consumes a 'boxed valueType'
+// override def produced = 1
+// override def producedTypes = List(msil_mgdptr(valueType))
+// }
+//
+// case class CIL_INITOBJ(valueType: TypeKind) extends Instruction {
+// override def toString(): String = "CIL_INITOBJ " + valueType
+// override def consumed = 1
+// override def consumedTypes = ObjectReference :: Nil // actually consumes a managed pointer
+// override def produced = 0
+// }
+//
+// case class CIL_NEWOBJ(method: Symbol) extends Instruction {
+// override def toString(): String = "CIL_NEWOBJ " + hostClass.fullName + method.fullName
+// var hostClass: Symbol = method.owner;
+// override def consumed = method.tpe.paramTypes.length
+// override def consumedTypes = method.tpe.paramTypes map toTypeKind
+// override def produced = 1
+// override def producedTypes = List(toTypeKind(method.tpe.resultType))
+// }
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index a485272ca6..998ac90778 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -423,11 +423,10 @@ trait TypeKinds { self: ICodes =>
primitiveTypeMap.getOrElse(sym, newReference(sym))
private def primitiveOrClassType(sym: Symbol, targs: List[Type]) =
primitiveTypeMap.getOrElse(sym, arrayOrClassType(sym, targs))
-
- def msil_mgdptr(tk: TypeKind): TypeKind = (tk: @unchecked) match {
- case REFERENCE(cls) => REFERENCE(loaders.clrTypes.mdgptrcls4clssym(cls))
- // TODO have ready class-symbols for the by-ref versions of built-in valuetypes
- case _ => abort("cannot obtain a managed pointer for " + tk)
- }
-
+ //
+ // def msil_mgdptr(tk: TypeKind): TypeKind = (tk: @unchecked) match {
+ // case REFERENCE(cls) => REFERENCE(loaders.clrTypes.mdgptrcls4clssym(cls))
+ // // TODO have ready class-symbols for the by-ref versions of built-in valuetypes
+ // case _ => abort("cannot obtain a managed pointer for " + tk)
+ // }
}
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index d2e54ff3f1..ab07f2e4fc 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -1,2357 +1,2357 @@
-/* NSC -- new scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Nikolay Mihaylov
- */
-
-
-package scala.tools.nsc
-package backend.msil
-
-import java.io.{File, IOException}
-import java.nio.{ByteBuffer, ByteOrder}
-import scala.collection.{ mutable, immutable }
-import scala.tools.nsc.symtab._
-
-import ch.epfl.lamp.compiler.msil.{Type => MsilType, _}
-import ch.epfl.lamp.compiler.msil.emit._
-import ch.epfl.lamp.compiler.msil.util.PECustomMod
-
-abstract class GenMSIL extends SubComponent {
- import global._
- import loaders.clrTypes
- import clrTypes.{types, constructors, methods, fields}
- import icodes._
- import icodes.opcodes._
-
- val x = loaders
-
- /** Create a new phase */
- override def newPhase(p: Phase) = new MsilPhase(p)
-
- val phaseName = "msil"
- /** MSIL code generation phase
- */
- class MsilPhase(prev: Phase) extends GlobalPhase(prev) {
- def name = phaseName
- override def newFlags = phaseNewFlags
-
- override def erasedTypes = true
-
- override def run() {
- if (settings.debug.value) inform("[running phase " + name + " on icode]")
-
- val codeGenerator = new BytecodeGenerator
-
- //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
-
- 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 {
- classesSorted foreach codeGenerator.genClass
- } finally {
- codeGenerator.writeAssembly
- }
- }
-
- override def apply(unit: CompilationUnit) {
- abort("MSIL works on icode classes, not on compilation units!")
- }
- }
-
- /**
- * MSIL bytecode generator.
- *
- */
- class BytecodeGenerator {
-
- val MODULE_INSTANCE_NAME = "MODULE$"
-
- 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,
- SYMTAB_CONSTR => SYMTAB_ATTRIBUTE_CONSTRUCTOR,
- SYMTAB_DEFAULT_CONSTR => SYMTAB_ATTRIBUTE_EMPTY_CONSTRUCTOR}
-
- val EXCEPTION = clrTypes.getType("System.Exception")
- val MBYTE_ARRAY = clrTypes.mkArrayType(MBYTE)
-
- val ICLONEABLE = clrTypes.getType("System.ICloneable")
- val MEMBERWISE_CLONE = MOBJECT.GetMethod("MemberwiseClone", MsilType.EmptyTypes)
-
- val MMONITOR = clrTypes.getType("System.Threading.Monitor")
- val MMONITOR_ENTER = MMONITOR.GetMethod("Enter", Array(MOBJECT))
- val MMONITOR_EXIT = MMONITOR.GetMethod("Exit", Array(MOBJECT))
-
- val MSTRING_BUILDER = clrTypes.getType("System.Text.StringBuilder")
- val MSTRING_BUILDER_CONSTR = MSTRING_BUILDER.GetConstructor(MsilType.EmptyTypes)
- val MSTRING_BUILDER_TOSTRING = MSTRING_BUILDER.GetMethod("ToString",
- MsilType.EmptyTypes)
-
- val TYPE_FROM_HANDLE =
- clrTypes.getType("System.Type").GetMethod("GetTypeFromHandle", Array(clrTypes.getType("System.RuntimeTypeHandle")))
-
- val INT_PTR = clrTypes.getType("System.IntPtr")
-
- val JOBJECT = definitions.ObjectClass
- val JSTRING = definitions.StringClass
-
- val SystemConvert = clrTypes.getType("System.Convert")
-
- val objParam = Array(MOBJECT)
-
- val toBool: MethodInfo = SystemConvert.GetMethod("ToBoolean", objParam) // see comment in emitUnbox
- 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)
-
- //val boxedUnit: FieldInfo = msilType(definitions.BoxedUnitModule.info).GetField("UNIT")
- val boxedUnit: FieldInfo = fields(definitions.BoxedUnit_UNIT)
-
- // Scala attributes
- // symtab.Definitions -> object (singleton..)
- val SerializableAttr = definitions.SerializableAttr.tpe
- val CloneableAttr = definitions.CloneableAttr.tpe
- val TransientAtt = definitions.TransientAttr.tpe
- // remoting: the architectures are too different, no mapping (no portable code
- // possible)
-
- // java instance methods that are mapped to static methods in .net
- // these will need to be called with OpCodes.Call (not Callvirt)
- val dynToStatMapped = mutable.HashSet[Symbol]()
-
- initMappings()
-
- /** Create the mappings between java and .net classes and methods */
- private def initMappings() {
- mapType(definitions.AnyClass, MOBJECT)
- mapType(definitions.AnyRefClass, MOBJECT)
- //mapType(definitions.NullClass, clrTypes.getType("scala.AllRef$"))
- //mapType(definitions.NothingClass, clrTypes.getType("scala.All$"))
- // FIXME: for some reason the upper two lines map to null
- mapType(definitions.NullClass, EXCEPTION)
- mapType(definitions.NothingClass, EXCEPTION)
-
- mapType(definitions.BooleanClass, MBOOL)
- mapType(definitions.ByteClass, MBYTE)
- mapType(definitions.ShortClass, MSHORT)
- mapType(definitions.CharClass, MCHAR)
- mapType(definitions.IntClass, MINT)
- mapType(definitions.LongClass, MLONG)
- mapType(definitions.FloatClass, MFLOAT)
- mapType(definitions.DoubleClass, MDOUBLE)
- }
-
- var clasz: IClass = _
- var method: IMethod = _
-
- var massembly: AssemblyBuilder = _
- var mmodule: ModuleBuilder = _
- var mcode: ILGenerator = _
-
- var assemName: String = _
- var firstSourceName = ""
- var outDir: File = _
- var srcPath: File = _
- var moduleName: String = _
-
- def initAssembly() {
-
- assemName = settings.assemname.value
-
- if (assemName == "") {
- if (entryPoint != null) {
- assemName = msilName(entryPoint.enclClass)
- // remove the $ at the end (from module-name)
- assemName = assemName.substring(0, assemName.length() - 1)
- } else {
- // assuming filename of first source file
- assert(firstSourceName.endsWith(".scala"), firstSourceName)
- assemName = firstSourceName.substring(0, firstSourceName.length() - 6)
- }
- } else {
- if (assemName.endsWith(".msil"))
- assemName = assemName.substring(0, assemName.length()-5)
- if (assemName.endsWith(".il"))
- assemName = assemName.substring(0, assemName.length()-3)
- val f: File = new File(assemName)
- assemName = f.getName()
- }
-
- outDir = new File(settings.outdir.value)
-
- srcPath = new File(settings.sourcedir.value)
-
- val assemblyName = new AssemblyName()
- assemblyName.Name = assemName
- massembly = AssemblyBuilderFactory.DefineDynamicAssembly(assemblyName)
-
- moduleName = assemName // + (if (entryPoint == null) ".dll" else ".exe")
- // filename here: .dll or .exe (in both parameters), second: give absolute-path
- mmodule = massembly.DefineDynamicModule(moduleName,
- new File(outDir, moduleName).getAbsolutePath())
- assert (mmodule != null)
- }
-
-
- /**
- * Form of the custom Attribute parameter (Ecma-335.pdf)
- * - p. 163 for CustomAttrib Form,
- * - p. 164 for FixedArg Form (Array and Element) (if array or not is known!)
- * !! least significant byte first if values longer than one byte !!
- *
- * 1: Prolog (unsigned int16, value 0x0001) -> symtab[0] = 0x01, symtab[1] = 0x00
- * 2: FixedArgs (directly the data, get number and types from related constructor)
- * 2.1: length of the array (unsigned int32, 4 bytes, least significant first)
- * 2.2: the byte array data
- * 3: NumNamed (unsigned int16, number of named fields and properties, 0x0000)
- */
- def addSymtabAttribute(sym: Symbol, tBuilder: TypeBuilder) {
- def addMarker() {
- val markerSymtab = new Array[Byte](4)
- markerSymtab(0) = 1.toByte
- tBuilder.SetCustomAttribute(SYMTAB_ATTRIBUTE_EMPTY_CONSTRUCTOR, markerSymtab)
- }
-
- // both conditions are needed (why exactly..?)
- if (tBuilder.Name.endsWith("$") || sym.isModuleClass) {
- addMarker()
- } else {
- currentRun.symData.get(sym) match {
- case Some(pickle) =>
- var size = pickle.writeIndex
- val symtab = new Array[Byte](size + 8)
- symtab(0) = 1.toByte
- for (i <- 2 until 6) {
- symtab(i) = (size & 0xff).toByte
- size = size >> 8
- }
- java.lang.System.arraycopy(pickle.bytes, 0, symtab, 6, pickle.writeIndex)
-
- tBuilder.SetCustomAttribute(SYMTAB_ATTRIBUTE_CONSTRUCTOR, symtab)
-
- currentRun.symData -= sym
- currentRun.symData -= sym.companionSymbol
-
- case _ =>
- addMarker()
- }
- }
- }
-
- /**
- * Mutates `member` adding CLR attributes (if any) based on sym.annotations.
- * Please notice that CLR custom modifiers are a different beast (see customModifiers below)
- * and thus shouldn't be added by this method.
- */
- def addAttributes(member: ICustomAttributeSetter, annotations: List[AnnotationInfo]) {
- val attributes = annotations.map(_.atp.typeSymbol).collect {
- case definitions.TransientAttr => null // TODO this is just an example
- }
- return // TODO: implement at some point
- }
-
- /**
- * What's a CLR custom modifier? Intro available as source comments in compiler.msil.CustomModifier.
- * It's basically a marker associated with a location (think of FieldInfo, ParameterInfo, and PropertyInfo)
- * and thus that marker (be it optional or required) becomes part of the signature of that location.
- * Some annotations will become CLR attributes (see addAttributes above), others custom modifiers (this method).
- */
- def customModifiers(annotations: List[AnnotationInfo]): Array[CustomModifier] = {
- annotations.map(_.atp.typeSymbol).collect {
- case definitions.VolatileAttr => new CustomModifier(true, CustomModifier.VolatileMarker)
- } toArray
- }
-
-
-
- /*
- debuglog("creating annotations: " + annotations + " for member : " + member)
- for (annot@ AnnotationInfo(typ, annArgs, nvPairs) <- annotations ;
- if annot.isConstant)
- //!typ.typeSymbol.isJavaDefined
- {
-// assert(consts.length <= 1,
-// "too many constant arguments for annotations; "+consts.toString())
-
- // Problem / TODO having the symbol of the annotations type would be nicer
- // (i hope that type.typeSymbol is the same as the one in types2create)
- // AND: this will crash if the annotations Type is already compiled (-> not a typeBuilder)
- // when this is solved, types2create will be the same as icodes.classes, thus superfluous
- val annType: TypeBuilder = getType(typ.typeSymbol).asInstanceOf[TypeBuilder]
-// val annType: MsilType = getType(typ.typeSymbol)
-
- // Problem / TODO: i have no idea which constructor is used. This
- // information should be available in AnnotationInfo.
- annType.CreateType() // else, GetConstructors can't be used
- val constr: ConstructorInfo = annType.GetConstructors()(0)
- // prevent a second call of CreateType, only needed because there's no
- // other way than GetConstructors()(0) to get the constructor, if there's
- // no constructor symbol available.
-
- val args: Array[Byte] =
- getAttributeArgs(
- annArgs map (_.constant.get),
- (for((n,v) <- nvPairs) yield (n, v.constant.get)))
- member.SetCustomAttribute(constr, args)
- }
- } */
-
-/* def getAttributeArgs(consts: List[Constant], nvPairs: List[(Name, Constant)]): Array[Byte] = {
- val buf = ByteBuffer.allocate(2048) // FIXME: this may be not enough!
- buf.order(ByteOrder.LITTLE_ENDIAN)
- buf.putShort(1.toShort) // signature
-
- def emitSerString(str: String) = {
- // this is wrong, it has to be the length of the UTF-8 byte array, which
- // may be longer (see clr-book on page 302)
-// val length: Int = str.length
- val strBytes: Array[Byte] = try {
- str.getBytes("UTF-8")
- } catch {
- case _: Error => abort("could not get byte-array for string: " + str)
- }
- val length: Int = strBytes.length //this length is stored big-endian
- if (length < 128)
- buf.put(length.toByte)
- else if (length < (1<<14)) {
- buf.put(((length >> 8) | 0x80).toByte) // the bits 14 and 15 of length are '0'
- buf.put((length | 0xff).toByte)
- } else if (length < (1 << 29)) {
- buf.put(((length >> 24) | 0xc0).toByte)
- buf.put(((length >> 16) & 0xff).toByte)
- buf.put(((length >> 8) & 0xff).toByte)
- buf.put(((length ) & 0xff).toByte)
- } else
- abort("string too long for attribute parameter: " + length)
- buf.put(strBytes)
- }
-
- def emitConst(const: Constant): Unit = const.tag match {
- case BooleanTag => buf.put((if (const.booleanValue) 1 else 0).toByte)
- case ByteTag => buf.put(const.byteValue)
- case ShortTag => buf.putShort(const.shortValue)
- case CharTag => buf.putChar(const.charValue)
- case IntTag => buf.putInt(const.intValue)
- case LongTag => buf.putLong(const.longValue)
- case FloatTag => buf.putFloat(const.floatValue)
- case DoubleTag => buf.putDouble(const.doubleValue)
- case StringTag =>
- val str: String = const.stringValue
- if (str == null) {
- buf.put(0xff.toByte)
- } else {
- emitSerString(str)
- }
- case ArrayTag =>
- val arr: Array[Constant] = const.arrayValue
- if (arr == null) {
- buf.putInt(0xffffffff)
- } else {
- buf.putInt(arr.length)
- arr.foreach(emitConst)
- }
-
- // TODO: other Tags: NoTag, UnitTag, ClassTag, EnumTag, ArrayTag ???
-
- case _ => abort("could not handle attribute argument: " + const)
- }
-
- consts foreach emitConst
- buf.putShort(nvPairs.length.toShort)
- def emitNamedArg(nvPair: (Name, Constant)) {
- // the named argument is a property of the attribute (it can't be a field, since
- // all fields in scala are private)
- buf.put(0x54.toByte)
-
- def emitType(c: Constant) = c.tag match { // type of the constant, Ecma-335.pdf, page 151
- case BooleanTag => buf.put(0x02.toByte)
- case ByteTag => buf.put(0x05.toByte)
- case ShortTag => buf.put(0x06.toByte)
- case CharTag => buf.put(0x07.toByte)
- case IntTag => buf.put(0x08.toByte)
- case LongTag => buf.put(0x0a.toByte)
- case FloatTag => buf.put(0x0c.toByte)
- case DoubleTag => buf.put(0x0d.toByte)
- case StringTag => buf.put(0x0e.toByte)
-
- // TODO: other Tags: NoTag, UnitTag, ClassTag, EnumTag ???
-
- // ArrayTag falls in here
- case _ => abort("could not handle attribute argument: " + c)
- }
-
- val cnst: Constant = nvPair._2
- if (cnst.tag == ArrayTag) {
- buf.put(0x1d.toByte)
- emitType(cnst.arrayValue(0)) // FIXME: will crash if array length = 0
- } else if (cnst.tag == EnumTag) {
- buf.put(0x55.toByte)
- // TODO: put a SerString (don't know what exactly, names of the enums somehow..)
- } else {
- buf.put(0x51.toByte)
- emitType(cnst)
- }
-
- emitSerString(nvPair._1.toString)
- emitConst(nvPair._2)
- }
-
- val length = buf.position()
- buf.array().slice(0, length)
- } */
-
- def writeAssembly() {
- if (entryPoint != null) {
- assert(entryPoint.enclClass.isModuleClass, entryPoint.enclClass)
- val mainMethod = methods(entryPoint)
- val stringArrayTypes: Array[MsilType] = Array(MSTRING_ARRAY)
- val globalMain = mmodule.DefineGlobalMethod(
- "Main", MethodAttributes.Public | MethodAttributes.Static,
- MVOID, stringArrayTypes)
- globalMain.DefineParameter(0, ParameterAttributes.None, "args")
- massembly.SetEntryPoint(globalMain)
- val code = globalMain.GetILGenerator()
- val moduleField = getModuleInstanceField(entryPoint.enclClass)
- code.Emit(OpCodes.Ldsfld, moduleField)
- code.Emit(OpCodes.Ldarg_0)
- code.Emit(OpCodes.Callvirt, mainMethod)
- code.Emit(OpCodes.Ret)
- }
- createTypes()
- var outDirName: String = null
- try {
- 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 " + outDirName + ": " + e.getMessage())
- }
- }
-
- private def createTypes() {
- for (sym <- classes.keys) {
- val iclass = classes(sym)
- val tBuilder = types(sym).asInstanceOf[TypeBuilder]
-
- debuglog("Calling CreatType for " + sym + ", " + tBuilder.toString)
-
- tBuilder.CreateType()
- tBuilder.setSourceFilepath(iclass.cunit.source.file.path)
- }
- }
-
- private[GenMSIL] def ilasmFileName(iclass: IClass) : String = {
- // method.sourceFile contains just the filename
- iclass.cunit.source.file.toString.replace("\\", "\\\\")
- }
-
- private[GenMSIL] def genClass(iclass: IClass) {
- val sym = iclass.symbol
- debuglog("Generating class " + sym + " flags: " + Flags.flagsToString(sym.flags))
- clasz = iclass
-
- val tBuilder = getType(sym).asInstanceOf[TypeBuilder]
- if (isCloneable(sym)) {
- // FIXME: why there's no nme.clone_ ?
- // "Clone": if the code is non-portable, "Clone" is defined, not "clone"
- // TODO: improve condition (should override AnyRef.clone)
- if (iclass.methods.forall(m => {
- !((m.symbol.name.toString != "clone" || m.symbol.name.toString != "Clone") &&
- m.symbol.tpe.paramTypes.length != 0)
- })) {
- debuglog("auto-generating cloneable method for " + sym)
- val attrs: Short = (MethodAttributes.Public | MethodAttributes.Virtual |
- MethodAttributes.HideBySig).toShort
- val cloneMethod = tBuilder.DefineMethod("Clone", attrs, MOBJECT,
- MsilType.EmptyTypes)
- val clCode = cloneMethod.GetILGenerator()
- clCode.Emit(OpCodes.Ldarg_0)
- clCode.Emit(OpCodes.Call, MEMBERWISE_CLONE)
- clCode.Emit(OpCodes.Ret)
- }
- }
-
- val line = sym.pos.line
- tBuilder.setPosition(line, ilasmFileName(iclass))
-
- if (isTopLevelModule(sym)) {
- if (sym.companionClass == NoSymbol)
- generateMirrorClass(sym)
- else
- log("No mirror class for module with linked class: " +
- sym.fullName)
- }
-
- addSymtabAttribute(sym, tBuilder)
- addAttributes(tBuilder, sym.annotations)
-
- if (iclass.symbol != definitions.ArrayClass)
- iclass.methods foreach genMethod
-
- } //genClass
-
-
- private def genMethod(m: IMethod) {
- debuglog("Generating method " + m.symbol + " flags: " + Flags.flagsToString(m.symbol.flags) +
- " owner: " + m.symbol.owner)
- method = m
- localBuilders.clear
- computeLocalVarsIndex(m)
-
- if (m.symbol.isClassConstructor) {
- mcode = constructors(m.symbol).asInstanceOf[ConstructorBuilder].GetILGenerator()
- } else {
- val mBuilder = methods(m.symbol).asInstanceOf[MethodBuilder]
- if (!mBuilder.IsAbstract())
- try {
- mcode = mBuilder.GetILGenerator()
- } catch {
- case e: Exception =>
- java.lang.System.out.println("m.symbol = " + Flags.flagsToString(m.symbol.flags) + " " + m.symbol)
- java.lang.System.out.println("m.symbol.owner = " + Flags.flagsToString(m.symbol.owner.flags) + " " + m.symbol.owner)
- java.lang.System.out.println("mBuilder = " + mBuilder)
- java.lang.System.out.println("mBuilder.DeclaringType = " +
- TypeAttributes.toString(mBuilder.DeclaringType.Attributes) +
- "::" + mBuilder.DeclaringType)
- throw e
- }
- else
- mcode = null
- }
-
- if (mcode != null) {
- for (local <- m.locals ; if !(m.params contains local)) {
- debuglog("add local var: " + local + ", of kind " + local.kind)
- val t: MsilType = msilType(local.kind)
- val localBuilder = mcode.DeclareLocal(t)
- localBuilder.SetLocalSymInfo(msilName(local.sym))
- localBuilders(local) = localBuilder
- }
- genCode(m)
- }
-
- }
-
- /** Special linearizer for methods with at least one exception handler. This
- * linearizer brings all basic blocks in the right order so that nested
- * try-catch and try-finally blocks can be emitted.
- */
- val msilLinearizer = new MSILLinearizer()
-
- val labels = mutable.HashMap[BasicBlock, Label]()
-
- /* when emitting .line, it's enough to include the full filename just once per method, thus reducing filesize.
- * this scheme relies on the fact that the entry block is emitted first. */
- var dbFilenameSeen = false
-
- def genCode(m: IMethod) {
-
- def makeLabels(blocks: List[BasicBlock]) = {
- debuglog("Making labels for: " + method)
- for (bb <- blocks) labels(bb) = mcode.DefineLabel()
- }
-
- labels.clear
-
- var linearization = if(!m.exh.isEmpty) msilLinearizer.linearize(m)
- else linearizer.linearize(m)
-
- 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) { }
-
- dbFilenameSeen = false
- genBlocks(linearization)
-
- // RETURN inside exception blocks are replaced by Leave. The target of the
- // leave is a `Ret` outside any exception block (generated here).
- if (handlerReturnMethod == m) {
- mcode.MarkLabel(handlerReturnLabel)
- if (handlerReturnKind != UNIT)
- mcode.Emit(OpCodes.Ldloc, handlerReturnLocal)
- mcode.Emit(OpCodes.Ret)
- }
-
- beginExBlock.clear()
- beginCatchBlock.clear()
- endExBlock.clear()
- endFinallyLabels.clear()
- }
-
- def genBlocks(blocks: List[BasicBlock], previous: BasicBlock = null) {
- blocks match {
- case Nil => ()
- case x :: Nil => genBlock(x, prev = previous, next = null)
- case x :: y :: ys => genBlock(x, prev = previous, next = y); genBlocks(y :: ys, previous = x)
- }
- }
-
- // the try blocks starting at a certain BasicBlock
- val beginExBlock = mutable.HashMap[BasicBlock, List[ExceptionHandler]]()
-
- // the catch blocks starting / endling at a certain BasicBlock
- val beginCatchBlock = mutable.HashMap[BasicBlock, ExceptionHandler]()
- val endExBlock = mutable.HashMap[BasicBlock, List[ExceptionHandler]]()
-
- /** When emitting the code (genBlock), the number of currently active try / catch
- * blocks. When seeing a `RETURN` inside a try / catch, we need to
- * - store the result in a local (if it's not UNIT)
- * - emit `Leave handlerReturnLabel` instead of the Return
- * - emit code at the end: load the local and return its value
- */
- var currentHandlers = new mutable.Stack[ExceptionHandler]
- // The IMethod the Local/Label/Kind below belong to
- var handlerReturnMethod: IMethod = _
- // Stores the result when returning inside an exception block
- var handlerReturnLocal: LocalBuilder = _
- // Label for a return instruction outside any exception block
- var handlerReturnLabel: Label = _
- // The result kind.
- var handlerReturnKind: TypeKind = _
- def returnFromHandler(kind: TypeKind): (LocalBuilder, Label) = {
- if (handlerReturnMethod != method) {
- handlerReturnMethod = method
- if (kind != UNIT) {
- handlerReturnLocal = mcode.DeclareLocal(msilType(kind))
- handlerReturnLocal.SetLocalSymInfo("$handlerReturn")
- }
- handlerReturnLabel = mcode.DefineLabel()
- handlerReturnKind = kind
- }
- (handlerReturnLocal, handlerReturnLabel)
- }
-
- /** For try/catch nested inside a finally, we can't use `Leave OutsideFinally`, the
- * Leave target has to be inside the finally (and it has to be the `endfinally` instruction).
- * So for every finalizer, we have a label which marks the place of the `endfinally`,
- * nested try/catch blocks will leave there.
- */
- val endFinallyLabels = mutable.HashMap[ExceptionHandler, Label]()
-
- /** Computes which blocks are the beginning / end of a try or catch block */
- private def computeExceptionMaps(blocks: List[BasicBlock], m: IMethod): List[BasicBlock] = {
- val visitedBlocks = new mutable.HashSet[BasicBlock]()
-
- // handlers which have not been introduced so far
- var openHandlers = m.exh
-
-
- /** Example
- * try {
- * try {
- * // *1*
- * } catch {
- * case h1 =>
- * }
- * } catch {
- * case h2 =>
- * case h3 =>
- * try {
- *
- * } catch {
- * case h4 => // *2*
- * case h5 =>
- * }
- * }
- */
-
- // Stack of nested try blocks. Each bloc has a List of ExceptionHandler (multiple
- // catch statements). Example *1*: Stack(List(h2, h3), List(h1))
- val currentTryHandlers = new mutable.Stack[List[ExceptionHandler]]()
-
- // Stack of nested catch blocks. The head of the list is the current catch block. The
- // tail is all following catch blocks. Example *2*: Stack(List(h3), List(h4, h5))
- val currentCatchHandlers = new mutable.Stack[List[ExceptionHandler]]()
-
- for (b <- blocks) {
-
- // are we past the current catch blocks?
- def endHandlers(): List[ExceptionHandler] = {
- var res: List[ExceptionHandler] = Nil
- if (!currentCatchHandlers.isEmpty) {
- val handler = currentCatchHandlers.top.head
- if (!handler.blocks.contains(b)) {
- // all blocks of the handler are either visited, or not part of the linearization (i.e. dead)
- assert(handler.blocks.forall(b => visitedBlocks.contains(b) || !blocks.contains(b)),
- "Bad linearization of basic blocks inside catch. Found block not part of the handler\n"+
- b.fullString +"\nwhile in catch-part of\n"+ handler)
-
- val rest = currentCatchHandlers.pop.tail
- if (rest.isEmpty) {
- // all catch blocks of that exception handler are covered
- res = handler :: endHandlers()
- } else {
- // there are more catch blocks for that try (handlers covering the same)
- currentCatchHandlers.push(rest)
- beginCatchBlock(b) = rest.head
- }
- }
- }
- res
- }
- val end = endHandlers()
- if (!end.isEmpty) endExBlock(b) = end
-
- // are we past the current try block?
- if (!currentTryHandlers.isEmpty) {
- val handler = currentTryHandlers.top.head
- if (!handler.covers(b)) {
- // all of the covered blocks are visited, or not part of the linearization
- assert(handler.covered.forall(b => visitedBlocks.contains(b) || !blocks.contains(b)),
- "Bad linearization of basic blocks inside try. Found non-covered block\n"+
- b.fullString +"\nwhile in try-part of\n"+ handler)
-
- assert(handler.startBlock == b,
- "Bad linearization of basic blocks. The entry block of a catch does not directly follow the try\n"+
- b.fullString +"\n"+ handler)
-
- val handlers = currentTryHandlers.pop
- currentCatchHandlers.push(handlers)
- beginCatchBlock(b) = handler
- }
- }
-
- // are there try blocks starting at b?
- val (newHandlers, stillOpen) = openHandlers.partition(_.covers(b))
- openHandlers = stillOpen
-
- val newHandlersBySize = newHandlers.groupBy(_.covered.size)
- // big handlers first, smaller ones are nested inside the try of the big one
- // (checked by the assertions below)
- val sizes = newHandlersBySize.keys.toList.sortWith(_ > _)
-
- val beginHandlers = new mutable.ListBuffer[ExceptionHandler]
- for (s <- sizes) {
- val sHandlers = newHandlersBySize(s)
- for (h <- sHandlers) {
- assert(h.covered == sHandlers.head.covered,
- "bad nesting of exception handlers. same size, but not covering same blocks\n"+
- h +"\n"+ sHandlers.head)
- assert(h.resultKind == sHandlers.head.resultKind,
- "bad nesting of exception handlers. same size, but the same resultKind\n"+
- h +"\n"+ sHandlers.head)
- }
- for (bigger <- beginHandlers; h <- sHandlers) {
- assert(h.covered.subsetOf(bigger.covered),
- "bad nesting of exception handlers. try blocks of smaller handler are not nested in bigger one.\n"+
- h +"\n"+ bigger)
- assert(h.blocks.toSet.subsetOf(bigger.covered),
- "bad nesting of exception handlers. catch blocks of smaller handler are not nested in bigger one.\n"+
- h +"\n"+ bigger)
- }
- beginHandlers += sHandlers.head
- currentTryHandlers.push(sHandlers)
- }
- beginExBlock(b) = beginHandlers.toList
- visitedBlocks += b
- }
-
- // if there handlers left (i.e. handlers covering nothing, or a
- // non-existent (dead) block), remove their catch-blocks.
- val liveBlocks = if (openHandlers.isEmpty) blocks else {
- blocks.filter(b => openHandlers.forall(h => !h.blocks.contains(b)))
- }
-
- /** There might be open handlers, but no more blocks. happens when try/catch end
- * with `throw` or `return`
- * def foo() { try { .. throw } catch { _ => .. throw } }
- *
- * In this case we need some code after the catch block for the auto-generated
- * `leave` instruction. So we're adding a (dead) `throw new Exception`.
- */
- val rest = currentCatchHandlers.map(handlers => {
- assert(handlers.length == 1, handlers)
- handlers.head
- }).toList
-
- if (rest.isEmpty) {
- liveBlocks
- } else {
- val b = m.code.newBlock
- b.emit(Seq(
- NEW(REFERENCE(definitions.ThrowableClass)),
- DUP(REFERENCE(definitions.ObjectClass)),
- CALL_METHOD(definitions.ThrowableClass.primaryConstructor, Static(true)),
- THROW(definitions.ThrowableClass)
- ))
- b.close
- endExBlock(b) = rest
- liveBlocks ::: List(b)
- }
- }
-
- /**
- * @param block the BasicBlock to emit code for
- * @param next the following BasicBlock, `null` if `block` is the last one
- */
- def genBlock(block: BasicBlock, prev: BasicBlock, next: BasicBlock) {
-
- def loadLocalOrAddress(local: Local, msg : String , loadAddr : Boolean) {
- debuglog(msg + " for " + local)
- val isArg = local.arg
- val i = local.index
- if (isArg)
- loadArg(mcode, loadAddr)(i)
- else
- loadLocal(i, local, mcode, loadAddr)
- }
-
- def loadFieldOrAddress(field: Symbol, isStatic: Boolean, msg: String, loadAddr : Boolean) {
- debuglog(msg + " with owner: " + field.owner +
- " flags: " + Flags.flagsToString(field.owner.flags))
- var fieldInfo = fields.get(field) match {
- case Some(fInfo) => fInfo
- case None =>
- val fInfo = getType(field.owner).GetField(msilName(field))
- fields(field) = fInfo
- fInfo
- }
- if (fieldInfo.IsVolatile) {
- mcode.Emit(OpCodes.Volatile)
- }
- if (!fieldInfo.IsLiteral) {
- if (loadAddr) {
- mcode.Emit(if (isStatic) OpCodes.Ldsflda else OpCodes.Ldflda, fieldInfo)
- } else {
- mcode.Emit(if (isStatic) OpCodes.Ldsfld else OpCodes.Ldfld, fieldInfo)
- }
- } else {
- assert(!loadAddr, "can't take AddressOf a literal field (not even with readonly. prefix) because no memory was allocated to such field ...")
- // TODO the above can be overcome by loading the value, boxing, and finally unboxing. An address to a copy of the raw value will be on the stack.
- /* We perform `field inlining' as required by CLR.
- * Emit as for a CONSTANT ICode stmt, with the twist that the constant value is available
- * as a java.lang.Object and its .NET type allows constant initialization in CLR, i.e. that type
- * is one of I1, I2, I4, I8, R4, R8, CHAR, BOOLEAN, STRING, or CLASS (in this last case,
- * only accepting nullref as value). See Table 9-1 in Lidin's book on ILAsm. */
- val value = fieldInfo.getValue()
- if (value == null) {
- mcode.Emit(OpCodes.Ldnull)
- } else {
- val typ = if (fieldInfo.FieldType.IsEnum) fieldInfo.FieldType.getUnderlyingType
- else fieldInfo.FieldType
- if (typ == clrTypes.STRING) {
- mcode.Emit(OpCodes.Ldstr, value.asInstanceOf[String])
- } else if (typ == clrTypes.BOOLEAN) {
- mcode.Emit(if (value.asInstanceOf[Boolean]) OpCodes.Ldc_I4_1
- else OpCodes.Ldc_I4_0)
- } else if (typ == clrTypes.BYTE || typ == clrTypes.UBYTE) {
- loadI4(value.asInstanceOf[Byte], mcode)
- } else if (typ == clrTypes.SHORT || typ == clrTypes.USHORT) {
- loadI4(value.asInstanceOf[Int], mcode)
- } else if (typ == clrTypes.CHAR) {
- loadI4(value.asInstanceOf[Char], mcode)
- } else if (typ == clrTypes.INT || typ == clrTypes.UINT) {
- loadI4(value.asInstanceOf[Int], mcode)
- } else if (typ == clrTypes.LONG || typ == clrTypes.ULONG) {
- mcode.Emit(OpCodes.Ldc_I8, value.asInstanceOf[Long])
- } else if (typ == clrTypes.FLOAT) {
- mcode.Emit(OpCodes.Ldc_R4, value.asInstanceOf[Float])
- } else if (typ == clrTypes.DOUBLE) {
- mcode.Emit(OpCodes.Ldc_R8, value.asInstanceOf[Double])
- } else {
- /* TODO one more case is described in Partition II, 16.2: bytearray(...) */
- abort("Unknown type for static literal field: " + fieldInfo)
- }
- }
- }
- }
-
- /** Creating objects works differently on .NET. On the JVM
- * - NEW(type) => reference on Stack
- * - DUP, load arguments, CALL_METHOD(constructor)
- *
- * On .NET, the NEW and DUP are ignored, but we emit a special method call
- * - load arguments
- * - NewObj(constructor) => reference on stack
- *
- * This variable tells whether the previous instruction was a NEW,
- * we expect a DUP which is not emitted. */
- var previousWasNEW = false
-
- var lastLineNr: Int = 0
- var lastPos: Position = NoPosition
-
-
- // EndExceptionBlock must happen before MarkLabel because it adds the
- // Leave instruction. Otherwise, labels(block) points to the Leave
- // (inside the catch) instead of the instruction afterwards.
- for (handlers <- endExBlock.get(block); exh <- handlers) {
- currentHandlers.pop()
- for (l <- endFinallyLabels.get(exh))
- mcode.MarkLabel(l)
- mcode.EndExceptionBlock()
- }
-
- mcode.MarkLabel(labels(block))
- debuglog("Generating code for block: " + block)
-
- for (handler <- beginCatchBlock.get(block)) {
- if (!currentHandlers.isEmpty && currentHandlers.top.covered == handler.covered) {
- currentHandlers.pop()
- currentHandlers.push(handler)
- }
- if (handler.cls == NoSymbol) {
- // `finally` blocks are represented the same as `catch`, but with no catch-type
- mcode.BeginFinallyBlock()
- } else {
- val t = getType(handler.cls)
- mcode.BeginCatchBlock(t)
- }
- }
- for (handlers <- beginExBlock.get(block); exh <- handlers) {
- currentHandlers.push(exh)
- mcode.BeginExceptionBlock()
- }
-
- for (instr <- block) {
- try {
- val currentLineNr = instr.pos.line
- val skip = if(instr.pos.isRange) instr.pos.sameRange(lastPos) else (currentLineNr == lastLineNr);
- if(!skip || !dbFilenameSeen) {
- val fileName = if(dbFilenameSeen) "" else {dbFilenameSeen = true; ilasmFileName(clasz)};
- if(instr.pos.isRange) {
- val startLine = instr.pos.focusStart.line
- val endLine = instr.pos.focusEnd.line
- val startCol = instr.pos.focusStart.column
- val endCol = instr.pos.focusEnd.column
- mcode.setPosition(startLine, endLine, startCol, endCol, fileName)
- } else {
- mcode.setPosition(instr.pos.line, fileName)
- }
- lastLineNr = currentLineNr
- lastPos = instr.pos
- }
- } catch { case _: UnsupportedOperationException => () }
-
- if (previousWasNEW)
- assert(instr.isInstanceOf[DUP], block)
-
- instr match {
- case THIS(clasz) =>
- mcode.Emit(OpCodes.Ldarg_0)
-
- case CONSTANT(const) =>
- const.tag match {
- case UnitTag => ()
- case BooleanTag => mcode.Emit(if (const.booleanValue) OpCodes.Ldc_I4_1
- else OpCodes.Ldc_I4_0)
- case ByteTag => loadI4(const.byteValue, mcode)
- case ShortTag => loadI4(const.shortValue, mcode)
- case CharTag => loadI4(const.charValue, mcode)
- case IntTag => loadI4(const.intValue, mcode)
- case LongTag => mcode.Emit(OpCodes.Ldc_I8, const.longValue)
- case FloatTag => mcode.Emit(OpCodes.Ldc_R4, const.floatValue)
- case DoubleTag => mcode.Emit(OpCodes.Ldc_R8, const.doubleValue)
- case StringTag => mcode.Emit(OpCodes.Ldstr, const.stringValue)
- case NullTag => mcode.Emit(OpCodes.Ldnull)
- case ClassTag =>
- mcode.Emit(OpCodes.Ldtoken, msilType(const.typeValue))
- mcode.Emit(OpCodes.Call, TYPE_FROM_HANDLE)
- case _ => abort("Unknown constant value: " + const)
- }
-
- case LOAD_ARRAY_ITEM(kind) =>
- (kind: @unchecked) match {
- case BOOL => mcode.Emit(OpCodes.Ldelem_I1)
- 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)
- case LONG => mcode.Emit(OpCodes.Ldelem_I8)
- case FLOAT => mcode.Emit(OpCodes.Ldelem_R4)
- case DOUBLE => mcode.Emit(OpCodes.Ldelem_R8)
- case REFERENCE(cls) => mcode.Emit(OpCodes.Ldelem_Ref)
- case ARRAY(elem) => mcode.Emit(OpCodes.Ldelem_Ref)
-
- // case UNIT is not possible: an Array[Unit] will be an
- // Array[scala.runtime.BoxedUnit] (-> case REFERENCE)
- }
-
- case LOAD_LOCAL(local) => loadLocalOrAddress(local, "load_local", false)
-
- case CIL_LOAD_LOCAL_ADDRESS(local) => loadLocalOrAddress(local, "cil_load_local_address", true)
-
- case LOAD_FIELD(field, isStatic) => loadFieldOrAddress(field, isStatic, "load_field", false)
-
- case CIL_LOAD_FIELD_ADDRESS(field, isStatic) => loadFieldOrAddress(field, isStatic, "cil_load_field_address", true)
-
- case CIL_LOAD_ARRAY_ITEM_ADDRESS(kind) => mcode.Emit(OpCodes.Ldelema, msilType(kind))
-
- case CIL_NEWOBJ(msym) =>
- assert(msym.isClassConstructor)
- val constructorInfo: ConstructorInfo = getConstructor(msym)
- mcode.Emit(OpCodes.Newobj, constructorInfo)
-
- case LOAD_MODULE(module) =>
- debuglog("Generating LOAD_MODULE for: " + showsym(module))
- mcode.Emit(OpCodes.Ldsfld, getModuleInstanceField(module))
-
- case STORE_ARRAY_ITEM(kind) =>
- (kind: @unchecked) match {
- case BOOL => mcode.Emit(OpCodes.Stelem_I1)
- case BYTE => mcode.Emit(OpCodes.Stelem_I1)
- case SHORT => mcode.Emit(OpCodes.Stelem_I2)
- case CHAR => mcode.Emit(OpCodes.Stelem_I2)
- case INT => mcode.Emit(OpCodes.Stelem_I4)
- case LONG => mcode.Emit(OpCodes.Stelem_I8)
- case FLOAT => mcode.Emit(OpCodes.Stelem_R4)
- case DOUBLE => mcode.Emit(OpCodes.Stelem_R8)
- case REFERENCE(cls) => mcode.Emit(OpCodes.Stelem_Ref)
- case ARRAY(elem) => mcode.Emit(OpCodes.Stelem_Ref) // @TODO: test this! (occurs when calling a Array[Object]* vararg param method)
-
- // case UNIT not possible (see comment at LOAD_ARRAY_ITEM)
- }
-
- case STORE_LOCAL(local) =>
- val isArg = local.arg
- val i = local.index
- debuglog("store_local for " + local + ", index " + i)
-
- // there are some locals defined by the compiler that
- // are isArg and are need to be stored.
- if (isArg) {
- if (i >= -128 && i <= 127)
- mcode.Emit(OpCodes.Starg_S, i)
- else
- mcode.Emit(OpCodes.Starg, i)
- } else {
- i match {
- case 0 => mcode.Emit(OpCodes.Stloc_0)
- case 1 => mcode.Emit(OpCodes.Stloc_1)
- case 2 => mcode.Emit(OpCodes.Stloc_2)
- case 3 => mcode.Emit(OpCodes.Stloc_3)
- case _ =>
- if (i >= -128 && i <= 127)
- mcode.Emit(OpCodes.Stloc_S, localBuilders(local))
- else
- mcode.Emit(OpCodes.Stloc, localBuilders(local))
- }
- }
-
- case STORE_THIS(_) =>
- // this only works for impl classes because the self parameter comes first
- // in the method signature. If that changes, this code has to be revisited.
- mcode.Emit(OpCodes.Starg_S, 0)
-
- case STORE_FIELD(field, isStatic) =>
- val fieldInfo = fields.get(field) match {
- case Some(fInfo) => fInfo
- case None =>
- val fInfo = getType(field.owner).GetField(msilName(field))
- fields(field) = fInfo
- fInfo
- }
- mcode.Emit(if (isStatic) OpCodes.Stsfld else OpCodes.Stfld, fieldInfo)
-
- case CALL_PRIMITIVE(primitive) =>
- genPrimitive(primitive, instr.pos)
-
- case CALL_METHOD(msym, style) =>
- if (msym.isClassConstructor) {
- val constructorInfo: ConstructorInfo = getConstructor(msym)
- (style: @unchecked) match {
- // normal constructor calls are Static..
- case Static(_) =>
- if (method.symbol.isClassConstructor && method.symbol.owner == msym.owner)
- // we're generating a constructor (method: IMethod is a constructor), and we're
- // calling another constructor of the same class.
-
- // @LUC TODO: this can probably break, namely when having: class A { def this() { new A() } }
- // instead, we should instruct the CALL_METHOD with additional information, know whether it's
- // an instance creation constructor call or not.
- mcode.Emit(OpCodes.Call, constructorInfo)
- else
- mcode.Emit(OpCodes.Newobj, constructorInfo)
- case SuperCall(_) =>
- mcode.Emit(OpCodes.Call, constructorInfo)
- if (isStaticModule(clasz.symbol) &&
- notInitializedModules.contains(clasz.symbol) &&
- method.symbol.isClassConstructor)
- {
- notInitializedModules -= clasz.symbol
- mcode.Emit(OpCodes.Ldarg_0)
- mcode.Emit(OpCodes.Stsfld, getModuleInstanceField(clasz.symbol))
- }
- }
-
- } else {
-
- var doEmit = true
- getTypeOpt(msym.owner) match {
- case Some(typ) if (typ.IsEnum) => {
- def negBool() = {
- mcode.Emit(OpCodes.Ldc_I4_0)
- mcode.Emit(OpCodes.Ceq)
- }
- doEmit = false
- val name = msym.name
- if (name eq nme.EQ) { mcode.Emit(OpCodes.Ceq) }
- else if (name eq nme.NE) { mcode.Emit(OpCodes.Ceq); negBool }
- else if (name eq nme.LT) { mcode.Emit(OpCodes.Clt) }
- else if (name eq nme.LE) { mcode.Emit(OpCodes.Cgt); negBool }
- else if (name eq nme.GT) { mcode.Emit(OpCodes.Cgt) }
- else if (name eq nme.GE) { mcode.Emit(OpCodes.Clt); negBool }
- else if (name eq nme.OR) { mcode.Emit(OpCodes.Or) }
- else if (name eq nme.AND) { mcode.Emit(OpCodes.And) }
- else if (name eq nme.XOR) { mcode.Emit(OpCodes.Xor) }
- else
- doEmit = true
- }
- case _ => ()
- }
-
- // method: implicit view(FunctionX[PType0, PType1, ...,PTypeN, ResType]):DelegateType
- val (isDelegateView, paramType, resType) = atPhase(currentRun.typerPhase) {
- msym.tpe match {
- case MethodType(params, resultType)
- if (params.length == 1 && msym.name == nme.view_) =>
- val paramType = params(0).tpe
- val isDel = definitions.isCorrespondingDelegate(resultType, paramType)
- (isDel, paramType, resultType)
- case _ => (false, null, null)
- }
- }
- if (doEmit && isDelegateView) {
- doEmit = false
- createDelegateCaller(paramType, resType)
- }
-
- if (doEmit &&
- (msym.name == nme.PLUS || msym.name == nme.MINUS)
- && clrTypes.isDelegateType(msilType(msym.owner.tpe)))
- {
- doEmit = false
- val methodInfo: MethodInfo = getMethod(msym)
- // call it as a static method, even if the compiler (symbol) thinks it's virtual
- mcode.Emit(OpCodes.Call, methodInfo)
- mcode.Emit(OpCodes.Castclass, msilType(msym.owner.tpe))
- }
-
- if (doEmit && definitions.Delegate_scalaCallers.contains(msym)) {
- doEmit = false
- val methodSym: Symbol = definitions.Delegate_scalaCallerTargets(msym)
- val delegateType: Type = msym.tpe match {
- case MethodType(_, retType) => retType
- case _ => abort("not a method type: " + msym.tpe)
- }
- val methodInfo: MethodInfo = getMethod(methodSym)
- val delegCtor = msilType(delegateType).GetConstructor(Array(MOBJECT, INT_PTR))
- if (methodSym.isStatic) {
- mcode.Emit(OpCodes.Ldftn, methodInfo)
- } else {
- mcode.Emit(OpCodes.Dup)
- mcode.Emit(OpCodes.Ldvirtftn, methodInfo)
- }
- mcode.Emit(OpCodes.Newobj, delegCtor)
- }
-
- if (doEmit) {
- val methodInfo: MethodInfo = getMethod(msym)
- (style: @unchecked) match {
- case SuperCall(_) =>
- mcode.Emit(OpCodes.Call, methodInfo)
- case Dynamic =>
- // methodInfo.DeclaringType is null for global methods
- val isValuetypeMethod = (methodInfo.DeclaringType ne null) && (methodInfo.DeclaringType.IsValueType)
- val isValuetypeVirtualMethod = isValuetypeMethod && (methodInfo.IsVirtual)
- if (dynToStatMapped(msym)) {
- mcode.Emit(OpCodes.Call, methodInfo)
- } else if (isValuetypeVirtualMethod) {
- mcode.Emit(OpCodes.Constrained, methodInfo.DeclaringType)
- mcode.Emit(OpCodes.Callvirt, methodInfo)
- } else if (isValuetypeMethod) {
- // otherwise error "Callvirt on a value type method" ensues
- mcode.Emit(OpCodes.Call, methodInfo)
- } else {
- mcode.Emit(OpCodes.Callvirt, methodInfo)
- }
- case Static(_) =>
- if(methodInfo.IsVirtual && !mcode.Ldarg0WasJustEmitted) {
- mcode.Emit(OpCodes.Callvirt, methodInfo)
- } else mcode.Emit(OpCodes.Call, methodInfo)
- }
- }
- }
-
- case BOX(boxType) =>
- emitBox(mcode, boxType)
-
- case UNBOX(boxType) =>
- emitUnbox(mcode, boxType)
-
- case CIL_UNBOX(boxType) =>
- mcode.Emit(OpCodes.Unbox, msilType(boxType))
-
- case CIL_INITOBJ(valueType) =>
- mcode.Emit(OpCodes.Initobj, msilType(valueType))
-
- case NEW(REFERENCE(cls)) =>
- // the next instruction must be a DUP, see comment on `var previousWasNEW`
- previousWasNEW = true
-
- // works also for arrays and reference-types
- case CREATE_ARRAY(elem, dims) =>
- // TODO: handle multi dimensional arrays
- assert(dims == 1, "Can't handle multi dimensional arrays")
- mcode.Emit(OpCodes.Newarr, msilType(elem))
-
- // works for arrays and reference-types
- case IS_INSTANCE(tpe) =>
- mcode.Emit(OpCodes.Isinst, msilType(tpe))
- mcode.Emit(OpCodes.Ldnull)
- mcode.Emit(OpCodes.Ceq)
- mcode.Emit(OpCodes.Ldc_I4_0)
- mcode.Emit(OpCodes.Ceq)
-
- // works for arrays and reference-types
- // part from the scala reference: "S <: T does not imply
- // Array[S] <: Array[T] in Scala. However, it is possible
- // to cast an array of S to an array of T if such a cast
- // is permitted in the host environment."
- case CHECK_CAST(tpknd) =>
- val tMSIL = msilType(tpknd)
- mcode.Emit(OpCodes.Castclass, tMSIL)
-
- // no SWITCH is generated when there's
- // - a default case ("case _ => ...") in the matching expr
- // - OR is used ("case 1 | 2 => ...")
- case SWITCH(tags, branches) =>
- // tags is List[List[Int]]; a list of integers for every label.
- // if the int on stack is 4, and 4 is in the second list => jump
- // to second label
- // branches is List[BasicBlock]
- // the labels to jump to (the last one is the default one)
-
- val switchLocal = mcode.DeclareLocal(MINT)
- // several switch variables will appear with the same name in the
- // assembly code, but this makes no truble
- switchLocal.SetLocalSymInfo("$switch_var")
-
- mcode.Emit(OpCodes.Stloc, switchLocal)
- var i = 0
- for (l <- tags) {
- var targetLabel = labels(branches(i))
- for (i <- l) {
- mcode.Emit(OpCodes.Ldloc, switchLocal)
- loadI4(i, mcode)
- mcode.Emit(OpCodes.Beq, targetLabel)
- }
- i += 1
- }
- val defaultTarget = labels(branches(i))
- if (next != branches(i))
- mcode.Emit(OpCodes.Br, defaultTarget)
-
- case JUMP(whereto) =>
- val (leaveHandler, leaveFinally, lfTarget) = leavesHandler(block, whereto)
- if (leaveHandler) {
- if (leaveFinally) {
- if (lfTarget.isDefined) mcode.Emit(OpCodes.Leave, lfTarget.get)
- else mcode.Emit(OpCodes.Endfinally)
- } else
- mcode.Emit(OpCodes.Leave, labels(whereto))
- } else if (next != whereto)
- mcode.Emit(OpCodes.Br, labels(whereto))
-
- case CJUMP(success, failure, cond, kind) =>
- // cond is TestOp (see Primitives.scala), and can take
- // values EQ, NE, LT, GE LE, GT
- // kind is TypeKind
- val isFloat = kind == FLOAT || kind == DOUBLE
- val emit = (c: TestOp, l: Label) => emitBr(c, l, isFloat)
- emitCondBr(block, cond, success, failure, next, emit)
-
- case CZJUMP(success, failure, cond, kind) =>
- emitCondBr(block, cond, success, failure, next, emitBrBool(_, _))
-
- case RETURN(kind) =>
- if (currentHandlers.isEmpty)
- mcode.Emit(OpCodes.Ret)
- else {
- val (local, label) = returnFromHandler(kind)
- if (kind != UNIT)
- mcode.Emit(OpCodes.Stloc, local)
- mcode.Emit(OpCodes.Leave, label)
- }
-
- case THROW(_) =>
- mcode.Emit(OpCodes.Throw)
-
- case DROP(kind) =>
- mcode.Emit(OpCodes.Pop)
-
- case DUP(kind) =>
- // see comment on `var previousWasNEW`
- if (!previousWasNEW)
- mcode.Emit(OpCodes.Dup)
- else
- previousWasNEW = false
-
- case MONITOR_ENTER() =>
- mcode.Emit(OpCodes.Call, MMONITOR_ENTER)
-
- case MONITOR_EXIT() =>
- mcode.Emit(OpCodes.Call, MMONITOR_EXIT)
-
- case SCOPE_ENTER(_) | SCOPE_EXIT(_) | LOAD_EXCEPTION(_) =>
- ()
- }
-
- } // end for (instr <- b) { .. }
- } // end genBlock
-
- def genPrimitive(primitive: Primitive, pos: Position) {
- primitive match {
- case Negation(kind) =>
- kind match {
- // CHECK: is ist possible to get this for BOOL? in this case, verify.
- case BOOL | BYTE | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE =>
- mcode.Emit(OpCodes.Neg)
-
- case _ => abort("Impossible to negate a " + kind)
- }
-
- case Arithmetic(op, kind) =>
- op match {
- case ADD => mcode.Emit(OpCodes.Add)
- case SUB => mcode.Emit(OpCodes.Sub)
- case MUL => mcode.Emit(OpCodes.Mul)
- case DIV => mcode.Emit(OpCodes.Div)
- case REM => mcode.Emit(OpCodes.Rem)
- case NOT => mcode.Emit(OpCodes.Not) //bitwise complement (one's complement)
- case _ => abort("Unknown arithmetic primitive " + primitive )
- }
-
- case Logical(op, kind) => op match {
- case AND => mcode.Emit(OpCodes.And)
- case OR => mcode.Emit(OpCodes.Or)
- case XOR => mcode.Emit(OpCodes.Xor)
- }
-
- case Shift(op, kind) => op match {
- case LSL => mcode.Emit(OpCodes.Shl)
- case ASR => mcode.Emit(OpCodes.Shr)
- case LSR => mcode.Emit(OpCodes.Shr_Un)
- }
-
- case Conversion(src, dst) =>
- debuglog("Converting from: " + src + " to: " + dst)
-
- dst match {
- 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)
- case LONG => mcode.Emit(OpCodes.Conv_I8)
- case FLOAT => mcode.Emit(OpCodes.Conv_R4)
- case DOUBLE => mcode.Emit(OpCodes.Conv_R8)
- case _ =>
- Console.println("Illegal conversion at: " + clasz +
- " at: " + pos.source + ":" + pos.line)
- }
-
- case ArrayLength(_) =>
- mcode.Emit(OpCodes.Ldlen)
-
- case StartConcat =>
- mcode.Emit(OpCodes.Newobj, MSTRING_BUILDER_CONSTR)
-
-
- case StringConcat(el) =>
- val elemType : MsilType = el match {
- case REFERENCE(_) | ARRAY(_) => MOBJECT
- case _ => msilType(el)
- }
-
- val argTypes:Array[MsilType] = Array(elemType)
- val stringBuilderAppend = MSTRING_BUILDER.GetMethod("Append", argTypes )
- mcode.Emit(OpCodes.Callvirt, stringBuilderAppend)
-
- case EndConcat =>
- mcode.Emit(OpCodes.Callvirt, MSTRING_BUILDER_TOSTRING)
-
- case _ =>
- abort("Unimplemented primitive " + primitive)
- }
- } // end genPrimitive
-
-
- ////////////////////// loading ///////////////////////
-
- def loadI4(value: Int, code: ILGenerator): Unit = value match {
- case -1 => code.Emit(OpCodes.Ldc_I4_M1)
- case 0 => code.Emit(OpCodes.Ldc_I4_0)
- case 1 => code.Emit(OpCodes.Ldc_I4_1)
- case 2 => code.Emit(OpCodes.Ldc_I4_2)
- case 3 => code.Emit(OpCodes.Ldc_I4_3)
- case 4 => code.Emit(OpCodes.Ldc_I4_4)
- case 5 => code.Emit(OpCodes.Ldc_I4_5)
- case 6 => code.Emit(OpCodes.Ldc_I4_6)
- case 7 => code.Emit(OpCodes.Ldc_I4_7)
- case 8 => code.Emit(OpCodes.Ldc_I4_8)
- case _ =>
- if (value >= -128 && value <= 127)
- code.Emit(OpCodes.Ldc_I4_S, value)
- else
- code.Emit(OpCodes.Ldc_I4, value)
- }
-
- def loadArg(code: ILGenerator, loadAddr: Boolean)(i: Int) =
- if (loadAddr) {
- if (i >= -128 && i <= 127)
- code.Emit(OpCodes.Ldarga_S, i)
- else
- code.Emit(OpCodes.Ldarga, i)
- } else {
- i match {
- case 0 => code.Emit(OpCodes.Ldarg_0)
- case 1 => code.Emit(OpCodes.Ldarg_1)
- case 2 => code.Emit(OpCodes.Ldarg_2)
- case 3 => code.Emit(OpCodes.Ldarg_3)
- case _ =>
- if (i >= -128 && i <= 127)
- code.Emit(OpCodes.Ldarg_S, i)
- else
- code.Emit(OpCodes.Ldarg, i)
- }
- }
-
- def loadLocal(i: Int, local: Local, code: ILGenerator, loadAddr: Boolean) =
- if (loadAddr) {
- if (i >= -128 && i <= 127)
- code.Emit(OpCodes.Ldloca_S, localBuilders(local))
- else
- code.Emit(OpCodes.Ldloca, localBuilders(local))
- } else {
- i match {
- case 0 => code.Emit(OpCodes.Ldloc_0)
- case 1 => code.Emit(OpCodes.Ldloc_1)
- case 2 => code.Emit(OpCodes.Ldloc_2)
- case 3 => code.Emit(OpCodes.Ldloc_3)
- case _ =>
- if (i >= -128 && i <= 127)
- code.Emit(OpCodes.Ldloc_S, localBuilders(local))
- else
- code.Emit(OpCodes.Ldloc, localBuilders(local))
- }
- }
-
- ////////////////////// branches ///////////////////////
-
- /** Returns a Triple (Boolean, Boolean, Option[Label])
- * - whether the jump leaves some exception block (try / catch / finally)
- * - whether it leaves a finally handler (finally block, but not it's try / catch)
- * - a label where to jump for leaving the finally handler
- * . None to leave directly using `endfinally`
- * . Some(label) to emit `leave label` (for try / catch inside a finally handler)
- */
- def leavesHandler(from: BasicBlock, to: BasicBlock): (Boolean, Boolean, Option[Label]) =
- if (currentHandlers.isEmpty) (false, false, None)
- else {
- val h = currentHandlers.head
- val leaveHead = { h.covers(from) != h.covers(to) ||
- h.blocks.contains(from) != h.blocks.contains(to) }
- if (leaveHead) {
- // we leave the innermost exception block.
- // find out if we also leave som e `finally` handler
- currentHandlers.find(e => {
- e.cls == NoSymbol && e.blocks.contains(from) != e.blocks.contains(to)
- }) match {
- case Some(finallyHandler) =>
- if (h == finallyHandler) {
- // the finally handler is the innermost, so we can emit `endfinally` directly
- (true, true, None)
- } else {
- // we need to `Leave` to the `endfinally` of the next outer finally handler
- val l = endFinallyLabels.getOrElseUpdate(finallyHandler, mcode.DefineLabel())
- (true, true, Some(l))
- }
- case None =>
- (true, false, None)
- }
- } else (false, false, None)
- }
-
- def emitCondBr(block: BasicBlock, cond: TestOp, success: BasicBlock, failure: BasicBlock,
- next: BasicBlock, emitBrFun: (TestOp, Label) => Unit) {
- val (sLeaveHandler, sLeaveFinally, slfTarget) = leavesHandler(block, success)
- val (fLeaveHandler, fLeaveFinally, flfTarget) = leavesHandler(block, failure)
-
- if (sLeaveHandler || fLeaveHandler) {
- val sLabelOpt = if (sLeaveHandler) {
- val leaveSLabel = mcode.DefineLabel()
- emitBrFun(cond, leaveSLabel)
- Some(leaveSLabel)
- } else {
- emitBrFun(cond, labels(success))
- None
- }
-
- if (fLeaveHandler) {
- if (fLeaveFinally) {
- if (flfTarget.isDefined) mcode.Emit(OpCodes.Leave, flfTarget.get)
- else mcode.Emit(OpCodes.Endfinally)
- } else
- mcode.Emit(OpCodes.Leave, labels(failure))
- } else
- mcode.Emit(OpCodes.Br, labels(failure))
-
- sLabelOpt.map(l => {
- mcode.MarkLabel(l)
- if (sLeaveFinally) {
- if (slfTarget.isDefined) mcode.Emit(OpCodes.Leave, slfTarget.get)
- else mcode.Emit(OpCodes.Endfinally)
- } else
- mcode.Emit(OpCodes.Leave, labels(success))
- })
- } else {
- if (next == success) {
- emitBrFun(cond.negate, labels(failure))
- } else {
- emitBrFun(cond, labels(success))
- if (next != failure) {
- mcode.Emit(OpCodes.Br, labels(failure))
- }
- }
- }
- }
-
- def emitBr(condition: TestOp, dest: Label, isFloat: Boolean) {
- condition match {
- case EQ => mcode.Emit(OpCodes.Beq, dest)
- case NE => mcode.Emit(OpCodes.Bne_Un, dest)
- case LT => mcode.Emit(if (isFloat) OpCodes.Blt_Un else OpCodes.Blt, dest)
- case GE => mcode.Emit(if (isFloat) OpCodes.Bge_Un else OpCodes.Bge, dest)
- case LE => mcode.Emit(if (isFloat) OpCodes.Ble_Un else OpCodes.Ble, dest)
- case GT => mcode.Emit(if (isFloat) OpCodes.Bgt_Un else OpCodes.Bgt, dest)
- }
- }
-
- def emitBrBool(cond: TestOp, dest: Label) {
- cond match {
- // EQ -> Brfalse, NE -> Brtrue; this is because we come from
- // a CZJUMP. If the value on the stack is 0 (e.g. a boolean
- // method returned false), and we are in the case EQ, then
- // we need to emit Brfalse (EQ Zero means false). vice versa
- case EQ => mcode.Emit(OpCodes.Brfalse, dest)
- case NE => mcode.Emit(OpCodes.Brtrue, dest)
- }
- }
-
- ////////////////////// local vars ///////////////////////
-
- /**
- * Compute the indexes of each local variable of the given
- * method.
- */
- def computeLocalVarsIndex(m: IMethod) {
- var idx = if (m.symbol.isStaticMember) 0 else 1
-
- val params = m.params
- for (l <- params) {
- debuglog("Index value for parameter " + l + ": " + idx)
- l.index = idx
- idx += 1 // sizeOf(l.kind)
- }
-
- val locvars = m.locals filterNot (params contains)
- idx = 0
-
- for (l <- locvars) {
- debuglog("Index value for local variable " + l + ": " + idx)
- l.index = idx
- idx += 1 // sizeOf(l.kind)
- }
-
- }
-
- ////////////////////// Utilities ////////////////////////
-
- /** Return the a name of this symbol that can be used on the .NET
- * platform. It removes spaces from names.
- *
- * Special handling: scala.All and scala.AllRef are 'erased' to
- * scala.All$ and scala.AllRef$. This is needed because they are
- * not real classes, and they mean 'abrupt termination upon evaluation
- * of that expression' or 'null' respectively. This handling is
- * done already in GenICode, but here we need to remove references
- * from method signatures to these types, because such classes can
- * not exist in the classpath: the type checker will be very confused.
- */
- def msilName(sym: Symbol): String = {
- val suffix = sym.moduleSuffix
- // Flags.JAVA: "symbol was not defined by a scala-class" (java, or .net-class)
-
- if (sym == definitions.NothingClass)
- return "scala.runtime.Nothing$"
- else if (sym == definitions.NullClass)
- return "scala.runtime.Null$"
-
- (if (sym.isClass || (sym.isModule && !sym.isMethod)) {
- if (sym.isNestedClass) sym.simpleName
- else sym.fullName
- } else
- sym.simpleName.toString.trim()) + suffix
- }
-
-
- ////////////////////// flags ///////////////////////
-
- def msilTypeFlags(sym: Symbol): Int = {
- var mf: Int = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass
-
- if(sym.isNestedClass) {
- mf = mf | (if (sym hasFlag Flags.PRIVATE) TypeAttributes.NestedPrivate else TypeAttributes.NestedPublic)
- } else {
- mf = mf | (if (sym hasFlag Flags.PRIVATE) TypeAttributes.NotPublic else TypeAttributes.Public)
- }
- mf = mf | (if (sym hasFlag Flags.ABSTRACT) TypeAttributes.Abstract else 0)
- mf = mf | (if (sym.isTrait && !sym.isImplClass) TypeAttributes.Interface else TypeAttributes.Class)
- mf = mf | (if (sym isFinal) TypeAttributes.Sealed else 0)
-
- sym.annotations foreach { a => a match {
- case AnnotationInfo(SerializableAttr, _, _) =>
- // TODO: add the Serializable TypeAttribute also if the annotation
- // System.SerializableAttribute is present (.net annotation, not scala)
- // Best way to do it: compare with
- // definitions.getClass("System.SerializableAttribute").tpe
- // when frontend available
- mf = mf | TypeAttributes.Serializable
- case _ => ()
- }}
-
- mf
- // static: not possible (or?)
- }
-
- def msilMethodFlags(sym: Symbol): Short = {
- var mf: Int = MethodAttributes.HideBySig |
- (if (sym hasFlag Flags.PRIVATE) MethodAttributes.Private
- else MethodAttributes.Public)
-
- if (!sym.isClassConstructor) {
- if (sym.isStaticMember)
- mf = mf | FieldAttributes.Static // coincidentally, same value as for MethodAttributes.Static ...
- else {
- mf = mf | MethodAttributes.Virtual
- if (sym.isFinal && !getType(sym.owner).IsInterface)
- mf = mf | MethodAttributes.Final
- if (sym.isDeferred || getType(sym.owner).IsInterface)
- mf = mf | MethodAttributes.Abstract
- }
- }
-
- if (sym.isStaticMember) {
- mf = mf | MethodAttributes.Static
- }
-
- // constructors of module classes should be private
- if (sym.isPrimaryConstructor && isTopLevelModule(sym.owner)) {
- mf |= MethodAttributes.Private
- mf &= ~(MethodAttributes.Public)
- }
-
- mf.toShort
- }
-
- def msilFieldFlags(sym: Symbol): Short = {
- var mf: Int =
- if (sym hasFlag Flags.PRIVATE) FieldAttributes.Private
- else if (sym hasFlag Flags.PROTECTED) FieldAttributes.FamORAssem
- else FieldAttributes.Public
-
- if (sym hasFlag Flags.FINAL)
- mf = mf | FieldAttributes.InitOnly
-
- if (sym.isStaticMember)
- mf = mf | FieldAttributes.Static
-
- // TRANSIENT: "not serialized", VOLATILE: doesn't exist on .net
- // TODO: add this annotation also if the class has the custom attribute
- // System.NotSerializedAttribute
- sym.annotations.foreach( a => a match {
- case AnnotationInfo(TransientAtt, _, _) =>
- mf = mf | FieldAttributes.NotSerialized
- case _ => ()
- })
-
- mf.toShort
- }
-
- ////////////////////// builders, types ///////////////////////
-
- var entryPoint: Symbol = _
-
- val notInitializedModules = mutable.HashSet[Symbol]()
-
- // TODO: create fields also in def createType, and not in genClass,
- // add a getField method (it only works as it is because fields never
- // accessed from outside a class)
-
- val localBuilders = mutable.HashMap[Local, LocalBuilder]()
-
- private[GenMSIL] def findEntryPoint(cls: IClass) {
-
- def isEntryPoint(sym: Symbol):Boolean = {
- if (isStaticModule(sym.owner) && msilName(sym) == "main")
- if (sym.tpe.paramTypes.length == 1) {
- toTypeKind(sym.tpe.paramTypes(0)) match {
- case ARRAY(elem) =>
- if (elem.toType.typeSymbol == definitions.StringClass) {
- return true
- }
- case _ => ()
- }
- }
- false
- }
-
- 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
- }
-
- // #####################################################################
- // get and create types
-
- private def msilType(t: TypeKind): MsilType = (t: @unchecked) match {
- case UNIT => MVOID
- case BOOL => MBOOL
- case BYTE => MBYTE
- case SHORT => MSHORT
- case CHAR => MCHAR
- case INT => MINT
- case LONG => MLONG
- case FLOAT => MFLOAT
- case DOUBLE => MDOUBLE
- case REFERENCE(cls) => getType(cls)
- case ARRAY(elem) =>
- msilType(elem) match {
- // For type builders, cannot call "clrTypes.mkArrayType" because this looks up
- // the type "tp" in the assembly (not in the HashMap "types" of the backend).
- // This can fail for nested types because the builders are not complete yet.
- case tb: TypeBuilder => tb.MakeArrayType()
- case tp: MsilType => clrTypes.mkArrayType(tp)
- }
- }
-
- private def msilType(tpe: Type): MsilType = msilType(toTypeKind(tpe))
-
- private def msilParamTypes(sym: Symbol): Array[MsilType] = {
- sym.tpe.paramTypes.map(msilType).toArray
- }
-
- def getType(sym: Symbol) = getTypeOpt(sym).getOrElse(abort(showsym(sym)))
-
- /**
- * 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] = {
- 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) {
- assert(mType != null, showsym(sym))
- types(sym) = mType
- }
-
- def createTypeBuilder(iclass: IClass) {
- /**
- * First look in the clrTypes.types map, if that fails check if it's a class being compiled, otherwise
- * lookup by name (clrTypes.getType calls the static method msil.Type.GetType(fullname)).
- */
- def msilTypeFromSym(sym: Symbol): MsilType = {
- types.get(sym).getOrElse {
- classes.get(sym) match {
- case Some(iclass) =>
- msilTypeBuilderFromSym(sym)
- case None =>
- getType(sym)
- }
- }
- }
-
- def msilTypeBuilderFromSym(sym: Symbol): TypeBuilder = {
- if(!(types.contains(sym) && types(sym).isInstanceOf[TypeBuilder])){
- val iclass = classes(sym)
- assert(iclass != null)
- createTypeBuilder(iclass)
- }
- types(sym).asInstanceOf[TypeBuilder]
- }
-
- val sym = iclass.symbol
- if (types.contains(sym) && types(sym).isInstanceOf[TypeBuilder])
- return
-
- def isInterface(s: Symbol) = s.isTrait && !s.isImplClass
- val parents: List[Type] =
- if (sym.info.parents.isEmpty) List(definitions.ObjectClass.tpe)
- else sym.info.parents.distinct
-
- val superType : MsilType = if (isInterface(sym)) null else msilTypeFromSym(parents.head.typeSymbol)
- debuglog("super type: " + parents(0).typeSymbol + ", msil type: " + superType)
-
- val interfaces: Array[MsilType] =
- parents.tail.map(p => msilTypeFromSym(p.typeSymbol)).toArray
- if (parents.length > 1) {
- if (settings.debug.value) {
- log("interfaces:")
- for (i <- 0.until(interfaces.length)) {
- log(" type: " + parents(i + 1).typeSymbol + ", msil type: " + interfaces(i))
- }
- }
- }
-
- val tBuilder = if (sym.isNestedClass) {
- val ownerT = msilTypeBuilderFromSym(sym.owner).asInstanceOf[TypeBuilder]
- ownerT.DefineNestedType(msilName(sym), msilTypeFlags(sym), superType, interfaces)
- } else {
- mmodule.DefineType(msilName(sym), msilTypeFlags(sym), superType, interfaces)
- }
- mapType(sym, tBuilder)
- } // createTypeBuilder
-
- def createClassMembers(iclass: IClass) {
- try {
- createClassMembers0(iclass)
- }
- catch {
- case e: Throwable =>
- java.lang.System.err.println(showsym(iclass.symbol))
- java.lang.System.err.println("with methods = " + iclass.methods)
- throw e
- }
- }
-
- def createClassMembers0(iclass: IClass) {
-
- val mtype = getType(iclass.symbol).asInstanceOf[TypeBuilder]
-
- for (ifield <- iclass.fields) {
- val sym = ifield.symbol
- debuglog("Adding field: " + sym.fullName)
-
- var attributes = msilFieldFlags(sym)
- val fieldTypeWithCustomMods =
- new PECustomMod(msilType(sym.tpe),
- customModifiers(sym.annotations))
- val fBuilder = mtype.DefineField(msilName(sym),
- fieldTypeWithCustomMods,
- attributes)
- fields(sym) = fBuilder
- addAttributes(fBuilder, sym.annotations)
- } // all iclass.fields iterated over
-
- if (isStaticModule(iclass.symbol)) {
- val sc = iclass.lookupStaticCtor
- if (sc.isDefined) {
- val m = sc.get
- val oldLastBlock = m.lastBlock
- val lastBlock = m.newBlock()
- oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock))
- // call object's private ctor from static ctor
- lastBlock.emit(CIL_NEWOBJ(iclass.symbol.primaryConstructor))
- lastBlock.emit(DROP(toTypeKind(iclass.symbol.tpe)))
- lastBlock emit RETURN(UNIT)
- lastBlock.close
- }
- }
-
- if (iclass.symbol != definitions.ArrayClass) {
- for (m: IMethod <- iclass.methods) {
- val sym = m.symbol
- debuglog("Creating MethodBuilder for " + Flags.flagsToString(sym.flags) + " " +
- sym.owner.fullName + "::" + sym.name)
-
- val ownerType = getType(sym.enclClass).asInstanceOf[TypeBuilder]
- assert(mtype == ownerType, "mtype = " + mtype + "; ownerType = " + ownerType)
- var paramTypes = msilParamTypes(sym)
- val attr = msilMethodFlags(sym)
-
- if (m.symbol.isClassConstructor) {
- val constr =
- ownerType.DefineConstructor(attr, CallingConventions.Standard, paramTypes)
- for (i <- 0.until(paramTypes.length)) {
- constr.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
- }
- mapConstructor(sym, constr)
- addAttributes(constr, sym.annotations)
- } else {
- var resType = msilType(m.returnType)
- val method =
- ownerType.DefineMethod(msilName(sym), attr, resType, paramTypes)
- for (i <- 0.until(paramTypes.length)) {
- method.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
- }
- if (!methods.contains(sym))
- mapMethod(sym, method)
- addAttributes(method, sym.annotations)
- debuglog("\t created MethodBuilder " + method)
- }
- }
- } // method builders created for non-array iclass
-
- if (isStaticModule(iclass.symbol)) {
- addModuleInstanceField(iclass.symbol)
- notInitializedModules += iclass.symbol
- if (iclass.lookupStaticCtor.isEmpty) {
- addStaticInit(iclass.symbol)
- }
- }
-
- } // createClassMembers0
-
- private def isTopLevelModule(sym: Symbol): Boolean =
- atPhase (currentRun.refchecksPhase) {
- sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass
- }
-
- // if the module is lifted it does not need to be initialized in
- // its static constructor, and the MODULE$ field is not required.
- // the outer class will care about it.
- private def isStaticModule(sym: Symbol): Boolean = {
- // .net inner classes: removed '!sym.hasFlag(Flags.LIFTED)', added
- // 'sym.isStatic'. -> no longer compatible without skipping flatten!
- sym.isModuleClass && sym.isStatic && !sym.isImplClass
- }
-
- private def isCloneable(sym: Symbol): Boolean = {
- !sym.annotations.forall( a => a match {
- case AnnotationInfo(CloneableAttr, _, _) => false
- case _ => true
- })
- }
-
- private def addModuleInstanceField(sym: Symbol) {
- debuglog("Adding Module-Instance Field for " + showsym(sym))
- val tBuilder = getType(sym).asInstanceOf[TypeBuilder]
- val fb = tBuilder.DefineField(MODULE_INSTANCE_NAME,
- tBuilder,
- (FieldAttributes.Public |
- //FieldAttributes.InitOnly |
- FieldAttributes.Static).toShort)
- fields(sym) = fb
- }
-
-
- // the symbol may be a object-symbol (module-symbol), or a module-class-symbol
- private def getModuleInstanceField(sym: Symbol): FieldInfo = {
- assert(sym.isModule || sym.isModuleClass, "Expected module: " + showsym(sym))
-
- // when called by LOAD_MODULE, the corresponding type maybe doesn't
- // exist yet -> make a getType
- val moduleClassSym = if (sym.isModule) sym.moduleClass else sym
-
- // TODO: get module field for modules not defined in the
- // source currently compiling (e.g. Console)
-
- fields get moduleClassSym match {
- case Some(sym) => sym
- case None =>
- //val mclass = types(moduleClassSym)
- val nameInMetadata = nestingAwareFullClassname(moduleClassSym)
- val mClass = clrTypes.getType(nameInMetadata)
- val mfield = mClass.GetField("MODULE$")
- assert(mfield ne null, "module not found " + showsym(moduleClassSym))
- fields(moduleClassSym) = mfield
- mfield
- }
-
- //fields(moduleClassSym)
- }
-
- def nestingAwareFullClassname(csym: Symbol) : String = {
- val suffix = csym.moduleSuffix
- val res = if (csym.isNestedClass)
- nestingAwareFullClassname(csym.owner) + "+" + csym.encodedName
- else
- csym.fullName
- res + suffix
- }
-
- /** Adds a static initializer which creates an instance of the module
- * class (calls the primary constructor). A special primary constructor
- * will be generated (notInitializedModules) which stores the new instance
- * in the MODULE$ field right after the super call.
- */
- private def addStaticInit(sym: Symbol) {
- val tBuilder = getType(sym).asInstanceOf[TypeBuilder]
-
- val staticInit = tBuilder.DefineConstructor(
- (MethodAttributes.Static | MethodAttributes.Public).toShort,
- CallingConventions.Standard,
- MsilType.EmptyTypes)
-
- val sicode = staticInit.GetILGenerator()
-
- val instanceConstructor = constructors(sym.primaryConstructor)
-
- // there are no constructor parameters. assuming the constructor takes no parameter
- // is fine: we call (in the static constructor) the constructor of the module class,
- // which takes no arguments - an object definition cannot take constructor arguments.
- sicode.Emit(OpCodes.Newobj, instanceConstructor)
- // the stsfld is done in the instance constructor, just after the super call.
- sicode.Emit(OpCodes.Pop)
-
- sicode.Emit(OpCodes.Ret)
- }
-
- private def generateMirrorClass(sym: Symbol) {
- val tBuilder = getType(sym)
- assert(sym.isModuleClass, "Can't generate Mirror-Class for the Non-Module class " + sym)
- debuglog("Dumping mirror class for object: " + sym)
- val moduleName = msilName(sym)
- val mirrorName = moduleName.substring(0, moduleName.length() - 1)
- val mirrorTypeBuilder = mmodule.DefineType(mirrorName,
- TypeAttributes.Class |
- TypeAttributes.Public |
- TypeAttributes.Sealed,
- MOBJECT,
- MsilType.EmptyTypes)
-
- val iclass = classes(sym)
-
- for (m <- sym.tpe.nonPrivateMembers
- if m.owner != definitions.ObjectClass && !m.isProtected &&
- m.isMethod && !m.isClassConstructor && !m.isStaticMember && !m.isCase &&
- !m.isDeferred)
- {
- debuglog(" Mirroring method: " + m)
- val paramTypes = msilParamTypes(m)
- val paramNames: Array[String] = new Array[String](paramTypes.length)
- for (i <- 0 until paramTypes.length)
- paramNames(i) = "x_" + i
-
- // CHECK: verify if getMethodName is better than msilName
- val mirrorMethod = mirrorTypeBuilder.DefineMethod(msilName(m),
- (MethodAttributes.Public |
- MethodAttributes.Static).toShort,
- msilType(m.tpe.resultType),
- paramTypes)
-
- var i = 0
- while (i < paramTypes.length) {
- mirrorMethod.DefineParameter(i, ParameterAttributes.None, paramNames(i))
- i += 1
- }
-
- val mirrorCode = mirrorMethod.GetILGenerator()
- mirrorCode.Emit(OpCodes.Ldsfld, getModuleInstanceField(sym))
- val mInfo = getMethod(m)
- for (paramidx <- 0.until(paramTypes.length)) {
- val mInfoParams = mInfo.GetParameters
- val loadAddr = mInfoParams(paramidx).ParameterType.IsByRef
- loadArg(mirrorCode, loadAddr)(paramidx)
- }
-
- mirrorCode.Emit(OpCodes.Callvirt, getMethod(m))
- mirrorCode.Emit(OpCodes.Ret)
- }
-
- addSymtabAttribute(sym.sourceModule, mirrorTypeBuilder)
-
- mirrorTypeBuilder.CreateType()
- mirrorTypeBuilder.setSourceFilepath(iclass.cunit.source.file.path)
- }
-
-
- // #####################################################################
- // delegate callers
-
- var delegateCallers: TypeBuilder = _
- var nbDelegateCallers: Int = 0
-
- private def initDelegateCallers() = {
- delegateCallers = mmodule.DefineType("$DelegateCallers", TypeAttributes.Public |
- TypeAttributes.Sealed)
- }
-
- private def createDelegateCaller(functionType: Type, delegateType: Type) = {
- if (delegateCallers == null)
- initDelegateCallers()
- // create a field an store the function-object
- val mFunctionType: MsilType = msilType(functionType)
- val anonfunField: FieldBuilder = delegateCallers.DefineField(
- "$anonfunField$$" + nbDelegateCallers, mFunctionType,
- (FieldAttributes.InitOnly | FieldAttributes.Public | FieldAttributes.Static).toShort)
- mcode.Emit(OpCodes.Stsfld, anonfunField)
-
-
- // create the static caller method and the delegate object
- val (params, returnType) = delegateType.member(nme.apply).tpe match {
- case MethodType(delParams, delReturn) => (delParams, delReturn)
- case _ => abort("not a delegate type: " + delegateType)
- }
- val caller: MethodBuilder = delegateCallers.DefineMethod(
- "$delegateCaller$$" + nbDelegateCallers,
- (MethodAttributes.Final | MethodAttributes.Public | MethodAttributes.Static).toShort,
- msilType(returnType), (params map (_.tpe)).map(msilType).toArray)
- for (i <- 0 until params.length)
- caller.DefineParameter(i, ParameterAttributes.None, "arg" + i) // FIXME: use name of parameter symbol
- val delegCtor = msilType(delegateType).GetConstructor(Array(MOBJECT, INT_PTR))
- mcode.Emit(OpCodes.Ldnull)
- mcode.Emit(OpCodes.Ldftn, caller)
- mcode.Emit(OpCodes.Newobj, delegCtor)
-
-
- // create the static caller method body
- val functionApply: MethodInfo = getMethod(functionType.member(nme.apply))
- val dcode: ILGenerator = caller.GetILGenerator()
- dcode.Emit(OpCodes.Ldsfld, anonfunField)
- for (i <- 0 until params.length) {
- loadArg(dcode, false /* TODO confirm whether passing actual as-is to formal is correct wrt the ByRef attribute of the param */)(i)
- emitBox(dcode, toTypeKind(params(i).tpe))
- }
- dcode.Emit(OpCodes.Callvirt, functionApply)
- emitUnbox(dcode, toTypeKind(returnType))
- dcode.Emit(OpCodes.Ret)
-
- nbDelegateCallers = nbDelegateCallers + 1
-
- } //def createDelegateCaller
-
- def emitBox(code: ILGenerator, boxType: TypeKind) = (boxType: @unchecked) match {
- // doesn't make sense, unit as parameter..
- 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 clrTypes.isValueType(cls) =>
- code.Emit(OpCodes.Box, (msilType(boxType)))
- 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)
- /* (1) it's essential to keep the code emitted here (as of now plain calls to System.Convert.ToBlaBla methods)
- behaviorally.equiv.wrt. BoxesRunTime.unboxToBlaBla methods
- (case null: that's easy, case boxed: track changes to unboxBlaBla)
- (2) See also: asInstanceOf to cast from Any to number,
- tracked in http://lampsvn.epfl.ch/trac/scala/ticket/4437 */
- case BOOL => code.Emit(OpCodes.Call, toBool)
- 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 clrTypes.isValueType(cls) =>
- code.Emit(OpCodes.Unbox, msilType(boxType))
- code.Emit(OpCodes.Ldobj, msilType(boxType))
- case REFERENCE(_) | ARRAY(_) =>
- warning("Tried to UNBOX a non-valuetype.")
- ()
- }
-
- // #####################################################################
- // get and create methods / constructors
-
- def getConstructor(sym: Symbol): ConstructorInfo = constructors.get(sym) match {
- case Some(constr) => constr
- case None =>
- val mClass = getType(sym.owner)
- val constr = mClass.GetConstructor(msilParamTypes(sym))
- if (constr eq null) {
- java.lang.System.out.println("Cannot find constructor " + sym.owner + "::" + sym.name)
- java.lang.System.out.println("scope = " + sym.owner.tpe.decls)
- abort(sym.fullName)
- }
- else {
- mapConstructor(sym, constr)
- constr
- }
- }
-
- def mapConstructor(sym: Symbol, cInfo: ConstructorInfo) = {
- constructors(sym) = cInfo
- }
-
- private def getMethod(sym: Symbol): MethodInfo = {
-
- methods.get(sym) match {
- case Some(method) => method
- case None =>
- val mClass = getType(sym.owner)
- try {
- 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))
- java.lang.System.out.println("scope = " + sym.owner.tpe.decls)
- abort(sym.fullName)
- }
- else {
- mapMethod(sym, method)
- method
- }
- }
- catch {
- case e: Exception =>
- Console.println("While looking up " + mClass + "::" + sym.nameString)
- Console.println("\t" + showsym(sym))
- throw e
- }
- }
- }
-
- /*
- * add a mapping between sym and mInfo
- */
- private def mapMethod(sym: Symbol, mInfo: MethodInfo) {
- assert (mInfo != null, mInfo)
- methods(sym) = mInfo
- }
-
- /*
- * add mapping between sym and method with newName, paramTypes of newClass
- */
- private def mapMethod(sym: Symbol, newClass: MsilType, newName: String, paramTypes: Array[MsilType]) {
- val methodInfo = newClass.GetMethod(newName, paramTypes)
- assert(methodInfo != null, "Can't find mapping for " + sym + " -> " +
- newName + "(" + paramTypes + ")")
- mapMethod(sym, methodInfo)
- if (methodInfo.IsStatic)
- dynToStatMapped += sym
- }
-
- /*
- * add mapping between method with name and paramTypes of clazz to
- * method with newName and newParamTypes of newClass (used for instance
- * for "wait")
- */
- private def mapMethod(
- clazz: Symbol, name: Name, paramTypes: Array[Type],
- newClass: MsilType, newName: String, newParamTypes: Array[MsilType]) {
- val methodSym = lookupMethod(clazz, name, paramTypes)
- assert(methodSym != null, "cannot find method " + name + "(" +
- paramTypes + ")" + " in class " + clazz)
- mapMethod(methodSym, newClass, newName, newParamTypes)
- }
-
- /*
- * add mapping for member with name and paramTypes to member
- * newName of newClass (same parameters)
- */
- private def mapMethod(
- clazz: Symbol, name: Name, paramTypes: Array[Type],
- newClass: MsilType, newName: String) {
- mapMethod(clazz, name, paramTypes, newClass, newName, paramTypes map msilType)
- }
-
- /*
- * add mapping for all methods with name of clazz to the corresponding
- * method (same parameters) with newName of newClass
- */
- private def mapMethod(
- clazz: Symbol, name: Name,
- newClass: MsilType, newName: String) {
- val memberSym: Symbol = clazz.tpe.member(name)
- memberSym.tpe match {
- // alternatives: List[Symbol]
- case OverloadedType(_, alternatives) =>
- alternatives.foreach(s => mapMethod(s, newClass, newName, msilParamTypes(s)))
-
- // paramTypes: List[Type], resType: Type
- case MethodType(params, resType) =>
- mapMethod(memberSym, newClass, newName, msilParamTypes(memberSym))
-
- case _ =>
- abort("member not found: " + clazz + ", " + name)
- }
- }
-
-
- /*
- * find the method in clazz with name and paramTypes
- */
- private def lookupMethod(clazz: Symbol, name: Name, paramTypes: Array[Type]): Symbol = {
- val memberSym = clazz.tpe.member(name)
- memberSym.tpe match {
- case OverloadedType(_, alternatives) =>
- alternatives.find(s => {
- var i: Int = 0
- var typesOK: Boolean = true
- if (paramTypes.length == s.tpe.paramTypes.length) {
- while(i < paramTypes.length) {
- if (paramTypes(i) != s.tpe.paramTypes(i))
- typesOK = false
- i += 1
- }
- } else {
- typesOK = false
- }
- typesOK
- }) match {
- case Some(sym) => sym
- case None => abort("member of " + clazz + ", " + name + "(" +
- paramTypes + ") not found")
- }
-
- case MethodType(_, _) => memberSym
-
- case _ => abort("member not found: " + name + " of " + clazz)
- }
- }
-
- private def showsym(sym: Symbol): String = (sym.toString +
- "\n symbol = " + Flags.flagsToString(sym.flags) + " " + sym +
- "\n owner = " + Flags.flagsToString(sym.owner.flags) + " " + sym.owner
- )
-
- } // class BytecodeGenerator
-
-} // class GenMSIL
+// /* NSC -- new scala compiler
+// * Copyright 2005-2011 LAMP/EPFL
+// * @author Nikolay Mihaylov
+// */
+//
+//
+// package scala.tools.nsc
+// package backend.msil
+//
+// import java.io.{File, IOException}
+// import java.nio.{ByteBuffer, ByteOrder}
+// import scala.collection.{ mutable, immutable }
+// import scala.tools.nsc.symtab._
+//
+// import ch.epfl.lamp.compiler.msil.{Type => MsilType, _}
+// import ch.epfl.lamp.compiler.msil.emit._
+// import ch.epfl.lamp.compiler.msil.util.PECustomMod
+//
+// abstract class GenMSIL extends SubComponent {
+// import global._
+// import loaders.clrTypes
+// import clrTypes.{types, constructors, methods, fields}
+// import icodes._
+// import icodes.opcodes._
+//
+// val x = loaders
+//
+// /** Create a new phase */
+// override def newPhase(p: Phase) = new MsilPhase(p)
+//
+// val phaseName = "msil"
+// /** MSIL code generation phase
+// */
+// class MsilPhase(prev: Phase) extends GlobalPhase(prev) {
+// def name = phaseName
+// override def newFlags = phaseNewFlags
+//
+// override def erasedTypes = true
+//
+// override def run() {
+// if (settings.debug.value) inform("[running phase " + name + " on icode]")
+//
+// val codeGenerator = new BytecodeGenerator
+//
+// //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
+//
+// 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 {
+// classesSorted foreach codeGenerator.genClass
+// } finally {
+// codeGenerator.writeAssembly
+// }
+// }
+//
+// override def apply(unit: CompilationUnit) {
+// abort("MSIL works on icode classes, not on compilation units!")
+// }
+// }
+//
+// /**
+// * MSIL bytecode generator.
+// *
+// */
+// class BytecodeGenerator {
+//
+// val MODULE_INSTANCE_NAME = "MODULE$"
+//
+// 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,
+// SYMTAB_CONSTR => SYMTAB_ATTRIBUTE_CONSTRUCTOR,
+// SYMTAB_DEFAULT_CONSTR => SYMTAB_ATTRIBUTE_EMPTY_CONSTRUCTOR}
+//
+// val EXCEPTION = clrTypes.getType("System.Exception")
+// val MBYTE_ARRAY = clrTypes.mkArrayType(MBYTE)
+//
+// val ICLONEABLE = clrTypes.getType("System.ICloneable")
+// val MEMBERWISE_CLONE = MOBJECT.GetMethod("MemberwiseClone", MsilType.EmptyTypes)
+//
+// val MMONITOR = clrTypes.getType("System.Threading.Monitor")
+// val MMONITOR_ENTER = MMONITOR.GetMethod("Enter", Array(MOBJECT))
+// val MMONITOR_EXIT = MMONITOR.GetMethod("Exit", Array(MOBJECT))
+//
+// val MSTRING_BUILDER = clrTypes.getType("System.Text.StringBuilder")
+// val MSTRING_BUILDER_CONSTR = MSTRING_BUILDER.GetConstructor(MsilType.EmptyTypes)
+// val MSTRING_BUILDER_TOSTRING = MSTRING_BUILDER.GetMethod("ToString",
+// MsilType.EmptyTypes)
+//
+// val TYPE_FROM_HANDLE =
+// clrTypes.getType("System.Type").GetMethod("GetTypeFromHandle", Array(clrTypes.getType("System.RuntimeTypeHandle")))
+//
+// val INT_PTR = clrTypes.getType("System.IntPtr")
+//
+// val JOBJECT = definitions.ObjectClass
+// val JSTRING = definitions.StringClass
+//
+// val SystemConvert = clrTypes.getType("System.Convert")
+//
+// val objParam = Array(MOBJECT)
+//
+// val toBool: MethodInfo = SystemConvert.GetMethod("ToBoolean", objParam) // see comment in emitUnbox
+// 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)
+//
+// //val boxedUnit: FieldInfo = msilType(definitions.BoxedUnitModule.info).GetField("UNIT")
+// val boxedUnit: FieldInfo = fields(definitions.BoxedUnit_UNIT)
+//
+// // Scala attributes
+// // symtab.Definitions -> object (singleton..)
+// val SerializableAttr = definitions.SerializableAttr.tpe
+// val CloneableAttr = definitions.CloneableAttr.tpe
+// val TransientAtt = definitions.TransientAttr.tpe
+// // remoting: the architectures are too different, no mapping (no portable code
+// // possible)
+//
+// // java instance methods that are mapped to static methods in .net
+// // these will need to be called with OpCodes.Call (not Callvirt)
+// val dynToStatMapped = mutable.HashSet[Symbol]()
+//
+// initMappings()
+//
+// /** Create the mappings between java and .net classes and methods */
+// private def initMappings() {
+// mapType(definitions.AnyClass, MOBJECT)
+// mapType(definitions.AnyRefClass, MOBJECT)
+// //mapType(definitions.NullClass, clrTypes.getType("scala.AllRef$"))
+// //mapType(definitions.NothingClass, clrTypes.getType("scala.All$"))
+// // FIXME: for some reason the upper two lines map to null
+// mapType(definitions.NullClass, EXCEPTION)
+// mapType(definitions.NothingClass, EXCEPTION)
+//
+// mapType(definitions.BooleanClass, MBOOL)
+// mapType(definitions.ByteClass, MBYTE)
+// mapType(definitions.ShortClass, MSHORT)
+// mapType(definitions.CharClass, MCHAR)
+// mapType(definitions.IntClass, MINT)
+// mapType(definitions.LongClass, MLONG)
+// mapType(definitions.FloatClass, MFLOAT)
+// mapType(definitions.DoubleClass, MDOUBLE)
+// }
+//
+// var clasz: IClass = _
+// var method: IMethod = _
+//
+// var massembly: AssemblyBuilder = _
+// var mmodule: ModuleBuilder = _
+// var mcode: ILGenerator = _
+//
+// var assemName: String = _
+// var firstSourceName = ""
+// var outDir: File = _
+// var srcPath: File = _
+// var moduleName: String = _
+//
+// def initAssembly() {
+//
+// assemName = settings.assemname.value
+//
+// if (assemName == "") {
+// if (entryPoint != null) {
+// assemName = msilName(entryPoint.enclClass)
+// // remove the $ at the end (from module-name)
+// assemName = assemName.substring(0, assemName.length() - 1)
+// } else {
+// // assuming filename of first source file
+// assert(firstSourceName.endsWith(".scala"), firstSourceName)
+// assemName = firstSourceName.substring(0, firstSourceName.length() - 6)
+// }
+// } else {
+// if (assemName.endsWith(".msil"))
+// assemName = assemName.substring(0, assemName.length()-5)
+// if (assemName.endsWith(".il"))
+// assemName = assemName.substring(0, assemName.length()-3)
+// val f: File = new File(assemName)
+// assemName = f.getName()
+// }
+//
+// outDir = new File(settings.outdir.value)
+//
+// srcPath = new File(settings.sourcedir.value)
+//
+// val assemblyName = new AssemblyName()
+// assemblyName.Name = assemName
+// massembly = AssemblyBuilderFactory.DefineDynamicAssembly(assemblyName)
+//
+// moduleName = assemName // + (if (entryPoint == null) ".dll" else ".exe")
+// // filename here: .dll or .exe (in both parameters), second: give absolute-path
+// mmodule = massembly.DefineDynamicModule(moduleName,
+// new File(outDir, moduleName).getAbsolutePath())
+// assert (mmodule != null)
+// }
+//
+//
+// /**
+// * Form of the custom Attribute parameter (Ecma-335.pdf)
+// * - p. 163 for CustomAttrib Form,
+// * - p. 164 for FixedArg Form (Array and Element) (if array or not is known!)
+// * !! least significant byte first if values longer than one byte !!
+// *
+// * 1: Prolog (unsigned int16, value 0x0001) -> symtab[0] = 0x01, symtab[1] = 0x00
+// * 2: FixedArgs (directly the data, get number and types from related constructor)
+// * 2.1: length of the array (unsigned int32, 4 bytes, least significant first)
+// * 2.2: the byte array data
+// * 3: NumNamed (unsigned int16, number of named fields and properties, 0x0000)
+// */
+// def addSymtabAttribute(sym: Symbol, tBuilder: TypeBuilder) {
+// def addMarker() {
+// val markerSymtab = new Array[Byte](4)
+// markerSymtab(0) = 1.toByte
+// tBuilder.SetCustomAttribute(SYMTAB_ATTRIBUTE_EMPTY_CONSTRUCTOR, markerSymtab)
+// }
+//
+// // both conditions are needed (why exactly..?)
+// if (tBuilder.Name.endsWith("$") || sym.isModuleClass) {
+// addMarker()
+// } else {
+// currentRun.symData.get(sym) match {
+// case Some(pickle) =>
+// var size = pickle.writeIndex
+// val symtab = new Array[Byte](size + 8)
+// symtab(0) = 1.toByte
+// for (i <- 2 until 6) {
+// symtab(i) = (size & 0xff).toByte
+// size = size >> 8
+// }
+// java.lang.System.arraycopy(pickle.bytes, 0, symtab, 6, pickle.writeIndex)
+//
+// tBuilder.SetCustomAttribute(SYMTAB_ATTRIBUTE_CONSTRUCTOR, symtab)
+//
+// currentRun.symData -= sym
+// currentRun.symData -= sym.companionSymbol
+//
+// case _ =>
+// addMarker()
+// }
+// }
+// }
+//
+// /**
+// * Mutates `member` adding CLR attributes (if any) based on sym.annotations.
+// * Please notice that CLR custom modifiers are a different beast (see customModifiers below)
+// * and thus shouldn't be added by this method.
+// */
+// def addAttributes(member: ICustomAttributeSetter, annotations: List[AnnotationInfo]) {
+// val attributes = annotations.map(_.atp.typeSymbol).collect {
+// case definitions.TransientAttr => null // TODO this is just an example
+// }
+// return // TODO: implement at some point
+// }
+//
+// /**
+// * What's a CLR custom modifier? Intro available as source comments in compiler.msil.CustomModifier.
+// * It's basically a marker associated with a location (think of FieldInfo, ParameterInfo, and PropertyInfo)
+// * and thus that marker (be it optional or required) becomes part of the signature of that location.
+// * Some annotations will become CLR attributes (see addAttributes above), others custom modifiers (this method).
+// */
+// def customModifiers(annotations: List[AnnotationInfo]): Array[CustomModifier] = {
+// annotations.map(_.atp.typeSymbol).collect {
+// case definitions.VolatileAttr => new CustomModifier(true, CustomModifier.VolatileMarker)
+// } toArray
+// }
+//
+//
+//
+// /*
+// debuglog("creating annotations: " + annotations + " for member : " + member)
+// for (annot@ AnnotationInfo(typ, annArgs, nvPairs) <- annotations ;
+// if annot.isConstant)
+// //!typ.typeSymbol.isJavaDefined
+// {
+// // assert(consts.length <= 1,
+// // "too many constant arguments for annotations; "+consts.toString())
+//
+// // Problem / TODO having the symbol of the annotations type would be nicer
+// // (i hope that type.typeSymbol is the same as the one in types2create)
+// // AND: this will crash if the annotations Type is already compiled (-> not a typeBuilder)
+// // when this is solved, types2create will be the same as icodes.classes, thus superfluous
+// val annType: TypeBuilder = getType(typ.typeSymbol).asInstanceOf[TypeBuilder]
+// // val annType: MsilType = getType(typ.typeSymbol)
+//
+// // Problem / TODO: i have no idea which constructor is used. This
+// // information should be available in AnnotationInfo.
+// annType.CreateType() // else, GetConstructors can't be used
+// val constr: ConstructorInfo = annType.GetConstructors()(0)
+// // prevent a second call of CreateType, only needed because there's no
+// // other way than GetConstructors()(0) to get the constructor, if there's
+// // no constructor symbol available.
+//
+// val args: Array[Byte] =
+// getAttributeArgs(
+// annArgs map (_.constant.get),
+// (for((n,v) <- nvPairs) yield (n, v.constant.get)))
+// member.SetCustomAttribute(constr, args)
+// }
+// } */
+//
+// /* def getAttributeArgs(consts: List[Constant], nvPairs: List[(Name, Constant)]): Array[Byte] = {
+// val buf = ByteBuffer.allocate(2048) // FIXME: this may be not enough!
+// buf.order(ByteOrder.LITTLE_ENDIAN)
+// buf.putShort(1.toShort) // signature
+//
+// def emitSerString(str: String) = {
+// // this is wrong, it has to be the length of the UTF-8 byte array, which
+// // may be longer (see clr-book on page 302)
+// // val length: Int = str.length
+// val strBytes: Array[Byte] = try {
+// str.getBytes("UTF-8")
+// } catch {
+// case _: Error => abort("could not get byte-array for string: " + str)
+// }
+// val length: Int = strBytes.length //this length is stored big-endian
+// if (length < 128)
+// buf.put(length.toByte)
+// else if (length < (1<<14)) {
+// buf.put(((length >> 8) | 0x80).toByte) // the bits 14 and 15 of length are '0'
+// buf.put((length | 0xff).toByte)
+// } else if (length < (1 << 29)) {
+// buf.put(((length >> 24) | 0xc0).toByte)
+// buf.put(((length >> 16) & 0xff).toByte)
+// buf.put(((length >> 8) & 0xff).toByte)
+// buf.put(((length ) & 0xff).toByte)
+// } else
+// abort("string too long for attribute parameter: " + length)
+// buf.put(strBytes)
+// }
+//
+// def emitConst(const: Constant): Unit = const.tag match {
+// case BooleanTag => buf.put((if (const.booleanValue) 1 else 0).toByte)
+// case ByteTag => buf.put(const.byteValue)
+// case ShortTag => buf.putShort(const.shortValue)
+// case CharTag => buf.putChar(const.charValue)
+// case IntTag => buf.putInt(const.intValue)
+// case LongTag => buf.putLong(const.longValue)
+// case FloatTag => buf.putFloat(const.floatValue)
+// case DoubleTag => buf.putDouble(const.doubleValue)
+// case StringTag =>
+// val str: String = const.stringValue
+// if (str == null) {
+// buf.put(0xff.toByte)
+// } else {
+// emitSerString(str)
+// }
+// case ArrayTag =>
+// val arr: Array[Constant] = const.arrayValue
+// if (arr == null) {
+// buf.putInt(0xffffffff)
+// } else {
+// buf.putInt(arr.length)
+// arr.foreach(emitConst)
+// }
+//
+// // TODO: other Tags: NoTag, UnitTag, ClassTag, EnumTag, ArrayTag ???
+//
+// case _ => abort("could not handle attribute argument: " + const)
+// }
+//
+// consts foreach emitConst
+// buf.putShort(nvPairs.length.toShort)
+// def emitNamedArg(nvPair: (Name, Constant)) {
+// // the named argument is a property of the attribute (it can't be a field, since
+// // all fields in scala are private)
+// buf.put(0x54.toByte)
+//
+// def emitType(c: Constant) = c.tag match { // type of the constant, Ecma-335.pdf, page 151
+// case BooleanTag => buf.put(0x02.toByte)
+// case ByteTag => buf.put(0x05.toByte)
+// case ShortTag => buf.put(0x06.toByte)
+// case CharTag => buf.put(0x07.toByte)
+// case IntTag => buf.put(0x08.toByte)
+// case LongTag => buf.put(0x0a.toByte)
+// case FloatTag => buf.put(0x0c.toByte)
+// case DoubleTag => buf.put(0x0d.toByte)
+// case StringTag => buf.put(0x0e.toByte)
+//
+// // TODO: other Tags: NoTag, UnitTag, ClassTag, EnumTag ???
+//
+// // ArrayTag falls in here
+// case _ => abort("could not handle attribute argument: " + c)
+// }
+//
+// val cnst: Constant = nvPair._2
+// if (cnst.tag == ArrayTag) {
+// buf.put(0x1d.toByte)
+// emitType(cnst.arrayValue(0)) // FIXME: will crash if array length = 0
+// } else if (cnst.tag == EnumTag) {
+// buf.put(0x55.toByte)
+// // TODO: put a SerString (don't know what exactly, names of the enums somehow..)
+// } else {
+// buf.put(0x51.toByte)
+// emitType(cnst)
+// }
+//
+// emitSerString(nvPair._1.toString)
+// emitConst(nvPair._2)
+// }
+//
+// val length = buf.position()
+// buf.array().slice(0, length)
+// } */
+//
+// def writeAssembly() {
+// if (entryPoint != null) {
+// assert(entryPoint.enclClass.isModuleClass, entryPoint.enclClass)
+// val mainMethod = methods(entryPoint)
+// val stringArrayTypes: Array[MsilType] = Array(MSTRING_ARRAY)
+// val globalMain = mmodule.DefineGlobalMethod(
+// "Main", MethodAttributes.Public | MethodAttributes.Static,
+// MVOID, stringArrayTypes)
+// globalMain.DefineParameter(0, ParameterAttributes.None, "args")
+// massembly.SetEntryPoint(globalMain)
+// val code = globalMain.GetILGenerator()
+// val moduleField = getModuleInstanceField(entryPoint.enclClass)
+// code.Emit(OpCodes.Ldsfld, moduleField)
+// code.Emit(OpCodes.Ldarg_0)
+// code.Emit(OpCodes.Callvirt, mainMethod)
+// code.Emit(OpCodes.Ret)
+// }
+// createTypes()
+// var outDirName: String = null
+// try {
+// 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 " + outDirName + ": " + e.getMessage())
+// }
+// }
+//
+// private def createTypes() {
+// for (sym <- classes.keys) {
+// val iclass = classes(sym)
+// val tBuilder = types(sym).asInstanceOf[TypeBuilder]
+//
+// debuglog("Calling CreatType for " + sym + ", " + tBuilder.toString)
+//
+// tBuilder.CreateType()
+// tBuilder.setSourceFilepath(iclass.cunit.source.file.path)
+// }
+// }
+//
+// private[GenMSIL] def ilasmFileName(iclass: IClass) : String = {
+// // method.sourceFile contains just the filename
+// iclass.cunit.source.file.toString.replace("\\", "\\\\")
+// }
+//
+// private[GenMSIL] def genClass(iclass: IClass) {
+// val sym = iclass.symbol
+// debuglog("Generating class " + sym + " flags: " + Flags.flagsToString(sym.flags))
+// clasz = iclass
+//
+// val tBuilder = getType(sym).asInstanceOf[TypeBuilder]
+// if (isCloneable(sym)) {
+// // FIXME: why there's no nme.clone_ ?
+// // "Clone": if the code is non-portable, "Clone" is defined, not "clone"
+// // TODO: improve condition (should override AnyRef.clone)
+// if (iclass.methods.forall(m => {
+// !((m.symbol.name.toString != "clone" || m.symbol.name.toString != "Clone") &&
+// m.symbol.tpe.paramTypes.length != 0)
+// })) {
+// debuglog("auto-generating cloneable method for " + sym)
+// val attrs: Short = (MethodAttributes.Public | MethodAttributes.Virtual |
+// MethodAttributes.HideBySig).toShort
+// val cloneMethod = tBuilder.DefineMethod("Clone", attrs, MOBJECT,
+// MsilType.EmptyTypes)
+// val clCode = cloneMethod.GetILGenerator()
+// clCode.Emit(OpCodes.Ldarg_0)
+// clCode.Emit(OpCodes.Call, MEMBERWISE_CLONE)
+// clCode.Emit(OpCodes.Ret)
+// }
+// }
+//
+// val line = sym.pos.line
+// tBuilder.setPosition(line, ilasmFileName(iclass))
+//
+// if (isTopLevelModule(sym)) {
+// if (sym.companionClass == NoSymbol)
+// generateMirrorClass(sym)
+// else
+// log("No mirror class for module with linked class: " +
+// sym.fullName)
+// }
+//
+// addSymtabAttribute(sym, tBuilder)
+// addAttributes(tBuilder, sym.annotations)
+//
+// if (iclass.symbol != definitions.ArrayClass)
+// iclass.methods foreach genMethod
+//
+// } //genClass
+//
+//
+// private def genMethod(m: IMethod) {
+// debuglog("Generating method " + m.symbol + " flags: " + Flags.flagsToString(m.symbol.flags) +
+// " owner: " + m.symbol.owner)
+// method = m
+// localBuilders.clear
+// computeLocalVarsIndex(m)
+//
+// if (m.symbol.isClassConstructor) {
+// mcode = constructors(m.symbol).asInstanceOf[ConstructorBuilder].GetILGenerator()
+// } else {
+// val mBuilder = methods(m.symbol).asInstanceOf[MethodBuilder]
+// if (!mBuilder.IsAbstract())
+// try {
+// mcode = mBuilder.GetILGenerator()
+// } catch {
+// case e: Exception =>
+// java.lang.System.out.println("m.symbol = " + Flags.flagsToString(m.symbol.flags) + " " + m.symbol)
+// java.lang.System.out.println("m.symbol.owner = " + Flags.flagsToString(m.symbol.owner.flags) + " " + m.symbol.owner)
+// java.lang.System.out.println("mBuilder = " + mBuilder)
+// java.lang.System.out.println("mBuilder.DeclaringType = " +
+// TypeAttributes.toString(mBuilder.DeclaringType.Attributes) +
+// "::" + mBuilder.DeclaringType)
+// throw e
+// }
+// else
+// mcode = null
+// }
+//
+// if (mcode != null) {
+// for (local <- m.locals ; if !(m.params contains local)) {
+// debuglog("add local var: " + local + ", of kind " + local.kind)
+// val t: MsilType = msilType(local.kind)
+// val localBuilder = mcode.DeclareLocal(t)
+// localBuilder.SetLocalSymInfo(msilName(local.sym))
+// localBuilders(local) = localBuilder
+// }
+// genCode(m)
+// }
+//
+// }
+//
+// /** Special linearizer for methods with at least one exception handler. This
+// * linearizer brings all basic blocks in the right order so that nested
+// * try-catch and try-finally blocks can be emitted.
+// */
+// val msilLinearizer = new MSILLinearizer()
+//
+// val labels = mutable.HashMap[BasicBlock, Label]()
+//
+// /* when emitting .line, it's enough to include the full filename just once per method, thus reducing filesize.
+// * this scheme relies on the fact that the entry block is emitted first. */
+// var dbFilenameSeen = false
+//
+// def genCode(m: IMethod) {
+//
+// def makeLabels(blocks: List[BasicBlock]) = {
+// debuglog("Making labels for: " + method)
+// for (bb <- blocks) labels(bb) = mcode.DefineLabel()
+// }
+//
+// labels.clear
+//
+// var linearization = if(!m.exh.isEmpty) msilLinearizer.linearize(m)
+// else linearizer.linearize(m)
+//
+// 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) { }
+//
+// dbFilenameSeen = false
+// genBlocks(linearization)
+//
+// // RETURN inside exception blocks are replaced by Leave. The target of the
+// // leave is a `Ret` outside any exception block (generated here).
+// if (handlerReturnMethod == m) {
+// mcode.MarkLabel(handlerReturnLabel)
+// if (handlerReturnKind != UNIT)
+// mcode.Emit(OpCodes.Ldloc, handlerReturnLocal)
+// mcode.Emit(OpCodes.Ret)
+// }
+//
+// beginExBlock.clear()
+// beginCatchBlock.clear()
+// endExBlock.clear()
+// endFinallyLabels.clear()
+// }
+//
+// def genBlocks(blocks: List[BasicBlock], previous: BasicBlock = null) {
+// blocks match {
+// case Nil => ()
+// case x :: Nil => genBlock(x, prev = previous, next = null)
+// case x :: y :: ys => genBlock(x, prev = previous, next = y); genBlocks(y :: ys, previous = x)
+// }
+// }
+//
+// // the try blocks starting at a certain BasicBlock
+// val beginExBlock = mutable.HashMap[BasicBlock, List[ExceptionHandler]]()
+//
+// // the catch blocks starting / endling at a certain BasicBlock
+// val beginCatchBlock = mutable.HashMap[BasicBlock, ExceptionHandler]()
+// val endExBlock = mutable.HashMap[BasicBlock, List[ExceptionHandler]]()
+//
+// /** When emitting the code (genBlock), the number of currently active try / catch
+// * blocks. When seeing a `RETURN` inside a try / catch, we need to
+// * - store the result in a local (if it's not UNIT)
+// * - emit `Leave handlerReturnLabel` instead of the Return
+// * - emit code at the end: load the local and return its value
+// */
+// var currentHandlers = new mutable.Stack[ExceptionHandler]
+// // The IMethod the Local/Label/Kind below belong to
+// var handlerReturnMethod: IMethod = _
+// // Stores the result when returning inside an exception block
+// var handlerReturnLocal: LocalBuilder = _
+// // Label for a return instruction outside any exception block
+// var handlerReturnLabel: Label = _
+// // The result kind.
+// var handlerReturnKind: TypeKind = _
+// def returnFromHandler(kind: TypeKind): (LocalBuilder, Label) = {
+// if (handlerReturnMethod != method) {
+// handlerReturnMethod = method
+// if (kind != UNIT) {
+// handlerReturnLocal = mcode.DeclareLocal(msilType(kind))
+// handlerReturnLocal.SetLocalSymInfo("$handlerReturn")
+// }
+// handlerReturnLabel = mcode.DefineLabel()
+// handlerReturnKind = kind
+// }
+// (handlerReturnLocal, handlerReturnLabel)
+// }
+//
+// /** For try/catch nested inside a finally, we can't use `Leave OutsideFinally`, the
+// * Leave target has to be inside the finally (and it has to be the `endfinally` instruction).
+// * So for every finalizer, we have a label which marks the place of the `endfinally`,
+// * nested try/catch blocks will leave there.
+// */
+// val endFinallyLabels = mutable.HashMap[ExceptionHandler, Label]()
+//
+// /** Computes which blocks are the beginning / end of a try or catch block */
+// private def computeExceptionMaps(blocks: List[BasicBlock], m: IMethod): List[BasicBlock] = {
+// val visitedBlocks = new mutable.HashSet[BasicBlock]()
+//
+// // handlers which have not been introduced so far
+// var openHandlers = m.exh
+//
+//
+// /** Example
+// * try {
+// * try {
+// * // *1*
+// * } catch {
+// * case h1 =>
+// * }
+// * } catch {
+// * case h2 =>
+// * case h3 =>
+// * try {
+// *
+// * } catch {
+// * case h4 => // *2*
+// * case h5 =>
+// * }
+// * }
+// */
+//
+// // Stack of nested try blocks. Each bloc has a List of ExceptionHandler (multiple
+// // catch statements). Example *1*: Stack(List(h2, h3), List(h1))
+// val currentTryHandlers = new mutable.Stack[List[ExceptionHandler]]()
+//
+// // Stack of nested catch blocks. The head of the list is the current catch block. The
+// // tail is all following catch blocks. Example *2*: Stack(List(h3), List(h4, h5))
+// val currentCatchHandlers = new mutable.Stack[List[ExceptionHandler]]()
+//
+// for (b <- blocks) {
+//
+// // are we past the current catch blocks?
+// def endHandlers(): List[ExceptionHandler] = {
+// var res: List[ExceptionHandler] = Nil
+// if (!currentCatchHandlers.isEmpty) {
+// val handler = currentCatchHandlers.top.head
+// if (!handler.blocks.contains(b)) {
+// // all blocks of the handler are either visited, or not part of the linearization (i.e. dead)
+// assert(handler.blocks.forall(b => visitedBlocks.contains(b) || !blocks.contains(b)),
+// "Bad linearization of basic blocks inside catch. Found block not part of the handler\n"+
+// b.fullString +"\nwhile in catch-part of\n"+ handler)
+//
+// val rest = currentCatchHandlers.pop.tail
+// if (rest.isEmpty) {
+// // all catch blocks of that exception handler are covered
+// res = handler :: endHandlers()
+// } else {
+// // there are more catch blocks for that try (handlers covering the same)
+// currentCatchHandlers.push(rest)
+// beginCatchBlock(b) = rest.head
+// }
+// }
+// }
+// res
+// }
+// val end = endHandlers()
+// if (!end.isEmpty) endExBlock(b) = end
+//
+// // are we past the current try block?
+// if (!currentTryHandlers.isEmpty) {
+// val handler = currentTryHandlers.top.head
+// if (!handler.covers(b)) {
+// // all of the covered blocks are visited, or not part of the linearization
+// assert(handler.covered.forall(b => visitedBlocks.contains(b) || !blocks.contains(b)),
+// "Bad linearization of basic blocks inside try. Found non-covered block\n"+
+// b.fullString +"\nwhile in try-part of\n"+ handler)
+//
+// assert(handler.startBlock == b,
+// "Bad linearization of basic blocks. The entry block of a catch does not directly follow the try\n"+
+// b.fullString +"\n"+ handler)
+//
+// val handlers = currentTryHandlers.pop
+// currentCatchHandlers.push(handlers)
+// beginCatchBlock(b) = handler
+// }
+// }
+//
+// // are there try blocks starting at b?
+// val (newHandlers, stillOpen) = openHandlers.partition(_.covers(b))
+// openHandlers = stillOpen
+//
+// val newHandlersBySize = newHandlers.groupBy(_.covered.size)
+// // big handlers first, smaller ones are nested inside the try of the big one
+// // (checked by the assertions below)
+// val sizes = newHandlersBySize.keys.toList.sortWith(_ > _)
+//
+// val beginHandlers = new mutable.ListBuffer[ExceptionHandler]
+// for (s <- sizes) {
+// val sHandlers = newHandlersBySize(s)
+// for (h <- sHandlers) {
+// assert(h.covered == sHandlers.head.covered,
+// "bad nesting of exception handlers. same size, but not covering same blocks\n"+
+// h +"\n"+ sHandlers.head)
+// assert(h.resultKind == sHandlers.head.resultKind,
+// "bad nesting of exception handlers. same size, but the same resultKind\n"+
+// h +"\n"+ sHandlers.head)
+// }
+// for (bigger <- beginHandlers; h <- sHandlers) {
+// assert(h.covered.subsetOf(bigger.covered),
+// "bad nesting of exception handlers. try blocks of smaller handler are not nested in bigger one.\n"+
+// h +"\n"+ bigger)
+// assert(h.blocks.toSet.subsetOf(bigger.covered),
+// "bad nesting of exception handlers. catch blocks of smaller handler are not nested in bigger one.\n"+
+// h +"\n"+ bigger)
+// }
+// beginHandlers += sHandlers.head
+// currentTryHandlers.push(sHandlers)
+// }
+// beginExBlock(b) = beginHandlers.toList
+// visitedBlocks += b
+// }
+//
+// // if there handlers left (i.e. handlers covering nothing, or a
+// // non-existent (dead) block), remove their catch-blocks.
+// val liveBlocks = if (openHandlers.isEmpty) blocks else {
+// blocks.filter(b => openHandlers.forall(h => !h.blocks.contains(b)))
+// }
+//
+// /** There might be open handlers, but no more blocks. happens when try/catch end
+// * with `throw` or `return`
+// * def foo() { try { .. throw } catch { _ => .. throw } }
+// *
+// * In this case we need some code after the catch block for the auto-generated
+// * `leave` instruction. So we're adding a (dead) `throw new Exception`.
+// */
+// val rest = currentCatchHandlers.map(handlers => {
+// assert(handlers.length == 1, handlers)
+// handlers.head
+// }).toList
+//
+// if (rest.isEmpty) {
+// liveBlocks
+// } else {
+// val b = m.code.newBlock
+// b.emit(Seq(
+// NEW(REFERENCE(definitions.ThrowableClass)),
+// DUP(REFERENCE(definitions.ObjectClass)),
+// CALL_METHOD(definitions.ThrowableClass.primaryConstructor, Static(true)),
+// THROW(definitions.ThrowableClass)
+// ))
+// b.close
+// endExBlock(b) = rest
+// liveBlocks ::: List(b)
+// }
+// }
+//
+// /**
+// * @param block the BasicBlock to emit code for
+// * @param next the following BasicBlock, `null` if `block` is the last one
+// */
+// def genBlock(block: BasicBlock, prev: BasicBlock, next: BasicBlock) {
+//
+// def loadLocalOrAddress(local: Local, msg : String , loadAddr : Boolean) {
+// debuglog(msg + " for " + local)
+// val isArg = local.arg
+// val i = local.index
+// if (isArg)
+// loadArg(mcode, loadAddr)(i)
+// else
+// loadLocal(i, local, mcode, loadAddr)
+// }
+//
+// def loadFieldOrAddress(field: Symbol, isStatic: Boolean, msg: String, loadAddr : Boolean) {
+// debuglog(msg + " with owner: " + field.owner +
+// " flags: " + Flags.flagsToString(field.owner.flags))
+// var fieldInfo = fields.get(field) match {
+// case Some(fInfo) => fInfo
+// case None =>
+// val fInfo = getType(field.owner).GetField(msilName(field))
+// fields(field) = fInfo
+// fInfo
+// }
+// if (fieldInfo.IsVolatile) {
+// mcode.Emit(OpCodes.Volatile)
+// }
+// if (!fieldInfo.IsLiteral) {
+// if (loadAddr) {
+// mcode.Emit(if (isStatic) OpCodes.Ldsflda else OpCodes.Ldflda, fieldInfo)
+// } else {
+// mcode.Emit(if (isStatic) OpCodes.Ldsfld else OpCodes.Ldfld, fieldInfo)
+// }
+// } else {
+// assert(!loadAddr, "can't take AddressOf a literal field (not even with readonly. prefix) because no memory was allocated to such field ...")
+// // TODO the above can be overcome by loading the value, boxing, and finally unboxing. An address to a copy of the raw value will be on the stack.
+// /* We perform `field inlining' as required by CLR.
+// * Emit as for a CONSTANT ICode stmt, with the twist that the constant value is available
+// * as a java.lang.Object and its .NET type allows constant initialization in CLR, i.e. that type
+// * is one of I1, I2, I4, I8, R4, R8, CHAR, BOOLEAN, STRING, or CLASS (in this last case,
+// * only accepting nullref as value). See Table 9-1 in Lidin's book on ILAsm. */
+// val value = fieldInfo.getValue()
+// if (value == null) {
+// mcode.Emit(OpCodes.Ldnull)
+// } else {
+// val typ = if (fieldInfo.FieldType.IsEnum) fieldInfo.FieldType.getUnderlyingType
+// else fieldInfo.FieldType
+// if (typ == clrTypes.STRING) {
+// mcode.Emit(OpCodes.Ldstr, value.asInstanceOf[String])
+// } else if (typ == clrTypes.BOOLEAN) {
+// mcode.Emit(if (value.asInstanceOf[Boolean]) OpCodes.Ldc_I4_1
+// else OpCodes.Ldc_I4_0)
+// } else if (typ == clrTypes.BYTE || typ == clrTypes.UBYTE) {
+// loadI4(value.asInstanceOf[Byte], mcode)
+// } else if (typ == clrTypes.SHORT || typ == clrTypes.USHORT) {
+// loadI4(value.asInstanceOf[Int], mcode)
+// } else if (typ == clrTypes.CHAR) {
+// loadI4(value.asInstanceOf[Char], mcode)
+// } else if (typ == clrTypes.INT || typ == clrTypes.UINT) {
+// loadI4(value.asInstanceOf[Int], mcode)
+// } else if (typ == clrTypes.LONG || typ == clrTypes.ULONG) {
+// mcode.Emit(OpCodes.Ldc_I8, value.asInstanceOf[Long])
+// } else if (typ == clrTypes.FLOAT) {
+// mcode.Emit(OpCodes.Ldc_R4, value.asInstanceOf[Float])
+// } else if (typ == clrTypes.DOUBLE) {
+// mcode.Emit(OpCodes.Ldc_R8, value.asInstanceOf[Double])
+// } else {
+// /* TODO one more case is described in Partition II, 16.2: bytearray(...) */
+// abort("Unknown type for static literal field: " + fieldInfo)
+// }
+// }
+// }
+// }
+//
+// /** Creating objects works differently on .NET. On the JVM
+// * - NEW(type) => reference on Stack
+// * - DUP, load arguments, CALL_METHOD(constructor)
+// *
+// * On .NET, the NEW and DUP are ignored, but we emit a special method call
+// * - load arguments
+// * - NewObj(constructor) => reference on stack
+// *
+// * This variable tells whether the previous instruction was a NEW,
+// * we expect a DUP which is not emitted. */
+// var previousWasNEW = false
+//
+// var lastLineNr: Int = 0
+// var lastPos: Position = NoPosition
+//
+//
+// // EndExceptionBlock must happen before MarkLabel because it adds the
+// // Leave instruction. Otherwise, labels(block) points to the Leave
+// // (inside the catch) instead of the instruction afterwards.
+// for (handlers <- endExBlock.get(block); exh <- handlers) {
+// currentHandlers.pop()
+// for (l <- endFinallyLabels.get(exh))
+// mcode.MarkLabel(l)
+// mcode.EndExceptionBlock()
+// }
+//
+// mcode.MarkLabel(labels(block))
+// debuglog("Generating code for block: " + block)
+//
+// for (handler <- beginCatchBlock.get(block)) {
+// if (!currentHandlers.isEmpty && currentHandlers.top.covered == handler.covered) {
+// currentHandlers.pop()
+// currentHandlers.push(handler)
+// }
+// if (handler.cls == NoSymbol) {
+// // `finally` blocks are represented the same as `catch`, but with no catch-type
+// mcode.BeginFinallyBlock()
+// } else {
+// val t = getType(handler.cls)
+// mcode.BeginCatchBlock(t)
+// }
+// }
+// for (handlers <- beginExBlock.get(block); exh <- handlers) {
+// currentHandlers.push(exh)
+// mcode.BeginExceptionBlock()
+// }
+//
+// for (instr <- block) {
+// try {
+// val currentLineNr = instr.pos.line
+// val skip = if(instr.pos.isRange) instr.pos.sameRange(lastPos) else (currentLineNr == lastLineNr);
+// if(!skip || !dbFilenameSeen) {
+// val fileName = if(dbFilenameSeen) "" else {dbFilenameSeen = true; ilasmFileName(clasz)};
+// if(instr.pos.isRange) {
+// val startLine = instr.pos.focusStart.line
+// val endLine = instr.pos.focusEnd.line
+// val startCol = instr.pos.focusStart.column
+// val endCol = instr.pos.focusEnd.column
+// mcode.setPosition(startLine, endLine, startCol, endCol, fileName)
+// } else {
+// mcode.setPosition(instr.pos.line, fileName)
+// }
+// lastLineNr = currentLineNr
+// lastPos = instr.pos
+// }
+// } catch { case _: UnsupportedOperationException => () }
+//
+// if (previousWasNEW)
+// assert(instr.isInstanceOf[DUP], block)
+//
+// instr match {
+// case THIS(clasz) =>
+// mcode.Emit(OpCodes.Ldarg_0)
+//
+// case CONSTANT(const) =>
+// const.tag match {
+// case UnitTag => ()
+// case BooleanTag => mcode.Emit(if (const.booleanValue) OpCodes.Ldc_I4_1
+// else OpCodes.Ldc_I4_0)
+// case ByteTag => loadI4(const.byteValue, mcode)
+// case ShortTag => loadI4(const.shortValue, mcode)
+// case CharTag => loadI4(const.charValue, mcode)
+// case IntTag => loadI4(const.intValue, mcode)
+// case LongTag => mcode.Emit(OpCodes.Ldc_I8, const.longValue)
+// case FloatTag => mcode.Emit(OpCodes.Ldc_R4, const.floatValue)
+// case DoubleTag => mcode.Emit(OpCodes.Ldc_R8, const.doubleValue)
+// case StringTag => mcode.Emit(OpCodes.Ldstr, const.stringValue)
+// case NullTag => mcode.Emit(OpCodes.Ldnull)
+// case ClassTag =>
+// mcode.Emit(OpCodes.Ldtoken, msilType(const.typeValue))
+// mcode.Emit(OpCodes.Call, TYPE_FROM_HANDLE)
+// case _ => abort("Unknown constant value: " + const)
+// }
+//
+// case LOAD_ARRAY_ITEM(kind) =>
+// (kind: @unchecked) match {
+// case BOOL => mcode.Emit(OpCodes.Ldelem_I1)
+// 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)
+// case LONG => mcode.Emit(OpCodes.Ldelem_I8)
+// case FLOAT => mcode.Emit(OpCodes.Ldelem_R4)
+// case DOUBLE => mcode.Emit(OpCodes.Ldelem_R8)
+// case REFERENCE(cls) => mcode.Emit(OpCodes.Ldelem_Ref)
+// case ARRAY(elem) => mcode.Emit(OpCodes.Ldelem_Ref)
+//
+// // case UNIT is not possible: an Array[Unit] will be an
+// // Array[scala.runtime.BoxedUnit] (-> case REFERENCE)
+// }
+//
+// case LOAD_LOCAL(local) => loadLocalOrAddress(local, "load_local", false)
+//
+// case CIL_LOAD_LOCAL_ADDRESS(local) => loadLocalOrAddress(local, "cil_load_local_address", true)
+//
+// case LOAD_FIELD(field, isStatic) => loadFieldOrAddress(field, isStatic, "load_field", false)
+//
+// case CIL_LOAD_FIELD_ADDRESS(field, isStatic) => loadFieldOrAddress(field, isStatic, "cil_load_field_address", true)
+//
+// case CIL_LOAD_ARRAY_ITEM_ADDRESS(kind) => mcode.Emit(OpCodes.Ldelema, msilType(kind))
+//
+// case CIL_NEWOBJ(msym) =>
+// assert(msym.isClassConstructor)
+// val constructorInfo: ConstructorInfo = getConstructor(msym)
+// mcode.Emit(OpCodes.Newobj, constructorInfo)
+//
+// case LOAD_MODULE(module) =>
+// debuglog("Generating LOAD_MODULE for: " + showsym(module))
+// mcode.Emit(OpCodes.Ldsfld, getModuleInstanceField(module))
+//
+// case STORE_ARRAY_ITEM(kind) =>
+// (kind: @unchecked) match {
+// case BOOL => mcode.Emit(OpCodes.Stelem_I1)
+// case BYTE => mcode.Emit(OpCodes.Stelem_I1)
+// case SHORT => mcode.Emit(OpCodes.Stelem_I2)
+// case CHAR => mcode.Emit(OpCodes.Stelem_I2)
+// case INT => mcode.Emit(OpCodes.Stelem_I4)
+// case LONG => mcode.Emit(OpCodes.Stelem_I8)
+// case FLOAT => mcode.Emit(OpCodes.Stelem_R4)
+// case DOUBLE => mcode.Emit(OpCodes.Stelem_R8)
+// case REFERENCE(cls) => mcode.Emit(OpCodes.Stelem_Ref)
+// case ARRAY(elem) => mcode.Emit(OpCodes.Stelem_Ref) // @TODO: test this! (occurs when calling a Array[Object]* vararg param method)
+//
+// // case UNIT not possible (see comment at LOAD_ARRAY_ITEM)
+// }
+//
+// case STORE_LOCAL(local) =>
+// val isArg = local.arg
+// val i = local.index
+// debuglog("store_local for " + local + ", index " + i)
+//
+// // there are some locals defined by the compiler that
+// // are isArg and are need to be stored.
+// if (isArg) {
+// if (i >= -128 && i <= 127)
+// mcode.Emit(OpCodes.Starg_S, i)
+// else
+// mcode.Emit(OpCodes.Starg, i)
+// } else {
+// i match {
+// case 0 => mcode.Emit(OpCodes.Stloc_0)
+// case 1 => mcode.Emit(OpCodes.Stloc_1)
+// case 2 => mcode.Emit(OpCodes.Stloc_2)
+// case 3 => mcode.Emit(OpCodes.Stloc_3)
+// case _ =>
+// if (i >= -128 && i <= 127)
+// mcode.Emit(OpCodes.Stloc_S, localBuilders(local))
+// else
+// mcode.Emit(OpCodes.Stloc, localBuilders(local))
+// }
+// }
+//
+// case STORE_THIS(_) =>
+// // this only works for impl classes because the self parameter comes first
+// // in the method signature. If that changes, this code has to be revisited.
+// mcode.Emit(OpCodes.Starg_S, 0)
+//
+// case STORE_FIELD(field, isStatic) =>
+// val fieldInfo = fields.get(field) match {
+// case Some(fInfo) => fInfo
+// case None =>
+// val fInfo = getType(field.owner).GetField(msilName(field))
+// fields(field) = fInfo
+// fInfo
+// }
+// mcode.Emit(if (isStatic) OpCodes.Stsfld else OpCodes.Stfld, fieldInfo)
+//
+// case CALL_PRIMITIVE(primitive) =>
+// genPrimitive(primitive, instr.pos)
+//
+// case CALL_METHOD(msym, style) =>
+// if (msym.isClassConstructor) {
+// val constructorInfo: ConstructorInfo = getConstructor(msym)
+// (style: @unchecked) match {
+// // normal constructor calls are Static..
+// case Static(_) =>
+// if (method.symbol.isClassConstructor && method.symbol.owner == msym.owner)
+// // we're generating a constructor (method: IMethod is a constructor), and we're
+// // calling another constructor of the same class.
+//
+// // @LUC TODO: this can probably break, namely when having: class A { def this() { new A() } }
+// // instead, we should instruct the CALL_METHOD with additional information, know whether it's
+// // an instance creation constructor call or not.
+// mcode.Emit(OpCodes.Call, constructorInfo)
+// else
+// mcode.Emit(OpCodes.Newobj, constructorInfo)
+// case SuperCall(_) =>
+// mcode.Emit(OpCodes.Call, constructorInfo)
+// if (isStaticModule(clasz.symbol) &&
+// notInitializedModules.contains(clasz.symbol) &&
+// method.symbol.isClassConstructor)
+// {
+// notInitializedModules -= clasz.symbol
+// mcode.Emit(OpCodes.Ldarg_0)
+// mcode.Emit(OpCodes.Stsfld, getModuleInstanceField(clasz.symbol))
+// }
+// }
+//
+// } else {
+//
+// var doEmit = true
+// getTypeOpt(msym.owner) match {
+// case Some(typ) if (typ.IsEnum) => {
+// def negBool() = {
+// mcode.Emit(OpCodes.Ldc_I4_0)
+// mcode.Emit(OpCodes.Ceq)
+// }
+// doEmit = false
+// val name = msym.name
+// if (name eq nme.EQ) { mcode.Emit(OpCodes.Ceq) }
+// else if (name eq nme.NE) { mcode.Emit(OpCodes.Ceq); negBool }
+// else if (name eq nme.LT) { mcode.Emit(OpCodes.Clt) }
+// else if (name eq nme.LE) { mcode.Emit(OpCodes.Cgt); negBool }
+// else if (name eq nme.GT) { mcode.Emit(OpCodes.Cgt) }
+// else if (name eq nme.GE) { mcode.Emit(OpCodes.Clt); negBool }
+// else if (name eq nme.OR) { mcode.Emit(OpCodes.Or) }
+// else if (name eq nme.AND) { mcode.Emit(OpCodes.And) }
+// else if (name eq nme.XOR) { mcode.Emit(OpCodes.Xor) }
+// else
+// doEmit = true
+// }
+// case _ => ()
+// }
+//
+// // method: implicit view(FunctionX[PType0, PType1, ...,PTypeN, ResType]):DelegateType
+// val (isDelegateView, paramType, resType) = atPhase(currentRun.typerPhase) {
+// msym.tpe match {
+// case MethodType(params, resultType)
+// if (params.length == 1 && msym.name == nme.view_) =>
+// val paramType = params(0).tpe
+// val isDel = definitions.isCorrespondingDelegate(resultType, paramType)
+// (isDel, paramType, resultType)
+// case _ => (false, null, null)
+// }
+// }
+// if (doEmit && isDelegateView) {
+// doEmit = false
+// createDelegateCaller(paramType, resType)
+// }
+//
+// if (doEmit &&
+// (msym.name == nme.PLUS || msym.name == nme.MINUS)
+// && clrTypes.isDelegateType(msilType(msym.owner.tpe)))
+// {
+// doEmit = false
+// val methodInfo: MethodInfo = getMethod(msym)
+// // call it as a static method, even if the compiler (symbol) thinks it's virtual
+// mcode.Emit(OpCodes.Call, methodInfo)
+// mcode.Emit(OpCodes.Castclass, msilType(msym.owner.tpe))
+// }
+//
+// if (doEmit && definitions.Delegate_scalaCallers.contains(msym)) {
+// doEmit = false
+// val methodSym: Symbol = definitions.Delegate_scalaCallerTargets(msym)
+// val delegateType: Type = msym.tpe match {
+// case MethodType(_, retType) => retType
+// case _ => abort("not a method type: " + msym.tpe)
+// }
+// val methodInfo: MethodInfo = getMethod(methodSym)
+// val delegCtor = msilType(delegateType).GetConstructor(Array(MOBJECT, INT_PTR))
+// if (methodSym.isStatic) {
+// mcode.Emit(OpCodes.Ldftn, methodInfo)
+// } else {
+// mcode.Emit(OpCodes.Dup)
+// mcode.Emit(OpCodes.Ldvirtftn, methodInfo)
+// }
+// mcode.Emit(OpCodes.Newobj, delegCtor)
+// }
+//
+// if (doEmit) {
+// val methodInfo: MethodInfo = getMethod(msym)
+// (style: @unchecked) match {
+// case SuperCall(_) =>
+// mcode.Emit(OpCodes.Call, methodInfo)
+// case Dynamic =>
+// // methodInfo.DeclaringType is null for global methods
+// val isValuetypeMethod = (methodInfo.DeclaringType ne null) && (methodInfo.DeclaringType.IsValueType)
+// val isValuetypeVirtualMethod = isValuetypeMethod && (methodInfo.IsVirtual)
+// if (dynToStatMapped(msym)) {
+// mcode.Emit(OpCodes.Call, methodInfo)
+// } else if (isValuetypeVirtualMethod) {
+// mcode.Emit(OpCodes.Constrained, methodInfo.DeclaringType)
+// mcode.Emit(OpCodes.Callvirt, methodInfo)
+// } else if (isValuetypeMethod) {
+// // otherwise error "Callvirt on a value type method" ensues
+// mcode.Emit(OpCodes.Call, methodInfo)
+// } else {
+// mcode.Emit(OpCodes.Callvirt, methodInfo)
+// }
+// case Static(_) =>
+// if(methodInfo.IsVirtual && !mcode.Ldarg0WasJustEmitted) {
+// mcode.Emit(OpCodes.Callvirt, methodInfo)
+// } else mcode.Emit(OpCodes.Call, methodInfo)
+// }
+// }
+// }
+//
+// case BOX(boxType) =>
+// emitBox(mcode, boxType)
+//
+// case UNBOX(boxType) =>
+// emitUnbox(mcode, boxType)
+//
+// case CIL_UNBOX(boxType) =>
+// mcode.Emit(OpCodes.Unbox, msilType(boxType))
+//
+// case CIL_INITOBJ(valueType) =>
+// mcode.Emit(OpCodes.Initobj, msilType(valueType))
+//
+// case NEW(REFERENCE(cls)) =>
+// // the next instruction must be a DUP, see comment on `var previousWasNEW`
+// previousWasNEW = true
+//
+// // works also for arrays and reference-types
+// case CREATE_ARRAY(elem, dims) =>
+// // TODO: handle multi dimensional arrays
+// assert(dims == 1, "Can't handle multi dimensional arrays")
+// mcode.Emit(OpCodes.Newarr, msilType(elem))
+//
+// // works for arrays and reference-types
+// case IS_INSTANCE(tpe) =>
+// mcode.Emit(OpCodes.Isinst, msilType(tpe))
+// mcode.Emit(OpCodes.Ldnull)
+// mcode.Emit(OpCodes.Ceq)
+// mcode.Emit(OpCodes.Ldc_I4_0)
+// mcode.Emit(OpCodes.Ceq)
+//
+// // works for arrays and reference-types
+// // part from the scala reference: "S <: T does not imply
+// // Array[S] <: Array[T] in Scala. However, it is possible
+// // to cast an array of S to an array of T if such a cast
+// // is permitted in the host environment."
+// case CHECK_CAST(tpknd) =>
+// val tMSIL = msilType(tpknd)
+// mcode.Emit(OpCodes.Castclass, tMSIL)
+//
+// // no SWITCH is generated when there's
+// // - a default case ("case _ => ...") in the matching expr
+// // - OR is used ("case 1 | 2 => ...")
+// case SWITCH(tags, branches) =>
+// // tags is List[List[Int]]; a list of integers for every label.
+// // if the int on stack is 4, and 4 is in the second list => jump
+// // to second label
+// // branches is List[BasicBlock]
+// // the labels to jump to (the last one is the default one)
+//
+// val switchLocal = mcode.DeclareLocal(MINT)
+// // several switch variables will appear with the same name in the
+// // assembly code, but this makes no truble
+// switchLocal.SetLocalSymInfo("$switch_var")
+//
+// mcode.Emit(OpCodes.Stloc, switchLocal)
+// var i = 0
+// for (l <- tags) {
+// var targetLabel = labels(branches(i))
+// for (i <- l) {
+// mcode.Emit(OpCodes.Ldloc, switchLocal)
+// loadI4(i, mcode)
+// mcode.Emit(OpCodes.Beq, targetLabel)
+// }
+// i += 1
+// }
+// val defaultTarget = labels(branches(i))
+// if (next != branches(i))
+// mcode.Emit(OpCodes.Br, defaultTarget)
+//
+// case JUMP(whereto) =>
+// val (leaveHandler, leaveFinally, lfTarget) = leavesHandler(block, whereto)
+// if (leaveHandler) {
+// if (leaveFinally) {
+// if (lfTarget.isDefined) mcode.Emit(OpCodes.Leave, lfTarget.get)
+// else mcode.Emit(OpCodes.Endfinally)
+// } else
+// mcode.Emit(OpCodes.Leave, labels(whereto))
+// } else if (next != whereto)
+// mcode.Emit(OpCodes.Br, labels(whereto))
+//
+// case CJUMP(success, failure, cond, kind) =>
+// // cond is TestOp (see Primitives.scala), and can take
+// // values EQ, NE, LT, GE LE, GT
+// // kind is TypeKind
+// val isFloat = kind == FLOAT || kind == DOUBLE
+// val emit = (c: TestOp, l: Label) => emitBr(c, l, isFloat)
+// emitCondBr(block, cond, success, failure, next, emit)
+//
+// case CZJUMP(success, failure, cond, kind) =>
+// emitCondBr(block, cond, success, failure, next, emitBrBool(_, _))
+//
+// case RETURN(kind) =>
+// if (currentHandlers.isEmpty)
+// mcode.Emit(OpCodes.Ret)
+// else {
+// val (local, label) = returnFromHandler(kind)
+// if (kind != UNIT)
+// mcode.Emit(OpCodes.Stloc, local)
+// mcode.Emit(OpCodes.Leave, label)
+// }
+//
+// case THROW(_) =>
+// mcode.Emit(OpCodes.Throw)
+//
+// case DROP(kind) =>
+// mcode.Emit(OpCodes.Pop)
+//
+// case DUP(kind) =>
+// // see comment on `var previousWasNEW`
+// if (!previousWasNEW)
+// mcode.Emit(OpCodes.Dup)
+// else
+// previousWasNEW = false
+//
+// case MONITOR_ENTER() =>
+// mcode.Emit(OpCodes.Call, MMONITOR_ENTER)
+//
+// case MONITOR_EXIT() =>
+// mcode.Emit(OpCodes.Call, MMONITOR_EXIT)
+//
+// case SCOPE_ENTER(_) | SCOPE_EXIT(_) | LOAD_EXCEPTION(_) =>
+// ()
+// }
+//
+// } // end for (instr <- b) { .. }
+// } // end genBlock
+//
+// def genPrimitive(primitive: Primitive, pos: Position) {
+// primitive match {
+// case Negation(kind) =>
+// kind match {
+// // CHECK: is ist possible to get this for BOOL? in this case, verify.
+// case BOOL | BYTE | CHAR | SHORT | INT | LONG | FLOAT | DOUBLE =>
+// mcode.Emit(OpCodes.Neg)
+//
+// case _ => abort("Impossible to negate a " + kind)
+// }
+//
+// case Arithmetic(op, kind) =>
+// op match {
+// case ADD => mcode.Emit(OpCodes.Add)
+// case SUB => mcode.Emit(OpCodes.Sub)
+// case MUL => mcode.Emit(OpCodes.Mul)
+// case DIV => mcode.Emit(OpCodes.Div)
+// case REM => mcode.Emit(OpCodes.Rem)
+// case NOT => mcode.Emit(OpCodes.Not) //bitwise complement (one's complement)
+// case _ => abort("Unknown arithmetic primitive " + primitive )
+// }
+//
+// case Logical(op, kind) => op match {
+// case AND => mcode.Emit(OpCodes.And)
+// case OR => mcode.Emit(OpCodes.Or)
+// case XOR => mcode.Emit(OpCodes.Xor)
+// }
+//
+// case Shift(op, kind) => op match {
+// case LSL => mcode.Emit(OpCodes.Shl)
+// case ASR => mcode.Emit(OpCodes.Shr)
+// case LSR => mcode.Emit(OpCodes.Shr_Un)
+// }
+//
+// case Conversion(src, dst) =>
+// debuglog("Converting from: " + src + " to: " + dst)
+//
+// dst match {
+// 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)
+// case LONG => mcode.Emit(OpCodes.Conv_I8)
+// case FLOAT => mcode.Emit(OpCodes.Conv_R4)
+// case DOUBLE => mcode.Emit(OpCodes.Conv_R8)
+// case _ =>
+// Console.println("Illegal conversion at: " + clasz +
+// " at: " + pos.source + ":" + pos.line)
+// }
+//
+// case ArrayLength(_) =>
+// mcode.Emit(OpCodes.Ldlen)
+//
+// case StartConcat =>
+// mcode.Emit(OpCodes.Newobj, MSTRING_BUILDER_CONSTR)
+//
+//
+// case StringConcat(el) =>
+// val elemType : MsilType = el match {
+// case REFERENCE(_) | ARRAY(_) => MOBJECT
+// case _ => msilType(el)
+// }
+//
+// val argTypes:Array[MsilType] = Array(elemType)
+// val stringBuilderAppend = MSTRING_BUILDER.GetMethod("Append", argTypes )
+// mcode.Emit(OpCodes.Callvirt, stringBuilderAppend)
+//
+// case EndConcat =>
+// mcode.Emit(OpCodes.Callvirt, MSTRING_BUILDER_TOSTRING)
+//
+// case _ =>
+// abort("Unimplemented primitive " + primitive)
+// }
+// } // end genPrimitive
+//
+//
+// ////////////////////// loading ///////////////////////
+//
+// def loadI4(value: Int, code: ILGenerator): Unit = value match {
+// case -1 => code.Emit(OpCodes.Ldc_I4_M1)
+// case 0 => code.Emit(OpCodes.Ldc_I4_0)
+// case 1 => code.Emit(OpCodes.Ldc_I4_1)
+// case 2 => code.Emit(OpCodes.Ldc_I4_2)
+// case 3 => code.Emit(OpCodes.Ldc_I4_3)
+// case 4 => code.Emit(OpCodes.Ldc_I4_4)
+// case 5 => code.Emit(OpCodes.Ldc_I4_5)
+// case 6 => code.Emit(OpCodes.Ldc_I4_6)
+// case 7 => code.Emit(OpCodes.Ldc_I4_7)
+// case 8 => code.Emit(OpCodes.Ldc_I4_8)
+// case _ =>
+// if (value >= -128 && value <= 127)
+// code.Emit(OpCodes.Ldc_I4_S, value)
+// else
+// code.Emit(OpCodes.Ldc_I4, value)
+// }
+//
+// def loadArg(code: ILGenerator, loadAddr: Boolean)(i: Int) =
+// if (loadAddr) {
+// if (i >= -128 && i <= 127)
+// code.Emit(OpCodes.Ldarga_S, i)
+// else
+// code.Emit(OpCodes.Ldarga, i)
+// } else {
+// i match {
+// case 0 => code.Emit(OpCodes.Ldarg_0)
+// case 1 => code.Emit(OpCodes.Ldarg_1)
+// case 2 => code.Emit(OpCodes.Ldarg_2)
+// case 3 => code.Emit(OpCodes.Ldarg_3)
+// case _ =>
+// if (i >= -128 && i <= 127)
+// code.Emit(OpCodes.Ldarg_S, i)
+// else
+// code.Emit(OpCodes.Ldarg, i)
+// }
+// }
+//
+// def loadLocal(i: Int, local: Local, code: ILGenerator, loadAddr: Boolean) =
+// if (loadAddr) {
+// if (i >= -128 && i <= 127)
+// code.Emit(OpCodes.Ldloca_S, localBuilders(local))
+// else
+// code.Emit(OpCodes.Ldloca, localBuilders(local))
+// } else {
+// i match {
+// case 0 => code.Emit(OpCodes.Ldloc_0)
+// case 1 => code.Emit(OpCodes.Ldloc_1)
+// case 2 => code.Emit(OpCodes.Ldloc_2)
+// case 3 => code.Emit(OpCodes.Ldloc_3)
+// case _ =>
+// if (i >= -128 && i <= 127)
+// code.Emit(OpCodes.Ldloc_S, localBuilders(local))
+// else
+// code.Emit(OpCodes.Ldloc, localBuilders(local))
+// }
+// }
+//
+// ////////////////////// branches ///////////////////////
+//
+// /** Returns a Triple (Boolean, Boolean, Option[Label])
+// * - whether the jump leaves some exception block (try / catch / finally)
+// * - whether it leaves a finally handler (finally block, but not it's try / catch)
+// * - a label where to jump for leaving the finally handler
+// * . None to leave directly using `endfinally`
+// * . Some(label) to emit `leave label` (for try / catch inside a finally handler)
+// */
+// def leavesHandler(from: BasicBlock, to: BasicBlock): (Boolean, Boolean, Option[Label]) =
+// if (currentHandlers.isEmpty) (false, false, None)
+// else {
+// val h = currentHandlers.head
+// val leaveHead = { h.covers(from) != h.covers(to) ||
+// h.blocks.contains(from) != h.blocks.contains(to) }
+// if (leaveHead) {
+// // we leave the innermost exception block.
+// // find out if we also leave som e `finally` handler
+// currentHandlers.find(e => {
+// e.cls == NoSymbol && e.blocks.contains(from) != e.blocks.contains(to)
+// }) match {
+// case Some(finallyHandler) =>
+// if (h == finallyHandler) {
+// // the finally handler is the innermost, so we can emit `endfinally` directly
+// (true, true, None)
+// } else {
+// // we need to `Leave` to the `endfinally` of the next outer finally handler
+// val l = endFinallyLabels.getOrElseUpdate(finallyHandler, mcode.DefineLabel())
+// (true, true, Some(l))
+// }
+// case None =>
+// (true, false, None)
+// }
+// } else (false, false, None)
+// }
+//
+// def emitCondBr(block: BasicBlock, cond: TestOp, success: BasicBlock, failure: BasicBlock,
+// next: BasicBlock, emitBrFun: (TestOp, Label) => Unit) {
+// val (sLeaveHandler, sLeaveFinally, slfTarget) = leavesHandler(block, success)
+// val (fLeaveHandler, fLeaveFinally, flfTarget) = leavesHandler(block, failure)
+//
+// if (sLeaveHandler || fLeaveHandler) {
+// val sLabelOpt = if (sLeaveHandler) {
+// val leaveSLabel = mcode.DefineLabel()
+// emitBrFun(cond, leaveSLabel)
+// Some(leaveSLabel)
+// } else {
+// emitBrFun(cond, labels(success))
+// None
+// }
+//
+// if (fLeaveHandler) {
+// if (fLeaveFinally) {
+// if (flfTarget.isDefined) mcode.Emit(OpCodes.Leave, flfTarget.get)
+// else mcode.Emit(OpCodes.Endfinally)
+// } else
+// mcode.Emit(OpCodes.Leave, labels(failure))
+// } else
+// mcode.Emit(OpCodes.Br, labels(failure))
+//
+// sLabelOpt.map(l => {
+// mcode.MarkLabel(l)
+// if (sLeaveFinally) {
+// if (slfTarget.isDefined) mcode.Emit(OpCodes.Leave, slfTarget.get)
+// else mcode.Emit(OpCodes.Endfinally)
+// } else
+// mcode.Emit(OpCodes.Leave, labels(success))
+// })
+// } else {
+// if (next == success) {
+// emitBrFun(cond.negate, labels(failure))
+// } else {
+// emitBrFun(cond, labels(success))
+// if (next != failure) {
+// mcode.Emit(OpCodes.Br, labels(failure))
+// }
+// }
+// }
+// }
+//
+// def emitBr(condition: TestOp, dest: Label, isFloat: Boolean) {
+// condition match {
+// case EQ => mcode.Emit(OpCodes.Beq, dest)
+// case NE => mcode.Emit(OpCodes.Bne_Un, dest)
+// case LT => mcode.Emit(if (isFloat) OpCodes.Blt_Un else OpCodes.Blt, dest)
+// case GE => mcode.Emit(if (isFloat) OpCodes.Bge_Un else OpCodes.Bge, dest)
+// case LE => mcode.Emit(if (isFloat) OpCodes.Ble_Un else OpCodes.Ble, dest)
+// case GT => mcode.Emit(if (isFloat) OpCodes.Bgt_Un else OpCodes.Bgt, dest)
+// }
+// }
+//
+// def emitBrBool(cond: TestOp, dest: Label) {
+// cond match {
+// // EQ -> Brfalse, NE -> Brtrue; this is because we come from
+// // a CZJUMP. If the value on the stack is 0 (e.g. a boolean
+// // method returned false), and we are in the case EQ, then
+// // we need to emit Brfalse (EQ Zero means false). vice versa
+// case EQ => mcode.Emit(OpCodes.Brfalse, dest)
+// case NE => mcode.Emit(OpCodes.Brtrue, dest)
+// }
+// }
+//
+// ////////////////////// local vars ///////////////////////
+//
+// /**
+// * Compute the indexes of each local variable of the given
+// * method.
+// */
+// def computeLocalVarsIndex(m: IMethod) {
+// var idx = if (m.symbol.isStaticMember) 0 else 1
+//
+// val params = m.params
+// for (l <- params) {
+// debuglog("Index value for parameter " + l + ": " + idx)
+// l.index = idx
+// idx += 1 // sizeOf(l.kind)
+// }
+//
+// val locvars = m.locals filterNot (params contains)
+// idx = 0
+//
+// for (l <- locvars) {
+// debuglog("Index value for local variable " + l + ": " + idx)
+// l.index = idx
+// idx += 1 // sizeOf(l.kind)
+// }
+//
+// }
+//
+// ////////////////////// Utilities ////////////////////////
+//
+// /** Return the a name of this symbol that can be used on the .NET
+// * platform. It removes spaces from names.
+// *
+// * Special handling: scala.All and scala.AllRef are 'erased' to
+// * scala.All$ and scala.AllRef$. This is needed because they are
+// * not real classes, and they mean 'abrupt termination upon evaluation
+// * of that expression' or 'null' respectively. This handling is
+// * done already in GenICode, but here we need to remove references
+// * from method signatures to these types, because such classes can
+// * not exist in the classpath: the type checker will be very confused.
+// */
+// def msilName(sym: Symbol): String = {
+// val suffix = sym.moduleSuffix
+// // Flags.JAVA: "symbol was not defined by a scala-class" (java, or .net-class)
+//
+// if (sym == definitions.NothingClass)
+// return "scala.runtime.Nothing$"
+// else if (sym == definitions.NullClass)
+// return "scala.runtime.Null$"
+//
+// (if (sym.isClass || (sym.isModule && !sym.isMethod)) {
+// if (sym.isNestedClass) sym.simpleName
+// else sym.fullName
+// } else
+// sym.simpleName.toString.trim()) + suffix
+// }
+//
+//
+// ////////////////////// flags ///////////////////////
+//
+// def msilTypeFlags(sym: Symbol): Int = {
+// var mf: Int = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass
+//
+// if(sym.isNestedClass) {
+// mf = mf | (if (sym hasFlag Flags.PRIVATE) TypeAttributes.NestedPrivate else TypeAttributes.NestedPublic)
+// } else {
+// mf = mf | (if (sym hasFlag Flags.PRIVATE) TypeAttributes.NotPublic else TypeAttributes.Public)
+// }
+// mf = mf | (if (sym hasFlag Flags.ABSTRACT) TypeAttributes.Abstract else 0)
+// mf = mf | (if (sym.isTrait && !sym.isImplClass) TypeAttributes.Interface else TypeAttributes.Class)
+// mf = mf | (if (sym isFinal) TypeAttributes.Sealed else 0)
+//
+// sym.annotations foreach { a => a match {
+// case AnnotationInfo(SerializableAttr, _, _) =>
+// // TODO: add the Serializable TypeAttribute also if the annotation
+// // System.SerializableAttribute is present (.net annotation, not scala)
+// // Best way to do it: compare with
+// // definitions.getClass("System.SerializableAttribute").tpe
+// // when frontend available
+// mf = mf | TypeAttributes.Serializable
+// case _ => ()
+// }}
+//
+// mf
+// // static: not possible (or?)
+// }
+//
+// def msilMethodFlags(sym: Symbol): Short = {
+// var mf: Int = MethodAttributes.HideBySig |
+// (if (sym hasFlag Flags.PRIVATE) MethodAttributes.Private
+// else MethodAttributes.Public)
+//
+// if (!sym.isClassConstructor) {
+// if (sym.isStaticMember)
+// mf = mf | FieldAttributes.Static // coincidentally, same value as for MethodAttributes.Static ...
+// else {
+// mf = mf | MethodAttributes.Virtual
+// if (sym.isFinal && !getType(sym.owner).IsInterface)
+// mf = mf | MethodAttributes.Final
+// if (sym.isDeferred || getType(sym.owner).IsInterface)
+// mf = mf | MethodAttributes.Abstract
+// }
+// }
+//
+// if (sym.isStaticMember) {
+// mf = mf | MethodAttributes.Static
+// }
+//
+// // constructors of module classes should be private
+// if (sym.isPrimaryConstructor && isTopLevelModule(sym.owner)) {
+// mf |= MethodAttributes.Private
+// mf &= ~(MethodAttributes.Public)
+// }
+//
+// mf.toShort
+// }
+//
+// def msilFieldFlags(sym: Symbol): Short = {
+// var mf: Int =
+// if (sym hasFlag Flags.PRIVATE) FieldAttributes.Private
+// else if (sym hasFlag Flags.PROTECTED) FieldAttributes.FamORAssem
+// else FieldAttributes.Public
+//
+// if (sym hasFlag Flags.FINAL)
+// mf = mf | FieldAttributes.InitOnly
+//
+// if (sym.isStaticMember)
+// mf = mf | FieldAttributes.Static
+//
+// // TRANSIENT: "not serialized", VOLATILE: doesn't exist on .net
+// // TODO: add this annotation also if the class has the custom attribute
+// // System.NotSerializedAttribute
+// sym.annotations.foreach( a => a match {
+// case AnnotationInfo(TransientAtt, _, _) =>
+// mf = mf | FieldAttributes.NotSerialized
+// case _ => ()
+// })
+//
+// mf.toShort
+// }
+//
+// ////////////////////// builders, types ///////////////////////
+//
+// var entryPoint: Symbol = _
+//
+// val notInitializedModules = mutable.HashSet[Symbol]()
+//
+// // TODO: create fields also in def createType, and not in genClass,
+// // add a getField method (it only works as it is because fields never
+// // accessed from outside a class)
+//
+// val localBuilders = mutable.HashMap[Local, LocalBuilder]()
+//
+// private[GenMSIL] def findEntryPoint(cls: IClass) {
+//
+// def isEntryPoint(sym: Symbol):Boolean = {
+// if (isStaticModule(sym.owner) && msilName(sym) == "main")
+// if (sym.tpe.paramTypes.length == 1) {
+// toTypeKind(sym.tpe.paramTypes(0)) match {
+// case ARRAY(elem) =>
+// if (elem.toType.typeSymbol == definitions.StringClass) {
+// return true
+// }
+// case _ => ()
+// }
+// }
+// false
+// }
+//
+// 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
+// }
+//
+// // #####################################################################
+// // get and create types
+//
+// private def msilType(t: TypeKind): MsilType = (t: @unchecked) match {
+// case UNIT => MVOID
+// case BOOL => MBOOL
+// case BYTE => MBYTE
+// case SHORT => MSHORT
+// case CHAR => MCHAR
+// case INT => MINT
+// case LONG => MLONG
+// case FLOAT => MFLOAT
+// case DOUBLE => MDOUBLE
+// case REFERENCE(cls) => getType(cls)
+// case ARRAY(elem) =>
+// msilType(elem) match {
+// // For type builders, cannot call "clrTypes.mkArrayType" because this looks up
+// // the type "tp" in the assembly (not in the HashMap "types" of the backend).
+// // This can fail for nested types because the builders are not complete yet.
+// case tb: TypeBuilder => tb.MakeArrayType()
+// case tp: MsilType => clrTypes.mkArrayType(tp)
+// }
+// }
+//
+// private def msilType(tpe: Type): MsilType = msilType(toTypeKind(tpe))
+//
+// private def msilParamTypes(sym: Symbol): Array[MsilType] = {
+// sym.tpe.paramTypes.map(msilType).toArray
+// }
+//
+// def getType(sym: Symbol) = getTypeOpt(sym).getOrElse(abort(showsym(sym)))
+//
+// /**
+// * 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] = {
+// 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) {
+// assert(mType != null, showsym(sym))
+// types(sym) = mType
+// }
+//
+// def createTypeBuilder(iclass: IClass) {
+// /**
+// * First look in the clrTypes.types map, if that fails check if it's a class being compiled, otherwise
+// * lookup by name (clrTypes.getType calls the static method msil.Type.GetType(fullname)).
+// */
+// def msilTypeFromSym(sym: Symbol): MsilType = {
+// types.get(sym).getOrElse {
+// classes.get(sym) match {
+// case Some(iclass) =>
+// msilTypeBuilderFromSym(sym)
+// case None =>
+// getType(sym)
+// }
+// }
+// }
+//
+// def msilTypeBuilderFromSym(sym: Symbol): TypeBuilder = {
+// if(!(types.contains(sym) && types(sym).isInstanceOf[TypeBuilder])){
+// val iclass = classes(sym)
+// assert(iclass != null)
+// createTypeBuilder(iclass)
+// }
+// types(sym).asInstanceOf[TypeBuilder]
+// }
+//
+// val sym = iclass.symbol
+// if (types.contains(sym) && types(sym).isInstanceOf[TypeBuilder])
+// return
+//
+// def isInterface(s: Symbol) = s.isTrait && !s.isImplClass
+// val parents: List[Type] =
+// if (sym.info.parents.isEmpty) List(definitions.ObjectClass.tpe)
+// else sym.info.parents.distinct
+//
+// val superType : MsilType = if (isInterface(sym)) null else msilTypeFromSym(parents.head.typeSymbol)
+// debuglog("super type: " + parents(0).typeSymbol + ", msil type: " + superType)
+//
+// val interfaces: Array[MsilType] =
+// parents.tail.map(p => msilTypeFromSym(p.typeSymbol)).toArray
+// if (parents.length > 1) {
+// if (settings.debug.value) {
+// log("interfaces:")
+// for (i <- 0.until(interfaces.length)) {
+// log(" type: " + parents(i + 1).typeSymbol + ", msil type: " + interfaces(i))
+// }
+// }
+// }
+//
+// val tBuilder = if (sym.isNestedClass) {
+// val ownerT = msilTypeBuilderFromSym(sym.owner).asInstanceOf[TypeBuilder]
+// ownerT.DefineNestedType(msilName(sym), msilTypeFlags(sym), superType, interfaces)
+// } else {
+// mmodule.DefineType(msilName(sym), msilTypeFlags(sym), superType, interfaces)
+// }
+// mapType(sym, tBuilder)
+// } // createTypeBuilder
+//
+// def createClassMembers(iclass: IClass) {
+// try {
+// createClassMembers0(iclass)
+// }
+// catch {
+// case e: Throwable =>
+// java.lang.System.err.println(showsym(iclass.symbol))
+// java.lang.System.err.println("with methods = " + iclass.methods)
+// throw e
+// }
+// }
+//
+// def createClassMembers0(iclass: IClass) {
+//
+// val mtype = getType(iclass.symbol).asInstanceOf[TypeBuilder]
+//
+// for (ifield <- iclass.fields) {
+// val sym = ifield.symbol
+// debuglog("Adding field: " + sym.fullName)
+//
+// var attributes = msilFieldFlags(sym)
+// val fieldTypeWithCustomMods =
+// new PECustomMod(msilType(sym.tpe),
+// customModifiers(sym.annotations))
+// val fBuilder = mtype.DefineField(msilName(sym),
+// fieldTypeWithCustomMods,
+// attributes)
+// fields(sym) = fBuilder
+// addAttributes(fBuilder, sym.annotations)
+// } // all iclass.fields iterated over
+//
+// if (isStaticModule(iclass.symbol)) {
+// val sc = iclass.lookupStaticCtor
+// if (sc.isDefined) {
+// val m = sc.get
+// val oldLastBlock = m.lastBlock
+// val lastBlock = m.newBlock()
+// oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock))
+// // call object's private ctor from static ctor
+// lastBlock.emit(CIL_NEWOBJ(iclass.symbol.primaryConstructor))
+// lastBlock.emit(DROP(toTypeKind(iclass.symbol.tpe)))
+// lastBlock emit RETURN(UNIT)
+// lastBlock.close
+// }
+// }
+//
+// if (iclass.symbol != definitions.ArrayClass) {
+// for (m: IMethod <- iclass.methods) {
+// val sym = m.symbol
+// debuglog("Creating MethodBuilder for " + Flags.flagsToString(sym.flags) + " " +
+// sym.owner.fullName + "::" + sym.name)
+//
+// val ownerType = getType(sym.enclClass).asInstanceOf[TypeBuilder]
+// assert(mtype == ownerType, "mtype = " + mtype + "; ownerType = " + ownerType)
+// var paramTypes = msilParamTypes(sym)
+// val attr = msilMethodFlags(sym)
+//
+// if (m.symbol.isClassConstructor) {
+// val constr =
+// ownerType.DefineConstructor(attr, CallingConventions.Standard, paramTypes)
+// for (i <- 0.until(paramTypes.length)) {
+// constr.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
+// }
+// mapConstructor(sym, constr)
+// addAttributes(constr, sym.annotations)
+// } else {
+// var resType = msilType(m.returnType)
+// val method =
+// ownerType.DefineMethod(msilName(sym), attr, resType, paramTypes)
+// for (i <- 0.until(paramTypes.length)) {
+// method.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
+// }
+// if (!methods.contains(sym))
+// mapMethod(sym, method)
+// addAttributes(method, sym.annotations)
+// debuglog("\t created MethodBuilder " + method)
+// }
+// }
+// } // method builders created for non-array iclass
+//
+// if (isStaticModule(iclass.symbol)) {
+// addModuleInstanceField(iclass.symbol)
+// notInitializedModules += iclass.symbol
+// if (iclass.lookupStaticCtor.isEmpty) {
+// addStaticInit(iclass.symbol)
+// }
+// }
+//
+// } // createClassMembers0
+//
+// private def isTopLevelModule(sym: Symbol): Boolean =
+// atPhase (currentRun.refchecksPhase) {
+// sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass
+// }
+//
+// // if the module is lifted it does not need to be initialized in
+// // its static constructor, and the MODULE$ field is not required.
+// // the outer class will care about it.
+// private def isStaticModule(sym: Symbol): Boolean = {
+// // .net inner classes: removed '!sym.hasFlag(Flags.LIFTED)', added
+// // 'sym.isStatic'. -> no longer compatible without skipping flatten!
+// sym.isModuleClass && sym.isStatic && !sym.isImplClass
+// }
+//
+// private def isCloneable(sym: Symbol): Boolean = {
+// !sym.annotations.forall( a => a match {
+// case AnnotationInfo(CloneableAttr, _, _) => false
+// case _ => true
+// })
+// }
+//
+// private def addModuleInstanceField(sym: Symbol) {
+// debuglog("Adding Module-Instance Field for " + showsym(sym))
+// val tBuilder = getType(sym).asInstanceOf[TypeBuilder]
+// val fb = tBuilder.DefineField(MODULE_INSTANCE_NAME,
+// tBuilder,
+// (FieldAttributes.Public |
+// //FieldAttributes.InitOnly |
+// FieldAttributes.Static).toShort)
+// fields(sym) = fb
+// }
+//
+//
+// // the symbol may be a object-symbol (module-symbol), or a module-class-symbol
+// private def getModuleInstanceField(sym: Symbol): FieldInfo = {
+// assert(sym.isModule || sym.isModuleClass, "Expected module: " + showsym(sym))
+//
+// // when called by LOAD_MODULE, the corresponding type maybe doesn't
+// // exist yet -> make a getType
+// val moduleClassSym = if (sym.isModule) sym.moduleClass else sym
+//
+// // TODO: get module field for modules not defined in the
+// // source currently compiling (e.g. Console)
+//
+// fields get moduleClassSym match {
+// case Some(sym) => sym
+// case None =>
+// //val mclass = types(moduleClassSym)
+// val nameInMetadata = nestingAwareFullClassname(moduleClassSym)
+// val mClass = clrTypes.getType(nameInMetadata)
+// val mfield = mClass.GetField("MODULE$")
+// assert(mfield ne null, "module not found " + showsym(moduleClassSym))
+// fields(moduleClassSym) = mfield
+// mfield
+// }
+//
+// //fields(moduleClassSym)
+// }
+//
+// def nestingAwareFullClassname(csym: Symbol) : String = {
+// val suffix = csym.moduleSuffix
+// val res = if (csym.isNestedClass)
+// nestingAwareFullClassname(csym.owner) + "+" + csym.encodedName
+// else
+// csym.fullName
+// res + suffix
+// }
+//
+// /** Adds a static initializer which creates an instance of the module
+// * class (calls the primary constructor). A special primary constructor
+// * will be generated (notInitializedModules) which stores the new instance
+// * in the MODULE$ field right after the super call.
+// */
+// private def addStaticInit(sym: Symbol) {
+// val tBuilder = getType(sym).asInstanceOf[TypeBuilder]
+//
+// val staticInit = tBuilder.DefineConstructor(
+// (MethodAttributes.Static | MethodAttributes.Public).toShort,
+// CallingConventions.Standard,
+// MsilType.EmptyTypes)
+//
+// val sicode = staticInit.GetILGenerator()
+//
+// val instanceConstructor = constructors(sym.primaryConstructor)
+//
+// // there are no constructor parameters. assuming the constructor takes no parameter
+// // is fine: we call (in the static constructor) the constructor of the module class,
+// // which takes no arguments - an object definition cannot take constructor arguments.
+// sicode.Emit(OpCodes.Newobj, instanceConstructor)
+// // the stsfld is done in the instance constructor, just after the super call.
+// sicode.Emit(OpCodes.Pop)
+//
+// sicode.Emit(OpCodes.Ret)
+// }
+//
+// private def generateMirrorClass(sym: Symbol) {
+// val tBuilder = getType(sym)
+// assert(sym.isModuleClass, "Can't generate Mirror-Class for the Non-Module class " + sym)
+// debuglog("Dumping mirror class for object: " + sym)
+// val moduleName = msilName(sym)
+// val mirrorName = moduleName.substring(0, moduleName.length() - 1)
+// val mirrorTypeBuilder = mmodule.DefineType(mirrorName,
+// TypeAttributes.Class |
+// TypeAttributes.Public |
+// TypeAttributes.Sealed,
+// MOBJECT,
+// MsilType.EmptyTypes)
+//
+// val iclass = classes(sym)
+//
+// for (m <- sym.tpe.nonPrivateMembers
+// if m.owner != definitions.ObjectClass && !m.isProtected &&
+// m.isMethod && !m.isClassConstructor && !m.isStaticMember && !m.isCase &&
+// !m.isDeferred)
+// {
+// debuglog(" Mirroring method: " + m)
+// val paramTypes = msilParamTypes(m)
+// val paramNames: Array[String] = new Array[String](paramTypes.length)
+// for (i <- 0 until paramTypes.length)
+// paramNames(i) = "x_" + i
+//
+// // CHECK: verify if getMethodName is better than msilName
+// val mirrorMethod = mirrorTypeBuilder.DefineMethod(msilName(m),
+// (MethodAttributes.Public |
+// MethodAttributes.Static).toShort,
+// msilType(m.tpe.resultType),
+// paramTypes)
+//
+// var i = 0
+// while (i < paramTypes.length) {
+// mirrorMethod.DefineParameter(i, ParameterAttributes.None, paramNames(i))
+// i += 1
+// }
+//
+// val mirrorCode = mirrorMethod.GetILGenerator()
+// mirrorCode.Emit(OpCodes.Ldsfld, getModuleInstanceField(sym))
+// val mInfo = getMethod(m)
+// for (paramidx <- 0.until(paramTypes.length)) {
+// val mInfoParams = mInfo.GetParameters
+// val loadAddr = mInfoParams(paramidx).ParameterType.IsByRef
+// loadArg(mirrorCode, loadAddr)(paramidx)
+// }
+//
+// mirrorCode.Emit(OpCodes.Callvirt, getMethod(m))
+// mirrorCode.Emit(OpCodes.Ret)
+// }
+//
+// addSymtabAttribute(sym.sourceModule, mirrorTypeBuilder)
+//
+// mirrorTypeBuilder.CreateType()
+// mirrorTypeBuilder.setSourceFilepath(iclass.cunit.source.file.path)
+// }
+//
+//
+// // #####################################################################
+// // delegate callers
+//
+// var delegateCallers: TypeBuilder = _
+// var nbDelegateCallers: Int = 0
+//
+// private def initDelegateCallers() = {
+// delegateCallers = mmodule.DefineType("$DelegateCallers", TypeAttributes.Public |
+// TypeAttributes.Sealed)
+// }
+//
+// private def createDelegateCaller(functionType: Type, delegateType: Type) = {
+// if (delegateCallers == null)
+// initDelegateCallers()
+// // create a field an store the function-object
+// val mFunctionType: MsilType = msilType(functionType)
+// val anonfunField: FieldBuilder = delegateCallers.DefineField(
+// "$anonfunField$$" + nbDelegateCallers, mFunctionType,
+// (FieldAttributes.InitOnly | FieldAttributes.Public | FieldAttributes.Static).toShort)
+// mcode.Emit(OpCodes.Stsfld, anonfunField)
+//
+//
+// // create the static caller method and the delegate object
+// val (params, returnType) = delegateType.member(nme.apply).tpe match {
+// case MethodType(delParams, delReturn) => (delParams, delReturn)
+// case _ => abort("not a delegate type: " + delegateType)
+// }
+// val caller: MethodBuilder = delegateCallers.DefineMethod(
+// "$delegateCaller$$" + nbDelegateCallers,
+// (MethodAttributes.Final | MethodAttributes.Public | MethodAttributes.Static).toShort,
+// msilType(returnType), (params map (_.tpe)).map(msilType).toArray)
+// for (i <- 0 until params.length)
+// caller.DefineParameter(i, ParameterAttributes.None, "arg" + i) // FIXME: use name of parameter symbol
+// val delegCtor = msilType(delegateType).GetConstructor(Array(MOBJECT, INT_PTR))
+// mcode.Emit(OpCodes.Ldnull)
+// mcode.Emit(OpCodes.Ldftn, caller)
+// mcode.Emit(OpCodes.Newobj, delegCtor)
+//
+//
+// // create the static caller method body
+// val functionApply: MethodInfo = getMethod(functionType.member(nme.apply))
+// val dcode: ILGenerator = caller.GetILGenerator()
+// dcode.Emit(OpCodes.Ldsfld, anonfunField)
+// for (i <- 0 until params.length) {
+// loadArg(dcode, false /* TODO confirm whether passing actual as-is to formal is correct wrt the ByRef attribute of the param */)(i)
+// emitBox(dcode, toTypeKind(params(i).tpe))
+// }
+// dcode.Emit(OpCodes.Callvirt, functionApply)
+// emitUnbox(dcode, toTypeKind(returnType))
+// dcode.Emit(OpCodes.Ret)
+//
+// nbDelegateCallers = nbDelegateCallers + 1
+//
+// } //def createDelegateCaller
+//
+// def emitBox(code: ILGenerator, boxType: TypeKind) = (boxType: @unchecked) match {
+// // doesn't make sense, unit as parameter..
+// 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 clrTypes.isValueType(cls) =>
+// code.Emit(OpCodes.Box, (msilType(boxType)))
+// 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)
+// /* (1) it's essential to keep the code emitted here (as of now plain calls to System.Convert.ToBlaBla methods)
+// behaviorally.equiv.wrt. BoxesRunTime.unboxToBlaBla methods
+// (case null: that's easy, case boxed: track changes to unboxBlaBla)
+// (2) See also: asInstanceOf to cast from Any to number,
+// tracked in http://lampsvn.epfl.ch/trac/scala/ticket/4437 */
+// case BOOL => code.Emit(OpCodes.Call, toBool)
+// 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 clrTypes.isValueType(cls) =>
+// code.Emit(OpCodes.Unbox, msilType(boxType))
+// code.Emit(OpCodes.Ldobj, msilType(boxType))
+// case REFERENCE(_) | ARRAY(_) =>
+// warning("Tried to UNBOX a non-valuetype.")
+// ()
+// }
+//
+// // #####################################################################
+// // get and create methods / constructors
+//
+// def getConstructor(sym: Symbol): ConstructorInfo = constructors.get(sym) match {
+// case Some(constr) => constr
+// case None =>
+// val mClass = getType(sym.owner)
+// val constr = mClass.GetConstructor(msilParamTypes(sym))
+// if (constr eq null) {
+// java.lang.System.out.println("Cannot find constructor " + sym.owner + "::" + sym.name)
+// java.lang.System.out.println("scope = " + sym.owner.tpe.decls)
+// abort(sym.fullName)
+// }
+// else {
+// mapConstructor(sym, constr)
+// constr
+// }
+// }
+//
+// def mapConstructor(sym: Symbol, cInfo: ConstructorInfo) = {
+// constructors(sym) = cInfo
+// }
+//
+// private def getMethod(sym: Symbol): MethodInfo = {
+//
+// methods.get(sym) match {
+// case Some(method) => method
+// case None =>
+// val mClass = getType(sym.owner)
+// try {
+// 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))
+// java.lang.System.out.println("scope = " + sym.owner.tpe.decls)
+// abort(sym.fullName)
+// }
+// else {
+// mapMethod(sym, method)
+// method
+// }
+// }
+// catch {
+// case e: Exception =>
+// Console.println("While looking up " + mClass + "::" + sym.nameString)
+// Console.println("\t" + showsym(sym))
+// throw e
+// }
+// }
+// }
+//
+// /*
+// * add a mapping between sym and mInfo
+// */
+// private def mapMethod(sym: Symbol, mInfo: MethodInfo) {
+// assert (mInfo != null, mInfo)
+// methods(sym) = mInfo
+// }
+//
+// /*
+// * add mapping between sym and method with newName, paramTypes of newClass
+// */
+// private def mapMethod(sym: Symbol, newClass: MsilType, newName: String, paramTypes: Array[MsilType]) {
+// val methodInfo = newClass.GetMethod(newName, paramTypes)
+// assert(methodInfo != null, "Can't find mapping for " + sym + " -> " +
+// newName + "(" + paramTypes + ")")
+// mapMethod(sym, methodInfo)
+// if (methodInfo.IsStatic)
+// dynToStatMapped += sym
+// }
+//
+// /*
+// * add mapping between method with name and paramTypes of clazz to
+// * method with newName and newParamTypes of newClass (used for instance
+// * for "wait")
+// */
+// private def mapMethod(
+// clazz: Symbol, name: Name, paramTypes: Array[Type],
+// newClass: MsilType, newName: String, newParamTypes: Array[MsilType]) {
+// val methodSym = lookupMethod(clazz, name, paramTypes)
+// assert(methodSym != null, "cannot find method " + name + "(" +
+// paramTypes + ")" + " in class " + clazz)
+// mapMethod(methodSym, newClass, newName, newParamTypes)
+// }
+//
+// /*
+// * add mapping for member with name and paramTypes to member
+// * newName of newClass (same parameters)
+// */
+// private def mapMethod(
+// clazz: Symbol, name: Name, paramTypes: Array[Type],
+// newClass: MsilType, newName: String) {
+// mapMethod(clazz, name, paramTypes, newClass, newName, paramTypes map msilType)
+// }
+//
+// /*
+// * add mapping for all methods with name of clazz to the corresponding
+// * method (same parameters) with newName of newClass
+// */
+// private def mapMethod(
+// clazz: Symbol, name: Name,
+// newClass: MsilType, newName: String) {
+// val memberSym: Symbol = clazz.tpe.member(name)
+// memberSym.tpe match {
+// // alternatives: List[Symbol]
+// case OverloadedType(_, alternatives) =>
+// alternatives.foreach(s => mapMethod(s, newClass, newName, msilParamTypes(s)))
+//
+// // paramTypes: List[Type], resType: Type
+// case MethodType(params, resType) =>
+// mapMethod(memberSym, newClass, newName, msilParamTypes(memberSym))
+//
+// case _ =>
+// abort("member not found: " + clazz + ", " + name)
+// }
+// }
+//
+//
+// /*
+// * find the method in clazz with name and paramTypes
+// */
+// private def lookupMethod(clazz: Symbol, name: Name, paramTypes: Array[Type]): Symbol = {
+// val memberSym = clazz.tpe.member(name)
+// memberSym.tpe match {
+// case OverloadedType(_, alternatives) =>
+// alternatives.find(s => {
+// var i: Int = 0
+// var typesOK: Boolean = true
+// if (paramTypes.length == s.tpe.paramTypes.length) {
+// while(i < paramTypes.length) {
+// if (paramTypes(i) != s.tpe.paramTypes(i))
+// typesOK = false
+// i += 1
+// }
+// } else {
+// typesOK = false
+// }
+// typesOK
+// }) match {
+// case Some(sym) => sym
+// case None => abort("member of " + clazz + ", " + name + "(" +
+// paramTypes + ") not found")
+// }
+//
+// case MethodType(_, _) => memberSym
+//
+// case _ => abort("member not found: " + name + " of " + clazz)
+// }
+// }
+//
+// private def showsym(sym: Symbol): String = (sym.toString +
+// "\n symbol = " + Flags.flagsToString(sym.flags) + " " + sym +
+// "\n owner = " + Flags.flagsToString(sym.owner.flags) + " " + sym.owner
+// )
+//
+// } // class BytecodeGenerator
+//
+// } // class GenMSIL
diff --git a/src/compiler/scala/tools/nsc/io/MsilFile.scala b/src/compiler/scala/tools/nsc/io/MsilFile.scala
index d970d0e9c9..2982812fdd 100644
--- a/src/compiler/scala/tools/nsc/io/MsilFile.scala
+++ b/src/compiler/scala/tools/nsc/io/MsilFile.scala
@@ -1,18 +1,18 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package io
-
-import ch.epfl.lamp.compiler.msil.{ Type => MsilType, _ }
-
-/** This class wraps an MsilType. It exists only so
- * ClassPath can treat all of JVM/MSIL/bin/src files
- * uniformly, as AbstractFiles.
- */
-class MsilFile(val msilType: MsilType) extends VirtualFile(msilType.FullName, msilType.Namespace) {
-}
-
-object NoMsilFile extends MsilFile(null) { }
+// /* NSC -- new Scala compiler
+// * Copyright 2005-2011 LAMP/EPFL
+// * @author Paul Phillips
+// */
+//
+// package scala.tools.nsc
+// package io
+//
+// import ch.epfl.lamp.compiler.msil.{ Type => MsilType, _ }
+//
+// /** This class wraps an MsilType. It exists only so
+// * ClassPath can treat all of JVM/MSIL/bin/src files
+// * uniformly, as AbstractFiles.
+// */
+// class MsilFile(val msilType: MsilType) extends VirtualFile(msilType.FullName, msilType.Namespace) {
+// }
+//
+// object NoMsilFile extends MsilFile(null) { }
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 942ec1fa86..2241bb224e 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -13,7 +13,7 @@ import classfile.ClassfileParser
import reflect.internal.Flags._
import reflect.internal.MissingRequirementError
import util.Statistics._
-import scala.tools.nsc.io.{ AbstractFile, MsilFile }
+import scala.tools.nsc.io.{ AbstractFile } //, MsilFile }
/** This class ...
*
@@ -236,16 +236,16 @@ abstract class SymbolLoaders {
}
override def sourcefile: Option[AbstractFile] = classfileParser.srcfile
}
-
- class MsilFileLoader(msilFile: MsilFile) extends SymbolLoader {
- private def typ = msilFile.msilType
- private object typeParser extends clr.TypeParser {
- val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
- }
-
- protected def description = "MsilFile "+ typ.FullName + ", assembly "+ typ.Assembly.FullName
- protected def doComplete(root: Symbol) { typeParser.parse(typ, root) }
- }
+ //
+ // class MsilFileLoader(msilFile: MsilFile) extends SymbolLoader {
+ // private def typ = msilFile.msilType
+ // private object typeParser extends clr.TypeParser {
+ // val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
+ // }
+ //
+ // protected def description = "MsilFile "+ typ.FullName + ", assembly "+ typ.Assembly.FullName
+ // protected def doComplete(root: Symbol) { typeParser.parse(typ, root) }
+ // }
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
protected def description = "source file "+ srcfile.toString
@@ -258,11 +258,11 @@ abstract class SymbolLoaders {
protected def description = "module class loader"
protected def doComplete(root: Symbol) { root.sourceModule.initialize }
}
-
- object clrTypes extends clr.CLRTypes {
- val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
- if (global.forMSIL) init()
- }
+ //
+ // object clrTypes extends clr.CLRTypes {
+ // val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
+ // if (global.forMSIL) init()
+ // }
/** used from classfile parser to avoid cyclies */
var parentsLevel = 0
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala
index 7be0fcb146..4346cb6f8d 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala
@@ -1,137 +1,137 @@
-/* NSC -- new scala compiler
- * Copyright 2004-2011 LAMP/EPFL
- */
-
-
-package scala.tools.nsc
-package symtab
-package clr
-
-import java.io.File
-import java.util.{Comparator, StringTokenizer}
-import scala.util.Sorting
-import ch.epfl.lamp.compiler.msil._
-import scala.collection.{ mutable, immutable }
-import scala.tools.nsc.util.{Position, NoPosition}
-
-/**
- * Collects all types from all reference assemblies.
- */
-abstract class CLRTypes {
-
- val global: Global
- import global.Symbol
- import global.definitions
-
- //##########################################################################
-
- var BYTE: Type = _
- var UBYTE: Type = _
- var SHORT: Type = _
- var USHORT: Type = _
- var CHAR: Type = _
- var INT: Type = _
- var UINT: Type = _
- var LONG: Type = _
- var ULONG: Type = _
- var FLOAT: Type = _
- var DOUBLE: Type = _
- var BOOLEAN: Type = _
- var VOID: Type = _
- var ENUM: Type = _
- var DELEGATE: Type = _
-
- var OBJECT: Type = _
- var STRING: Type = _
- var STRING_ARRAY: Type = _
-
- var VALUE_TYPE: Type = _
-
- var SCALA_SYMTAB_ATTR: Type = _
- var SYMTAB_CONSTR: ConstructorInfo = _
- var SYMTAB_DEFAULT_CONSTR: ConstructorInfo = _
-
- var DELEGATE_COMBINE: MethodInfo = _
- var DELEGATE_REMOVE: MethodInfo = _
-
- val types: mutable.Map[Symbol,Type] = new mutable.HashMap
- val constructors: mutable.Map[Symbol,ConstructorInfo] = new mutable.HashMap
- val methods: mutable.Map[Symbol,MethodInfo] = new mutable.HashMap
- val fields: mutable.Map[Symbol, FieldInfo] = new mutable.HashMap
- val sym2type: mutable.Map[Type,Symbol] = new mutable.HashMap
- val addressOfViews = new mutable.HashSet[Symbol]
- val mdgptrcls4clssym: mutable.Map[ /*cls*/ Symbol, /*cls*/ Symbol] = new mutable.HashMap
-
- def isAddressOf(msym : Symbol) = addressOfViews.contains(msym)
-
- def isNonEnumValuetype(cls: Symbol) = {
- val msilTOpt = types.get(cls)
- val res = msilTOpt.isDefined && {
- val msilT = msilTOpt.get
- msilT.IsValueType && !msilT.IsEnum
- }
- res
- }
-
- def isValueType(cls: Symbol): Boolean = {
- val opt = types.get(cls)
- opt.isDefined && opt.get.IsValueType
- }
-
- def init() = try { // initialize
- // the MsilClasspath (nsc/util/Classpath.scala) initializes the msil-library by calling
- // Assembly.LoadFrom("mscorlib.dll"), so this type should be found
- Type.initMSCORLIB(getTypeSafe("System.String").Assembly)
-
- BYTE = getTypeSafe("System.SByte")
- UBYTE = getTypeSafe("System.Byte")
- CHAR = getTypeSafe("System.Char")
- SHORT = getTypeSafe("System.Int16")
- USHORT = getTypeSafe("System.UInt16")
- INT = getTypeSafe("System.Int32")
- UINT = getTypeSafe("System.UInt32")
- LONG = getTypeSafe("System.Int64")
- ULONG = getTypeSafe("System.UInt64")
- FLOAT = getTypeSafe("System.Single")
- DOUBLE = getTypeSafe("System.Double")
- BOOLEAN = getTypeSafe("System.Boolean")
- VOID = getTypeSafe("System.Void")
- ENUM = getTypeSafe("System.Enum")
- DELEGATE = getTypeSafe("System.MulticastDelegate")
-
- OBJECT = getTypeSafe("System.Object")
- STRING = getTypeSafe("System.String")
- STRING_ARRAY = getTypeSafe("System.String[]")
- VALUE_TYPE = getTypeSafe("System.ValueType")
-
- SCALA_SYMTAB_ATTR = getTypeSafe("scala.runtime.SymtabAttribute")
- val bytearray: Array[Type] = Array(Type.GetType("System.Byte[]"))
- SYMTAB_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(bytearray)
- SYMTAB_DEFAULT_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(Type.EmptyTypes)
-
- val delegate: Type = getTypeSafe("System.Delegate")
- val dargs: Array[Type] = Array(delegate, delegate)
- DELEGATE_COMBINE = delegate.GetMethod("Combine", dargs)
- DELEGATE_REMOVE = delegate.GetMethod("Remove", dargs)
- }
- catch {
- case e: RuntimeException =>
- Console.println(e.getMessage)
- throw e
- }
-
- //##########################################################################
- // type mapping and lookup
-
- def getType(name: String): Type = Type.GetType(name)
-
- def getTypeSafe(name: String): Type = {
- val t = Type.GetType(name)
- assert(t != null, name)
- t
- }
-
- def mkArrayType(elemType: Type): Type = getType(elemType.FullName + "[]")
-
- def isDelegateType(t: Type): Boolean = { t.BaseType() == DELEGATE }
-} // CLRTypes
+// /* NSC -- new scala compiler
+// * Copyright 2004-2011 LAMP/EPFL
+// */
+//
+//
+// package scala.tools.nsc
+// package symtab
+// package clr
+//
+// import java.io.File
+// import java.util.{Comparator, StringTokenizer}
+// import scala.util.Sorting
+// import ch.epfl.lamp.compiler.msil._
+// import scala.collection.{ mutable, immutable }
+// import scala.tools.nsc.util.{Position, NoPosition}
+//
+// /**
+// * Collects all types from all reference assemblies.
+// */
+// abstract class CLRTypes {
+//
+// val global: Global
+// import global.Symbol
+// import global.definitions
+//
+// //##########################################################################
+//
+// var BYTE: Type = _
+// var UBYTE: Type = _
+// var SHORT: Type = _
+// var USHORT: Type = _
+// var CHAR: Type = _
+// var INT: Type = _
+// var UINT: Type = _
+// var LONG: Type = _
+// var ULONG: Type = _
+// var FLOAT: Type = _
+// var DOUBLE: Type = _
+// var BOOLEAN: Type = _
+// var VOID: Type = _
+// var ENUM: Type = _
+// var DELEGATE: Type = _
+//
+// var OBJECT: Type = _
+// var STRING: Type = _
+// var STRING_ARRAY: Type = _
+//
+// var VALUE_TYPE: Type = _
+//
+// var SCALA_SYMTAB_ATTR: Type = _
+// var SYMTAB_CONSTR: ConstructorInfo = _
+// var SYMTAB_DEFAULT_CONSTR: ConstructorInfo = _
+//
+// var DELEGATE_COMBINE: MethodInfo = _
+// var DELEGATE_REMOVE: MethodInfo = _
+//
+// val types: mutable.Map[Symbol,Type] = new mutable.HashMap
+// val constructors: mutable.Map[Symbol,ConstructorInfo] = new mutable.HashMap
+// val methods: mutable.Map[Symbol,MethodInfo] = new mutable.HashMap
+// val fields: mutable.Map[Symbol, FieldInfo] = new mutable.HashMap
+// val sym2type: mutable.Map[Type,Symbol] = new mutable.HashMap
+// val addressOfViews = new mutable.HashSet[Symbol]
+// val mdgptrcls4clssym: mutable.Map[ /*cls*/ Symbol, /*cls*/ Symbol] = new mutable.HashMap
+//
+// def isAddressOf(msym : Symbol) = addressOfViews.contains(msym)
+//
+// def isNonEnumValuetype(cls: Symbol) = {
+// val msilTOpt = types.get(cls)
+// val res = msilTOpt.isDefined && {
+// val msilT = msilTOpt.get
+// msilT.IsValueType && !msilT.IsEnum
+// }
+// res
+// }
+//
+// def isValueType(cls: Symbol): Boolean = {
+// val opt = types.get(cls)
+// opt.isDefined && opt.get.IsValueType
+// }
+//
+// def init() = try { // initialize
+// // the MsilClasspath (nsc/util/Classpath.scala) initializes the msil-library by calling
+// // Assembly.LoadFrom("mscorlib.dll"), so this type should be found
+// Type.initMSCORLIB(getTypeSafe("System.String").Assembly)
+//
+// BYTE = getTypeSafe("System.SByte")
+// UBYTE = getTypeSafe("System.Byte")
+// CHAR = getTypeSafe("System.Char")
+// SHORT = getTypeSafe("System.Int16")
+// USHORT = getTypeSafe("System.UInt16")
+// INT = getTypeSafe("System.Int32")
+// UINT = getTypeSafe("System.UInt32")
+// LONG = getTypeSafe("System.Int64")
+// ULONG = getTypeSafe("System.UInt64")
+// FLOAT = getTypeSafe("System.Single")
+// DOUBLE = getTypeSafe("System.Double")
+// BOOLEAN = getTypeSafe("System.Boolean")
+// VOID = getTypeSafe("System.Void")
+// ENUM = getTypeSafe("System.Enum")
+// DELEGATE = getTypeSafe("System.MulticastDelegate")
+//
+// OBJECT = getTypeSafe("System.Object")
+// STRING = getTypeSafe("System.String")
+// STRING_ARRAY = getTypeSafe("System.String[]")
+// VALUE_TYPE = getTypeSafe("System.ValueType")
+//
+// SCALA_SYMTAB_ATTR = getTypeSafe("scala.runtime.SymtabAttribute")
+// val bytearray: Array[Type] = Array(Type.GetType("System.Byte[]"))
+// SYMTAB_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(bytearray)
+// SYMTAB_DEFAULT_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(Type.EmptyTypes)
+//
+// val delegate: Type = getTypeSafe("System.Delegate")
+// val dargs: Array[Type] = Array(delegate, delegate)
+// DELEGATE_COMBINE = delegate.GetMethod("Combine", dargs)
+// DELEGATE_REMOVE = delegate.GetMethod("Remove", dargs)
+// }
+// catch {
+// case e: RuntimeException =>
+// Console.println(e.getMessage)
+// throw e
+// }
+//
+// //##########################################################################
+// // type mapping and lookup
+//
+// def getType(name: String): Type = Type.GetType(name)
+//
+// def getTypeSafe(name: String): Type = {
+// val t = Type.GetType(name)
+// assert(t != null, name)
+// t
+// }
+//
+// def mkArrayType(elemType: Type): Type = getType(elemType.FullName + "[]")
+//
+// def isDelegateType(t: Type): Boolean = { t.BaseType() == DELEGATE }
+// } // CLRTypes
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 736d1c78a3..82d1dd6bc3 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -1,851 +1,851 @@
-/* NSC -- new scala compiler
- * Copyright 2004-2011 LAMP/EPFL
- */
-
-package scala.tools.nsc
-package symtab
-package clr
-
-import java.io.IOException
-import io.MsilFile
-import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute, _}
-import scala.collection.{ mutable, immutable }
-import scala.reflect.internal.pickling.UnPickler
-import ch.epfl.lamp.compiler.msil.Type.TMVarUsage
-
-/**
- * @author Nikolay Mihaylov
- */
-abstract class TypeParser {
-
- val global: Global
-
- import global._
- import loaders.clrTypes
-
- //##########################################################################
-
- private var clazz: Symbol = _
- private var instanceDefs: Scope = _ // was members
- private var staticModule: Symbol = _ // was staticsClass
- private var staticDefs: Scope = _ // was statics
-
- protected def statics: Symbol = staticModule.moduleClass
-
- protected var busy: Boolean = false // lock to detect recursive reads
-
- private implicit def stringToTermName(s: String): TermName = newTermName(s)
-
- private object unpickler extends UnPickler {
- val global: TypeParser.this.global.type = TypeParser.this.global
- }
-
- def parse(typ: MSILType, root: Symbol) {
-
- def handleError(e: Throwable) = {
- if (settings.debug.value) e.printStackTrace() //debug
- throw new IOException("type '" + typ.FullName + "' is broken\n(" + e.getMessage() + ")")
- }
- assert(!busy)
- busy = true
-
- if (root.isModule) {
- this.clazz = root.companionClass
- this.staticModule = root
- } else {
- this.clazz = root
- this.staticModule = root.companionModule
- }
- try {
- parseClass(typ)
- } catch {
- case e: FatalError => handleError(e)
- case e: RuntimeException => handleError(e)
- }
- busy = false
- }
-
- class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType {
- override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
- }
-
- /* the names `classTParams` and `newTParams` stem from the forJVM version (ClassfileParser.sigToType())
- * but there are differences that should be kept in mind.
- * forMSIL, a nested class knows nothing about any type-params in the nesting class,
- * therefore newTParams is redundant (other than for recording lexical order),
- * it always contains the same elements as classTParams.value */
- val classTParams = scala.collection.mutable.Map[Int,Symbol]() // TODO should this be a stack? (i.e., is it possible for >1 invocation to getCLRType on the same TypeParser instance be active )
- val newTParams = new scala.collection.mutable.ListBuffer[Symbol]()
- val methodTParams = scala.collection.mutable.Map[Int,Symbol]()
-
- private def sig2typeBounds(tvarCILDef: GenericParamAndConstraints): Type = {
- val ts = new scala.collection.mutable.ListBuffer[Type]
- for (cnstrnt <- tvarCILDef.Constraints) {
- ts += getCLRType(cnstrnt) // TODO we're definitely not at or after erasure, no need to call objToAny, right?
- }
- TypeBounds.upper(intersectionType(ts.toList, clazz))
- // TODO variance???
- }
-
- private def createViewFromTo(viewSuffix : String, fromTpe : Type, toTpe : Type,
- addToboxMethodMap : Boolean, isAddressOf : Boolean) : Symbol = {
- val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? shouldn't be final instead?
- val viewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(List(fromTpe)), toTpe)
- val vmsym = createMethod(nme.view_ + viewSuffix, flags, viewMethodType, null, true);
- // !!! this used to mutate a mutable map in definitions, but that map became
- // immutable and this kept "working" with a no-op. So now it's commented out
- // since I retired the deprecated code which allowed for that bug.
- //
- // if (addToboxMethodMap) definitions.boxMethod(clazz) = vmsym
-
- if (isAddressOf) clrTypes.addressOfViews += vmsym
- vmsym
- }
-
- private def createDefaultConstructor(typ: MSILType) {
- val attrs = MethodAttributes.Public | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName // TODO instance
- val declType= typ
- val method = new ConstructorInfo(declType, attrs, Array[MSILType]())
- val flags = Flags.JAVA
- val owner = clazz
- val methodSym = owner.newMethod(NoPosition, nme.CONSTRUCTOR).setFlag(flags)
- val rettype = clazz.tpe
- val mtype = methodType(Array[MSILType](), rettype);
- val mInfo = mtype(methodSym)
- methodSym.setInfo(mInfo)
- instanceDefs.enter(methodSym);
- clrTypes.constructors(methodSym) = method
- }
-
- private def parseClass(typ: MSILType) {
-
- {
- val t4c = clrTypes.types.get(clazz)
- assert(t4c == None || t4c == Some(typ))
- }
- clrTypes.types(clazz) = typ
-
- {
- val c4t = clrTypes.sym2type.get(typ)
- assert(c4t == None || c4t == Some(clazz))
- }
- clrTypes.sym2type(typ) = clazz
-
- if (typ.IsDefined(clrTypes.SCALA_SYMTAB_ATTR, false)) {
- val attrs = typ.GetCustomAttributes(clrTypes.SCALA_SYMTAB_ATTR, false);
- assert (attrs.length == 1, attrs.length);
- val a = attrs(0).asInstanceOf[MSILAttribute];
- assert (a.getConstructor() == clrTypes.SYMTAB_CONSTR);
- val symtab = a.getConstructorArguments()(0).asInstanceOf[Array[Byte]]
- unpickler.unpickle(symtab, 0, clazz, staticModule, typ.FullName);
- val mClass = clrTypes.getType(typ.FullName + "$");
- if (mClass != null) {
- clrTypes.types(statics) = mClass;
- val moduleInstance = mClass.GetField("MODULE$");
- assert (moduleInstance != null, mClass);
- clrTypes.fields(statics) = moduleInstance;
- }
- return
- }
- val flags = translateAttributes(typ)
-
- var clazzBoxed : Symbol = NoSymbol
- var clazzMgdPtr : Symbol = NoSymbol
-
- val canBeTakenAddressOf = (typ.IsValueType || typ.IsEnum) && (typ.FullName != "System.Enum")
-
- if(canBeTakenAddressOf) {
- clazzBoxed = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("Boxed"))
- clazzMgdPtr = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("MgdPtr"))
- clrTypes.mdgptrcls4clssym(clazz) = clazzMgdPtr
- /* adding typMgdPtr to clrTypes.sym2type should happen early (before metadata for supertypes is parsed,
- before metadata for members are parsed) so that clazzMgdPtr can be found by getClRType. */
- val typMgdPtr = MSILType.mkByRef(typ)
- clrTypes.types(clazzMgdPtr) = typMgdPtr
- clrTypes.sym2type(typMgdPtr) = clazzMgdPtr
- /* clazzMgdPtr but not clazzBoxed is mapped by clrTypes.types into an msil.Type instance,
- because there's no metadata-level representation for a "boxed valuetype" */
- val instanceDefsMgdPtr = newScope
- val classInfoMgdPtr = ClassInfoType(definitions.anyvalparam, instanceDefsMgdPtr, clazzMgdPtr)
- clazzMgdPtr.setFlag(flags)
- clazzMgdPtr.setInfo(classInfoMgdPtr)
- }
-
-/* START CLR generics (snippet 1) */
- // first pass
- for (tvarCILDef <- typ.getSortedTVars() ) {
- val tpname = newTypeName(tvarCILDef.Name.replaceAll("!", "")) // TODO are really all type-params named in all assemblies out there? (NO)
- val tpsym = clazz.newTypeParameter(tpname)
- classTParams.put(tvarCILDef.Number, tpsym)
- newTParams += tpsym
- // TODO wouldn't the following also be needed later, i.e. during getCLRType
- tpsym.setInfo(definitions.AnyClass.tpe)
- }
- // second pass
- for (tvarCILDef <- typ.getSortedTVars() ) {
- val tpsym = classTParams(tvarCILDef.Number)
- tpsym.setInfo(sig2typeBounds(tvarCILDef)) // we never skip bounds unlike in forJVM
- }
-/* END CLR generics (snippet 1) */
- val ownTypeParams = newTParams.toList
-/* START CLR generics (snippet 2) */
- if (!ownTypeParams.isEmpty) {
- clazz.setInfo(new TypeParamsType(ownTypeParams))
- if(typ.IsValueType && !typ.IsEnum) {
- clazzBoxed.setInfo(new TypeParamsType(ownTypeParams))
- }
- }
-/* END CLR generics (snippet 2) */
- instanceDefs = newScope
- staticDefs = newScope
-
- val classInfoAsInMetadata = {
- val ifaces: Array[MSILType] = typ.getInterfaces()
- val superType = if (typ.BaseType() != null) getCLRType(typ.BaseType())
- else if (typ.IsInterface()) definitions.ObjectClass.tpe
- else definitions.AnyClass.tpe; // this branch activates for System.Object only.
- // parents (i.e., base type and interfaces)
- val parents = new scala.collection.mutable.ListBuffer[Type]()
- parents += superType
- for (iface <- ifaces) {
- parents += getCLRType(iface) // here the variance doesn't matter
- }
- // methods, properties, events, fields are entered in a moment
- if (canBeTakenAddressOf) {
- val instanceDefsBoxed = newScope
- ClassInfoType(parents.toList, instanceDefsBoxed, clazzBoxed)
- } else
- ClassInfoType(parents.toList, instanceDefs, clazz)
- }
-
- val staticInfo = ClassInfoType(List(), staticDefs, statics)
-
- clazz.setFlag(flags)
-
- if (canBeTakenAddressOf) {
- clazzBoxed.setInfo( if (ownTypeParams.isEmpty) classInfoAsInMetadata
- else GenPolyType(ownTypeParams, classInfoAsInMetadata) )
- clazzBoxed.setFlag(flags)
- val rawValueInfoType = ClassInfoType(definitions.anyvalparam, instanceDefs, clazz)
- clazz.setInfo( if (ownTypeParams.isEmpty) rawValueInfoType
- else GenPolyType(ownTypeParams, rawValueInfoType) )
- } else {
- clazz.setInfo( if (ownTypeParams.isEmpty) classInfoAsInMetadata
- else GenPolyType(ownTypeParams, classInfoAsInMetadata) )
- }
-
- // TODO I don't remember if statics.setInfo and staticModule.setInfo should also know about type params
- statics.setFlag(Flags.JAVA)
- statics.setInfo(staticInfo)
- staticModule.setFlag(Flags.JAVA)
- staticModule.setInfo(statics.tpe)
-
-
- if (canBeTakenAddressOf) {
- // implicit conversions are owned by staticModule.moduleClass
- createViewFromTo("2Boxed", clazz.tpe, clazzBoxed.tpe, addToboxMethodMap = true, isAddressOf = false)
- // createViewFromTo("2Object", clazz.tpe, definitions.ObjectClass.tpe, addToboxMethodMap = true, isAddressOf = false)
- createViewFromTo("2MgdPtr", clazz.tpe, clazzMgdPtr.tpe, addToboxMethodMap = false, isAddressOf = true)
- // a return can't have type managed-pointer, thus a dereference-conversion is not needed
- // similarly, a method can't declare as return type "boxed valuetype"
- if (!typ.IsEnum) {
- // a synthetic default constructor for raw-type allows `new X' syntax
- createDefaultConstructor(typ)
- }
- }
-
- // import nested types
- for (ntype <- typ.getNestedTypes() if !(ntype.IsNestedPrivate || ntype.IsNestedAssembly || ntype.IsNestedFamANDAssem)
- || ntype.IsInterface /* TODO why shouldn't nested ifaces be type-parsed too? */ )
- {
- val loader = new loaders.MsilFileLoader(new MsilFile(ntype))
- val nclazz = statics.newClass(ntype.Name.toTypeName)
- val nmodule = statics.newModule(ntype.Name)
- nclazz.setInfo(loader)
- nmodule.setInfo(loader)
- staticDefs.enter(nclazz)
- staticDefs.enter(nmodule)
-
- assert(nclazz.companionModule == nmodule, nmodule)
- assert(nmodule.companionClass == nclazz, nclazz)
- }
-
- val fields = typ.getFields()
- for (field <- fields
- if !(field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly)
- if (getCLRType(field.FieldType) != null)
- ) {
- assert (!field.FieldType.IsPointer && !field.FieldType.IsByRef, "CLR requirement")
- val flags = translateAttributes(field);
- val name = newTermName(field.Name);
- val fieldType =
- if (field.IsLiteral && !field.FieldType.IsEnum && isDefinedAtgetConstant(getCLRType(field.FieldType)))
- ConstantType(getConstant(getCLRType(field.FieldType), field.getValue))
- else
- getCLRType(field.FieldType)
- val owner = if (field.IsStatic()) statics else clazz;
- val sym = owner.newValue(NoPosition, name).setFlag(flags).setInfo(fieldType);
- // TODO: set private within!!! -> look at typechecker/Namers.scala
- (if (field.IsStatic()) staticDefs else instanceDefs).enter(sym);
- clrTypes.fields(sym) = field;
- }
-
- for (constr <- typ.getConstructors() if !constr.IsStatic() && !constr.IsPrivate() &&
- !constr.IsAssembly() && !constr.IsFamilyAndAssembly() && !constr.HasPtrParamOrRetType())
- createMethod(constr);
-
- // initially also contains getters and setters of properties.
- val methodsSet = new mutable.HashSet[MethodInfo]();
- methodsSet ++= typ.getMethods();
-
- for (prop <- typ.getProperties) {
- val propType: Type = getCLSType(prop.PropertyType);
- if (propType != null) {
- val getter: MethodInfo = prop.GetGetMethod(true);
- val setter: MethodInfo = prop.GetSetMethod(true);
- var gparamsLength: Int = -1;
- if (!(getter == null || getter.IsPrivate || getter.IsAssembly
- || getter.IsFamilyAndAssembly || getter.HasPtrParamOrRetType))
- {
- assert(prop.PropertyType == getter.ReturnType);
- val gparams: Array[ParameterInfo] = getter.GetParameters();
- gparamsLength = gparams.length;
- val name: Name = if (gparamsLength == 0) prop.Name else nme.apply;
- val flags = translateAttributes(getter);
- val owner: Symbol = if (getter.IsStatic) statics else clazz;
- val methodSym = owner.newMethod(NoPosition, name).setFlag(flags)
- val mtype: Type = if (gparamsLength == 0) NullaryMethodType(propType) // .NET properties can't be polymorphic
- else methodType(getter, getter.ReturnType)(methodSym)
- methodSym.setInfo(mtype);
- methodSym.setFlag(Flags.ACCESSOR);
- (if (getter.IsStatic) staticDefs else instanceDefs).enter(methodSym)
- clrTypes.methods(methodSym) = getter;
- methodsSet -= getter;
- }
- if (!(setter == null || setter.IsPrivate || setter.IsAssembly
- || setter.IsFamilyAndAssembly || setter.HasPtrParamOrRetType))
- {
- val sparams: Array[ParameterInfo] = setter.GetParameters()
- if(getter != null)
- assert(getter.IsStatic == setter.IsStatic);
- assert(setter.ReturnType == clrTypes.VOID);
- if(getter != null)
- assert(sparams.length == gparamsLength + 1, "" + getter + "; " + setter);
-
- val name: Name = if (gparamsLength == 0) nme.getterToSetter(prop.Name)
- else nme.update;
- val flags = translateAttributes(setter);
- val mtype = methodType(setter, definitions.UnitClass.tpe);
- val owner: Symbol = if (setter.IsStatic) statics else clazz;
- val methodSym = owner.newMethod(NoPosition, name).setFlag(flags)
- methodSym.setInfo(mtype(methodSym))
- methodSym.setFlag(Flags.ACCESSOR);
- (if (setter.IsStatic) staticDefs else instanceDefs).enter(methodSym);
- clrTypes.methods(methodSym) = setter;
- methodsSet -= setter;
- }
- }
- }
-
-/* for (event <- typ.GetEvents) {
- // adding += and -= methods to add delegates to an event.
- // raising the event ist not possible from outside the class (this is so
- // generally in .net world)
- val adder: MethodInfo = event.GetAddMethod();
- val remover: MethodInfo = event.GetRemoveMethod();
- if (!(adder == null || adder.IsPrivate || adder.IsAssembly
- || adder.IsFamilyAndAssembly))
- {
- assert(adder.ReturnType == clrTypes.VOID);
- assert(adder.GetParameters().map(_.ParameterType).toList == List(event.EventHandlerType));
- val name = encode("+=");
- val flags = translateAttributes(adder);
- val mtype: Type = methodType(adder, adder.ReturnType);
- createMethod(name, flags, mtype, adder, adder.IsStatic)
- methodsSet -= adder;
- }
- if (!(remover == null || remover.IsPrivate || remover.IsAssembly
- || remover.IsFamilyAndAssembly))
- {
- assert(remover.ReturnType == clrTypes.VOID);
- assert(remover.GetParameters().map(_.ParameterType).toList == List(event.EventHandlerType));
- val name = encode("-=");
- val flags = translateAttributes(remover);
- val mtype: Type = methodType(remover, remover.ReturnType);
- createMethod(name, flags, mtype, remover, remover.IsStatic)
- methodsSet -= remover;
- }
- } */
-
-/* Adds view amounting to syntax sugar for a CLR implicit overload.
- The long-form syntax can also be supported if "methodsSet -= method" (last statement) is removed.
-
- /* remember, there's typ.getMethods and type.GetMethods */
- for (method <- typ.getMethods)
- if(!method.HasPtrParamOrRetType &&
- method.IsPublic && method.IsStatic && method.IsSpecialName &&
- method.Name == "op_Implicit") {
- // create a view: typ => method's return type
- val viewRetType: Type = getCLRType(method.ReturnType)
- val viewParamTypes: List[Type] = method.GetParameters().map(_.ParameterType).map(getCLSType).toList;
- /* The spec says "The operator method shall be defined as a static method on either the operand or return type."
- * We don't consider the declaring type for the purposes of definitions.functionType,
- * instead we regard op_Implicit's argument type and return type as defining the view's signature.
- */
- if (viewRetType != null && !viewParamTypes.contains(null)) {
- /* The check above applies e.g. to System.Decimal that has a conversion from UInt16, a non-CLS type, whose CLS-mapping returns null */
- val funType: Type = definitions.functionType(viewParamTypes, viewRetType);
- val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? shouldn't be final instead?
- val viewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(viewParamTypes), funType)
- val vmsym = createMethod(nme.view_, flags, viewMethodType, method, true);
- methodsSet -= method;
- }
- }
-*/
-
- for (method <- methodsSet.iterator)
- if (!method.IsPrivate() && !method.IsAssembly() && !method.IsFamilyAndAssembly()
- && !method.HasPtrParamOrRetType)
- createMethod(method);
-
- // Create methods and views for delegate support
- if (clrTypes.isDelegateType(typ)) {
- createDelegateView(typ)
- createDelegateChainers(typ)
- }
-
- // for enumerations introduce comparison and bitwise logical operations;
- // the backend will recognize them and replace them with comparison or
- // bitwise logical operations on the primitive underlying type
-
- if (typ.IsEnum) {
- val ENUM_CMP_NAMES = List(nme.EQ, nme.NE, nme.LT, nme.LE, nme.GT, nme.GE);
- val ENUM_BIT_LOG_NAMES = List(nme.OR, nme.AND, nme.XOR);
-
- val flags = Flags.JAVA | Flags.FINAL
- for (cmpName <- ENUM_CMP_NAMES) {
- val enumCmp = clazz.newMethod(NoPosition, cmpName)
- val enumCmpType = JavaMethodType(enumCmp.newSyntheticValueParams(List(clazz.tpe)), definitions.BooleanClass.tpe)
- enumCmp.setFlag(flags).setInfo(enumCmpType)
- instanceDefs.enter(enumCmp)
- }
-
- for (bitLogName <- ENUM_BIT_LOG_NAMES) {
- val enumBitLog = clazz.newMethod(NoPosition, bitLogName)
- val enumBitLogType = JavaMethodType(enumBitLog.newSyntheticValueParams(List(clazz.tpe)), clazz.tpe /* was classInfo, infinite typer */)
- enumBitLog.setFlag(flags).setInfo(enumBitLogType)
- instanceDefs.enter(enumBitLog)
- }
- }
-
- } // parseClass
-
- private def populateMethodTParams(method: MethodBase, methodSym: MethodSymbol) : List[Symbol] = {
- if(!method.IsGeneric) Nil
- else {
- methodTParams.clear
- val newMethodTParams = new scala.collection.mutable.ListBuffer[Symbol]()
-
- // first pass
- for (mvarCILDef <- method.getSortedMVars() ) {
- val mtpname = newTypeName(mvarCILDef.Name.replaceAll("!", "")) // TODO are really all method-level-type-params named in all assemblies out there? (NO)
- val mtpsym = methodSym.newTypeParameter(mtpname)
- methodTParams.put(mvarCILDef.Number, mtpsym)
- newMethodTParams += mtpsym
- // TODO wouldn't the following also be needed later, i.e. during getCLRType
- mtpsym.setInfo(definitions.AnyClass.tpe)
- }
- // second pass
- for (mvarCILDef <- method.getSortedMVars() ) {
- val mtpsym = methodTParams(mvarCILDef.Number)
- mtpsym.setInfo(sig2typeBounds(mvarCILDef)) // we never skip bounds unlike in forJVM
- }
-
- newMethodTParams.toList
- }
- }
-
- private def createMethod(method: MethodBase) {
-
- val flags = translateAttributes(method);
- val owner = if (method.IsStatic()) statics else clazz;
- val methodSym = owner.newMethod(NoPosition, getName(method)).setFlag(flags)
- /* START CLR generics (snippet 3) */
- val newMethodTParams = populateMethodTParams(method, methodSym)
- /* END CLR generics (snippet 3) */
-
- val rettype = if (method.IsConstructor()) clazz.tpe
- else getCLSType(method.asInstanceOf[MethodInfo].ReturnType);
- if (rettype == null) return;
- val mtype = methodType(method, rettype);
- if (mtype == null) return;
-/* START CLR generics (snippet 4) */
- val mInfo = if (method.IsGeneric) GenPolyType(newMethodTParams, mtype(methodSym))
- else mtype(methodSym)
-/* END CLR generics (snippet 4) */
-/* START CLR non-generics (snippet 4)
- val mInfo = mtype(methodSym)
- END CLR non-generics (snippet 4) */
- methodSym.setInfo(mInfo)
- (if (method.IsStatic()) staticDefs else instanceDefs).enter(methodSym);
- if (method.IsConstructor())
- clrTypes.constructors(methodSym) = method.asInstanceOf[ConstructorInfo]
- else clrTypes.methods(methodSym) = method.asInstanceOf[MethodInfo];
- }
-
- private def createMethod(name: Name, flags: Long, args: Array[MSILType], retType: MSILType, method: MethodInfo, statik: Boolean): Symbol = {
- val mtype = methodType(args, getCLSType(retType))
- assert(mtype != null)
- createMethod(name, flags, mtype, method, statik)
- }
-
- private def createMethod(name: Name, flags: Long, mtype: Symbol => Type, method: MethodInfo, statik: Boolean): Symbol = {
- val methodSym: Symbol = (if (statik) statics else clazz).newMethod(NoPosition, name)
- methodSym.setFlag(flags).setInfo(mtype(methodSym))
- (if (statik) staticDefs else instanceDefs).enter(methodSym)
- if (method != null)
- clrTypes.methods(methodSym) = method
- methodSym
- }
-
- private def createDelegateView(typ: MSILType) = {
- val invoke: MethodInfo = typ.GetMember("Invoke")(0).asInstanceOf[MethodInfo];
- val invokeRetType: Type = getCLRType(invoke.ReturnType);
- val invokeParamTypes: List[Type] =invoke.GetParameters().map(_.ParameterType).map(getCLSType).toList;
- val funType: Type = definitions.functionType(invokeParamTypes, invokeRetType);
-
- val typClrType: Type = getCLRType(typ);
- val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? think not needed
-
- // create the forward view: delegate => function
- val delegateParamTypes: List[Type] = List(typClrType);
- // not ImplicitMethodType, this is for methods with implicit parameters (not implicit methods)
- val forwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(delegateParamTypes), funType)
- val fmsym = createMethod(nme.view_, flags, forwardViewMethodType, null, true);
-
- // create the backward view: function => delegate
- val functionParamTypes: List[Type] = List(funType);
- val backwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(functionParamTypes), typClrType)
- val bmsym = createMethod(nme.view_, flags, backwardViewMethodType, null, true);
- }
-
- private def createDelegateChainers(typ: MSILType) = {
- val flags: Long = Flags.JAVA | Flags.FINAL
- val args: Array[MSILType] = Array(typ)
-
- var s = createMethod(encode("+="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_COMBINE, false);
- s = createMethod(encode("-="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_REMOVE, false);
-
- s = createMethod(nme.PLUS, flags, args, typ, clrTypes.DELEGATE_COMBINE, false);
- s = createMethod(nme.MINUS, flags, args, typ, clrTypes.DELEGATE_REMOVE, false);
- }
-
- private def getName(method: MethodBase): Name = {
-
- def operatorOverload(name : String, paramsArity : Int) : Option[Name] = paramsArity match {
- case 1 => name match {
- // PartitionI.10.3.1
- case "op_Decrement" => Some(encode("--"))
- case "op_Increment" => Some(encode("++"))
- case "op_UnaryNegation" => Some(nme.UNARY_-)
- case "op_UnaryPlus" => Some(nme.UNARY_+)
- case "op_LogicalNot" => Some(nme.UNARY_!)
- case "op_OnesComplement" => Some(nme.UNARY_~)
- /* op_True and op_False have no operator symbol assigned,
- Other methods that will have to be written in full are:
- op_AddressOf & (unary)
- op_PointerDereference * (unary) */
- case _ => None
- }
- case 2 => name match {
- // PartitionI.10.3.2
- case "op_Addition" => Some(nme.ADD)
- case "op_Subtraction" => Some(nme.SUB)
- case "op_Multiply" => Some(nme.MUL)
- case "op_Division" => Some(nme.DIV)
- case "op_Modulus" => Some(nme.MOD)
- case "op_ExclusiveOr" => Some(nme.XOR)
- case "op_BitwiseAnd" => Some(nme.AND)
- case "op_BitwiseOr" => Some(nme.OR)
- case "op_LogicalAnd" => Some(nme.ZAND)
- case "op_LogicalOr" => Some(nme.ZOR)
- case "op_LeftShift" => Some(nme.LSL)
- case "op_RightShift" => Some(nme.ASR)
- case "op_Equality" => Some(nme.EQ)
- case "op_GreaterThan" => Some(nme.GT)
- case "op_LessThan" => Some(nme.LT)
- case "op_Inequality" => Some(nme.NE)
- case "op_GreaterThanOrEqual" => Some(nme.GE)
- case "op_LessThanOrEqual" => Some(nme.LE)
-
- /* op_MemberSelection is reserved in Scala */
-
- /* The standard does not assign operator symbols to op_Assign , op_SignedRightShift , op_UnsignedRightShift ,
- * and op_UnsignedRightShiftAssignment so those names will be used instead to invoke those methods. */
-
- /*
- The remaining binary operators are not overloaded in C# and are therefore not in widespread use. They have to be written in full.
-
- op_RightShiftAssignment >>=
- op_MultiplicationAssignment *=
- op_PointerToMemberSelection ->*
- op_SubtractionAssignment -=
- op_ExclusiveOrAssignment ^=
- op_LeftShiftAssignment <<=
- op_ModulusAssignment %=
- op_AdditionAssignment +=
- op_BitwiseAndAssignment &=
- op_BitwiseOrAssignment |=
- op_Comma ,
- op_DivisionAssignment /=
- */
- case _ => None
- }
- case _ => None
- }
-
- if (method.IsConstructor()) return nme.CONSTRUCTOR;
- val name = method.Name;
- if (method.IsStatic()) {
- if(method.IsSpecialName) {
- val paramsArity = method.GetParameters().size
- // handle operator overload, otherwise handle as any static method
- val operName = operatorOverload(name, paramsArity)
- if (operName.isDefined) { return operName.get; }
- }
- return newTermName(name);
- }
- val params = method.GetParameters();
- name match {
- case "GetHashCode" if (params.length == 0) => nme.hashCode_;
- case "ToString" if (params.length == 0) => nme.toString_;
- case "Finalize" if (params.length == 0) => nme.finalize_;
- case "Equals" if (params.length == 1 && params(0).ParameterType == clrTypes.OBJECT) =>
- nme.equals_;
- case "Invoke" if (clrTypes.isDelegateType(method.DeclaringType)) => nme.apply;
- case _ => newTermName(name);
- }
- }
-
- //##########################################################################
-
- private def methodType(method: MethodBase, rettype: MSILType): Symbol => Type = {
- val rtype = getCLSType(rettype);
- if (rtype == null) null else methodType(method, rtype);
- }
-
- /** Return a method type for the given method. */
- private def methodType(method: MethodBase, rettype: Type): Symbol => Type =
- methodType(method.GetParameters().map(_.ParameterType), rettype);
-
- /** Return a method type for the provided argument types and return type. */
- private def methodType(argtypes: Array[MSILType], rettype: Type): Symbol => Type = {
- def paramType(typ: MSILType): Type =
- if (typ eq clrTypes.OBJECT) definitions.AnyClass.tpe // TODO a hack to compile scalalib, should be definitions.AnyRefClass.tpe
- else getCLSType(typ);
- val ptypes = argtypes.map(paramType).toList;
- if (ptypes.contains(null)) null
- else method => JavaMethodType(method.newSyntheticValueParams(ptypes), rettype);
- }
-
- //##########################################################################
-
- private def getClassType(typ: MSILType): Type = {
- assert(typ != null);
- val res = definitions.getClass(typ.FullName.replace('+', '.')).tpe;
- //if (res.isError())
- // global.reporter.error("unknown class reference " + type.FullName);
- res
- }
-
- private def getCLSType(typ: MSILType): Type = { // getCLS returns non-null for types GenMSIL can handle, be they CLS-compliant or not
- if (typ.IsTMVarUsage())
- /* START CLR generics (snippet 5) */
- getCLRType(typ)
- /* END CLR generics (snippet 5) */
- /* START CLR non-generics (snippet 5)
- null
- END CLR non-generics (snippet 5) */
- else if ( /* TODO hack if UBYE, uncommented, "ambiguous reference to overloaded definition" ensues, for example for System.Math.Max(x, y) */
- typ == clrTypes.USHORT || typ == clrTypes.UINT || typ == clrTypes.ULONG
- /* || typ == clrTypes.UBYTE */
- || typ.IsNotPublic() || typ.IsNestedPrivate()
- || typ.IsNestedAssembly() || typ.IsNestedFamANDAssem()
- || typ.IsPointer()
- || (typ.IsArray() && getCLRType(typ.GetElementType()) == null) /* TODO hack: getCLR instead of getCLS */
- || (typ.IsByRef() && !typ.GetElementType().CanBeTakenAddressOf()))
- null
- else
- getCLRType(typ)
- }
-
- private def getCLRTypeIfPrimitiveNullOtherwise(typ: MSILType): Type =
- if (typ == clrTypes.OBJECT)
- definitions.ObjectClass.tpe;
- else if (typ == clrTypes.VALUE_TYPE)
- definitions.AnyValClass.tpe
- else if (typ == clrTypes.STRING)
- definitions.StringClass.tpe;
- else if (typ == clrTypes.VOID)
- definitions.UnitClass.tpe
- else if (typ == clrTypes.BOOLEAN)
- definitions.BooleanClass.tpe
- else if (typ == clrTypes.CHAR)
- definitions.CharClass.tpe
- else if ((typ == clrTypes.BYTE) || (typ == clrTypes.UBYTE)) // TODO U... is a hack to compile scalalib
- definitions.ByteClass.tpe
- else if ((typ == clrTypes.SHORT) || (typ == clrTypes.SHORT)) // TODO U... is a hack to compile scalalib
- definitions.ShortClass.tpe
- else if ((typ == clrTypes.INT) || (typ == clrTypes.UINT)) // TODO U... is a hack to compile scalalib
- definitions.IntClass.tpe
- else if ((typ == clrTypes.LONG) || (typ == clrTypes.LONG)) // TODO U... is a hack to compile scalalib
- definitions.LongClass.tpe
- else if (typ == clrTypes.FLOAT)
- definitions.FloatClass.tpe
- else if (typ == clrTypes.DOUBLE)
- definitions.DoubleClass.tpe
- else null
-
-
- private def getCLRType(tMSIL: MSILType): Type = {
- var res = getCLRTypeIfPrimitiveNullOtherwise(tMSIL)
- if (res != null) res
- else if (tMSIL.isInstanceOf[ConstructedType]) {
- val ct = tMSIL.asInstanceOf[ConstructedType]
- /* START CLR generics (snippet 6) */
- val cttpArgs = ct.typeArgs.map(tmsil => getCLRType(tmsil)).toList
- appliedType(getCLRType(ct.instantiatedType), cttpArgs)
- /* END CLR generics (snippet 6) */
- /* START CLR non-generics (snippet 6)
- getCLRType(ct.instantiatedType)
- END CLR non-generics (snippet 6) */
- } else if (tMSIL.isInstanceOf[TMVarUsage]) {
- /* START CLR generics (snippet 7) */
- val tVarUsage = tMSIL.asInstanceOf[TMVarUsage]
- val tVarNumber = tVarUsage.Number
- if (tVarUsage.isTVar) classTParams(tVarNumber).typeConstructor // shouldn't fail, just return definitions.AnyClass.tpe at worst
- else methodTParams(tVarNumber).typeConstructor // shouldn't fail, just return definitions.AnyClass.tpe at worst
- /* END CLR generics (snippet 7) */
- /* START CLR non-generics (snippet 7)
- null // definitions.ObjectClass.tpe
- END CLR non-generics (snippet 7) */
- } else if (tMSIL.IsArray()) {
- var elemtp = getCLRType(tMSIL.GetElementType())
- // cut&pasted from ClassfileParser
- // make unbounded Array[T] where T is a type variable into Array[T with Object]
- // (this is necessary because such arrays have a representation which is incompatible
- // with arrays of primitive types).
- // TODO does that incompatibility also apply to .NET?
- if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe))
- elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe))
- appliedType(definitions.ArrayClass.tpe, List(elemtp))
- } else {
- res = clrTypes.sym2type.get(tMSIL) match {
- case Some(sym) => sym.tpe
- case None => if (tMSIL.IsByRef && tMSIL.GetElementType.IsValueType) {
- val addressed = getCLRType(tMSIL.GetElementType)
- val clasym = addressed.typeSymbolDirect // TODO should be .typeSymbol?
- clasym.info.load(clasym)
- val secondAttempt = clrTypes.sym2type.get(tMSIL)
- secondAttempt match { case Some(sym) => sym.tpe
- case None => null
- }
- } else getClassType(tMSIL)
- }
- if (res == null)
- null // TODO new RuntimeException()
- else res
- }
- }
-
- // the values are Java-Box-Classes (e.g. Integer, Boolean, Character)
- // java.lang.Number to get the value (if a number, not for boolean, character)
- // see ch.epfl.lamp.compiler.msil.util.PEStream.java
- def getConstant(constType: Type, value: Object): Constant = {
- val typeClass = constType.typeSymbol
- if (typeClass == definitions.BooleanClass)
- Constant(value.asInstanceOf[java.lang.Boolean].booleanValue)
- else if (typeClass == definitions.ByteClass)
- Constant(value.asInstanceOf[java.lang.Number].byteValue)
- else if (typeClass == definitions.ShortClass)
- Constant(value.asInstanceOf[java.lang.Number].shortValue)
- else if (typeClass == definitions.CharClass)
- Constant(value.asInstanceOf[java.lang.Character].charValue)
- else if (typeClass == definitions.IntClass)
- Constant(value.asInstanceOf[java.lang.Number].intValue)
- else if (typeClass == definitions.LongClass)
- Constant(value.asInstanceOf[java.lang.Number].longValue)
- else if (typeClass == definitions.FloatClass)
- Constant(value.asInstanceOf[java.lang.Number].floatValue)
- else if (typeClass == definitions.DoubleClass)
- Constant(value.asInstanceOf[java.lang.Number].doubleValue)
- else if (typeClass == definitions.StringClass)
- Constant(value.asInstanceOf[java.lang.String])
- else
- abort("illegal value: " + value + ", class-symbol: " + typeClass)
- }
-
- def isDefinedAtgetConstant(constType: Type): Boolean = {
- val typeClass = constType.typeSymbol
- if ( (typeClass == definitions.BooleanClass)
- || (typeClass == definitions.ByteClass)
- || (typeClass == definitions.ShortClass)
- || (typeClass == definitions.CharClass)
- || (typeClass == definitions.IntClass)
- || (typeClass == definitions.LongClass)
- || (typeClass == definitions.FloatClass)
- || (typeClass == definitions.DoubleClass)
- || (typeClass == definitions.StringClass)
- )
- true
- else
- false
- }
-
- private def translateAttributes(typ: MSILType): Long = {
- var flags: Long = Flags.JAVA;
- if (typ.IsNotPublic() || typ.IsNestedPrivate()
- || typ.IsNestedAssembly() || typ.IsNestedFamANDAssem())
- flags = flags | Flags.PRIVATE;
- else if (typ.IsNestedFamily() || typ.IsNestedFamORAssem())
- flags = flags | Flags.PROTECTED;
- if (typ.IsAbstract())
- flags = flags | Flags.ABSTRACT;
- if (typ.IsSealed())
- flags = flags | Flags.FINAL;
- if (typ.IsInterface())
- flags = flags | Flags.INTERFACE | Flags.TRAIT | Flags.ABSTRACT;
-
- flags
- }
-
- private def translateAttributes(field: FieldInfo): Long = {
- var flags: Long = Flags.JAVA;
- if (field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly())
- flags = flags | Flags.PRIVATE;
- else if (field.IsFamily() || field.IsFamilyOrAssembly())
- flags = flags | Flags.PROTECTED;
- if (field.IsInitOnly() || field.IsLiteral())
- flags = flags | Flags.FINAL;
- else
- flags = flags | Flags.MUTABLE;
- if (field.IsStatic)
- flags = flags | Flags.STATIC
-
- flags
- }
-
- private def translateAttributes(method: MethodBase): Long = {
- var flags: Long = Flags.JAVA;
- if (method.IsPrivate() || method.IsAssembly() || method.IsFamilyAndAssembly())
- flags = flags | Flags.PRIVATE;
- else if (method.IsFamily() || method.IsFamilyOrAssembly())
- flags = flags | Flags.PROTECTED;
- if (method.IsAbstract())
- flags = flags | Flags.DEFERRED;
- if (method.IsStatic)
- flags = flags | Flags.STATIC
-
- flags
- }
-}
+// /* NSC -- new scala compiler
+// * Copyright 2004-2011 LAMP/EPFL
+// */
+//
+// package scala.tools.nsc
+// package symtab
+// package clr
+//
+// import java.io.IOException
+// import io.MsilFile
+// import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute, _}
+// import scala.collection.{ mutable, immutable }
+// import scala.reflect.internal.pickling.UnPickler
+// import ch.epfl.lamp.compiler.msil.Type.TMVarUsage
+//
+// /**
+// * @author Nikolay Mihaylov
+// */
+// abstract class TypeParser {
+//
+// val global: Global
+//
+// import global._
+// import loaders.clrTypes
+//
+// //##########################################################################
+//
+// private var clazz: Symbol = _
+// private var instanceDefs: Scope = _ // was members
+// private var staticModule: Symbol = _ // was staticsClass
+// private var staticDefs: Scope = _ // was statics
+//
+// protected def statics: Symbol = staticModule.moduleClass
+//
+// protected var busy: Boolean = false // lock to detect recursive reads
+//
+// private implicit def stringToTermName(s: String): TermName = newTermName(s)
+//
+// private object unpickler extends UnPickler {
+// val global: TypeParser.this.global.type = TypeParser.this.global
+// }
+//
+// def parse(typ: MSILType, root: Symbol) {
+//
+// def handleError(e: Throwable) = {
+// if (settings.debug.value) e.printStackTrace() //debug
+// throw new IOException("type '" + typ.FullName + "' is broken\n(" + e.getMessage() + ")")
+// }
+// assert(!busy)
+// busy = true
+//
+// if (root.isModule) {
+// this.clazz = root.companionClass
+// this.staticModule = root
+// } else {
+// this.clazz = root
+// this.staticModule = root.companionModule
+// }
+// try {
+// parseClass(typ)
+// } catch {
+// case e: FatalError => handleError(e)
+// case e: RuntimeException => handleError(e)
+// }
+// busy = false
+// }
+//
+// class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType {
+// override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
+// }
+//
+// /* the names `classTParams` and `newTParams` stem from the forJVM version (ClassfileParser.sigToType())
+// * but there are differences that should be kept in mind.
+// * forMSIL, a nested class knows nothing about any type-params in the nesting class,
+// * therefore newTParams is redundant (other than for recording lexical order),
+// * it always contains the same elements as classTParams.value */
+// val classTParams = scala.collection.mutable.Map[Int,Symbol]() // TODO should this be a stack? (i.e., is it possible for >1 invocation to getCLRType on the same TypeParser instance be active )
+// val newTParams = new scala.collection.mutable.ListBuffer[Symbol]()
+// val methodTParams = scala.collection.mutable.Map[Int,Symbol]()
+//
+// private def sig2typeBounds(tvarCILDef: GenericParamAndConstraints): Type = {
+// val ts = new scala.collection.mutable.ListBuffer[Type]
+// for (cnstrnt <- tvarCILDef.Constraints) {
+// ts += getCLRType(cnstrnt) // TODO we're definitely not at or after erasure, no need to call objToAny, right?
+// }
+// TypeBounds.upper(intersectionType(ts.toList, clazz))
+// // TODO variance???
+// }
+//
+// private def createViewFromTo(viewSuffix : String, fromTpe : Type, toTpe : Type,
+// addToboxMethodMap : Boolean, isAddressOf : Boolean) : Symbol = {
+// val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? shouldn't be final instead?
+// val viewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(List(fromTpe)), toTpe)
+// val vmsym = createMethod(nme.view_ + viewSuffix, flags, viewMethodType, null, true);
+// // !!! this used to mutate a mutable map in definitions, but that map became
+// // immutable and this kept "working" with a no-op. So now it's commented out
+// // since I retired the deprecated code which allowed for that bug.
+// //
+// // if (addToboxMethodMap) definitions.boxMethod(clazz) = vmsym
+//
+// if (isAddressOf) clrTypes.addressOfViews += vmsym
+// vmsym
+// }
+//
+// private def createDefaultConstructor(typ: MSILType) {
+// val attrs = MethodAttributes.Public | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName // TODO instance
+// val declType= typ
+// val method = new ConstructorInfo(declType, attrs, Array[MSILType]())
+// val flags = Flags.JAVA
+// val owner = clazz
+// val methodSym = owner.newMethod(NoPosition, nme.CONSTRUCTOR).setFlag(flags)
+// val rettype = clazz.tpe
+// val mtype = methodType(Array[MSILType](), rettype);
+// val mInfo = mtype(methodSym)
+// methodSym.setInfo(mInfo)
+// instanceDefs.enter(methodSym);
+// clrTypes.constructors(methodSym) = method
+// }
+//
+// private def parseClass(typ: MSILType) {
+//
+// {
+// val t4c = clrTypes.types.get(clazz)
+// assert(t4c == None || t4c == Some(typ))
+// }
+// clrTypes.types(clazz) = typ
+//
+// {
+// val c4t = clrTypes.sym2type.get(typ)
+// assert(c4t == None || c4t == Some(clazz))
+// }
+// clrTypes.sym2type(typ) = clazz
+//
+// if (typ.IsDefined(clrTypes.SCALA_SYMTAB_ATTR, false)) {
+// val attrs = typ.GetCustomAttributes(clrTypes.SCALA_SYMTAB_ATTR, false);
+// assert (attrs.length == 1, attrs.length);
+// val a = attrs(0).asInstanceOf[MSILAttribute];
+// assert (a.getConstructor() == clrTypes.SYMTAB_CONSTR);
+// val symtab = a.getConstructorArguments()(0).asInstanceOf[Array[Byte]]
+// unpickler.unpickle(symtab, 0, clazz, staticModule, typ.FullName);
+// val mClass = clrTypes.getType(typ.FullName + "$");
+// if (mClass != null) {
+// clrTypes.types(statics) = mClass;
+// val moduleInstance = mClass.GetField("MODULE$");
+// assert (moduleInstance != null, mClass);
+// clrTypes.fields(statics) = moduleInstance;
+// }
+// return
+// }
+// val flags = translateAttributes(typ)
+//
+// var clazzBoxed : Symbol = NoSymbol
+// var clazzMgdPtr : Symbol = NoSymbol
+//
+// val canBeTakenAddressOf = (typ.IsValueType || typ.IsEnum) && (typ.FullName != "System.Enum")
+//
+// if(canBeTakenAddressOf) {
+// clazzBoxed = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("Boxed"))
+// clazzMgdPtr = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("MgdPtr"))
+// clrTypes.mdgptrcls4clssym(clazz) = clazzMgdPtr
+// /* adding typMgdPtr to clrTypes.sym2type should happen early (before metadata for supertypes is parsed,
+// before metadata for members are parsed) so that clazzMgdPtr can be found by getClRType. */
+// val typMgdPtr = MSILType.mkByRef(typ)
+// clrTypes.types(clazzMgdPtr) = typMgdPtr
+// clrTypes.sym2type(typMgdPtr) = clazzMgdPtr
+// /* clazzMgdPtr but not clazzBoxed is mapped by clrTypes.types into an msil.Type instance,
+// because there's no metadata-level representation for a "boxed valuetype" */
+// val instanceDefsMgdPtr = newScope
+// val classInfoMgdPtr = ClassInfoType(definitions.anyvalparam, instanceDefsMgdPtr, clazzMgdPtr)
+// clazzMgdPtr.setFlag(flags)
+// clazzMgdPtr.setInfo(classInfoMgdPtr)
+// }
+//
+// /* START CLR generics (snippet 1) */
+// // first pass
+// for (tvarCILDef <- typ.getSortedTVars() ) {
+// val tpname = newTypeName(tvarCILDef.Name.replaceAll("!", "")) // TODO are really all type-params named in all assemblies out there? (NO)
+// val tpsym = clazz.newTypeParameter(tpname)
+// classTParams.put(tvarCILDef.Number, tpsym)
+// newTParams += tpsym
+// // TODO wouldn't the following also be needed later, i.e. during getCLRType
+// tpsym.setInfo(definitions.AnyClass.tpe)
+// }
+// // second pass
+// for (tvarCILDef <- typ.getSortedTVars() ) {
+// val tpsym = classTParams(tvarCILDef.Number)
+// tpsym.setInfo(sig2typeBounds(tvarCILDef)) // we never skip bounds unlike in forJVM
+// }
+// /* END CLR generics (snippet 1) */
+// val ownTypeParams = newTParams.toList
+// /* START CLR generics (snippet 2) */
+// if (!ownTypeParams.isEmpty) {
+// clazz.setInfo(new TypeParamsType(ownTypeParams))
+// if(typ.IsValueType && !typ.IsEnum) {
+// clazzBoxed.setInfo(new TypeParamsType(ownTypeParams))
+// }
+// }
+// /* END CLR generics (snippet 2) */
+// instanceDefs = newScope
+// staticDefs = newScope
+//
+// val classInfoAsInMetadata = {
+// val ifaces: Array[MSILType] = typ.getInterfaces()
+// val superType = if (typ.BaseType() != null) getCLRType(typ.BaseType())
+// else if (typ.IsInterface()) definitions.ObjectClass.tpe
+// else definitions.AnyClass.tpe; // this branch activates for System.Object only.
+// // parents (i.e., base type and interfaces)
+// val parents = new scala.collection.mutable.ListBuffer[Type]()
+// parents += superType
+// for (iface <- ifaces) {
+// parents += getCLRType(iface) // here the variance doesn't matter
+// }
+// // methods, properties, events, fields are entered in a moment
+// if (canBeTakenAddressOf) {
+// val instanceDefsBoxed = newScope
+// ClassInfoType(parents.toList, instanceDefsBoxed, clazzBoxed)
+// } else
+// ClassInfoType(parents.toList, instanceDefs, clazz)
+// }
+//
+// val staticInfo = ClassInfoType(List(), staticDefs, statics)
+//
+// clazz.setFlag(flags)
+//
+// if (canBeTakenAddressOf) {
+// clazzBoxed.setInfo( if (ownTypeParams.isEmpty) classInfoAsInMetadata
+// else GenPolyType(ownTypeParams, classInfoAsInMetadata) )
+// clazzBoxed.setFlag(flags)
+// val rawValueInfoType = ClassInfoType(definitions.anyvalparam, instanceDefs, clazz)
+// clazz.setInfo( if (ownTypeParams.isEmpty) rawValueInfoType
+// else GenPolyType(ownTypeParams, rawValueInfoType) )
+// } else {
+// clazz.setInfo( if (ownTypeParams.isEmpty) classInfoAsInMetadata
+// else GenPolyType(ownTypeParams, classInfoAsInMetadata) )
+// }
+//
+// // TODO I don't remember if statics.setInfo and staticModule.setInfo should also know about type params
+// statics.setFlag(Flags.JAVA)
+// statics.setInfo(staticInfo)
+// staticModule.setFlag(Flags.JAVA)
+// staticModule.setInfo(statics.tpe)
+//
+//
+// if (canBeTakenAddressOf) {
+// // implicit conversions are owned by staticModule.moduleClass
+// createViewFromTo("2Boxed", clazz.tpe, clazzBoxed.tpe, addToboxMethodMap = true, isAddressOf = false)
+// // createViewFromTo("2Object", clazz.tpe, definitions.ObjectClass.tpe, addToboxMethodMap = true, isAddressOf = false)
+// createViewFromTo("2MgdPtr", clazz.tpe, clazzMgdPtr.tpe, addToboxMethodMap = false, isAddressOf = true)
+// // a return can't have type managed-pointer, thus a dereference-conversion is not needed
+// // similarly, a method can't declare as return type "boxed valuetype"
+// if (!typ.IsEnum) {
+// // a synthetic default constructor for raw-type allows `new X' syntax
+// createDefaultConstructor(typ)
+// }
+// }
+//
+// // import nested types
+// for (ntype <- typ.getNestedTypes() if !(ntype.IsNestedPrivate || ntype.IsNestedAssembly || ntype.IsNestedFamANDAssem)
+// || ntype.IsInterface /* TODO why shouldn't nested ifaces be type-parsed too? */ )
+// {
+// val loader = new loaders.MsilFileLoader(new MsilFile(ntype))
+// val nclazz = statics.newClass(ntype.Name.toTypeName)
+// val nmodule = statics.newModule(ntype.Name)
+// nclazz.setInfo(loader)
+// nmodule.setInfo(loader)
+// staticDefs.enter(nclazz)
+// staticDefs.enter(nmodule)
+//
+// assert(nclazz.companionModule == nmodule, nmodule)
+// assert(nmodule.companionClass == nclazz, nclazz)
+// }
+//
+// val fields = typ.getFields()
+// for (field <- fields
+// if !(field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly)
+// if (getCLRType(field.FieldType) != null)
+// ) {
+// assert (!field.FieldType.IsPointer && !field.FieldType.IsByRef, "CLR requirement")
+// val flags = translateAttributes(field);
+// val name = newTermName(field.Name);
+// val fieldType =
+// if (field.IsLiteral && !field.FieldType.IsEnum && isDefinedAtgetConstant(getCLRType(field.FieldType)))
+// ConstantType(getConstant(getCLRType(field.FieldType), field.getValue))
+// else
+// getCLRType(field.FieldType)
+// val owner = if (field.IsStatic()) statics else clazz;
+// val sym = owner.newValue(NoPosition, name).setFlag(flags).setInfo(fieldType);
+// // TODO: set private within!!! -> look at typechecker/Namers.scala
+// (if (field.IsStatic()) staticDefs else instanceDefs).enter(sym);
+// clrTypes.fields(sym) = field;
+// }
+//
+// for (constr <- typ.getConstructors() if !constr.IsStatic() && !constr.IsPrivate() &&
+// !constr.IsAssembly() && !constr.IsFamilyAndAssembly() && !constr.HasPtrParamOrRetType())
+// createMethod(constr);
+//
+// // initially also contains getters and setters of properties.
+// val methodsSet = new mutable.HashSet[MethodInfo]();
+// methodsSet ++= typ.getMethods();
+//
+// for (prop <- typ.getProperties) {
+// val propType: Type = getCLSType(prop.PropertyType);
+// if (propType != null) {
+// val getter: MethodInfo = prop.GetGetMethod(true);
+// val setter: MethodInfo = prop.GetSetMethod(true);
+// var gparamsLength: Int = -1;
+// if (!(getter == null || getter.IsPrivate || getter.IsAssembly
+// || getter.IsFamilyAndAssembly || getter.HasPtrParamOrRetType))
+// {
+// assert(prop.PropertyType == getter.ReturnType);
+// val gparams: Array[ParameterInfo] = getter.GetParameters();
+// gparamsLength = gparams.length;
+// val name: Name = if (gparamsLength == 0) prop.Name else nme.apply;
+// val flags = translateAttributes(getter);
+// val owner: Symbol = if (getter.IsStatic) statics else clazz;
+// val methodSym = owner.newMethod(NoPosition, name).setFlag(flags)
+// val mtype: Type = if (gparamsLength == 0) NullaryMethodType(propType) // .NET properties can't be polymorphic
+// else methodType(getter, getter.ReturnType)(methodSym)
+// methodSym.setInfo(mtype);
+// methodSym.setFlag(Flags.ACCESSOR);
+// (if (getter.IsStatic) staticDefs else instanceDefs).enter(methodSym)
+// clrTypes.methods(methodSym) = getter;
+// methodsSet -= getter;
+// }
+// if (!(setter == null || setter.IsPrivate || setter.IsAssembly
+// || setter.IsFamilyAndAssembly || setter.HasPtrParamOrRetType))
+// {
+// val sparams: Array[ParameterInfo] = setter.GetParameters()
+// if(getter != null)
+// assert(getter.IsStatic == setter.IsStatic);
+// assert(setter.ReturnType == clrTypes.VOID);
+// if(getter != null)
+// assert(sparams.length == gparamsLength + 1, "" + getter + "; " + setter);
+//
+// val name: Name = if (gparamsLength == 0) nme.getterToSetter(prop.Name)
+// else nme.update;
+// val flags = translateAttributes(setter);
+// val mtype = methodType(setter, definitions.UnitClass.tpe);
+// val owner: Symbol = if (setter.IsStatic) statics else clazz;
+// val methodSym = owner.newMethod(NoPosition, name).setFlag(flags)
+// methodSym.setInfo(mtype(methodSym))
+// methodSym.setFlag(Flags.ACCESSOR);
+// (if (setter.IsStatic) staticDefs else instanceDefs).enter(methodSym);
+// clrTypes.methods(methodSym) = setter;
+// methodsSet -= setter;
+// }
+// }
+// }
+//
+// /* for (event <- typ.GetEvents) {
+// // adding += and -= methods to add delegates to an event.
+// // raising the event ist not possible from outside the class (this is so
+// // generally in .net world)
+// val adder: MethodInfo = event.GetAddMethod();
+// val remover: MethodInfo = event.GetRemoveMethod();
+// if (!(adder == null || adder.IsPrivate || adder.IsAssembly
+// || adder.IsFamilyAndAssembly))
+// {
+// assert(adder.ReturnType == clrTypes.VOID);
+// assert(adder.GetParameters().map(_.ParameterType).toList == List(event.EventHandlerType));
+// val name = encode("+=");
+// val flags = translateAttributes(adder);
+// val mtype: Type = methodType(adder, adder.ReturnType);
+// createMethod(name, flags, mtype, adder, adder.IsStatic)
+// methodsSet -= adder;
+// }
+// if (!(remover == null || remover.IsPrivate || remover.IsAssembly
+// || remover.IsFamilyAndAssembly))
+// {
+// assert(remover.ReturnType == clrTypes.VOID);
+// assert(remover.GetParameters().map(_.ParameterType).toList == List(event.EventHandlerType));
+// val name = encode("-=");
+// val flags = translateAttributes(remover);
+// val mtype: Type = methodType(remover, remover.ReturnType);
+// createMethod(name, flags, mtype, remover, remover.IsStatic)
+// methodsSet -= remover;
+// }
+// } */
+//
+// /* Adds view amounting to syntax sugar for a CLR implicit overload.
+// The long-form syntax can also be supported if "methodsSet -= method" (last statement) is removed.
+//
+// /* remember, there's typ.getMethods and type.GetMethods */
+// for (method <- typ.getMethods)
+// if(!method.HasPtrParamOrRetType &&
+// method.IsPublic && method.IsStatic && method.IsSpecialName &&
+// method.Name == "op_Implicit") {
+// // create a view: typ => method's return type
+// val viewRetType: Type = getCLRType(method.ReturnType)
+// val viewParamTypes: List[Type] = method.GetParameters().map(_.ParameterType).map(getCLSType).toList;
+// /* The spec says "The operator method shall be defined as a static method on either the operand or return type."
+// * We don't consider the declaring type for the purposes of definitions.functionType,
+// * instead we regard op_Implicit's argument type and return type as defining the view's signature.
+// */
+// if (viewRetType != null && !viewParamTypes.contains(null)) {
+// /* The check above applies e.g. to System.Decimal that has a conversion from UInt16, a non-CLS type, whose CLS-mapping returns null */
+// val funType: Type = definitions.functionType(viewParamTypes, viewRetType);
+// val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? shouldn't be final instead?
+// val viewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(viewParamTypes), funType)
+// val vmsym = createMethod(nme.view_, flags, viewMethodType, method, true);
+// methodsSet -= method;
+// }
+// }
+// */
+//
+// for (method <- methodsSet.iterator)
+// if (!method.IsPrivate() && !method.IsAssembly() && !method.IsFamilyAndAssembly()
+// && !method.HasPtrParamOrRetType)
+// createMethod(method);
+//
+// // Create methods and views for delegate support
+// if (clrTypes.isDelegateType(typ)) {
+// createDelegateView(typ)
+// createDelegateChainers(typ)
+// }
+//
+// // for enumerations introduce comparison and bitwise logical operations;
+// // the backend will recognize them and replace them with comparison or
+// // bitwise logical operations on the primitive underlying type
+//
+// if (typ.IsEnum) {
+// val ENUM_CMP_NAMES = List(nme.EQ, nme.NE, nme.LT, nme.LE, nme.GT, nme.GE);
+// val ENUM_BIT_LOG_NAMES = List(nme.OR, nme.AND, nme.XOR);
+//
+// val flags = Flags.JAVA | Flags.FINAL
+// for (cmpName <- ENUM_CMP_NAMES) {
+// val enumCmp = clazz.newMethod(NoPosition, cmpName)
+// val enumCmpType = JavaMethodType(enumCmp.newSyntheticValueParams(List(clazz.tpe)), definitions.BooleanClass.tpe)
+// enumCmp.setFlag(flags).setInfo(enumCmpType)
+// instanceDefs.enter(enumCmp)
+// }
+//
+// for (bitLogName <- ENUM_BIT_LOG_NAMES) {
+// val enumBitLog = clazz.newMethod(NoPosition, bitLogName)
+// val enumBitLogType = JavaMethodType(enumBitLog.newSyntheticValueParams(List(clazz.tpe)), clazz.tpe /* was classInfo, infinite typer */)
+// enumBitLog.setFlag(flags).setInfo(enumBitLogType)
+// instanceDefs.enter(enumBitLog)
+// }
+// }
+//
+// } // parseClass
+//
+// private def populateMethodTParams(method: MethodBase, methodSym: MethodSymbol) : List[Symbol] = {
+// if(!method.IsGeneric) Nil
+// else {
+// methodTParams.clear
+// val newMethodTParams = new scala.collection.mutable.ListBuffer[Symbol]()
+//
+// // first pass
+// for (mvarCILDef <- method.getSortedMVars() ) {
+// val mtpname = newTypeName(mvarCILDef.Name.replaceAll("!", "")) // TODO are really all method-level-type-params named in all assemblies out there? (NO)
+// val mtpsym = methodSym.newTypeParameter(mtpname)
+// methodTParams.put(mvarCILDef.Number, mtpsym)
+// newMethodTParams += mtpsym
+// // TODO wouldn't the following also be needed later, i.e. during getCLRType
+// mtpsym.setInfo(definitions.AnyClass.tpe)
+// }
+// // second pass
+// for (mvarCILDef <- method.getSortedMVars() ) {
+// val mtpsym = methodTParams(mvarCILDef.Number)
+// mtpsym.setInfo(sig2typeBounds(mvarCILDef)) // we never skip bounds unlike in forJVM
+// }
+//
+// newMethodTParams.toList
+// }
+// }
+//
+// private def createMethod(method: MethodBase) {
+//
+// val flags = translateAttributes(method);
+// val owner = if (method.IsStatic()) statics else clazz;
+// val methodSym = owner.newMethod(NoPosition, getName(method)).setFlag(flags)
+// /* START CLR generics (snippet 3) */
+// val newMethodTParams = populateMethodTParams(method, methodSym)
+// /* END CLR generics (snippet 3) */
+//
+// val rettype = if (method.IsConstructor()) clazz.tpe
+// else getCLSType(method.asInstanceOf[MethodInfo].ReturnType);
+// if (rettype == null) return;
+// val mtype = methodType(method, rettype);
+// if (mtype == null) return;
+// /* START CLR generics (snippet 4) */
+// val mInfo = if (method.IsGeneric) GenPolyType(newMethodTParams, mtype(methodSym))
+// else mtype(methodSym)
+// /* END CLR generics (snippet 4) */
+// /* START CLR non-generics (snippet 4)
+// val mInfo = mtype(methodSym)
+// END CLR non-generics (snippet 4) */
+// methodSym.setInfo(mInfo)
+// (if (method.IsStatic()) staticDefs else instanceDefs).enter(methodSym);
+// if (method.IsConstructor())
+// clrTypes.constructors(methodSym) = method.asInstanceOf[ConstructorInfo]
+// else clrTypes.methods(methodSym) = method.asInstanceOf[MethodInfo];
+// }
+//
+// private def createMethod(name: Name, flags: Long, args: Array[MSILType], retType: MSILType, method: MethodInfo, statik: Boolean): Symbol = {
+// val mtype = methodType(args, getCLSType(retType))
+// assert(mtype != null)
+// createMethod(name, flags, mtype, method, statik)
+// }
+//
+// private def createMethod(name: Name, flags: Long, mtype: Symbol => Type, method: MethodInfo, statik: Boolean): Symbol = {
+// val methodSym: Symbol = (if (statik) statics else clazz).newMethod(NoPosition, name)
+// methodSym.setFlag(flags).setInfo(mtype(methodSym))
+// (if (statik) staticDefs else instanceDefs).enter(methodSym)
+// if (method != null)
+// clrTypes.methods(methodSym) = method
+// methodSym
+// }
+//
+// private def createDelegateView(typ: MSILType) = {
+// val invoke: MethodInfo = typ.GetMember("Invoke")(0).asInstanceOf[MethodInfo];
+// val invokeRetType: Type = getCLRType(invoke.ReturnType);
+// val invokeParamTypes: List[Type] =invoke.GetParameters().map(_.ParameterType).map(getCLSType).toList;
+// val funType: Type = definitions.functionType(invokeParamTypes, invokeRetType);
+//
+// val typClrType: Type = getCLRType(typ);
+// val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? think not needed
+//
+// // create the forward view: delegate => function
+// val delegateParamTypes: List[Type] = List(typClrType);
+// // not ImplicitMethodType, this is for methods with implicit parameters (not implicit methods)
+// val forwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(delegateParamTypes), funType)
+// val fmsym = createMethod(nme.view_, flags, forwardViewMethodType, null, true);
+//
+// // create the backward view: function => delegate
+// val functionParamTypes: List[Type] = List(funType);
+// val backwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(functionParamTypes), typClrType)
+// val bmsym = createMethod(nme.view_, flags, backwardViewMethodType, null, true);
+// }
+//
+// private def createDelegateChainers(typ: MSILType) = {
+// val flags: Long = Flags.JAVA | Flags.FINAL
+// val args: Array[MSILType] = Array(typ)
+//
+// var s = createMethod(encode("+="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_COMBINE, false);
+// s = createMethod(encode("-="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_REMOVE, false);
+//
+// s = createMethod(nme.PLUS, flags, args, typ, clrTypes.DELEGATE_COMBINE, false);
+// s = createMethod(nme.MINUS, flags, args, typ, clrTypes.DELEGATE_REMOVE, false);
+// }
+//
+// private def getName(method: MethodBase): Name = {
+//
+// def operatorOverload(name : String, paramsArity : Int) : Option[Name] = paramsArity match {
+// case 1 => name match {
+// // PartitionI.10.3.1
+// case "op_Decrement" => Some(encode("--"))
+// case "op_Increment" => Some(encode("++"))
+// case "op_UnaryNegation" => Some(nme.UNARY_-)
+// case "op_UnaryPlus" => Some(nme.UNARY_+)
+// case "op_LogicalNot" => Some(nme.UNARY_!)
+// case "op_OnesComplement" => Some(nme.UNARY_~)
+// /* op_True and op_False have no operator symbol assigned,
+// Other methods that will have to be written in full are:
+// op_AddressOf & (unary)
+// op_PointerDereference * (unary) */
+// case _ => None
+// }
+// case 2 => name match {
+// // PartitionI.10.3.2
+// case "op_Addition" => Some(nme.ADD)
+// case "op_Subtraction" => Some(nme.SUB)
+// case "op_Multiply" => Some(nme.MUL)
+// case "op_Division" => Some(nme.DIV)
+// case "op_Modulus" => Some(nme.MOD)
+// case "op_ExclusiveOr" => Some(nme.XOR)
+// case "op_BitwiseAnd" => Some(nme.AND)
+// case "op_BitwiseOr" => Some(nme.OR)
+// case "op_LogicalAnd" => Some(nme.ZAND)
+// case "op_LogicalOr" => Some(nme.ZOR)
+// case "op_LeftShift" => Some(nme.LSL)
+// case "op_RightShift" => Some(nme.ASR)
+// case "op_Equality" => Some(nme.EQ)
+// case "op_GreaterThan" => Some(nme.GT)
+// case "op_LessThan" => Some(nme.LT)
+// case "op_Inequality" => Some(nme.NE)
+// case "op_GreaterThanOrEqual" => Some(nme.GE)
+// case "op_LessThanOrEqual" => Some(nme.LE)
+//
+// /* op_MemberSelection is reserved in Scala */
+//
+// /* The standard does not assign operator symbols to op_Assign , op_SignedRightShift , op_UnsignedRightShift ,
+// * and op_UnsignedRightShiftAssignment so those names will be used instead to invoke those methods. */
+//
+// /*
+// The remaining binary operators are not overloaded in C# and are therefore not in widespread use. They have to be written in full.
+//
+// op_RightShiftAssignment >>=
+// op_MultiplicationAssignment *=
+// op_PointerToMemberSelection ->*
+// op_SubtractionAssignment -=
+// op_ExclusiveOrAssignment ^=
+// op_LeftShiftAssignment <<=
+// op_ModulusAssignment %=
+// op_AdditionAssignment +=
+// op_BitwiseAndAssignment &=
+// op_BitwiseOrAssignment |=
+// op_Comma ,
+// op_DivisionAssignment /=
+// */
+// case _ => None
+// }
+// case _ => None
+// }
+//
+// if (method.IsConstructor()) return nme.CONSTRUCTOR;
+// val name = method.Name;
+// if (method.IsStatic()) {
+// if(method.IsSpecialName) {
+// val paramsArity = method.GetParameters().size
+// // handle operator overload, otherwise handle as any static method
+// val operName = operatorOverload(name, paramsArity)
+// if (operName.isDefined) { return operName.get; }
+// }
+// return newTermName(name);
+// }
+// val params = method.GetParameters();
+// name match {
+// case "GetHashCode" if (params.length == 0) => nme.hashCode_;
+// case "ToString" if (params.length == 0) => nme.toString_;
+// case "Finalize" if (params.length == 0) => nme.finalize_;
+// case "Equals" if (params.length == 1 && params(0).ParameterType == clrTypes.OBJECT) =>
+// nme.equals_;
+// case "Invoke" if (clrTypes.isDelegateType(method.DeclaringType)) => nme.apply;
+// case _ => newTermName(name);
+// }
+// }
+//
+// //##########################################################################
+//
+// private def methodType(method: MethodBase, rettype: MSILType): Symbol => Type = {
+// val rtype = getCLSType(rettype);
+// if (rtype == null) null else methodType(method, rtype);
+// }
+//
+// /** Return a method type for the given method. */
+// private def methodType(method: MethodBase, rettype: Type): Symbol => Type =
+// methodType(method.GetParameters().map(_.ParameterType), rettype);
+//
+// /** Return a method type for the provided argument types and return type. */
+// private def methodType(argtypes: Array[MSILType], rettype: Type): Symbol => Type = {
+// def paramType(typ: MSILType): Type =
+// if (typ eq clrTypes.OBJECT) definitions.AnyClass.tpe // TODO a hack to compile scalalib, should be definitions.AnyRefClass.tpe
+// else getCLSType(typ);
+// val ptypes = argtypes.map(paramType).toList;
+// if (ptypes.contains(null)) null
+// else method => JavaMethodType(method.newSyntheticValueParams(ptypes), rettype);
+// }
+//
+// //##########################################################################
+//
+// private def getClassType(typ: MSILType): Type = {
+// assert(typ != null);
+// val res = definitions.getClass(typ.FullName.replace('+', '.')).tpe;
+// //if (res.isError())
+// // global.reporter.error("unknown class reference " + type.FullName);
+// res
+// }
+//
+// private def getCLSType(typ: MSILType): Type = { // getCLS returns non-null for types GenMSIL can handle, be they CLS-compliant or not
+// if (typ.IsTMVarUsage())
+// /* START CLR generics (snippet 5) */
+// getCLRType(typ)
+// /* END CLR generics (snippet 5) */
+// /* START CLR non-generics (snippet 5)
+// null
+// END CLR non-generics (snippet 5) */
+// else if ( /* TODO hack if UBYE, uncommented, "ambiguous reference to overloaded definition" ensues, for example for System.Math.Max(x, y) */
+// typ == clrTypes.USHORT || typ == clrTypes.UINT || typ == clrTypes.ULONG
+// /* || typ == clrTypes.UBYTE */
+// || typ.IsNotPublic() || typ.IsNestedPrivate()
+// || typ.IsNestedAssembly() || typ.IsNestedFamANDAssem()
+// || typ.IsPointer()
+// || (typ.IsArray() && getCLRType(typ.GetElementType()) == null) /* TODO hack: getCLR instead of getCLS */
+// || (typ.IsByRef() && !typ.GetElementType().CanBeTakenAddressOf()))
+// null
+// else
+// getCLRType(typ)
+// }
+//
+// private def getCLRTypeIfPrimitiveNullOtherwise(typ: MSILType): Type =
+// if (typ == clrTypes.OBJECT)
+// definitions.ObjectClass.tpe;
+// else if (typ == clrTypes.VALUE_TYPE)
+// definitions.AnyValClass.tpe
+// else if (typ == clrTypes.STRING)
+// definitions.StringClass.tpe;
+// else if (typ == clrTypes.VOID)
+// definitions.UnitClass.tpe
+// else if (typ == clrTypes.BOOLEAN)
+// definitions.BooleanClass.tpe
+// else if (typ == clrTypes.CHAR)
+// definitions.CharClass.tpe
+// else if ((typ == clrTypes.BYTE) || (typ == clrTypes.UBYTE)) // TODO U... is a hack to compile scalalib
+// definitions.ByteClass.tpe
+// else if ((typ == clrTypes.SHORT) || (typ == clrTypes.SHORT)) // TODO U... is a hack to compile scalalib
+// definitions.ShortClass.tpe
+// else if ((typ == clrTypes.INT) || (typ == clrTypes.UINT)) // TODO U... is a hack to compile scalalib
+// definitions.IntClass.tpe
+// else if ((typ == clrTypes.LONG) || (typ == clrTypes.LONG)) // TODO U... is a hack to compile scalalib
+// definitions.LongClass.tpe
+// else if (typ == clrTypes.FLOAT)
+// definitions.FloatClass.tpe
+// else if (typ == clrTypes.DOUBLE)
+// definitions.DoubleClass.tpe
+// else null
+//
+//
+// private def getCLRType(tMSIL: MSILType): Type = {
+// var res = getCLRTypeIfPrimitiveNullOtherwise(tMSIL)
+// if (res != null) res
+// else if (tMSIL.isInstanceOf[ConstructedType]) {
+// val ct = tMSIL.asInstanceOf[ConstructedType]
+// /* START CLR generics (snippet 6) */
+// val cttpArgs = ct.typeArgs.map(tmsil => getCLRType(tmsil)).toList
+// appliedType(getCLRType(ct.instantiatedType), cttpArgs)
+// /* END CLR generics (snippet 6) */
+// /* START CLR non-generics (snippet 6)
+// getCLRType(ct.instantiatedType)
+// END CLR non-generics (snippet 6) */
+// } else if (tMSIL.isInstanceOf[TMVarUsage]) {
+// /* START CLR generics (snippet 7) */
+// val tVarUsage = tMSIL.asInstanceOf[TMVarUsage]
+// val tVarNumber = tVarUsage.Number
+// if (tVarUsage.isTVar) classTParams(tVarNumber).typeConstructor // shouldn't fail, just return definitions.AnyClass.tpe at worst
+// else methodTParams(tVarNumber).typeConstructor // shouldn't fail, just return definitions.AnyClass.tpe at worst
+// /* END CLR generics (snippet 7) */
+// /* START CLR non-generics (snippet 7)
+// null // definitions.ObjectClass.tpe
+// END CLR non-generics (snippet 7) */
+// } else if (tMSIL.IsArray()) {
+// var elemtp = getCLRType(tMSIL.GetElementType())
+// // cut&pasted from ClassfileParser
+// // make unbounded Array[T] where T is a type variable into Array[T with Object]
+// // (this is necessary because such arrays have a representation which is incompatible
+// // with arrays of primitive types).
+// // TODO does that incompatibility also apply to .NET?
+// if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe))
+// elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe))
+// appliedType(definitions.ArrayClass.tpe, List(elemtp))
+// } else {
+// res = clrTypes.sym2type.get(tMSIL) match {
+// case Some(sym) => sym.tpe
+// case None => if (tMSIL.IsByRef && tMSIL.GetElementType.IsValueType) {
+// val addressed = getCLRType(tMSIL.GetElementType)
+// val clasym = addressed.typeSymbolDirect // TODO should be .typeSymbol?
+// clasym.info.load(clasym)
+// val secondAttempt = clrTypes.sym2type.get(tMSIL)
+// secondAttempt match { case Some(sym) => sym.tpe
+// case None => null
+// }
+// } else getClassType(tMSIL)
+// }
+// if (res == null)
+// null // TODO new RuntimeException()
+// else res
+// }
+// }
+//
+// // the values are Java-Box-Classes (e.g. Integer, Boolean, Character)
+// // java.lang.Number to get the value (if a number, not for boolean, character)
+// // see ch.epfl.lamp.compiler.msil.util.PEStream.java
+// def getConstant(constType: Type, value: Object): Constant = {
+// val typeClass = constType.typeSymbol
+// if (typeClass == definitions.BooleanClass)
+// Constant(value.asInstanceOf[java.lang.Boolean].booleanValue)
+// else if (typeClass == definitions.ByteClass)
+// Constant(value.asInstanceOf[java.lang.Number].byteValue)
+// else if (typeClass == definitions.ShortClass)
+// Constant(value.asInstanceOf[java.lang.Number].shortValue)
+// else if (typeClass == definitions.CharClass)
+// Constant(value.asInstanceOf[java.lang.Character].charValue)
+// else if (typeClass == definitions.IntClass)
+// Constant(value.asInstanceOf[java.lang.Number].intValue)
+// else if (typeClass == definitions.LongClass)
+// Constant(value.asInstanceOf[java.lang.Number].longValue)
+// else if (typeClass == definitions.FloatClass)
+// Constant(value.asInstanceOf[java.lang.Number].floatValue)
+// else if (typeClass == definitions.DoubleClass)
+// Constant(value.asInstanceOf[java.lang.Number].doubleValue)
+// else if (typeClass == definitions.StringClass)
+// Constant(value.asInstanceOf[java.lang.String])
+// else
+// abort("illegal value: " + value + ", class-symbol: " + typeClass)
+// }
+//
+// def isDefinedAtgetConstant(constType: Type): Boolean = {
+// val typeClass = constType.typeSymbol
+// if ( (typeClass == definitions.BooleanClass)
+// || (typeClass == definitions.ByteClass)
+// || (typeClass == definitions.ShortClass)
+// || (typeClass == definitions.CharClass)
+// || (typeClass == definitions.IntClass)
+// || (typeClass == definitions.LongClass)
+// || (typeClass == definitions.FloatClass)
+// || (typeClass == definitions.DoubleClass)
+// || (typeClass == definitions.StringClass)
+// )
+// true
+// else
+// false
+// }
+//
+// private def translateAttributes(typ: MSILType): Long = {
+// var flags: Long = Flags.JAVA;
+// if (typ.IsNotPublic() || typ.IsNestedPrivate()
+// || typ.IsNestedAssembly() || typ.IsNestedFamANDAssem())
+// flags = flags | Flags.PRIVATE;
+// else if (typ.IsNestedFamily() || typ.IsNestedFamORAssem())
+// flags = flags | Flags.PROTECTED;
+// if (typ.IsAbstract())
+// flags = flags | Flags.ABSTRACT;
+// if (typ.IsSealed())
+// flags = flags | Flags.FINAL;
+// if (typ.IsInterface())
+// flags = flags | Flags.INTERFACE | Flags.TRAIT | Flags.ABSTRACT;
+//
+// flags
+// }
+//
+// private def translateAttributes(field: FieldInfo): Long = {
+// var flags: Long = Flags.JAVA;
+// if (field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly())
+// flags = flags | Flags.PRIVATE;
+// else if (field.IsFamily() || field.IsFamilyOrAssembly())
+// flags = flags | Flags.PROTECTED;
+// if (field.IsInitOnly() || field.IsLiteral())
+// flags = flags | Flags.FINAL;
+// else
+// flags = flags | Flags.MUTABLE;
+// if (field.IsStatic)
+// flags = flags | Flags.STATIC
+//
+// flags
+// }
+//
+// private def translateAttributes(method: MethodBase): Long = {
+// var flags: Long = Flags.JAVA;
+// if (method.IsPrivate() || method.IsAssembly() || method.IsFamilyAndAssembly())
+// flags = flags | Flags.PRIVATE;
+// else if (method.IsFamily() || method.IsFamilyOrAssembly())
+// flags = flags | Flags.PROTECTED;
+// if (method.IsAbstract())
+// flags = flags | Flags.DEFERRED;
+// if (method.IsStatic)
+// flags = flags | Flags.STATIC
+//
+// flags
+// }
+// }
diff --git a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala
index 6215506141..260c350ede 100644
--- a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala
@@ -1,169 +1,169 @@
-/* NSC -- new Scala compiler
- * Copyright 2006-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-// $Id$
-
-package scala.tools.nsc
-package util
-
-import java.io.File
-import java.net.URL
-import java.util.StringTokenizer
-import scala.util.Sorting
-import scala.collection.mutable
-import scala.tools.nsc.io.{ AbstractFile, MsilFile }
-import ch.epfl.lamp.compiler.msil.{ Type => MSILType, Assembly }
-import ClassPath.{ ClassPathContext, isTraitImplementation }
-
-/** Keeping the MSIL classpath code in its own file is important to make sure
- * we don't accidentally introduce a dependency on msil.jar in the jvm.
- */
-
-object MsilClassPath {
- def collectTypes(assemFile: AbstractFile) = {
- var res: Array[MSILType] = MSILType.EmptyTypes
- val assem = Assembly.LoadFrom(assemFile.path)
- if (assem != null) {
- // DeclaringType == null: true for non-inner classes
- res = assem.GetTypes() filter (_.DeclaringType == null)
- Sorting.stableSort(res, (t1: MSILType, t2: MSILType) => (t1.FullName compareTo t2.FullName) < 0)
- }
- res
- }
-
- /** On the java side this logic is in PathResolver, but as I'm not really
- * up to folding MSIL into that, I am encapsulating it here.
- */
- def fromSettings(settings: Settings): MsilClassPath = {
- val context =
- if (settings.inline.value) new MsilContext
- else new MsilContext { override def isValidName(name: String) = !isTraitImplementation(name) }
-
- import settings._
- new MsilClassPath(assemextdirs.value, assemrefs.value, sourcepath.value, context)
- }
-
- class MsilContext extends ClassPathContext[MsilFile] {
- def toBinaryName(rep: MsilFile) = rep.msilType.Name
- def newClassPath(assemFile: AbstractFile) = new AssemblyClassPath(MsilClassPath collectTypes assemFile, "", this)
- }
-
- private def assembleEntries(ext: String, user: String, source: String, context: MsilContext): List[ClassPath[MsilFile]] = {
- import ClassPath._
- val etr = new mutable.ListBuffer[ClassPath[MsilFile]]
- val names = new mutable.HashSet[String]
-
- // 1. Assemblies from -Xassem-extdirs
- for (dirName <- expandPath(ext, expandStar = false)) {
- val dir = AbstractFile.getDirectory(dirName)
- if (dir ne null) {
- for (file <- dir) {
- val name = file.name.toLowerCase
- if (name.endsWith(".dll") || name.endsWith(".exe")) {
- names += name
- etr += context.newClassPath(file)
- }
- }
- }
- }
-
- // 2. Assemblies from -Xassem-path
- for (fileName <- expandPath(user, expandStar = false)) {
- val file = AbstractFile.getFile(fileName)
- if (file ne null) {
- val name = file.name.toLowerCase
- if (name.endsWith(".dll") || name.endsWith(".exe")) {
- names += name
- etr += context.newClassPath(file)
- }
- }
- }
-
- def check(n: String) {
- if (!names.contains(n))
- throw new AssertionError("Cannot find assembly "+ n +
- ". Use -Xassem-extdirs or -Xassem-path to specify its location")
- }
- check("mscorlib.dll")
- check("scalaruntime.dll")
-
- // 3. Source path
- for (dirName <- expandPath(source, expandStar = false)) {
- val file = AbstractFile.getDirectory(dirName)
- if (file ne null) etr += new SourcePath[MsilFile](file, context)
- }
-
- etr.toList
- }
-}
-import MsilClassPath._
-
-/**
- * A assembly file (dll / exe) containing classes and namespaces
- */
-class AssemblyClassPath(types: Array[MSILType], namespace: String, val context: MsilContext) extends ClassPath[MsilFile] {
- def name = {
- val i = namespace.lastIndexOf('.')
- if (i < 0) namespace
- else namespace drop (i + 1)
- }
- def asURLs = List(new java.net.URL(name))
- def asClasspathString = sys.error("Unknown") // I don't know what if anything makes sense here?
-
- private lazy val first: Int = {
- var m = 0
- var n = types.length - 1
- while (m < n) {
- val l = (m + n) / 2
- val res = types(l).FullName.compareTo(namespace)
- if (res < 0) m = l + 1
- else n = l
- }
- if (types(m).FullName.startsWith(namespace)) m else types.length
- }
-
- lazy val classes = {
- val cls = new mutable.ListBuffer[ClassRep]
- var i = first
- while (i < types.length && types(i).Namespace.startsWith(namespace)) {
- // CLRTypes used to exclude java.lang.Object and java.lang.String (no idea why..)
- if (types(i).Namespace == namespace)
- cls += ClassRep(Some(new MsilFile(types(i))), None)
- i += 1
- }
- cls.toIndexedSeq
- }
-
- lazy val packages = {
- val nsSet = new mutable.HashSet[String]
- var i = first
- while (i < types.length && types(i).Namespace.startsWith(namespace)) {
- val subns = types(i).Namespace
- if (subns.length > namespace.length) {
- // example: namespace = "System", subns = "System.Reflection.Emit"
- // => find second "." and "System.Reflection" to nsSet.
- val end = subns.indexOf('.', namespace.length + 1)
- nsSet += (if (end < 0) subns
- else subns.substring(0, end))
- }
- i += 1
- }
- val xs = for (ns <- nsSet.toList)
- yield new AssemblyClassPath(types, ns, context)
-
- xs.toIndexedSeq
- }
-
- val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq()
-
- override def toString() = "assembly classpath "+ namespace
-}
-
-/**
- * The classpath when compiling with target:msil. Binary files are represented as
- * MSILType values.
- */
-class MsilClassPath(ext: String, user: String, source: String, context: MsilContext)
-extends MergedClassPath[MsilFile](MsilClassPath.assembleEntries(ext, user, source, context), context) { } \ No newline at end of file
+// /* NSC -- new Scala compiler
+// * Copyright 2006-2011 LAMP/EPFL
+// * @author Martin Odersky
+// */
+//
+// // $Id$
+//
+// package scala.tools.nsc
+// package util
+//
+// import java.io.File
+// import java.net.URL
+// import java.util.StringTokenizer
+// import scala.util.Sorting
+// import scala.collection.mutable
+// import scala.tools.nsc.io.{ AbstractFile, MsilFile }
+// import ch.epfl.lamp.compiler.msil.{ Type => MSILType, Assembly }
+// import ClassPath.{ ClassPathContext, isTraitImplementation }
+//
+// /** Keeping the MSIL classpath code in its own file is important to make sure
+// * we don't accidentally introduce a dependency on msil.jar in the jvm.
+// */
+//
+// object MsilClassPath {
+// def collectTypes(assemFile: AbstractFile) = {
+// var res: Array[MSILType] = MSILType.EmptyTypes
+// val assem = Assembly.LoadFrom(assemFile.path)
+// if (assem != null) {
+// // DeclaringType == null: true for non-inner classes
+// res = assem.GetTypes() filter (_.DeclaringType == null)
+// Sorting.stableSort(res, (t1: MSILType, t2: MSILType) => (t1.FullName compareTo t2.FullName) < 0)
+// }
+// res
+// }
+//
+// /** On the java side this logic is in PathResolver, but as I'm not really
+// * up to folding MSIL into that, I am encapsulating it here.
+// */
+// def fromSettings(settings: Settings): MsilClassPath = {
+// val context =
+// if (settings.inline.value) new MsilContext
+// else new MsilContext { override def isValidName(name: String) = !isTraitImplementation(name) }
+//
+// import settings._
+// new MsilClassPath(assemextdirs.value, assemrefs.value, sourcepath.value, context)
+// }
+//
+// class MsilContext extends ClassPathContext[MsilFile] {
+// def toBinaryName(rep: MsilFile) = rep.msilType.Name
+// def newClassPath(assemFile: AbstractFile) = new AssemblyClassPath(MsilClassPath collectTypes assemFile, "", this)
+// }
+//
+// private def assembleEntries(ext: String, user: String, source: String, context: MsilContext): List[ClassPath[MsilFile]] = {
+// import ClassPath._
+// val etr = new mutable.ListBuffer[ClassPath[MsilFile]]
+// val names = new mutable.HashSet[String]
+//
+// // 1. Assemblies from -Xassem-extdirs
+// for (dirName <- expandPath(ext, expandStar = false)) {
+// val dir = AbstractFile.getDirectory(dirName)
+// if (dir ne null) {
+// for (file <- dir) {
+// val name = file.name.toLowerCase
+// if (name.endsWith(".dll") || name.endsWith(".exe")) {
+// names += name
+// etr += context.newClassPath(file)
+// }
+// }
+// }
+// }
+//
+// // 2. Assemblies from -Xassem-path
+// for (fileName <- expandPath(user, expandStar = false)) {
+// val file = AbstractFile.getFile(fileName)
+// if (file ne null) {
+// val name = file.name.toLowerCase
+// if (name.endsWith(".dll") || name.endsWith(".exe")) {
+// names += name
+// etr += context.newClassPath(file)
+// }
+// }
+// }
+//
+// def check(n: String) {
+// if (!names.contains(n))
+// throw new AssertionError("Cannot find assembly "+ n +
+// ". Use -Xassem-extdirs or -Xassem-path to specify its location")
+// }
+// check("mscorlib.dll")
+// check("scalaruntime.dll")
+//
+// // 3. Source path
+// for (dirName <- expandPath(source, expandStar = false)) {
+// val file = AbstractFile.getDirectory(dirName)
+// if (file ne null) etr += new SourcePath[MsilFile](file, context)
+// }
+//
+// etr.toList
+// }
+// }
+// import MsilClassPath._
+//
+// /**
+// * A assembly file (dll / exe) containing classes and namespaces
+// */
+// class AssemblyClassPath(types: Array[MSILType], namespace: String, val context: MsilContext) extends ClassPath[MsilFile] {
+// def name = {
+// val i = namespace.lastIndexOf('.')
+// if (i < 0) namespace
+// else namespace drop (i + 1)
+// }
+// def asURLs = List(new java.net.URL(name))
+// def asClasspathString = sys.error("Unknown") // I don't know what if anything makes sense here?
+//
+// private lazy val first: Int = {
+// var m = 0
+// var n = types.length - 1
+// while (m < n) {
+// val l = (m + n) / 2
+// val res = types(l).FullName.compareTo(namespace)
+// if (res < 0) m = l + 1
+// else n = l
+// }
+// if (types(m).FullName.startsWith(namespace)) m else types.length
+// }
+//
+// lazy val classes = {
+// val cls = new mutable.ListBuffer[ClassRep]
+// var i = first
+// while (i < types.length && types(i).Namespace.startsWith(namespace)) {
+// // CLRTypes used to exclude java.lang.Object and java.lang.String (no idea why..)
+// if (types(i).Namespace == namespace)
+// cls += ClassRep(Some(new MsilFile(types(i))), None)
+// i += 1
+// }
+// cls.toIndexedSeq
+// }
+//
+// lazy val packages = {
+// val nsSet = new mutable.HashSet[String]
+// var i = first
+// while (i < types.length && types(i).Namespace.startsWith(namespace)) {
+// val subns = types(i).Namespace
+// if (subns.length > namespace.length) {
+// // example: namespace = "System", subns = "System.Reflection.Emit"
+// // => find second "." and "System.Reflection" to nsSet.
+// val end = subns.indexOf('.', namespace.length + 1)
+// nsSet += (if (end < 0) subns
+// else subns.substring(0, end))
+// }
+// i += 1
+// }
+// val xs = for (ns <- nsSet.toList)
+// yield new AssemblyClassPath(types, ns, context)
+//
+// xs.toIndexedSeq
+// }
+//
+// val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq()
+//
+// override def toString() = "assembly classpath "+ namespace
+// }
+//
+// /**
+// * The classpath when compiling with target:msil. Binary files are represented as
+// * MSILType values.
+// */
+// class MsilClassPath(ext: String, user: String, source: String, context: MsilContext)
+// extends MergedClassPath[MsilFile](MsilClassPath.assembleEntries(ext, user, source, context), context) { } \ No newline at end of file