diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF index 28a70d2879a8..4dd69827c34d 100644 --- a/META-INF/MANIFEST.MF +++ b/META-INF/MANIFEST.MF @@ -7,9 +7,7 @@ Eclipse-LazyStart: true Bundle-ClassPath: ., bin, - lib/fjbg.jar, lib/jline.jar, - lib/msil.jar Export-Package: scala.tools.nsc, scala.tools.nsc.ast, @@ -47,11 +45,6 @@ Export-Package: scala.reflect.runtime, scala.reflect.internal.transform, scala.reflect.api, - ch.epfl.lamp.compiler.msil, - ch.epfl.lamp.compiler.msil.emit, - ch.epfl.lamp.compiler.msil.util, - ch.epfl.lamp.fjbg, - ch.epfl.lamp.util Require-Bundle: org.apache.ant, org.scala-ide.scala.library diff --git a/README.rst b/README.rst index 72c4b6028b3e..7a1ed1dcf4a3 100644 --- a/README.rst +++ b/README.rst @@ -18,7 +18,6 @@ build script or user-created if needed. This is not a complete listing. :: +--dist/ The destination folder for Scala distributions. +--docs/ Documentation and sample code. +--lib/ Pre-compiled libraries for the build. - | +--fjbg.jar The Java byte-code generation library. | +--scala-compiler.jar The stable reference ('starr') compiler jar | +--scala-library.jar The stable reference ('starr') library jar | +--scala-library-src.jar A snapshot of the source used to build starr. diff --git a/build.detach.xml b/build.detach.xml index 132c812a26d0..03360e36d59a 100644 --- a/build.detach.xml +++ b/build.detach.xml @@ -11,7 +11,7 @@ SuperSabbus for Scala detach plugin. - + @@ -72,8 +72,6 @@ QUICK BUILD (QUICK) - - @@ -120,9 +118,9 @@ QUICK BUILD (QUICK) - + - + - - - - @@ -59,7 +55,7 @@ INITIALISATION - - - - - - - - - - - - @@ -110,14 +88,9 @@ INITIALISATION - - - - - diff --git a/build.xml b/build.xml index a828d71a444f..68fcc46478e0 100644 --- a/build.xml +++ b/build.xml @@ -203,7 +203,6 @@ PROPERTIES - @@ -461,9 +460,7 @@ INITIALISATION - - @@ -592,58 +589,11 @@ LOCAL DEPENDENCY (FORKJOIN) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -669,9 +619,6 @@ LOCAL REFERENCE BUILD (LOCKER) - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -845,7 +753,6 @@ LOCAL REFERENCE BUILD (LOCKER) - @@ -855,7 +762,6 @@ LOCAL REFERENCE BUILD (LOCKER) - @@ -953,7 +859,6 @@ PACKED LOCKER BUILD (PALO) - @@ -1163,33 +1068,6 @@ QUICK BUILD (QUICK) - - - - - - - - - - - - - - - - @@ -1254,7 +1131,6 @@ QUICK BUILD (QUICK) - @@ -1376,7 +1252,6 @@ QUICK BUILD (QUICK) - @@ -1406,7 +1281,6 @@ QUICK BUILD (QUICK) - @@ -1533,7 +1407,6 @@ PACKED QUICK BUILD (PACK) - @@ -1945,33 +1818,6 @@ BOOTSTRAPPING BUILD (STRAP) - - - - - - - - - - - - - - - - @@ -2036,7 +1881,6 @@ BOOTSTRAPPING BUILD (STRAP) - @@ -2168,7 +2012,7 @@ BOOTSTRAPPING BUILD (STRAP) @@ -2834,8 +2678,6 @@ STABLE REFERENCE (STARR) - - diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1 deleted file mode 100644 index 6f3ccc77bdde..000000000000 --- a/lib/fjbg.jar.desired.sha1 +++ /dev/null @@ -1 +0,0 @@ -8acc87f222210b4a5eb2675477602fc1759e7684 *fjbg.jar diff --git a/lib/msil.jar.desired.sha1 b/lib/msil.jar.desired.sha1 deleted file mode 100644 index 9396b273abf5..000000000000 --- a/lib/msil.jar.desired.sha1 +++ /dev/null @@ -1 +0,0 @@ -d48cb950ceded82a5e0ffae8ef2c68d0923ed00c *msil.jar diff --git a/project/Build.scala b/project/Build.scala index a50a572d5450..efa8a7a038f8 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -11,7 +11,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { override lazy val settings = super.settings ++ Versions.settings ++ Seq( autoScalaLibrary := false, resolvers += Resolver.url( - "Typesafe nightlies", + "Typesafe nightlies", url("https://typesafe.artifactoryonline.com/typesafe/ivy-snapshots/") )(Resolver.ivyStylePatterns), resolvers ++= Seq( @@ -21,14 +21,14 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { organization := "org.scala-lang", version <<= Versions.mavenVersion, pomExtra := epflPomExtra - ) + ) // Collections of projects to run 'compile' on. - lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, forkjoin, fjbg) + lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, forkjoin) // Collection of projects to 'package' and 'publish' together. lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, actors, continuationsPlugin, jline, scalap) lazy val partestRunProjects = Seq(testsuite, continuationsTestsuite) - + private def epflPomExtra = ( 2002 @@ -47,7 +47,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { ) - + // Settings used to make sure publishing goes smoothly. def publishSettings: Seq[Setting[_]] = Seq( ivyScala ~= ((is: Option[IvyScala]) => is.map(_.copy(checkExplicit = false))), @@ -82,7 +82,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { makeExplodedDist <<= (makeExplodedDist in scaladist).identity, // Note: We override unmanagedSources so that ~ compile will look at all these sources, then run our aggregated compile... unmanagedSourceDirectories in Compile <<= baseDirectory apply (_ / "src") apply { dir => - Seq("library/scala","actors","compiler","fjbg","swing","continuations/library","forkjoin") map (dir / _) + Seq("library/scala","actors","compiler","swing","continuations/library","forkjoin") map (dir / _) }, // TODO - Make exported products == makeDist so we can use this when creating a *real* distribution. commands += Release.pushStarr @@ -91,7 +91,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { lazy val aaa_root = Project("scala", file(".")) settings(projectSettings: _*) settings(ShaResolve.settings: _*) // External dependencies used for various projects - lazy val externalDeps: Setting[_] = libraryDependencies <<= (sbtVersion)(v => + lazy val externalDeps: Setting[_] = libraryDependencies <<= (sbtVersion)(v => Seq( "org.apache.ant" % "ant" % "1.8.2", "org.scala-sbt" % "compiler-interface" % v % "provided" @@ -132,9 +132,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { // Jline nested project. Compile this sucker once and be done. lazy val jline = Project("jline", file("src/jline")) - // Fast Java Bytecode Generator (nested in every scala-compiler.jar) - lazy val fjbg = Project("fjbg", file(".")) settings(settingOverrides : _*) - // Our wrapped version of msil. + // Our wrapped version of asm. lazy val asm = Project("asm", file(".")) settings(settingOverrides : _*) // Forkjoin backport lazy val forkjoin = Project("forkjoin", file(".")) settings(settingOverrides : _*) @@ -175,9 +173,9 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { // -------------------------------------------------------------- // Projects dependent on layered compilation (quick) // -------------------------------------------------------------- - def addCheaterDependency(projectName: String): Setting[_] = - pomPostProcess <<= (version, organization, pomPostProcess) apply { (v,o,k) => - val dependency: scala.xml.Node = + def addCheaterDependency(projectName: String): Setting[_] = + pomPostProcess <<= (version, organization, pomPostProcess) apply { (v,o,k) => + val dependency: scala.xml.Node = {o} {projectName} @@ -193,10 +191,10 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { case n: scala.xml.Elem if n.label == "dependencies" => n } isEmpty) // TODO - Keep namespace on project... - k andThen { + k andThen { case n @ { nested@_*} if hasDependencies(n) => {nested}{dependency} - case { nested@_*} => + case { nested@_*} => { nested map fixDependencies } } } @@ -205,7 +203,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { lazy val dependentProjectSettings = settingOverrides ++ Seq(quickScalaInstance, quickScalaLibraryDependency, addCheaterDependency("scala-library")) lazy val actors = Project("scala-actors", file(".")) settings(dependentProjectSettings:_*) dependsOn(forkjoin % "provided") lazy val swing = Project("scala-swing", file(".")) settings(dependentProjectSettings:_*) dependsOn(actors % "provided") - // This project will generate man pages (in man1 and html) for scala. + // This project will generate man pages (in man1 and html) for scala. lazy val manmakerSettings: Seq[Setting[_]] = dependentProjectSettings :+ externalDeps lazy val manmaker = Project("manual", file(".")) settings(manmakerSettings:_*) @@ -234,7 +232,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { lazy val continuationsPlugin = Project("continuations-plugin", file(".")) settings(continuationsPluginSettings:_*) lazy val continuationsLibrarySettings = dependentProjectSettings ++ Seq( scalaSource in Compile <<= baseDirectory(_ / "src/continuations/library/"), - scalacOptions in Compile <++= (exportedProducts in Compile in continuationsPlugin) map { + scalacOptions in Compile <++= (exportedProducts in Compile in continuationsPlugin) map { case Seq(cpDir) => Seq("-Xplugin-require:continuations", "-P:continuations:enable", "-Xplugin:"+cpDir.data.getAbsolutePath) } ) @@ -283,7 +281,7 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { // -------------------------------------------------------------- // Real Compiler Artifact // -------------------------------------------------------------- - lazy val packageScalaBinTask = Seq(quickComp, fjbg, asm).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) + lazy val packageScalaBinTask = Seq(quickComp, asm).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) lazy val scalaBinArtifactSettings : Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaBinTask)) ++ Seq( name := "scala-compiler", crossPaths := false, @@ -297,11 +295,11 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { lazy val scalaCompiler = Project("scala-compiler", file(".")) settings(publishSettings:_*) settings(scalaBinArtifactSettings:_*) dependsOn(scalaReflect) lazy val fullQuickScalaReference = makeScalaReference("pack", scalaLibrary, scalaReflect, scalaCompiler) - + // -------------------------------------------------------------- // Generating Documentation. // -------------------------------------------------------------- - + // TODO - Migrate this into the dist project. // Scaladocs lazy val documentationSettings: Seq[Setting[_]] = dependentProjectSettings ++ Seq( @@ -331,6 +329,6 @@ object ScalaBuild extends Build with Layers with Packaging with Testing { lazy val documentation = ( Project("documentation", file(".")) settings (documentationSettings: _*) - dependsOn(quickLib, quickComp, actors, fjbg, forkjoin, swing, continuationsLibrary) + dependsOn(quickLib, quickComp, actors, forkjoin, swing, continuationsLibrary) ) } diff --git a/project/Layers.scala b/project/Layers.scala index 35cc79c13043..6c939d0ff79d 100644 --- a/project/Layers.scala +++ b/project/Layers.scala @@ -13,8 +13,6 @@ trait Layers extends Build { def jline: Project /** Reference to forkjoin library */ def forkjoin: Project - /** Reference to Fast-Java-Bytecode-Generator library */ - def fjbg: Project /** Reference to the ASM wrapped project. */ def asm: Project /** A setting that adds some external dependencies. */ @@ -23,7 +21,7 @@ trait Layers extends Build { def aaa_root: Project /** Creates a reference Scala version that can be used to build other projects. This takes in the raw - * library, compiler and fjbg libraries as well as a string representing the layer name (used for compiling the compile-interface). + * library, compiler as well as a string representing the layer name (used for compiling the compile-interface). */ def makeScalaReference(layer: String, library: Project, reflect: Project, compiler: Project) = scalaInstance <<= (appConfiguration in library, @@ -31,10 +29,9 @@ trait Layers extends Build { (exportedProducts in library in Compile), (exportedProducts in reflect in Compile), (exportedProducts in compiler in Compile), - (exportedProducts in fjbg in Compile), (fullClasspath in jline in Runtime), (exportedProducts in asm in Runtime)) map { - (app, version: String, lib: Classpath, reflect: Classpath, comp: Classpath, fjbg: Classpath, jline: Classpath, asm: Classpath) => + (app, version: String, lib: Classpath, reflect: Classpath, comp: Classpath, jline: Classpath, asm: Classpath) => val launcher = app.provider.scalaProvider.launcher (lib,comp) match { case (Seq(libraryJar), Seq(compilerJar)) => @@ -43,14 +40,14 @@ trait Layers extends Build { libraryJar.data, compilerJar.data, launcher, - ((fjbg.files ++ jline.files ++ asm.files ++ reflect.files):_*)) + ((jline.files ++ asm.files ++ reflect.files):_*)) case _ => error("Cannot build a ScalaReference with more than one classpath element") } } /** Creates a "layer" of Scala compilation. That is, this will build the next version of Scala from a previous version. * Returns the library project and compiler project from the next layer. - * Note: The library and compiler are not *complete* in the sense that they are missing things like "actors" and "fjbg". + * Note: The library and compiler are not *complete* in the sense that they are missing things like "actors". */ def makeLayer(layer: String, referenceScala: Setting[Task[ScalaInstance]], autoLock: Boolean = false) : (Project, Project, Project) = { val autoLockSettings: Seq[Setting[_]] = @@ -96,7 +93,6 @@ trait Layers extends Build { version := layer, scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "compiler"), resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "compiler"), - unmanagedSourceDirectories in Compile <+= (baseDirectory) apply (_ / "src" / "msil"), defaultExcludes := ("tests"), defaultExcludes in unmanagedResources := "*.scala", resourceGenerators in Compile <+= (resourceManaged, Versions.scalaVersions, skip in Compile, streams) map Versions.generateVersionPropertiesFile("compiler.properties"), @@ -108,7 +104,7 @@ trait Layers extends Build { dirs.descendentsExcept( ("*.xml" | "*.html" | "*.gif" | "*.png" | "*.js" | "*.css" | "*.tmpl" | "*.swf" | "*.properties" | "*.txt"),"*.scala").get }, // TODO - Use depends on *and* SBT's magic dependency mechanisms... - unmanagedClasspath in Compile <<= Seq(forkjoin, library, reflect, fjbg, jline, asm).map(exportedProducts in Compile in _).join.map(_.flatten), + unmanagedClasspath in Compile <<= Seq(forkjoin, library, reflect, jline, asm).map(exportedProducts in Compile in _).join.map(_.flatten), externalDeps, referenceScala ) diff --git a/project/Packaging.scala b/project/Packaging.scala index eb4e69f99e61..6cb51a10a67c 100644 --- a/project/Packaging.scala +++ b/project/Packaging.scala @@ -19,7 +19,7 @@ trait Packaging { self: ScalaBuild.type => genBin <<= genBinTask(genBinRunner, binDir, fullClasspath in Runtime, false), binDir in genBinQuick <<= baseDirectory apply (_ / "target" / "bin"), // Configure the classpath this way to avoid having .jar files and previous layers on the classpath. - fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,fjbg,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq), + fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq), fullClasspath in Runtime in genBinQuick <++= (fullClasspath in Compile in jline), genBinQuick <<= genBinTask(genBinRunner, binDir in genBinQuick, fullClasspath in Runtime in genBinQuick, true), runManmakerMan <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitManPage", "man1", ".1"), diff --git a/project/Testing.scala b/project/Testing.scala index 5de72116a36f..5b4135a31a48 100644 --- a/project/Testing.scala +++ b/project/Testing.scala @@ -17,7 +17,7 @@ trait Testing { self: ScalaBuild.type => autoScalaLibrary := false ) lazy val continuationsTestsuiteSettings: Seq[Setting[_]] = testsuiteSettings ++ Seq( - scalacOptions in Test <++= (exportedProducts in Compile in continuationsPlugin) map { + scalacOptions in Test <++= (exportedProducts in Compile in continuationsPlugin) map { case Seq(cpDir) => Seq("-Xplugin-require:continuations", "-P:continuations:enable", "-Xplugin:"+cpDir.data.getAbsolutePath) }, partestDirs <<= baseDirectory apply { bd => @@ -27,14 +27,14 @@ trait Testing { self: ScalaBuild.type => } ) val testsuite = ( - Project("testsuite", file(".")) + Project("testsuite", file(".")) settings (testsuiteSettings:_*) - dependsOn (scalaLibrary, scalaCompiler, fjbg, partest, scalacheck) + dependsOn (scalaLibrary, scalaCompiler, partest, scalacheck) ) val continuationsTestsuite = ( Project("continuations-testsuite", file(".")) - settings (continuationsTestsuiteSettings:_*) - dependsOn (partest, scalaLibrary, scalaCompiler, fjbg) + settings (continuationsTestsuiteSettings:_*) + dependsOn (partest, scalaLibrary, scalaCompiler) ) } diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala index cf3b5f949b0b..3b8ae202f66f 100644 --- a/src/compiler/scala/tools/ant/Scalac.scala +++ b/src/compiler/scala/tools/ant/Scalac.scala @@ -56,8 +56,6 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} * - `usejavacp`, * - `failonerror`, * - `scalacdebugging`, - * - `assemname`, - * - `assemrefs`. * * It also takes the following parameters as nested elements: * - `src` (for `srcdir`), @@ -100,7 +98,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared { /** Defines valid values for the `target` property. */ object Target extends PermissibleValue { - val values = List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "msil") + val values = List("jvm-1.5", "jvm-1.6", "jvm-1.7") } /** Defines valid values for the `deprecation` and `unchecked` properties. */ @@ -170,11 +168,6 @@ class Scalac extends ScalaMatchingTask with ScalacShared { /** Indicates whether compilation errors will fail the build; defaults to true. */ protected var failonerror: Boolean = true - // Name of the output assembly (only relevant with -target:msil) - protected var assemname: Option[String] = None - // List of assemblies referenced by the program (only relevant with -target:msil) - protected var assemrefs: Option[String] = None - /** Prints out the files being compiled by the scalac ant task * (not only the number of files). */ protected var scalacDebugging: Boolean = false @@ -421,9 +414,6 @@ class Scalac extends ScalaMatchingTask with ScalacShared { * @param input The specified flag */ def setScalacdebugging(input: Boolean) { scalacDebugging = input } - def setAssemname(input: String) { assemname = Some(input) } - def setAssemrefs(input: String) { assemrefs = Some(input) } - /** Sets the `compilerarg` as a nested compilerarg Ant parameter. * @return A compiler argument to be configured. */ def createCompilerArg(): ImplementationSpecificArgument = { @@ -616,9 +606,6 @@ class Scalac extends ScalaMatchingTask with ScalacShared { if (!unchecked.isEmpty) settings.unchecked.value = unchecked.get if (!usejavacp.isEmpty) settings.usejavacp.value = usejavacp.get - if (!assemname.isEmpty) settings.assemname.value = assemname.get - if (!assemrefs.isEmpty) settings.assemrefs.value = assemrefs.get - val jvmargs = scalacCompilerArgs.getArgs filter (_ startsWith "-J") if (!jvmargs.isEmpty) settings.jvmargs.value = jvmargs.toList val defines = scalacCompilerArgs.getArgs filter (_ startsWith "-D") diff --git a/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala b/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala index 9cdf4840806a..d5545fe76a3b 100644 --- a/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala +++ b/src/compiler/scala/tools/ant/sabbus/ScalacFork.scala @@ -80,7 +80,7 @@ class ScalacFork extends ScalaMatchingTask with ScalacShared with TaskArgs { private def createMapper() = { val mapper = new GlobPatternMapper() - val extension = if (isMSIL) "*.msil" else "*.class" + val extension = "*.class" mapper setTo extension mapper setFrom "*.scala" @@ -104,9 +104,6 @@ class ScalacFork extends ScalaMatchingTask with ScalacShared with TaskArgs { sourcePath foreach (settings.sourcepath = _) settings.extraParams = extraArgsFlat - if (isMSIL) - settings.sourcedir = sourceDir - val mapper = createMapper() val includedFiles: Array[File] = diff --git a/src/compiler/scala/tools/ant/sabbus/TaskArgs.scala b/src/compiler/scala/tools/ant/sabbus/TaskArgs.scala index 6bb1aaa30628..b061bcf7fb4a 100644 --- a/src/compiler/scala/tools/ant/sabbus/TaskArgs.scala +++ b/src/compiler/scala/tools/ant/sabbus/TaskArgs.scala @@ -98,6 +98,4 @@ trait TaskArgs extends CompilationPathProperty { val parts = a.getParts if(parts eq null) Seq[String]() else parts.toSeq } - - def isMSIL = compTarget exists (_ == "msil") } diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 397e6c42d7d5..34d5d10cbf25 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -23,8 +23,8 @@ import ast.parser._ import typechecker._ import transform._ import backend.icode.{ ICodes, GenICode, ICodeCheckers } -import backend.{ ScalaPrimitives, Platform, MSILPlatform, JavaPlatform } -import backend.jvm.{GenJVM, GenASM} +import backend.{ ScalaPrimitives, Platform, JavaPlatform } +import backend.jvm.GenASM import backend.opt.{ Inliners, InlineExceptionHandlers, ClosureElimination, DeadCodeElimination } import backend.icode.analysis._ import scala.language.postfixOps @@ -77,8 +77,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) 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 + new { val global: Global.this.type = Global.this } with JavaPlatform type PlatformClassPath = ClassPath[platform.BinaryRepr] type OptClassPath = Option[PlatformClassPath] @@ -594,13 +593,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val runsRightAfter = None } with DeadCodeElimination - // phaseName = "jvm", FJBG-based version - object genJVM extends { - val global: Global.this.type = Global.this - val runsAfter = List("dce") - val runsRightAfter = None - } with GenJVM - // phaseName = "jvm", ASM-based version object genASM extends { val global: Global.this.type = Global.this @@ -620,7 +612,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) object terminal extends { val global: Global.this.type = Global.this val phaseName = "terminal" - val runsAfter = List("jvm", "msil") + val runsAfter = List("jvm") val runsRightAfter = None } with SubComponent { private var cache: Option[GlobalPhase] = None @@ -1314,7 +1306,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val closelimPhase = phaseNamed("closelim") val dcePhase = phaseNamed("dce") // val jvmPhase = phaseNamed("jvm") - // val msilPhase = phaseNamed("msil") def runIsAt(ph: Phase) = globalPhase.id == ph.id def runIsAtOptimiz = { @@ -1675,14 +1666,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } }) } - // In order to not outright break code which overrides onlyPresentation (like sbt 0.7.5.RC0) - // I restored and deprecated it. That would be enough to avoid the compilation - // failure, but the override wouldn't accomplish anything. So now forInteractive - // and forScaladoc default to onlyPresentation, which is the same as defaulting - // to false except in old code. The downside is that this leaves us calling a - // deprecated method: but I see no simple way out, so I leave it for now. - // def forJVM = settings.target.value startsWith "jvm" - override def forMSIL = settings.target.value startsWith "msil" def forInteractive = false def forScaladoc = false def createJavadoc = false diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala index 5a3ea56f677a..a4b22b0e112c 100644 --- a/src/compiler/scala/tools/nsc/Main.scala +++ b/src/compiler/scala/tools/nsc/Main.scala @@ -9,7 +9,6 @@ import java.io.File import File.pathSeparator import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager } import scala.tools.nsc.io.AbstractFile -import Properties.msilLibPath /** The main class for NSC, a compiler for the programming * language Scala. @@ -60,11 +59,7 @@ object Main extends Driver with EvalLoop { } false } - else { - if (settings.target.value == "msil") - msilLibPath foreach (x => settings.assemrefs.value += (pathSeparator + x)) - true - } + else true override def newCompiler(): Global = if (settings.Yrangepos.value) new Global(settings, reporter) with interactive.RangePositions diff --git a/src/compiler/scala/tools/nsc/Properties.scala b/src/compiler/scala/tools/nsc/Properties.scala index 570d5572d619..feb4ded2f23e 100644 --- a/src/compiler/scala/tools/nsc/Properties.scala +++ b/src/compiler/scala/tools/nsc/Properties.scala @@ -16,9 +16,6 @@ object Properties extends scala.util.PropertiesTrait { def residentPromptString = scalaPropOrElse("resident.prompt", "\nnsc> ") def shellPromptString = scalaPropOrElse("shell.prompt", "\nscala> ") - // settings based on system properties - def msilLibPath = propOrNone("msil.libpath") - // derived values def isEmacsShell = propOrEmpty("env.emacs") != "" } diff --git a/src/compiler/scala/tools/nsc/ScalaDoc.scala b/src/compiler/scala/tools/nsc/ScalaDoc.scala index ba434bc79730..14b76b53b373 100644 --- a/src/compiler/scala/tools/nsc/ScalaDoc.scala +++ b/src/compiler/scala/tools/nsc/ScalaDoc.scala @@ -10,7 +10,6 @@ import java.io.File.pathSeparator import scala.tools.nsc.doc.DocFactory import scala.tools.nsc.reporters.ConsoleReporter import scala.reflect.internal.util.FakePos -import Properties.msilLibPath /** The main class for scaladoc, a front-end for the Scala compiler * that generates documentation from source files. @@ -42,12 +41,8 @@ class ScalaDoc { reporter.warning(null, "Phases are restricted when using Scaladoc") else if (docSettings.help.value || !hasFiles) reporter.echo(command.usageMsg) - else try { - if (docSettings.target.value == "msil") - msilLibPath foreach (x => docSettings.assemrefs.value += (pathSeparator + x)) - - new DocFactory(reporter, docSettings) document command.files - } + else + try { new DocFactory(reporter, docSettings) document command.files } catch { case ex @ FatalError(msg) => if (docSettings.debug.value) ex.printStackTrace() diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala index fd4366baf1ca..5cc4404ca152 100644 --- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala +++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala @@ -42,13 +42,9 @@ trait JavaPlatform extends Platform { if (settings.make.isDefault) Nil else List(dependencyAnalysis) - private def classEmitPhase = - if (settings.target.value == "jvm-1.5-fjbg") genJVM - else genASM - def platformPhases = List( flatten, // get rid of inner classes - classEmitPhase // generate .class files + genASM // generate .class files ) ++ depAnalysisPhase lazy val externalEquals = getDecl(BoxesRunTimeClass, nme.equals_) diff --git a/src/compiler/scala/tools/nsc/backend/MSILPlatform.scala b/src/compiler/scala/tools/nsc/backend/MSILPlatform.scala deleted file mode 100644 index 4493685b524b..000000000000 --- a/src/compiler/scala/tools/nsc/backend/MSILPlatform.scala +++ /dev/null @@ -1,69 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 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. - - /** Update classpath with a substituted subentry */ - def updateClassPath(subst: Map[ClassPath[BinaryRepr], ClassPath[BinaryRepr]]) = - throw new UnsupportedOperationException("classpath invalidations not supported on MSIL") - - 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/ExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala index 7c2961778fe6..a872e9cd0014 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala @@ -27,9 +27,6 @@ trait ExceptionHandlers { private var _startBlock: BasicBlock = _; var finalizer: Finalizer = _; - /** Needed for the MSIL backend. */ - var resultKind: TypeKind = _; - def setStartBlock(b: BasicBlock) = { _startBlock = b; b.exceptionHandlerStart = true diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index fb9e68a3a16a..4e973c86ea77 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -164,10 +164,7 @@ abstract class GenICode extends SubComponent { private def genStat(tree: Tree, ctx: Context): Context = tree match { 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 genLoadQualifier(lhs, ctx) + var ctx1 = if (isStatic) ctx else genLoadQualifier(lhs, ctx) ctx1 = genLoad(rhs, ctx1, toTypeKind(lhs.symbol.info)) ctx1.bb.emit(STORE_FIELD(lhs.symbol, isStatic), tree.pos) @@ -301,9 +298,6 @@ abstract class GenICode extends SubComponent { val Apply(fun, args) = tree val monitor = ctx.makeLocal(tree.pos, ObjectClass.tpe, "monitor") var monitorResult: Local = null - - // if the synchronized block returns a result, store it in a local variable. just leaving - // it on the stack is not valid in MSIL (stack is cleaned when leaving try-blocks) val argTpe = args.head.tpe val hasResult = expectedType != UNIT if (hasResult) @@ -461,131 +455,6 @@ abstract class GenICode extends SubComponent { ) } - /** - * 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 Select(receiver, _) = fun - 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 * @@ -808,31 +677,15 @@ 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 nw = NEW(rt) - ctx.bb.emit(nw, tree.pos) - ctx.bb.emit(DUP(generatedType)) - val ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx) - - val init = CALL_METHOD(ctor, Static(true)) - nw.init = init - ctx1.bb.emit(init, tree.pos) - ctx1 - } - ctx2 + val nw = NEW(rt) + ctx.bb.emit(nw, tree.pos) + ctx.bb.emit(DUP(generatedType)) + val ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx) + val init = CALL_METHOD(ctor, Static(true)) + nw.init = init + ctx1.bb.emit(init, tree.pos) + ctx1 case _ => abort("Cannot instantiate " + tpt + " of kind: " + generatedType) } @@ -866,12 +719,6 @@ abstract class GenICode extends SubComponent { 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 app @ Apply(fun, args) => def genLoadApply6 = { val sym = fun.symbol @@ -913,19 +760,12 @@ abstract class GenICode extends SubComponent { else Dynamic - var ctx1 = - if (invokeStyle.hasInstance) { - if (forMSIL && !(invokeStyle.isInstanceOf[SuperCall]) && msil_IsValuetypeInstMethod(sym)) - msil_genLoadQualifierAddress(fun, ctx) - else - genLoadQualifier(fun, ctx) - } else ctx - + var ctx1 = if (invokeStyle.hasInstance) genLoadQualifier(fun, ctx) else ctx ctx1 = genLoadArguments(args, sym.info.paramTypes, ctx1) val cm = CALL_METHOD(sym, invokeStyle) /** In a couple cases, squirrel away a little extra information in the - * CALL_METHOD for use by GenJVM. + * CALL_METHOD for use by GenASM. */ fun match { case Select(qual, _) => @@ -956,7 +796,6 @@ abstract class GenICode extends SubComponent { genLoadApply6 case ApplyDynamic(qual, args) => - assert(!forMSIL, tree) // TODO - this is where we'd catch dynamic applies for invokedynamic. sys.error("No invokedynamic support yet.") // val ctx1 = genLoad(qual, ctx, ObjectReference) @@ -1189,15 +1028,6 @@ abstract class GenICode extends SubComponent { 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. */ @@ -1385,7 +1215,7 @@ abstract class GenICode extends SubComponent { def genStringConcat(tree: Tree, ctx: Context): Context = { liftStringConcat(tree) match { // Optimization for expressions of the form "" + x. We can avoid the StringBuilder. - case List(Literal(Constant("")), arg) if !forMSIL => + case List(Literal(Constant("")), arg) => debuglog("Rewriting \"\" + x as String.valueOf(x) for: " + arg) val ctx1 = genLoad(arg, ctx, ObjectReference) ctx1.bb.emit(CALL_METHOD(String_valueOf, Static(false)), arg.pos) @@ -1988,10 +1818,9 @@ abstract class GenICode extends SubComponent { * 'covered' by this exception handler (in addition to the * previously active handlers). */ - private def newExceptionHandler(cls: Symbol, resultKind: TypeKind, pos: Position): ExceptionHandler = { + private def newExceptionHandler(cls: Symbol, pos: Position): ExceptionHandler = { handlerCount += 1 val exh = new ExceptionHandler(method, newTermNameCached("" + handlerCount), cls, pos) - exh.resultKind = resultKind method.addHandler(exh) handlers = exh :: handlers debuglog("added handler: " + exh); @@ -2051,7 +1880,7 @@ abstract class GenICode extends SubComponent { def Try(body: Context => Context, handlers: List[(Symbol, TypeKind, Context => Context)], finalizer: Tree, - tree: Tree) = if (forMSIL) TryMsil(body, handlers, finalizer, tree) else { + tree: Tree) = { val outerCtx = this.dup // context for generating exception handlers, covered by finalizer val finalizerCtx = this.dup // context for generating finalizer handler @@ -2083,7 +1912,7 @@ abstract class GenICode extends SubComponent { if (finalizer != EmptyTree) { - val exh = outerCtx.newExceptionHandler(NoSymbol, toTypeKind(finalizer.tpe), finalizer.pos) // finalizer covers exception handlers + val exh = outerCtx.newExceptionHandler(NoSymbol, finalizer.pos) // finalizer covers exception handlers this.addActiveHandler(exh) // .. and body aswell val ctx = finalizerCtx.enterExceptionHandler(exh) val exception = ctx.makeLocal(finalizer.pos, ThrowableClass.tpe, "exc") @@ -2098,7 +1927,7 @@ abstract class GenICode extends SubComponent { } for ((sym, kind, handler) <- handlers) { - val exh = this.newExceptionHandler(sym, kind, tree.pos) + val exh = this.newExceptionHandler(sym, tree.pos) var ctx1 = outerCtx.enterExceptionHandler(exh) ctx1.addFinalizer(finalizer, finalizerCtx) loadException(ctx1, exh, tree.pos) @@ -2122,67 +1951,6 @@ abstract class GenICode extends SubComponent { afterCtx } - - - /** try-catch-finally blocks are actually simpler to emit in MSIL, because there - * is support for `finally` in bytecode. - * - * A - * try { .. } catch { .. } finally { .. } - * block is de-sugared into - * try { try { ..} catch { .. } } finally { .. } - * - * In ICode `finally` block is represented exactly the same as an exception handler, - * but with `NoSymbol` as the exception class. The covered blocks are all blocks of - * the `try { .. } catch { .. }`. - * - * Also, TryMsil does not enter any Finalizers into the `cleanups`, because the - * CLI takes care of running the finalizer when seeing a `leave` statement inside - * a try / catch. - */ - def TryMsil(body: Context => Context, - handlers: List[(Symbol, TypeKind, (Context => Context))], - finalizer: Tree, - tree: Tree) = { - - val outerCtx = this.dup // context for generating exception handlers, covered by finalizer - val finalizerCtx = this.dup // context for generating finalizer handler - val afterCtx = outerCtx.newBlock - - if (finalizer != EmptyTree) { - // finalizer is covers try and all catch blocks, i.e. - // try { try { .. } catch { ..} } finally { .. } - val exh = outerCtx.newExceptionHandler(NoSymbol, UNIT, tree.pos) - this.addActiveHandler(exh) - val ctx = finalizerCtx.enterExceptionHandler(exh) - loadException(ctx, exh, tree.pos) - val ctx1 = genLoad(finalizer, ctx, UNIT) - // need jump for the ICode to be valid. MSIL backend will emit `Endfinally` instead. - ctx1.bb.closeWith(JUMP(afterCtx.bb)) - finalizerCtx.endHandler() - } - - for (handler <- handlers) { - val exh = this.newExceptionHandler(handler._1, handler._2, tree.pos) - var ctx1 = outerCtx.enterExceptionHandler(exh) - loadException(ctx1, exh, tree.pos) - ctx1 = handler._3(ctx1) - // msil backend will emit `Leave` to jump out of a handler - ctx1.bb.closeWith(JUMP(afterCtx.bb)) - outerCtx.endHandler() - } - - val bodyCtx = this.newBlock - - val finalCtx = body(bodyCtx) - - outerCtx.bb.closeWith(JUMP(bodyCtx.bb)) - - // msil backend will emit `Leave` to jump out of a try-block - finalCtx.bb.closeWith(JUMP(afterCtx.bb)) - - afterCtx - } } } diff --git a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala index b8a98955c9e6..80477f0c6e9c 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala @@ -197,142 +197,4 @@ trait Linearizers { def linearize(m: IMethod): List[BasicBlock] = m.blocks def linearizeAt(m: IMethod, start: BasicBlock): List[BasicBlock] = sys.error("not implemented") } - - /** The MSIL linearizer is used only for methods with at least one exception handler. - * It makes sure that all the blocks belonging to a `try`, `catch` or `finally` block - * are emitted in an order that allows the lexical nesting of try-catch-finally, just - * like in the source code. - */ - class MSILLinearizer extends Linearizer { - /** The MSIL linearizer first calls a NormalLInearizer. This is because the ILGenerator checks - * the stack size before emitting instructions. For instance, to emit a `store`, there needs - * to be some value on the stack. This can blow up in situations like this: - * ... - * jump 3 - * 4: store_local 0 - * jump 5 - * 3: load_value - * jump 4 - * 5: ... - * here, 3 must be scheduled first. - * - * The NormalLinearizer also removes dead blocks (blocks without predecessor). This is important - * in the following example: - * try { throw new Exception } - * catch { case e => throw e } - * which adds a dead block containing just a "throw" (which, again, would blow up code generation - * because of the stack size; there's no value on the stack when emitting that `throw`) - */ - val normalLinearizer = new NormalLinearizer() - - def linearize(m: IMethod): List[BasicBlock] = { - - val handlersByCovered = m.exh.groupBy(_.covered) - - // number of basic blocks covered by the entire try-catch expression - def size(covered: scala.collection.immutable.Set[BasicBlock]) = { - val hs = handlersByCovered(covered) - covered.size + (hs :\ 0)((h, s) => h.blocks.length + s) - } - - val tryBlocks = handlersByCovered.keys.toList sortBy size - var result = normalLinearizer.linearize(m) - val frozen = mutable.HashSet[BasicBlock](result.head) - - for (tryBlock <- tryBlocks) { - result = groupBlocks(m, result, handlersByCovered(tryBlock), frozen) - } - result - } - - /** @param handlers a list of handlers covering the same blocks (same try, multiple catches) - * @param frozen blocks can't be moved (fist block of a method, blocks directly following a try-catch) - */ - def groupBlocks(method: IMethod, blocks: List[BasicBlock], handlers: List[ExceptionHandler], frozen: mutable.HashSet[BasicBlock]) = { - assert(blocks.head == method.startBlock, method) - - // blocks before the try, and blocks for the try - val beforeAndTry = new ListBuffer[BasicBlock]() - // blocks for the handlers - val catches = handlers map (_ => new ListBuffer[BasicBlock]()) - // blocks to be put at the end - val after = new ListBuffer[BasicBlock]() - - var beforeTry = true - val head = handlers.head - - for (b <- blocks) { - if (head covers b) { - beforeTry = false - beforeAndTry += b - } else { - val handlerIndex = handlers.indexWhere(_.blocks.contains(b)) - if (handlerIndex >= 0) { - catches(handlerIndex) += b - } else if (beforeTry) { - beforeAndTry += b - } else { - after += b - } - } - } - - // reorder the blocks in "catches" so that the "firstBlock" is actually first - (catches, handlers).zipped foreach { (lb, handler) => - lb -= handler.startBlock - handler.startBlock +=: lb - } - - // The first block emitted after a try-catch must be the one that the try / catch - // blocks jump to (because in msil, these jumps cannot be emitted manually) - var firstAfter: Option[BasicBlock] = None - - // Find the (hopefully) unique successor, look at the try and all catch blocks - var blks = head.covered.toList :: handlers.map(_.blocks) - while (firstAfter.isEmpty && !blks.isEmpty) { - val b = blks.head - blks = blks.tail - - val leaving = leavingBlocks(b) - // no leaving blocks when the try or catch ends with THROW or RET - if (!leaving.isEmpty) { - assert(leaving.size <= 1, leaving) - firstAfter = Some(leaving.head) - } - } - if (firstAfter.isDefined) { - val b = firstAfter.get - if (frozen(b)) { - assert(after contains b, b +", "+ method) - } else { - frozen += b - if (beforeAndTry contains b) { - beforeAndTry -= b - } else { - assert(after contains b, after) - after -= b - } - b +=: after - } - } - - for (lb <- catches) { beforeAndTry ++= lb } - beforeAndTry ++= after - beforeAndTry.toList - } - - /** Returns all direct successors of `blocks` wich are not part - * that list, i.e. successors outside the `blocks` list. - */ - private def leavingBlocks(blocks: List[BasicBlock]) = { - val res = new mutable.HashSet[BasicBlock]() - for (b <- blocks; s <- b.directSuccessors; if (!blocks.contains(s))) - res += s - res - } - - def linearizeAt(m: IMethod, start: BasicBlock): List[BasicBlock] = { - sys.error("not implemented") - } - } } diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index eaa742a1da35..137e2b556f80 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -734,74 +734,5 @@ trait Opcodes { self: ICodes => case class SuperCall(mix: Name) extends InvokeStyle { override def toString(): String = { "super(" + mix + ")" } } - - - // 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 = msil_mgdptr(local.kind) :: Nil - - override def category = localsCat - } - - 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 REFERENCE(field.owner) :: Nil; - override def producedTypes = msil_mgdptr(REFERENCE(field.owner)) :: Nil; - - override def category = fldsCat - } - - 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 = ARRAY(kind) :: INT :: Nil - override def producedTypes = msil_mgdptr(kind) :: Nil - - override def category = arraysCat - } - - case class CIL_UNBOX(valueType: TypeKind) extends Instruction { - override def toString(): String = "CIL_UNBOX " + valueType - override def consumed = 1 - override def consumedTypes = ObjectReferenceList // actually consumes a 'boxed valueType' - override def produced = 1 - override def producedTypes = msil_mgdptr(valueType) :: Nil - override def category = objsCat - } - - case class CIL_INITOBJ(valueType: TypeKind) extends Instruction { - override def toString(): String = "CIL_INITOBJ " + valueType - override def consumed = 1 - override def consumedTypes = ObjectReferenceList // actually consumes a managed pointer - override def produced = 0 - override def category = objsCat - } - - case class CIL_NEWOBJ(method: Symbol) extends Instruction { - override def toString(): String = "CIL_NEWOBJ " + hostClass.fullName + method.fullName - val 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 = toTypeKind(method.tpe.resultType) :: Nil - override def category = objsCat - } } } diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index 0990cfba6f05..84f5fe267818 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -427,11 +427,4 @@ 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) - } - } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 6edd089e75f8..819178935bae 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -190,7 +190,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { /* don't javaNameCache.clear() because that causes the following tests to fail: * test/files/run/macro-repl-dontexpand.scala * test/files/jvm/interpreter.scala - * TODO but why? what use could javaNameCache possibly see once GenJVM is over? + * TODO but why? what use could javaNameCache possibly see once GenASM is over? */ /* TODO After emitting all class files (e.g., in a separate compiler phase) ASM can perform bytecode verification: diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala deleted file mode 100644 index 92bca1921381..000000000000 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala +++ /dev/null @@ -1,62 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Stephane Micheloud - */ - - -package scala.tools.nsc -package backend.jvm - -import ch.epfl.lamp.fjbg._ -import symtab.Flags - -trait GenAndroid { - self: GenJVM => - - import global._ - import icodes._ - import opcodes._ - - /** From the reference documentation of the Android SDK: - * The `Parcelable` interface identifies classes whose instances can be - * written to and restored from a `Parcel`. Classes implementing the - * `Parcelable` interface must also have a static field called `CREATOR`, - * which is an object implementing the `Parcelable.Creator` interface. - */ - private val fieldName = newTermName("CREATOR") - - private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable") - private lazy val AndroidCreatorClass = rootMirror.getClassIfDefined("android.os.Parcelable$Creator") - - def isAndroidParcelableClass(sym: Symbol) = - (AndroidParcelableInterface != NoSymbol) && - (sym.parentSymbols contains AndroidParcelableInterface) - - def addCreatorCode(codegen: BytecodeGenerator, block: BasicBlock) { - import codegen._ - val fieldSymbol = ( - clasz.symbol.newValue(fieldName, NoPosition, Flags.STATIC | Flags.FINAL) - setInfo AndroidCreatorClass.tpe - ) - val methodSymbol = definitions.getMember(clasz.symbol.companionModule, fieldName) - clasz addField new IField(fieldSymbol) - block emit CALL_METHOD(methodSymbol, Static(false)) - block emit STORE_FIELD(fieldSymbol, true) - } - - def legacyAddCreatorCode(codegen: BytecodeGenerator, clinit: JExtendedCode) { - import codegen._ - val creatorType = javaType(AndroidCreatorClass) - jclass.addNewField(PublicStaticFinal, - fieldName.toString, - creatorType) - val moduleName = javaName(clasz.symbol)+"$" - clinit.emitGETSTATIC(moduleName, - nme.MODULE_INSTANCE_FIELD.toString, - new JObjectType(moduleName)) - clinit.emitINVOKEVIRTUAL(moduleName, fieldName.toString, - new JMethodType(creatorType, Array())) - clinit.emitPUTSTATIC(jclass.getName(), fieldName.toString, creatorType) - } - -} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala deleted file mode 100644 index e1484d1f97e2..000000000000 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ /dev/null @@ -1,1950 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Iulian Dragos - */ - -package scala.tools.nsc -package backend.jvm - -import java.nio.ByteBuffer -import scala.collection.{ mutable, immutable } -import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer } -import scala.tools.nsc.symtab._ -import scala.reflect.internal.util.{ SourceFile, NoSourceFile } -import scala.reflect.internal.ClassfileConstants._ -import ch.epfl.lamp.fjbg._ -import JAccessFlags._ -import JObjectType.{ JAVA_LANG_STRING, JAVA_LANG_OBJECT } -import scala.language.postfixOps - -/** This class ... - * - * @author Iulian Dragos - * @version 1.0 - * - */ -abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with BytecodeWriters { - import global._ - import icodes._ - import icodes.opcodes._ - import definitions._ - - val phaseName = "jvm" - - /** Create a new phase */ - override def newPhase(p: Phase): Phase = new JvmPhase(p) - - /** JVM code generation phase - */ - class JvmPhase(prev: Phase) extends ICodePhase(prev) { - def name = phaseName - override def erasedTypes = true - def apply(cls: IClass) = sys.error("no implementation") - - def isJavaEntryPoint(clasz: IClass) = { - val sym = clasz.symbol - def fail(msg: String, pos: Position = sym.pos) = { - clasz.cunit.warning(sym.pos, - sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" + - " Reason: " + msg - // TODO: make this next claim true, if possible - // by generating valid main methods as static in module classes - // not sure what the jvm allows here - // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead." - ) - false - } - def failNoForwarder(msg: String) = { - fail(msg + ", which means no static forwarder can be generated.\n") - } - val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil - val hasApproximate = possibles exists { m => - m.info match { - case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass - case _ => false - } - } - // At this point it's a module with a main-looking method, so either - // succeed or warn that it isn't. - hasApproximate && { - // Before erasure so we can identify generic mains. - enteringErasure { - val companion = sym.linkedClassOfClass - - if (hasJavaMainMethod(companion)) - failNoForwarder("companion contains its own main method") - else if (companion.tpe.member(nme.main) != NoSymbol) - // this is only because forwarders aren't smart enough yet - failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)") - else if (companion.isTrait) - failNoForwarder("companion is a trait") - // Now either succeeed, or issue some additional warnings for things which look like - // attempts to be java main methods. - else possibles exists { m => - m.info match { - case PolyType(_, _) => - fail("main methods cannot be generic.") - case MethodType(params, res) => - if (res.typeSymbol :: params exists (_.isAbstractType)) - fail("main methods cannot refer to type parameters or abstract types.", m.pos) - else - isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos) - case tp => - fail("don't know what this is: " + tp, m.pos) - } - } - } - } - } - - override def run() { - // we reinstantiate the bytecode generator at each run, to allow the GC - // to collect everything - if (settings.debug.value) - inform("[running phase " + name + " on icode]") - - if (settings.Xdce.value) - for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) { - log(s"Optimizer eliminated ${sym.fullNameString}") - icodes.classes -= sym - } - - // For predictably ordered error messages. - val sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName) - val entryPoints = sortedClasses filter isJavaEntryPoint - - val bytecodeWriter = settings.outputDirs.getSingleOutput match { - case Some(f) if f hasExtension "jar" => - // If no main class was specified, see if there's only one - // entry point among the classes going into the jar. - if (settings.mainClass.isDefault) { - entryPoints map (_.symbol fullName '.') match { - case Nil => - log("No Main-Class designated or discovered.") - case name :: Nil => - log("Unique entry point: setting Main-Class to " + name) - settings.mainClass.value = name - case names => - log("No Main-Class due to multiple entry points:\n " + names.mkString("\n ")) - } - } - else log("Main-Class was specified: " + settings.mainClass.value) - - new DirectToJarfileWriter(f.file) - - case _ => - if (settings.Ygenjavap.isDefault) { - if(settings.Ydumpclasses.isDefault) - new ClassBytecodeWriter { } - else - new ClassBytecodeWriter with DumpBytecodeWriter { } - } - else new ClassBytecodeWriter with JavapBytecodeWriter { } - } - - val codeGenerator = new BytecodeGenerator(bytecodeWriter) - debuglog("Created new bytecode generator for " + classes.size + " classes.") - - sortedClasses foreach { c => - try codeGenerator.genClass(c) - catch { - case e: JCode.CodeSizeTooBigException => - log("Skipped class %s because it has methods that are too long.".format(c)) - } - } - - bytecodeWriter.close() - classes.clear() - } - } - - var pickledBytes = 0 // statistics - - /** - * Java bytecode generator. - * - */ - class BytecodeGenerator(bytecodeWriter: BytecodeWriter) extends BytecodeUtil { - def this() = this(new ClassBytecodeWriter { }) - def debugLevel = settings.debuginfo.indexOfChoice - import bytecodeWriter.writeClass - - val MIN_SWITCH_DENSITY = 0.7 - val INNER_CLASSES_FLAGS = - (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_INTERFACE | ACC_ABSTRACT) - - val PublicStatic = ACC_PUBLIC | ACC_STATIC - val PublicStaticFinal = ACC_PUBLIC | ACC_STATIC | ACC_FINAL - - val StringBuilderClassName = javaName(definitions.StringBuilderClass) - val BoxesRunTime = "scala.runtime.BoxesRunTime" - - val StringBuilderType = new JObjectType(StringBuilderClassName) // TODO use ASMType.getObjectType - val toStringType = new JMethodType(JAVA_LANG_STRING, JType.EMPTY_ARRAY) // TODO use ASMType.getMethodType - val arrayCloneType = new JMethodType(JAVA_LANG_OBJECT, JType.EMPTY_ARRAY) - - // Scala attributes - val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo") - - final val ExcludedForwarderFlags = { - import Flags._ - // Should include DEFERRED but this breaks findMember. - ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags ) - } - - // Additional interface parents based on annotations and other cues - def newParentForAttr(attr: Symbol): Option[Symbol] = attr match { - case CloneableAttr => Some(JavaCloneableClass) - case RemoteAttr => Some(RemoteInterfaceClass) - case _ => None - } - - val versionPickle = { - val vp = new PickleBuffer(new Array[Byte](16), -1, 0) - assert(vp.writeIndex == 0, vp) - vp writeNat PickleFormat.MajorVersion - vp writeNat PickleFormat.MinorVersion - vp writeNat 0 - vp - } - - private def helperBoxTo(kind: ValueTypeKind): Tuple2[String, JMethodType] = { - val boxedType = definitions.boxedClass(kind.toType.typeSymbol) - val mtype = new JMethodType(javaType(boxedType), Array(javaType(kind))) - - Pair("boxTo" + boxedType.decodedName, mtype) - } - - private val jBoxTo: Map[TypeKind, Tuple2[String, JMethodType]] = Map( - BOOL -> helperBoxTo(BOOL) , - BYTE -> helperBoxTo(BYTE) , - CHAR -> helperBoxTo(CHAR) , - SHORT -> helperBoxTo(SHORT) , - INT -> helperBoxTo(INT) , - LONG -> helperBoxTo(LONG) , - FLOAT -> helperBoxTo(FLOAT) , - DOUBLE -> helperBoxTo(DOUBLE) - ) - - private def helperUnboxTo(kind: ValueTypeKind): Tuple2[String, JMethodType] = { - val mtype = new JMethodType(javaType(kind), Array(JAVA_LANG_OBJECT)) - val mname = "unboxTo" + kind.toType.typeSymbol.decodedName - - Pair(mname, mtype) - } - - private val jUnboxTo: Map[TypeKind, Tuple2[String, JMethodType]] = Map( - BOOL -> helperUnboxTo(BOOL) , - BYTE -> helperUnboxTo(BYTE) , - CHAR -> helperUnboxTo(CHAR) , - SHORT -> helperUnboxTo(SHORT) , - INT -> helperUnboxTo(INT) , - LONG -> helperUnboxTo(LONG) , - FLOAT -> helperUnboxTo(FLOAT) , - DOUBLE -> helperUnboxTo(DOUBLE) - ) - - var clasz: IClass = _ - var method: IMethod = _ - var jclass: JClass = _ - var jmethod: JMethod = _ - - def isParcelableClass = isAndroidParcelableClass(clasz.symbol) - def isRemoteClass = clasz.symbol hasAnnotation RemoteAttr - def serialVUID = clasz.symbol getAnnotation SerialVersionUIDAttr collect { - case AnnotationInfo(_, Literal(const) :: _, _) => const.longValue - } - - val fjbgContext = new FJBGContext(49, 0) - val emitVars = debugLevel >= 3 - - // bug had phase with wrong name; leaving enabled for brief pseudo deprecation - private val checkSignatures = ( - (settings.check containsName phaseName) - || (settings.check.value contains "genjvm") && { - global.warning("This option will be removed: please use -Ycheck:%s, not -Ycheck:genjvm." format phaseName) - true - } - ) - - /** For given symbol return a symbol corresponding to a class that should be declared as inner class. - * - * For example: - * class A { - * class B - * object C - * } - * - * then method will return NoSymbol for A, the same symbol for A.B (corresponding to A$B class) and A$C$ symbol - * for A.C. - */ - private def innerClassSymbolFor(s: Symbol): Symbol = - if (s.isClass) s else if (s.isModule) s.moduleClass else NoSymbol - - override def javaName(sym: Symbol): String = { // TODO Miguel says: check whether a single pass over `icodes.classes` can populate `innerClassBuffer` faster. - /** - * Checks if given symbol corresponds to inner class/object and add it to innerClassBuffer - * - * Note: This method is called recursively thus making sure that we add complete chain - * of inner class all until root class. - */ - def collectInnerClass(s: Symbol): Unit = { - // TODO: some enteringFlatten { ... } which accounts for - // being nested in parameterized classes (if we're going to selectively flatten.) - val x = innerClassSymbolFor(s) - if(x ne NoSymbol) { - assert(x.isClass, "not an inner-class symbol") - val isInner = !x.rawowner.isPackageClass - if (isInner) { - innerClassBuffer += x - collectInnerClass(x.rawowner) - } - } - } - collectInnerClass(sym) - - super.javaName(sym) - } - - /** Write a class to disk, adding the Scala signature (pickled type - * information) and inner classes. - * - * @param jclass The FJBG class, where code was emitted - * @param sym The corresponding symbol, used for looking up pickled information - */ - def emitClass(jclass: JClass, sym: Symbol) { - addInnerClasses(jclass) - writeClass("" + sym.name, jclass.getName(), toByteArray(jclass), sym) - } - - /** Returns the ScalaSignature annotation if it must be added to this class, - * none otherwise; furthermore, it adds to `jclass` the ScalaSig marker - * attribute (marking that a scala signature annotation is present) or the - * Scala marker attribute (marking that the signature for this class is in - * another file). The annotation that is returned by this method must be - * added to the class' annotations list when generating them. - * - * @param jclass The class file that is being readied. - * @param sym The symbol for which the signature has been entered in - * the symData map. This is different than the symbol - * that is being generated in the case of a mirror class. - * @return An option that is: - * - defined and contains an annotation info of the - * ScalaSignature type, instantiated with the pickle - * signature for sym (a ScalaSig marker attribute has - * been written); - * - undefined if the jclass/sym couple must not contain a - * signature (a Scala marker attribute has been written). - */ - def scalaSignatureAddingMarker(jclass: JClass, sym: Symbol): Option[AnnotationInfo] = - currentRun.symData get sym match { - case Some(pickle) if !nme.isModuleName(newTermName(jclass.getName)) => - val scalaAttr = - fjbgContext.JOtherAttribute(jclass, jclass, tpnme.ScalaSignatureATTR.toString, - versionPickle.bytes, versionPickle.writeIndex) - jclass addAttribute scalaAttr - val scalaAnnot = { - val sigBytes = ScalaSigBytes(pickle.bytes.take(pickle.writeIndex)) - AnnotationInfo(sigBytes.sigAnnot, Nil, List((nme.bytes, sigBytes))) - } - pickledBytes += pickle.writeIndex - currentRun.symData -= sym - currentRun.symData -= sym.companionSymbol - Some(scalaAnnot) - case _ => - val markerAttr = - fjbgContext.JOtherAttribute(jclass, jclass, tpnme.ScalaATTR.toString, new Array[Byte](0), 0) - jclass addAttribute markerAttr - None - } - - private var innerClassBuffer = mutable.LinkedHashSet[Symbol]() - - /** Drop redundant interfaces (ones which are implemented by some other parent) from the immediate parents. - * This is important on Android because there is otherwise an interface explosion. - */ - private def minimizeInterfaces(interfaces: List[Symbol]): List[Symbol] = { - var rest = interfaces - var leaves = List.empty[Symbol] - while(!rest.isEmpty) { - val candidate = rest.head - val nonLeaf = leaves exists { lsym => lsym isSubClass candidate } - if(!nonLeaf) { - leaves = candidate :: (leaves filterNot { lsym => candidate isSubClass lsym }) - } - rest = rest.tail - } - - leaves - } - - def genClass(c: IClass) { - clasz = c - innerClassBuffer.clear() - - val name = javaName(c.symbol) - - val ps = c.symbol.info.parents - - val superClass: Symbol = if(ps.isEmpty) ObjectClass else ps.head.typeSymbol; - - val superInterfaces0: List[Symbol] = if(ps.isEmpty) Nil else c.symbol.mixinClasses; - val superInterfaces = superInterfaces0 ++ c.symbol.annotations.flatMap(ann => newParentForAttr(ann.symbol)) distinct - - val ifaces = - if(superInterfaces.isEmpty) JClass.NO_INTERFACES - else mkArray(minimizeInterfaces(superInterfaces) map javaName) - - jclass = fjbgContext.JClass(javaFlags(c.symbol), - name, - javaName(superClass), - ifaces, - c.cunit.source.toString) - - if (isStaticModule(c.symbol) || serialVUID != None || isParcelableClass) { - if (isStaticModule(c.symbol)) - addModuleInstanceField - addStaticInit(jclass, c.lookupStaticCtor) - - if (isTopLevelModule(c.symbol)) { - if (c.symbol.companionClass == NoSymbol) - generateMirrorClass(c.symbol, c.cunit.source) - else - log("No mirror class for module with linked class: " + - c.symbol.fullName) - } - } - else { - c.lookupStaticCtor foreach (constructor => addStaticInit(jclass, Some(constructor))) - - // it must be a top level class (name contains no $s) - def isCandidateForForwarders(sym: Symbol): Boolean = - exitingPickler { - !(sym.name.toString contains '$') && sym.hasModuleFlag && !sym.isImplClass && !sym.isNestedClass - } - - // At some point this started throwing lots of exceptions as a compile was finishing. - // error: java.lang.AssertionError: - // assertion failed: List(object package$CompositeThrowable, object package$CompositeThrowable) - // ...is the one I've seen repeatedly. Suppressing. - val lmoc = ( - try c.symbol.companionModule - catch { case x: AssertionError => - Console.println("Suppressing failed assert: " + x) - NoSymbol - } - ) - // add static forwarders if there are no name conflicts; see bugs #363 and #1735 - if (lmoc != NoSymbol && !c.symbol.isInterface) { - if (isCandidateForForwarders(lmoc) && !settings.noForwarders.value) { - log("Adding static forwarders from '%s' to implementations in '%s'".format(c.symbol, lmoc)) - addForwarders(jclass, lmoc.moduleClass) - } - } - } - - clasz.fields foreach genField - clasz.methods foreach genMethod - - val ssa = scalaSignatureAddingMarker(jclass, c.symbol) - addGenericSignature(jclass, c.symbol, c.symbol.owner) - addAnnotations(jclass, c.symbol.annotations ++ ssa) - addEnclosingMethodAttribute(jclass, c.symbol) - emitClass(jclass, c.symbol) - - if (c.symbol hasAnnotation BeanInfoAttr) - genBeanInfoClass(c) - } - - private def addEnclosingMethodAttribute(jclass: JClass, clazz: Symbol) { - val sym = clazz.originalEnclosingMethod - if (sym.isMethod) { - debuglog("enclosing method for %s is %s (in %s)".format(clazz, sym, sym.enclClass)) - jclass addAttribute fjbgContext.JEnclosingMethodAttribute( - jclass, - javaName(sym.enclClass), - javaName(sym), - javaType(sym) - ) - } else if (clazz.isAnonymousClass) { - val enclClass = clazz.rawowner - assert(enclClass.isClass, enclClass) - val sym = enclClass.primaryConstructor - if (sym == NoSymbol) - log("Ran out of room looking for an enclosing method for %s: no constructor here.".format( - enclClass, clazz) - ) - else { - debuglog("enclosing method for %s is %s (in %s)".format(clazz, sym, enclClass)) - jclass addAttribute fjbgContext.JEnclosingMethodAttribute( - jclass, - javaName(enclClass), - javaName(sym), - javaType(sym).asInstanceOf[JMethodType] - ) - } - } - } - - private def toByteArray(jc: JClass): Array[Byte] = { - val bos = new java.io.ByteArrayOutputStream() - val dos = new java.io.DataOutputStream(bos) - jc.writeTo(dos) - dos.close() - bos.toByteArray - } - - /** - * Generate a bean info class that describes the given class. - * - * @author Ross Judson (ross.judson@soletta.com) - */ - def genBeanInfoClass(c: IClass) { - val beanInfoClass = fjbgContext.JClass(javaFlags(c.symbol), - javaName(c.symbol) + "BeanInfo", - "scala/beans/ScalaBeanInfo", - JClass.NO_INTERFACES, - c.cunit.source.toString) - - var fieldList = List[String]() - for (f <- clasz.fields if f.symbol.hasGetter; - g = f.symbol.getter(c.symbol); - s = f.symbol.setter(c.symbol); - if g.isPublic && !(f.symbol.name startsWith "$")) // inserting $outer breaks the bean - fieldList = javaName(f.symbol) :: javaName(g) :: (if (s != NoSymbol) javaName(s) else null) :: fieldList - val methodList = - for (m <- clasz.methods - if !m.symbol.isConstructor && - m.symbol.isPublic && - !(m.symbol.name startsWith "$") && - !m.symbol.isGetter && - !m.symbol.isSetter) yield javaName(m.symbol) - - val constructor = beanInfoClass.addNewMethod(ACC_PUBLIC, "", JType.VOID, new Array[JType](0), new Array[String](0)) - val jcode = constructor.getCode().asInstanceOf[JExtendedCode] - val strKind = new JObjectType(javaName(StringClass)) - val stringArrayKind = new JArrayType(strKind) - val conType = new JMethodType(JType.VOID, Array(javaType(ClassClass), stringArrayKind, stringArrayKind)) - - def push(lst:Seq[String]) { - var fi = 0 - for (f <- lst) { - jcode.emitDUP() - jcode emitPUSH fi - if (f != null) - jcode emitPUSH f - else - jcode.emitACONST_NULL() - jcode emitASTORE strKind - fi += 1 - } - } - - jcode.emitALOAD_0() - // push the class - jcode emitPUSH javaType(c.symbol).asInstanceOf[JReferenceType] - - // push the string array of field information - jcode emitPUSH fieldList.length - jcode emitANEWARRAY strKind - push(fieldList) - - // push the string array of method information - jcode emitPUSH methodList.length - jcode emitANEWARRAY strKind - push(methodList) - - // invoke the superclass constructor, which will do the - // necessary java reflection and create Method objects. - jcode.emitINVOKESPECIAL("scala/beans/ScalaBeanInfo", "", conType) - jcode.emitRETURN() - - // write the bean information class file. - writeClass("BeanInfo ", beanInfoClass.getName(), toByteArray(beanInfoClass), c.symbol) - } - - /** Add the given 'throws' attributes to jmethod */ - def addExceptionsAttribute(jmethod: JMethod, excs: List[AnnotationInfo]) { - if (excs.isEmpty) return - - val cpool = jmethod.getConstantPool - val buf: ByteBuffer = ByteBuffer.allocate(512) - var nattr = 0 - - // put some random value; the actual number is determined at the end - buf putShort 0xbaba.toShort - - for (ThrownException(exc) <- excs.distinct) { - buf.putShort( - cpool.addClass( - javaName(exc)).shortValue) - nattr += 1 - } - - assert(nattr > 0, nattr) - buf.putShort(0, nattr.toShort) - addAttribute(jmethod, tpnme.ExceptionsATTR, buf) - } - - /** Whether an annotation should be emitted as a Java annotation - * .initialize: if 'annot' is read from pickle, atp might be un-initialized - */ - private def shouldEmitAnnotation(annot: AnnotationInfo) = - annot.symbol.initialize.isJavaDefined && - annot.matches(ClassfileAnnotationClass) && - annot.args.isEmpty - - private def emitJavaAnnotations(cpool: JConstantPool, buf: ByteBuffer, annotations: List[AnnotationInfo]): Int = { - def emitArgument(arg: ClassfileAnnotArg): Unit = arg match { - case LiteralAnnotArg(const) => - const.tag match { - case BooleanTag => - buf put 'Z'.toByte - buf putShort cpool.addInteger(if(const.booleanValue) 1 else 0).toShort - case ByteTag => - buf put 'B'.toByte - buf putShort cpool.addInteger(const.byteValue).toShort - case ShortTag => - buf put 'S'.toByte - buf putShort cpool.addInteger(const.shortValue).toShort - case CharTag => - buf put 'C'.toByte - buf putShort cpool.addInteger(const.charValue).toShort - case IntTag => - buf put 'I'.toByte - buf putShort cpool.addInteger(const.intValue).toShort - case LongTag => - buf put 'J'.toByte - buf putShort cpool.addLong(const.longValue).toShort - case FloatTag => - buf put 'F'.toByte - buf putShort cpool.addFloat(const.floatValue).toShort - case DoubleTag => - buf put 'D'.toByte - buf putShort cpool.addDouble(const.doubleValue).toShort - case StringTag => - buf put 's'.toByte - buf putShort cpool.addUtf8(const.stringValue).toShort - case ClazzTag => - buf put 'c'.toByte - buf putShort cpool.addUtf8(javaType(const.typeValue).getSignature()).toShort - case EnumTag => - buf put 'e'.toByte - buf putShort cpool.addUtf8(javaType(const.tpe).getSignature()).toShort - buf putShort cpool.addUtf8(const.symbolValue.name.toString).toShort - } - - case sb@ScalaSigBytes(bytes) if !sb.isLong => - buf put 's'.toByte - buf putShort cpool.addUtf8(sb.encodedBytes).toShort - - case sb@ScalaSigBytes(bytes) if sb.isLong => - buf put '['.toByte - val stringCount = (sb.encodedBytes.length / 65534) + 1 - buf putShort stringCount.toShort - for (i <- 0 until stringCount) { - buf put 's'.toByte - val j = i * 65535 - val string = sb.encodedBytes.slice(j, j + 65535) - buf putShort cpool.addUtf8(string).toShort - } - - case ArrayAnnotArg(args) => - buf put '['.toByte - buf putShort args.length.toShort - args foreach emitArgument - - case NestedAnnotArg(annInfo) => - buf put '@'.toByte - emitAnnotation(annInfo) - } - - def emitAnnotation(annotInfo: AnnotationInfo) { - val AnnotationInfo(typ, args, assocs) = annotInfo - val jtype = javaType(typ) - buf putShort cpool.addUtf8(jtype.getSignature()).toShort - assert(args.isEmpty, args) - buf putShort assocs.length.toShort - for ((name, value) <- assocs) { - buf putShort cpool.addUtf8(name.toString).toShort - emitArgument(value) - } - } - - var nannots = 0 - val pos = buf.position() - - // put some random value; the actual number of annotations is determined at the end - buf putShort 0xbaba.toShort - - for (annot <- annotations if shouldEmitAnnotation(annot)) { - nannots += 1 - emitAnnotation(annot) - } - - // save the number of annotations - buf.putShort(pos, nannots.toShort) - nannots - } - - // @M don't generate java generics sigs for (members of) implementation - // classes, as they are monomorphic (TODO: ok?) - private def needsGenericSignature(sym: Symbol) = !( - // PP: This condition used to include sym.hasExpandedName, but this leads - // to the total loss of generic information if a private member is - // accessed from a closure: both the field and the accessor were generated - // without it. This is particularly bad because the availability of - // generic information could disappear as a consequence of a seemingly - // unrelated change. - settings.Ynogenericsig.value - || sym.isArtifact - || sym.isLiftedMethod - || sym.isBridge - || (sym.ownerChain exists (_.isImplClass)) - ) - def addGenericSignature(jmember: JMember, sym: Symbol, owner: Symbol) { - if (needsGenericSignature(sym)) { - val memberTpe = enteringErasure(owner.thisType.memberInfo(sym)) - - erasure.javaSig(sym, memberTpe) foreach { sig => - // This seems useful enough in the general case. - log(sig) - if (checkSignatures) { - val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe)) - val bytecodeTpe = owner.thisType.memberInfo(sym) - if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) { - clasz.cunit.warning(sym.pos, - """|compiler bug: created generic signature for %s in %s that does not conform to its erasure - |signature: %s - |original type: %s - |normalized type: %s - |erasure type: %s - |if this is reproducible, please report bug at https://issues.scala-lang.org/ - """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe)) - return - } - } - val index = jmember.getConstantPool.addUtf8(sig).toShort - if (settings.verbose.value && settings.debug.value) - enteringErasure(println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index)) - - val buf = ByteBuffer.allocate(2) - buf putShort index - addAttribute(jmember, tpnme.SignatureATTR, buf) - } - } - } - - def addAnnotations(jmember: JMember, annotations: List[AnnotationInfo]) { - if (annotations exists (_ matches definitions.DeprecatedAttr)) { - val attr = jmember.getContext().JOtherAttribute( - jmember.getJClass(), jmember, tpnme.DeprecatedATTR.toString, - new Array[Byte](0), 0) - jmember addAttribute attr - } - - val toEmit = annotations filter shouldEmitAnnotation - if (toEmit.isEmpty) return - - val buf: ByteBuffer = ByteBuffer.allocate(2048) - emitJavaAnnotations(jmember.getConstantPool, buf, toEmit) - addAttribute(jmember, tpnme.RuntimeAnnotationATTR, buf) - } - - def addParamAnnotations(jmethod: JMethod, pannotss: List[List[AnnotationInfo]]) { - val annotations = pannotss map (_ filter shouldEmitAnnotation) - if (annotations forall (_.isEmpty)) return - - val buf: ByteBuffer = ByteBuffer.allocate(2048) - - // number of parameters - buf.put(annotations.length.toByte) - for (annots <- annotations) - emitJavaAnnotations(jmethod.getConstantPool, buf, annots) - - addAttribute(jmethod, tpnme.RuntimeParamAnnotationATTR, buf) - } - - def addAttribute(jmember: JMember, name: Name, buf: ByteBuffer) { - if (buf.position() < 2) - return - - val length = buf.position() - val arr = buf.array().slice(0, length) - - val attr = jmember.getContext().JOtherAttribute(jmember.getJClass(), - jmember, - name.toString, - arr, - length) - jmember addAttribute attr - } - - def addInnerClasses(jclass: JClass) { - /** The outer name for this inner class. Note that it returns null - * when the inner class should not get an index in the constant pool. - * That means non-member classes (anonymous). See Section 4.7.5 in the JVMS. - */ - def outerName(innerSym: Symbol): String = { - if (innerSym.originalEnclosingMethod != NoSymbol) - null - else { - val outerName = javaName(innerSym.rawowner) - if (isTopLevelModule(innerSym.rawowner)) "" + nme.stripModuleSuffix(newTermName(outerName)) - else outerName - } - } - - def innerName(innerSym: Symbol): String = - if (innerSym.isAnonymousClass || innerSym.isAnonymousFunction) - null - else - innerSym.rawname + innerSym.moduleSuffix - - // add inner classes which might not have been referenced yet - exitingErasure { - for (sym <- List(clasz.symbol, clasz.symbol.linkedClassOfClass); m <- sym.info.decls.map(innerClassSymbolFor) if m.isClass) - innerClassBuffer += m - } - - val allInners = innerClassBuffer.toList - if (allInners.nonEmpty) { - debuglog(clasz.symbol.fullName('.') + " contains " + allInners.size + " inner classes.") - val innerClassesAttr = jclass.getInnerClasses() - // sort them so inner classes succeed their enclosing class - // to satisfy the Eclipse Java compiler - for (innerSym <- allInners sortBy (_.name.length)) { - val flags = { - val staticFlag = if (innerSym.rawowner.hasModuleFlag) ACC_STATIC else 0 - (javaFlags(innerSym) | staticFlag) & INNER_CLASSES_FLAGS - } - val jname = javaName(innerSym) - val oname = outerName(innerSym) - val iname = innerName(innerSym) - - // Mimicking javap inner class output - debuglog( - if (oname == null || iname == null) "//class " + jname - else "//%s=class %s of class %s".format(iname, jname, oname) - ) - - innerClassesAttr.addEntry(jname, oname, iname, flags) - } - } - } - - def genField(f: IField) { - debuglog("Adding field: " + f.symbol.fullName) - - val jfield = jclass.addNewField( - javaFieldFlags(f.symbol), - javaName(f.symbol), - javaType(f.symbol.tpe) - ) - - addGenericSignature(jfield, f.symbol, clasz.symbol) - addAnnotations(jfield, f.symbol.annotations) - } - - def genMethod(m: IMethod) { - if (m.symbol.isStaticConstructor || definitions.isGetClass(m.symbol)) return - - debuglog("Generating method " + m.symbol.fullName) - method = m - endPC.clear - computeLocalVarsIndex(m) - - var resTpe = javaType(m.symbol.tpe.resultType) - if (m.symbol.isClassConstructor) - resTpe = JType.VOID - - var flags = javaFlags(m.symbol) - if (jclass.isInterface) - flags |= ACC_ABSTRACT - - if (m.symbol.isStrictFP) - flags |= ACC_STRICT - - // native methods of objects are generated in mirror classes - if (method.native) - flags |= ACC_NATIVE - - jmethod = jclass.addNewMethod(flags, - javaName(m.symbol), - resTpe, - mkArray(m.params map (p => javaType(p.kind))), - mkArray(m.params map (p => javaName(p.sym)))) - - addRemoteException(jmethod, m.symbol) - - if (!jmethod.isAbstract() && !method.native) { - val jcode = jmethod.getCode().asInstanceOf[JExtendedCode] - - // add a fake local for debugging purposes - if (emitVars && isClosureApply(method.symbol)) { - val outerField = clasz.symbol.info.decl(nme.OUTER_LOCAL) - if (outerField != NoSymbol) { - log("Adding fake local to represent outer 'this' for closure " + clasz) - val _this = new Local( - method.symbol.newVariable(nme.FAKE_LOCAL_THIS), toTypeKind(outerField.tpe), false) - m.locals = m.locals ::: List(_this) - computeLocalVarsIndex(m) // since we added a new local, we need to recompute indexes - - jcode.emitALOAD_0() - jcode.emitGETFIELD(javaName(clasz.symbol), - javaName(outerField), - javaType(outerField)) - jcode.emitSTORE(indexOf(_this), javaType(_this.kind)) - } - } - - for (local <- m.locals if ! m.params.contains(local)) { - debuglog("add local var: " + local) - jmethod.addNewLocalVariable(javaType(local.kind), javaName(local.sym)) - } - - genCode(m) - if (emitVars) - genLocalVariableTable(m, jcode) - } - - addGenericSignature(jmethod, m.symbol, clasz.symbol) - val (excs, others) = m.symbol.annotations partition (_.symbol == ThrowsClass) - addExceptionsAttribute(jmethod, excs) - addAnnotations(jmethod, others) - addParamAnnotations(jmethod, m.params.map(_.sym.annotations)) - - // check for code size - try jmethod.freeze() - catch { - case e: JCode.CodeSizeTooBigException => - clasz.cunit.error(m.symbol.pos, "Code size exceeds JVM limits: %d".format(e.codeSize)) - throw e - } - } - - /** Adds a @remote annotation, actual use unknown. - */ - private def addRemoteException(jmethod: JMethod, meth: Symbol) { - val needsAnnotation = ( - (isRemoteClass || (meth hasAnnotation RemoteAttr) && jmethod.isPublic) - && !(meth.throwsAnnotations contains RemoteExceptionClass) - ) - if (needsAnnotation) { - val c = Constant(RemoteExceptionClass.tpe) - val arg = Literal(c) setType c.tpe - meth.addAnnotation(ThrowsClass, arg) - } - } - - private def isClosureApply(sym: Symbol): Boolean = { - (sym.name == nme.apply) && - sym.owner.isSynthetic && - sym.owner.tpe.parents.exists { t => - val TypeRef(_, sym, _) = t - FunctionClass contains sym - } - } - - def addModuleInstanceField() { - jclass.addNewField(PublicStaticFinal, - nme.MODULE_INSTANCE_FIELD.toString, - jclass.getType()) - } - - def addStaticInit(cls: JClass, mopt: Option[IMethod]) { - val clinitMethod = cls.addNewMethod(PublicStatic, - "", - JType.VOID, - JType.EMPTY_ARRAY, - new Array[String](0)) - val clinit = clinitMethod.getCode().asInstanceOf[JExtendedCode] - - mopt match { - case Some(m) => - val oldLastBlock = m.lastBlock - val lastBlock = m.newBlock() - oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock)) - - if (isStaticModule(clasz.symbol)) { - // call object's private ctor from static ctor - lastBlock emit NEW(REFERENCE(m.symbol.enclClass)) - lastBlock emit CALL_METHOD(m.symbol.enclClass.primaryConstructor, Static(true)) - } - - // add serialVUID code - serialVUID foreach { value => - import Flags._, definitions._ - val fieldName = "serialVersionUID" - val fieldSymbol = clasz.symbol.newValue(newTermName(fieldName), NoPosition, STATIC | FINAL) setInfo LongClass.tpe - clasz addField new IField(fieldSymbol) - lastBlock emit CONSTANT(Constant(value)) - lastBlock emit STORE_FIELD(fieldSymbol, true) - } - - if (isParcelableClass) - addCreatorCode(BytecodeGenerator.this, lastBlock) - - lastBlock emit RETURN(UNIT) - lastBlock.close - - method = m - jmethod = clinitMethod - genCode(m) - case None => - legacyStaticInitializer(cls, clinit) - } - } - - private def legacyStaticInitializer(cls: JClass, clinit: JExtendedCode) { - if (isStaticModule(clasz.symbol)) { - clinit emitNEW cls.getName() - clinit.emitINVOKESPECIAL(cls.getName(), - JMethod.INSTANCE_CONSTRUCTOR_NAME, - JMethodType.ARGLESS_VOID_FUNCTION) - } - - serialVUID foreach { value => - val fieldName = "serialVersionUID" - jclass.addNewField(PublicStaticFinal, fieldName, JType.LONG) - clinit emitPUSH value - clinit.emitPUSH(value) - clinit.emitPUTSTATIC(jclass.getName(), fieldName, JType.LONG) - } - - if (isParcelableClass) - legacyAddCreatorCode(BytecodeGenerator.this, clinit) - - clinit.emitRETURN() - } - - /** Add a forwarder for method m */ - def addForwarder(jclass: JClass, module: Symbol, m: Symbol) { - val moduleName = javaName(module) - val methodInfo = module.thisType.memberInfo(m) - val paramJavaTypes = methodInfo.paramTypes map javaType - val paramNames = 0 until paramJavaTypes.length map ("x_" + _) - // TODO: evaluate the other flags we might be dropping on the floor here. - val flags = PublicStatic | ( - if (m.isVarargsMethod) ACC_VARARGS else 0 - ) - - /** Forwarders must not be marked final, as the JVM will not allow - * redefinition of a final static method, and we don't know what classes - * might be subclassing the companion class. See SI-4827. - */ - val mirrorMethod = jclass.addNewMethod( - flags, - javaName(m), - javaType(methodInfo.resultType), - mkArray(paramJavaTypes), - mkArray(paramNames)) - val mirrorCode = mirrorMethod.getCode().asInstanceOf[JExtendedCode] - mirrorCode.emitGETSTATIC(moduleName, - nme.MODULE_INSTANCE_FIELD.toString, - new JObjectType(moduleName)) - - var i = 0 - var index = 0 - val argTypes = mirrorMethod.getArgumentTypes() - while (i < argTypes.length) { - mirrorCode.emitLOAD(index, argTypes(i)) - index += argTypes(i).getSize() - i += 1 - } - - mirrorCode.emitINVOKEVIRTUAL(moduleName, mirrorMethod.getName, javaType(m).asInstanceOf[JMethodType]) - mirrorCode emitRETURN mirrorMethod.getReturnType() - - addRemoteException(mirrorMethod, m) - // only add generic signature if the method is concrete; bug #1745 - if (!m.isDeferred) - addGenericSignature(mirrorMethod, m, module) - - val (throws, others) = m.annotations partition (_.symbol == ThrowsClass) - addExceptionsAttribute(mirrorMethod, throws) - addAnnotations(mirrorMethod, others) - addParamAnnotations(mirrorMethod, m.info.params.map(_.annotations)) - } - - /** Add forwarders for all methods defined in `module` that don't conflict - * with methods in the companion class of `module`. A conflict arises when - * a method with the same name is defined both in a class and its companion - * object: method signature is not taken into account. - */ - def addForwarders(jclass: JClass, moduleClass: Symbol) { - assert(moduleClass.isModuleClass, moduleClass) - debuglog("Dumping mirror class for object: " + moduleClass) - - val className = jclass.getName - val linkedClass = moduleClass.companionClass - lazy val conflictingNames: Set[Name] = { - linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name } toSet - } - debuglog("Potentially conflicting names for forwarders: " + conflictingNames) - - for (m <- moduleClass.info.membersBasedOnFlags(ExcludedForwarderFlags, Flags.METHOD)) { - if (m.isType || m.isDeferred || (m.owner eq ObjectClass) || m.isConstructor) - debuglog("No forwarder for '%s' from %s to '%s'".format(m, className, moduleClass)) - else if (conflictingNames(m.name)) - log("No forwarder for " + m + " due to conflict with " + linkedClass.info.member(m.name)) - else { - log("Adding static forwarder for '%s' from %s to '%s'".format(m, className, moduleClass)) - addForwarder(jclass, moduleClass, m) - } - } - } - - /** Generate a mirror class for a top-level module. A mirror class is a class - * containing only static methods that forward to the corresponding method - * on the MODULE instance of the given Scala object. It will only be - * generated if there is no companion class: if there is, an attempt will - * instead be made to add the forwarder methods to the companion class. - */ - def generateMirrorClass(clasz: Symbol, sourceFile: SourceFile) { - import JAccessFlags._ - /* We need to save inner classes buffer and create a new one to make sure - * that we do confuse inner classes of the class we mirror with inner - * classes of the class we are mirroring. These two sets can be different - * as seen in this case: - * - * class A { - * class B - * def b: B = new B - * } - * object C extends A - * - * Here mirror class of C has a static forwarder for (inherited) method `b` - * therefore it refers to class `B` and needs InnerClasses entry. However, - * the real class for `C` (named `C$`) is empty and does not refer to `B` - * thus does not need InnerClasses entry it. - * - * NOTE: This logic has been refactored in GenASM and everything is - * implemented in a much cleaner way by having two separate buffers. - */ - val savedInnerClasses = innerClassBuffer - innerClassBuffer = mutable.LinkedHashSet[Symbol]() - val moduleName = javaName(clasz) // + "$" - val mirrorName = moduleName.substring(0, moduleName.length() - 1) - val mirrorClass = fjbgContext.JClass(ACC_SUPER | ACC_PUBLIC | ACC_FINAL, - mirrorName, - JAVA_LANG_OBJECT.getName, - JClass.NO_INTERFACES, - "" + sourceFile) - - log("Dumping mirror class for '%s'".format(mirrorClass.getName)) - addForwarders(mirrorClass, clasz) - val ssa = scalaSignatureAddingMarker(mirrorClass, clasz.companionSymbol) - addAnnotations(mirrorClass, clasz.annotations ++ ssa) - emitClass(mirrorClass, clasz) - innerClassBuffer = savedInnerClasses - } - - var linearization: List[BasicBlock] = Nil - var isModuleInitialized = false - - def genCode(m: IMethod) { - val jcode = jmethod.getCode.asInstanceOf[JExtendedCode] - - def makeLabels(bs: List[BasicBlock]) = { - debuglog("Making labels for: " + method) - - mutable.HashMap(bs map (_ -> jcode.newLabel) : _*) - } - - isModuleInitialized = false - - linearization = linearizer.linearize(m) - val labels = makeLabels(linearization) - - var nextBlock: BasicBlock = linearization.head - - def genBlocks(l: List[BasicBlock]): Unit = l match { - case Nil => () - case x :: Nil => nextBlock = null; genBlock(x) - case x :: y :: ys => nextBlock = y; genBlock(x); genBlocks(y :: ys) - } - - /** Generate exception handlers for the current method. */ - def genExceptionHandlers() { - - /** Return a list of pairs of intervals where the handler is active. - * The intervals in the list have to be inclusive in the beginning and - * exclusive in the end: [start, end). - */ - def ranges(e: ExceptionHandler): List[(Int, Int)] = { - var covered = e.covered - var ranges: List[(Int, Int)] = Nil - var start = -1 - var end = -1 - - linearization foreach { b => - if (! (covered contains b) ) { - if (start >= 0) { // we're inside a handler range - end = labels(b).getAnchor() - ranges ::= ((start, end)) - start = -1 - } - } else { - if (start < 0) // we're not inside a handler range - start = labels(b).getAnchor() - - end = endPC(b) - covered -= b - } - } - - /* Add the last interval. Note that since the intervals are - * open-ended to the right, we have to give a number past the actual - * code! - */ - if (start >= 0) { - ranges ::= ((start, jcode.getPC())) - } - - if (!covered.isEmpty) - debuglog("Some covered blocks were not found in method: " + method + - " covered: " + covered + " not in " + linearization) - ranges - } - - for (e <- this.method.exh ; p <- ranges(e).sortBy(_._1)) { - if (p._1 < p._2) { - debuglog("Adding exception handler " + e + "at block: " + e.startBlock + " for " + method + - " from: " + p._1 + " to: " + p._2 + " catching: " + e.cls); - val cls = if (e.cls == NoSymbol || e.cls == ThrowableClass) null - else javaName(e.cls) - jcode.addExceptionHandler(p._1, p._2, - labels(e.startBlock).getAnchor(), - cls) - } else - log("Empty exception range: " + p) - } - } - - def isAccessibleFrom(target: Symbol, site: Symbol): Boolean = { - target.isPublic || target.isProtected && { - (site.enclClass isSubClass target.enclClass) || - (site.enclosingPackage == target.privateWithin) - } - } - - def genCallMethod(call: CALL_METHOD) { - val CALL_METHOD(method, style) = call - val siteSymbol = clasz.symbol - val hostSymbol = call.hostClass - val methodOwner = method.owner - // info calls so that types are up to date; erasure may add lateINTERFACE to traits - hostSymbol.info ; methodOwner.info - - def isInterfaceCall(sym: Symbol) = ( - sym.isInterface && methodOwner != ObjectClass - || sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass) - ) - // whether to reference the type of the receiver or - // the type of the method owner (if not an interface!) - val useMethodOwner = ( - style != Dynamic - || !isInterfaceCall(hostSymbol) && isAccessibleFrom(methodOwner, siteSymbol) - || hostSymbol.isBottomClass - ) - val receiver = if (useMethodOwner) methodOwner else hostSymbol - val jowner = javaName(receiver) - val jname = javaName(method) - val jtype = javaType(method).asInstanceOf[JMethodType] - - def dbg(invoke: String) { - debuglog("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype)) - } - - def initModule() { - // we initialize the MODULE$ field immediately after the super ctor - if (isStaticModule(siteSymbol) && !isModuleInitialized && - jmethod.getName() == JMethod.INSTANCE_CONSTRUCTOR_NAME && - jname == JMethod.INSTANCE_CONSTRUCTOR_NAME) { - isModuleInitialized = true - jcode.emitALOAD_0() - jcode.emitPUTSTATIC(jclass.getName(), - nme.MODULE_INSTANCE_FIELD.toString, - jclass.getType()) - } - } - - style match { - case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype) - case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype) - case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.emitINVOKEINTERFACE(jowner, jname, jtype) - case Dynamic => dbg("invokevirtual"); jcode.emitINVOKEVIRTUAL(jowner, jname, jtype) - case SuperCall(_) => - dbg("invokespecial") - jcode.emitINVOKESPECIAL(jowner, jname, jtype) - initModule() - } - } - - def genBlock(b: BasicBlock) { - labels(b).anchorToNext() - - debuglog("Generating code for block: " + b + " at pc: " + labels(b).getAnchor()) - var lastMappedPC = 0 - var lastLineNr = 0 - var crtPC = 0 - - /** local variables whose scope appears in this block. */ - val varsInBlock: mutable.Set[Local] = new mutable.HashSet - val lastInstr = b.lastInstruction - - for (instr <- b) { - instr match { - case THIS(clasz) => jcode.emitALOAD_0() - - case CONSTANT(const) => genConstant(jcode, const) - - case LOAD_ARRAY_ITEM(kind) => - if(kind.isRefOrArrayType) { jcode.emitAALOAD() } - else { - (kind: @unchecked) match { - case UNIT => throw new IllegalArgumentException("invalid type for aload " + kind) - case BOOL | BYTE => jcode.emitBALOAD() - case SHORT => jcode.emitSALOAD() - case CHAR => jcode.emitCALOAD() - case INT => jcode.emitIALOAD() - case LONG => jcode.emitLALOAD() - case FLOAT => jcode.emitFALOAD() - case DOUBLE => jcode.emitDALOAD() - } - } - - case LOAD_LOCAL(local) => jcode.emitLOAD(indexOf(local), javaType(local.kind)) - - case lf @ LOAD_FIELD(field, isStatic) => - val owner = javaName(lf.hostClass) - debuglog("LOAD_FIELD with owner: " + owner + - " flags: " + field.owner.flagString) - val fieldJName = javaName(field) - val fieldJType = javaType(field) - if (isStatic) jcode.emitGETSTATIC(owner, fieldJName, fieldJType) - else jcode.emitGETFIELD( owner, fieldJName, fieldJType) - - case LOAD_MODULE(module) => - // assert(module.isModule, "Expected module: " + module) - debuglog("generating LOAD_MODULE for: " + module + " flags: " + module.flagString); - if (clasz.symbol == module.moduleClass && jmethod.getName() != nme.readResolve.toString) - jcode.emitALOAD_0() - else - jcode.emitGETSTATIC(javaName(module) /* + "$" */ , - nme.MODULE_INSTANCE_FIELD.toString, - javaType(module)) - - case STORE_ARRAY_ITEM(kind) => - if(kind.isRefOrArrayType) { jcode.emitAASTORE() } - else { - (kind: @unchecked) match { - case UNIT => throw new IllegalArgumentException("invalid type for astore " + kind) - case BOOL | BYTE => jcode.emitBASTORE() - case SHORT => jcode.emitSASTORE() - case CHAR => jcode.emitCASTORE() - case INT => jcode.emitIASTORE() - case LONG => jcode.emitLASTORE() - case FLOAT => jcode.emitFASTORE() - case DOUBLE => jcode.emitDASTORE() - } - } - - case STORE_LOCAL(local) => - jcode.emitSTORE(indexOf(local), javaType(local.kind)) - - 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. - jcode.emitASTORE_0() - - case STORE_FIELD(field, isStatic) => - val owner = javaName(field.owner) - val fieldJName = javaName(field) - val fieldJType = javaType(field) - if (isStatic) jcode.emitPUTSTATIC(owner, fieldJName, fieldJType) - else jcode.emitPUTFIELD( owner, fieldJName, fieldJType) - - case CALL_PRIMITIVE(primitive) => genPrimitive(primitive, instr.pos) - - /** Special handling to access native Array.clone() */ - case call @ CALL_METHOD(definitions.Array_clone, Dynamic) => - val target: String = javaType(call.targetTypeKind).getSignature() - jcode.emitINVOKEVIRTUAL(target, "clone", arrayCloneType) - - case call @ CALL_METHOD(method, style) => genCallMethod(call) - - case BOX(kind) => - val Pair(mname, mtype) = jBoxTo(kind) - jcode.emitINVOKESTATIC(BoxesRunTime, mname, mtype) - - case UNBOX(kind) => - val Pair(mname, mtype) = jUnboxTo(kind) - jcode.emitINVOKESTATIC(BoxesRunTime, mname, mtype) - - case NEW(REFERENCE(cls)) => - val className = javaName(cls) - jcode emitNEW className - - case CREATE_ARRAY(elem, 1) => - if(elem.isRefOrArrayType) { jcode emitANEWARRAY javaType(elem).asInstanceOf[JReferenceType] } - else { jcode emitNEWARRAY javaType(elem) } - - case CREATE_ARRAY(elem, dims) => - jcode.emitMULTIANEWARRAY(javaType(ArrayN(elem, dims)).asInstanceOf[JReferenceType], dims) - - case IS_INSTANCE(tpe) => - tpe match { - case REFERENCE(cls) => jcode emitINSTANCEOF new JObjectType(javaName(cls)) - case ARRAY(elem) => jcode emitINSTANCEOF new JArrayType(javaType(elem)) - case _ => abort("Unknown reference type in IS_INSTANCE: " + tpe) - } - - case CHECK_CAST(tpe) => - tpe match { - case REFERENCE(cls) => if (cls != ObjectClass) { jcode emitCHECKCAST new JObjectType(javaName(cls)) } // No need to checkcast for Objects - case ARRAY(elem) => jcode emitCHECKCAST new JArrayType(javaType(elem)) - case _ => abort("Unknown reference type in IS_INSTANCE: " + tpe) - } - - case SWITCH(tags, branches) => - val tagArray = new Array[Array[Int]](tags.length) - var caze = tags - var i = 0 - - while (i < tagArray.length) { - tagArray(i) = new Array[Int](caze.head.length) - caze.head.copyToArray(tagArray(i), 0) - i += 1 - caze = caze.tail - } - val branchArray = jcode.newLabels(tagArray.length) - i = 0 - while (i < branchArray.length) { - branchArray(i) = labels(branches(i)) - i += 1 - } - debuglog("Emitting SWITCH:\ntags: " + tags + "\nbranches: " + branches) - jcode.emitSWITCH(tagArray, - branchArray, - labels(branches.last), - MIN_SWITCH_DENSITY) - () - - case JUMP(whereto) => - if (nextBlock != whereto) - jcode.emitGOTO_maybe_W(labels(whereto), false) // default to short jumps - - case CJUMP(success, failure, cond, kind) => - if(kind.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT - if (nextBlock == success) { - jcode.emitIF_ICMP(conds(cond.negate()), labels(failure)) - // .. and fall through to success label - } else { - jcode.emitIF_ICMP(conds(cond), labels(success)) - if (nextBlock != failure) - jcode.emitGOTO_maybe_W(labels(failure), false) - } - } else if(kind.isRefOrArrayType) { // REFERENCE(_) | ARRAY(_) - if (nextBlock == success) { - jcode.emitIF_ACMP(conds(cond.negate()), labels(failure)) - // .. and fall through to success label - } else { - jcode.emitIF_ACMP(conds(cond), labels(success)) - if (nextBlock != failure) - jcode.emitGOTO_maybe_W(labels(failure), false) - } - } else { - (kind: @unchecked) match { - case LONG => jcode.emitLCMP() - case FLOAT => - if (cond == LT || cond == LE) jcode.emitFCMPG() - else jcode.emitFCMPL() - case DOUBLE => - if (cond == LT || cond == LE) jcode.emitDCMPG() - else jcode.emitDCMPL() - } - if (nextBlock == success) { - jcode.emitIF(conds(cond.negate()), labels(failure)) - // .. and fall through to success label - } else { - jcode.emitIF(conds(cond), labels(success)); - if (nextBlock != failure) - jcode.emitGOTO_maybe_W(labels(failure), false) - } - } - - case CZJUMP(success, failure, cond, kind) => - if(kind.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT - if (nextBlock == success) { - jcode.emitIF(conds(cond.negate()), labels(failure)) - } else { - jcode.emitIF(conds(cond), labels(success)) - if (nextBlock != failure) - jcode.emitGOTO_maybe_W(labels(failure), false) - } - } else if(kind.isRefOrArrayType) { // REFERENCE(_) | ARRAY(_) - val Success = success - val Failure = failure - (cond, nextBlock) match { - case (EQ, Success) => jcode emitIFNONNULL labels(failure) - case (NE, Failure) => jcode emitIFNONNULL labels(success) - case (EQ, Failure) => jcode emitIFNULL labels(success) - case (NE, Success) => jcode emitIFNULL labels(failure) - case (EQ, _) => - jcode emitIFNULL labels(success) - jcode.emitGOTO_maybe_W(labels(failure), false) - case (NE, _) => - jcode emitIFNONNULL labels(success) - jcode.emitGOTO_maybe_W(labels(failure), false) - case _ => - } - } else { - (kind: @unchecked) match { - case LONG => - jcode.emitLCONST_0() - jcode.emitLCMP() - case FLOAT => - jcode.emitFCONST_0() - if (cond == LT || cond == LE) jcode.emitFCMPG() - else jcode.emitFCMPL() - case DOUBLE => - jcode.emitDCONST_0() - if (cond == LT || cond == LE) jcode.emitDCMPG() - else jcode.emitDCMPL() - } - if (nextBlock == success) { - jcode.emitIF(conds(cond.negate()), labels(failure)) - } else { - jcode.emitIF(conds(cond), labels(success)) - if (nextBlock != failure) - jcode.emitGOTO_maybe_W(labels(failure), false) - } - } - - case RETURN(kind) => jcode emitRETURN javaType(kind) - - case THROW(_) => jcode.emitATHROW() - - case DROP(kind) => - if(kind.isWideType) jcode.emitPOP2() - else jcode.emitPOP() - - case DUP(kind) => - if(kind.isWideType) jcode.emitDUP2() - else jcode.emitDUP() - - case MONITOR_ENTER() => jcode.emitMONITORENTER() - - case MONITOR_EXIT() => jcode.emitMONITOREXIT() - - case SCOPE_ENTER(lv) => - varsInBlock += lv - lv.start = jcode.getPC() - - case SCOPE_EXIT(lv) => - if (varsInBlock(lv)) { - lv.ranges = (lv.start, jcode.getPC()) :: lv.ranges - varsInBlock -= lv - } - else if (b.varsInScope(lv)) { - lv.ranges = (labels(b).getAnchor(), jcode.getPC()) :: lv.ranges - b.varsInScope -= lv - } - else dumpMethodAndAbort(method, "Illegal local var nesting") - - case LOAD_EXCEPTION(_) => - () - } - - crtPC = jcode.getPC() - - // assert(instr.pos.source.isEmpty || instr.pos.source.get == (clasz.cunit.source), "sources don't match") - // val crtLine = instr.pos.line.get(lastLineNr); - - val crtLine = try { - if (instr.pos == NoPosition) lastLineNr else (instr.pos).line // check NoPosition to avoid costly exception - } catch { - case _: UnsupportedOperationException => - log("Warning: wrong position in: " + method) - lastLineNr - } - - if (instr eq lastInstr) { endPC(b) = jcode.getPC() } - - //System.err.println("CRTLINE: " + instr.pos + " " + - // /* (if (instr.pos < clasz.cunit.source.content.length) clasz.cunit.source.content(instr.pos) else '*') + */ " " + crtLine); - - if (crtPC > lastMappedPC) { - jcode.completeLineNumber(lastMappedPC, crtPC, crtLine) - lastMappedPC = crtPC - lastLineNr = crtLine - } - } - - // local vars that survived this basic block - for (lv <- varsInBlock) { - lv.ranges = (lv.start, jcode.getPC()) :: lv.ranges - } - for (lv <- b.varsInScope) { - lv.ranges = (labels(b).getAnchor(), jcode.getPC()) :: lv.ranges - } - } - - def genPrimitive(primitive: Primitive, pos: Position) { - primitive match { - case Negation(kind) => - if(kind.isIntSizedType) { jcode.emitINEG() } - else { - kind match { - case LONG => jcode.emitLNEG() - case FLOAT => jcode.emitFNEG() - case DOUBLE => jcode.emitDNEG() - case _ => abort("Impossible to negate a " + kind) - } - } - - case Arithmetic(op, kind) => - op match { - case ADD => - if(kind.isIntSizedType) { jcode.emitIADD() } - else { - (kind: @unchecked) match { - case LONG => jcode.emitLADD() - case FLOAT => jcode.emitFADD() - case DOUBLE => jcode.emitDADD() - } - } - - case SUB => - if(kind.isIntSizedType) { jcode.emitISUB() } - else { - (kind: @unchecked) match { - case LONG => jcode.emitLSUB() - case FLOAT => jcode.emitFSUB() - case DOUBLE => jcode.emitDSUB() - } - } - - case MUL => - if(kind.isIntSizedType) { jcode.emitIMUL() } - else { - (kind: @unchecked) match { - case LONG => jcode.emitLMUL() - case FLOAT => jcode.emitFMUL() - case DOUBLE => jcode.emitDMUL() - } - } - - case DIV => - if(kind.isIntSizedType) { jcode.emitIDIV() } - else { - (kind: @unchecked) match { - case LONG => jcode.emitLDIV() - case FLOAT => jcode.emitFDIV() - case DOUBLE => jcode.emitDDIV() - } - } - - case REM => - if(kind.isIntSizedType) { jcode.emitIREM() } - else { - (kind: @unchecked) match { - case LONG => jcode.emitLREM() - case FLOAT => jcode.emitFREM() - case DOUBLE => jcode.emitDREM() - } - } - - case NOT => - if(kind.isIntSizedType) { - jcode.emitPUSH(-1) - jcode.emitIXOR() - } else if(kind == LONG) { - jcode.emitPUSH(-1l) - jcode.emitLXOR() - } else { - abort("Impossible to negate an " + kind) - } - - case _ => - abort("Unknown arithmetic primitive " + primitive) - } - - case Logical(op, kind) => ((op, kind): @unchecked) match { - case (AND, LONG) => jcode.emitLAND() - case (AND, INT) => jcode.emitIAND() - case (AND, _) => - jcode.emitIAND() - if (kind != BOOL) - jcode.emitT2T(javaType(INT), javaType(kind)); - - case (OR, LONG) => jcode.emitLOR() - case (OR, INT) => jcode.emitIOR() - case (OR, _) => - jcode.emitIOR() - if (kind != BOOL) - jcode.emitT2T(javaType(INT), javaType(kind)); - - case (XOR, LONG) => jcode.emitLXOR() - case (XOR, INT) => jcode.emitIXOR() - case (XOR, _) => - jcode.emitIXOR() - if (kind != BOOL) - jcode.emitT2T(javaType(INT), javaType(kind)); - } - - case Shift(op, kind) => ((op, kind): @unchecked) match { - case (LSL, LONG) => jcode.emitLSHL() - case (LSL, INT) => jcode.emitISHL() - case (LSL, _) => - jcode.emitISHL() - jcode.emitT2T(javaType(INT), javaType(kind)) - - case (ASR, LONG) => jcode.emitLSHR() - case (ASR, INT) => jcode.emitISHR() - case (ASR, _) => - jcode.emitISHR() - jcode.emitT2T(javaType(INT), javaType(kind)) - - case (LSR, LONG) => jcode.emitLUSHR() - case (LSR, INT) => jcode.emitIUSHR() - case (LSR, _) => - jcode.emitIUSHR() - jcode.emitT2T(javaType(INT), javaType(kind)) - } - - case Comparison(op, kind) => ((op, kind): @unchecked) match { - case (CMP, LONG) => jcode.emitLCMP() - case (CMPL, FLOAT) => jcode.emitFCMPL() - case (CMPG, FLOAT) => jcode.emitFCMPG() - case (CMPL, DOUBLE) => jcode.emitDCMPL() - case (CMPG, DOUBLE) => jcode.emitDCMPL() - } - - case Conversion(src, dst) => - debuglog("Converting from: " + src + " to: " + dst) - if (dst == BOOL) { - println("Illegal conversion at: " + clasz + " at: " + pos.source + ":" + pos.line) - } else - jcode.emitT2T(javaType(src), javaType(dst)) - - case ArrayLength(_) => - jcode.emitARRAYLENGTH() - - case StartConcat => - jcode emitNEW StringBuilderClassName - jcode.emitDUP() - jcode.emitINVOKESPECIAL(StringBuilderClassName, - JMethod.INSTANCE_CONSTRUCTOR_NAME, - JMethodType.ARGLESS_VOID_FUNCTION) - - case StringConcat(el) => - val jtype = el match { - case REFERENCE(_) | ARRAY(_) => JAVA_LANG_OBJECT - case _ => javaType(el) - } - jcode.emitINVOKEVIRTUAL(StringBuilderClassName, - "append", - new JMethodType(StringBuilderType, - Array(jtype))) - case EndConcat => - jcode.emitINVOKEVIRTUAL(StringBuilderClassName, - "toString", - toStringType) - - case _ => - abort("Unimplemented primitive " + primitive) - } - } - - // genCode starts here - genBlocks(linearization) - - if (this.method.exh != Nil) - genExceptionHandlers; - } - - - /** Emit a Local variable table for debugging purposes. - * Synthetic locals are skipped. All variables are method-scoped. - */ - private def genLocalVariableTable(m: IMethod, jcode: JCode) { - val vars = m.locals filterNot (_.sym.isArtifact) - if (vars.isEmpty) return - - val pool = jclass.getConstantPool - val pc = jcode.getPC() - var anonCounter = 0 - var entries = 0 - vars.foreach { lv => - lv.ranges = mergeEntries(lv.ranges.reverse); - entries += lv.ranges.length - } - if (!jmethod.isStatic()) entries += 1 - - val lvTab = ByteBuffer.allocate(2 + 10 * entries) - def emitEntry(name: String, signature: String, idx: Short, start: Short, end: Short) { - lvTab putShort start - lvTab putShort end - lvTab putShort pool.addUtf8(name).toShort - lvTab putShort pool.addUtf8(signature).toShort - lvTab putShort idx - } - - lvTab.putShort(entries.toShort) - - if (!jmethod.isStatic()) { - emitEntry("this", jclass.getType().getSignature(), 0, 0.toShort, pc.toShort) - } - - for (lv <- vars) { - val name = if (javaName(lv.sym) eq null) { - anonCounter += 1 - "" - } else javaName(lv.sym) - - val index = indexOf(lv).toShort - val tpe = javaType(lv.kind).getSignature() - for ((start, end) <- lv.ranges) { - emitEntry(name, tpe, index, start.toShort, (end - start).toShort) - } - } - val attr = - fjbgContext.JOtherAttribute(jclass, - jcode, - tpnme.LocalVariableTableATTR.toString, - lvTab.array()) - jcode addAttribute attr - } - - - /** For each basic block, the first PC address following it. */ - val endPC = new mutable.HashMap[BasicBlock, Int] - - ////////////////////// local vars /////////////////////// - - def sizeOf(k: TypeKind): Int = if(k.isWideType) 2 else 1 - - def indexOf(local: Local): Int = { - assert(local.index >= 0, "Invalid index for: " + local + "{" + local.## + "}: ") - local.index - } - - /** - * Compute the indexes of each local variable of the given - * method. *Does not assume the parameters come first!* - */ - def computeLocalVarsIndex(m: IMethod) { - var idx = if (m.symbol.isStaticMember) 0 else 1; - - for (l <- m.params) { - debuglog("Index value for " + l + "{" + l.## + "}: " + idx) - l.index = idx - idx += sizeOf(l.kind) - } - - for (l <- m.locals if !(m.params contains l)) { - debuglog("Index value for " + l + "{" + l.## + "}: " + idx) - l.index = idx - idx += sizeOf(l.kind) - } - } - - ////////////////////// Utilities //////////////////////// - - /** Merge adjacent ranges. */ - private def mergeEntries(ranges: List[(Int, Int)]): List[(Int, Int)] = - (ranges.foldLeft(Nil: List[(Int, Int)]) { (collapsed: List[(Int, Int)], p: (Int, Int)) => (collapsed, p) match { - case (Nil, _) => List(p) - case ((s1, e1) :: rest, (s2, e2)) if (e1 == s2) => (s1, e2) :: rest - case _ => p :: collapsed - }}).reverse - } - - private def mkFlags(args: Int*) = args.foldLeft(0)(_ | _) - - /** - * Return the Java modifiers for the given symbol. - * Java modifiers for classes: - * - public, abstract, final, strictfp (not used) - * for interfaces: - * - the same as for classes, without 'final' - * for fields: - * - public, private (*) - * - static, final - * for methods: - * - the same as for fields, plus: - * - abstract, synchronized (not used), strictfp (not used), native (not used) - * - * (*) protected cannot be used, since inner classes 'see' protected members, - * and they would fail verification after lifted. - */ - def javaFlags(sym: Symbol): Int = { - // constructors of module classes should be private - // PP: why are they only being marked private at this stage and not earlier? - val privateFlag = - sym.isPrivate || (sym.isPrimaryConstructor && isTopLevelModule(sym.owner)) - - // Final: the only fields which can receive ACC_FINAL are eager vals. - // Neither vars nor lazy vals can, because: - // - // Source: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3 - // "Another problem is that the specification allows aggressive - // optimization of final fields. Within a thread, it is permissible to - // reorder reads of a final field with those modifications of a final - // field that do not take place in the constructor." - // - // A var or lazy val which is marked final still has meaning to the - // scala compiler. The word final is heavily overloaded unfortunately; - // for us it means "not overridable". At present you can't override - // vars regardless; this may change. - // - // The logic does not check .isFinal (which checks flags for the FINAL flag, - // and includes symbols marked lateFINAL) instead inspecting rawflags so - // we can exclude lateFINAL. Such symbols are eligible for inlining, but to - // avoid breaking proxy software which depends on subclassing, we do not - // emit ACC_FINAL. - // Nested objects won't receive ACC_FINAL in order to allow for their overriding. - - val finalFlag = ( - (((sym.rawflags & Flags.FINAL) != 0) || isTopLevelModule(sym)) - && !sym.enclClass.isInterface - && !sym.isClassConstructor - && !sym.isMutable // lazy vals and vars both - ) - - // Primitives are "abstract final" to prohibit instantiation - // without having to provide any implementations, but that is an - // illegal combination of modifiers at the bytecode level so - // suppress final if abstract if present. - mkFlags( - if (privateFlag) ACC_PRIVATE else ACC_PUBLIC, - if (sym.isDeferred || sym.hasAbstractFlag) ACC_ABSTRACT else 0, - if (sym.isInterface) ACC_INTERFACE else 0, - if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0, - if (sym.isStaticMember) ACC_STATIC else 0, - if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0, - if (sym.isArtifact) ACC_SYNTHETIC else 0, - if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, - if (sym.isVarargsMethod) ACC_VARARGS else 0, - if (sym.hasFlag(Flags.SYNCHRONIZED)) JAVA_ACC_SYNCHRONIZED else 0 - ) - } - def javaFieldFlags(sym: Symbol) = ( - javaFlags(sym) | mkFlags( - if (sym hasAnnotation TransientAttr) ACC_TRANSIENT else 0, - if (sym hasAnnotation VolatileAttr) ACC_VOLATILE else 0, - if (sym.isMutable) 0 else ACC_FINAL - ) - ) - - def isTopLevelModule(sym: Symbol): Boolean = - exitingPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } - - def isStaticModule(sym: Symbol): Boolean = { - sym.isModuleClass && !sym.isImplClass && !sym.isLifted - } - -} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala deleted file mode 100644 index 613f8f893e5e..000000000000 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala +++ /dev/null @@ -1,141 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Iulian Dragos - */ - -package scala.tools.nsc -package backend.jvm - -import scala.collection.{ mutable, immutable } -import ch.epfl.lamp.fjbg._ - -trait GenJVMUtil { - self: GenJVM => - - import global._ - import icodes._ - import definitions._ - - /** Map from type kinds to the Java reference types. It is used for - * loading class constants. @see Predef.classOf. - */ - val classLiteral = immutable.Map[TypeKind, JObjectType]( - UNIT -> new JObjectType("java.lang.Void"), - BOOL -> new JObjectType("java.lang.Boolean"), - BYTE -> new JObjectType("java.lang.Byte"), - SHORT -> new JObjectType("java.lang.Short"), - CHAR -> new JObjectType("java.lang.Character"), - INT -> new JObjectType("java.lang.Integer"), - LONG -> new JObjectType("java.lang.Long"), - FLOAT -> new JObjectType("java.lang.Float"), - DOUBLE -> new JObjectType("java.lang.Double") - ) - - // Don't put this in per run caches. - private val javaNameCache = new mutable.WeakHashMap[Symbol, Name]() ++= List( - NothingClass -> binarynme.RuntimeNothing, - RuntimeNothingClass -> binarynme.RuntimeNothing, - NullClass -> binarynme.RuntimeNull, - RuntimeNullClass -> binarynme.RuntimeNull - ) - - /** This trait may be used by tools who need access to - * utility methods like javaName and javaType. (for instance, - * the Eclipse plugin uses it). - */ - trait BytecodeUtil { - - val conds = immutable.Map[TestOp, Int]( - EQ -> JExtendedCode.COND_EQ, - NE -> JExtendedCode.COND_NE, - LT -> JExtendedCode.COND_LT, - GT -> JExtendedCode.COND_GT, - LE -> JExtendedCode.COND_LE, - GE -> JExtendedCode.COND_GE - ) - - /** Specialized array conversion to prevent calling - * java.lang.reflect.Array.newInstance via TraversableOnce.toArray - */ - - def mkArray(xs: Traversable[JType]): Array[JType] = { val a = new Array[JType](xs.size); xs.copyToArray(a); a } - def mkArray(xs: Traversable[String]): Array[String] = { val a = new Array[String](xs.size); xs.copyToArray(a); a } - - /** Return the a name of this symbol that can be used on the Java - * platform. It removes spaces from names. - * - * Special handling: - * scala.Nothing erases to scala.runtime.Nothing$ - * scala.Null erases to scala.runtime.Null$ - * - * 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 javaName(sym: Symbol): String = - javaNameCache.getOrElseUpdate(sym, { - if (sym.isClass || (sym.isModule && !sym.isMethod)) - sym.javaBinaryName - else - sym.javaSimpleName - }).toString - - def javaType(t: TypeKind): JType = (t: @unchecked) match { - case UNIT => JType.VOID - case BOOL => JType.BOOLEAN - case BYTE => JType.BYTE - case SHORT => JType.SHORT - case CHAR => JType.CHAR - case INT => JType.INT - case LONG => JType.LONG - case FLOAT => JType.FLOAT - case DOUBLE => JType.DOUBLE - case REFERENCE(cls) => new JObjectType(javaName(cls)) - case ARRAY(elem) => new JArrayType(javaType(elem)) - } - - def javaType(t: Type): JType = javaType(toTypeKind(t)) - - def javaType(s: Symbol): JType = - if (s.isMethod) - new JMethodType( - if (s.isClassConstructor) JType.VOID else javaType(s.tpe.resultType), - mkArray(s.tpe.paramTypes map javaType) - ) - else - javaType(s.tpe) - - protected def genConstant(jcode: JExtendedCode, const: Constant) { - const.tag match { - case UnitTag => () - case BooleanTag => jcode emitPUSH const.booleanValue - case ByteTag => jcode emitPUSH const.byteValue - case ShortTag => jcode emitPUSH const.shortValue - case CharTag => jcode emitPUSH const.charValue - case IntTag => jcode emitPUSH const.intValue - case LongTag => jcode emitPUSH const.longValue - case FloatTag => jcode emitPUSH const.floatValue - case DoubleTag => jcode emitPUSH const.doubleValue - case StringTag => jcode emitPUSH const.stringValue - case NullTag => jcode.emitACONST_NULL() - case ClazzTag => - val kind = toTypeKind(const.typeValue) - val toPush = - if (kind.isValueType) classLiteral(kind) - else javaType(kind).asInstanceOf[JReferenceType] - - jcode emitPUSH toPush - - case EnumTag => - val sym = const.symbolValue - jcode.emitGETSTATIC(javaName(sym.owner), - javaName(sym), - javaType(sym.tpe.underlying)) - case _ => - abort("Unknown constant value: " + const) - } - } - } -} diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala deleted file mode 100644 index 2fb6550239dd..000000000000 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ /dev/null @@ -1,2244 +0,0 @@ -/* NSC -- new scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Nikolay Mihaylov - */ - - -package scala.tools.nsc -package backend.msil - -import java.io.{File, IOException} -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 -import scala.language.postfixOps - -abstract class GenMSIL extends SubComponent { - import global._ - import loaders.clrTypes - import clrTypes.{types, constructors, methods, fields} - import icodes._ - import icodes.opcodes._ - - /** 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( settings.Xshowcls.isSetByUser && (codeGenerator.entryPoint == null) ) { // TODO introduce dedicated setting instead - val entryclass = settings.Xshowcls.value.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 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 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 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(java.nio.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, ClazzTag, 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, ClazzTag, 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: " + sym.flagString) - 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: " + m.symbol.flagString + - " 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 = " + m.symbol.flagString + " " + m.symbol) - java.lang.System.out.println("m.symbol.owner = " + m.symbol.owner.flagString + " " + 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 - */ - val 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: " + field.owner.flagString) - val 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 ClazzTag => - 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) = enteringTyper { - 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) { - val 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: @unchecked) 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) - 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) && settings.Xshowcls.isSetByUser) { // TODO introduce dedicated setting instead - val entryclass = settings.Xshowcls.value.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) - - val 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 " + sym.flagString + " " + - sym.owner.fullName + "::" + sym.name) - - val ownerType = getType(sym.enclClass).asInstanceOf[TypeBuilder] - assert(mtype == ownerType, "mtype = " + mtype + "; ownerType = " + ownerType) - val 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 { - val 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 = - enteringRefchecks { - 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) { - 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 - } - - private def showsym(sym: Symbol): String = (sym.toString + - "\n symbol = " + sym.flagString + " " + sym + - "\n owner = " + sym.owner.flagString + " " + 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 deleted file mode 100644 index bda13a5ed050..000000000000 --- a/src/compiler/scala/tools/nsc/io/MsilFile.scala +++ /dev/null @@ -1,15 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 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) { } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index cf6579a69624..8f964cf9e1be 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -69,10 +69,6 @@ trait ScalaSettings extends AbsScalaSettings * -X "Advanced" settings */ val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options.") - val assemname = StringSetting ("-Xassem-name", "file", "(Requires -target:msil) Name of the output assembly.", "").dependsOn(target, "msil") - val assemrefs = StringSetting ("-Xassem-path", "path", "(Requires -target:msil) List of assemblies referenced by the program.", ".").dependsOn(target, "msil") - val assemextdirs = StringSetting ("-Xassem-extdirs", "dirs", "(Requires -target:msil) List of directories containing assemblies. default:lib", Defaults.scalaLibDir.path).dependsOn(target, "msil") - val sourcedir = StringSetting ("-Xsourcedir", "directory", "(Requires -target:msil) Mirror source folder structure in output directory.", ".").dependsOn(target, "msil") val checkInit = BooleanSetting ("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.") val developer = BooleanSetting ("-Xdev", "Indicates user is a developer - issue warnings about anything which seems amiss") val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions or assumptions.") diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala index 98ef74aee372..9338d9e5b5b2 100644 --- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala @@ -41,8 +41,7 @@ trait StandardScalaSettings { val optimise: BooleanSetting // depends on post hook which mutates other settings val print = BooleanSetting ("-print", "Print program with Scala-specific features removed.") val target = ChoiceSetting ("-target", "target", "Target platform for object files. All JVM 1.5 targets are deprecated.", - List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "msil"), - "jvm-1.6") + List("jvm-1.5", "jvm-1.6", "jvm-1.7"), "jvm-1.6") val unchecked = BooleanSetting ("-unchecked", "Enable additional warnings where generated code depends on assumptions.") val uniqid = BooleanSetting ("-uniqid", "Uniquely tag all identifiers in debugging output.") val usejavacp = BooleanSetting ("-usejavacp", "Utilize the java.class.path in classpath resolution.") diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 19502f0d7ef6..bbff03f67fdd 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -12,7 +12,7 @@ import scala.tools.nsc.util.{ ClassPath } import classfile.ClassfileParser import scala.reflect.internal.MissingRequirementError import scala.reflect.internal.util.Statistics -import scala.tools.nsc.io.{ AbstractFile, MsilFile } +import scala.tools.nsc.io.{ AbstractFile } /** This class ... * @@ -152,7 +152,7 @@ abstract class SymbolLoaders { def sourcefile: Option[AbstractFile] = None /** - * Description of the resource (ClassPath, AbstractFile, MsilFile) + * Description of the resource (ClassPath, AbstractFile) * being processed by this loader */ protected def description: String @@ -265,16 +265,6 @@ abstract class SymbolLoaders { override def sourcefile: Option[AbstractFile] = classfileParser.srcfile } - class MsilFileLoader(msilFile: MsilFile) extends SymbolLoader with FlagAssigningCompleter { - 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 with FlagAssigningCompleter { protected def description = "source file "+ srcfile.toString override def fromSource = true @@ -287,11 +277,6 @@ abstract class SymbolLoaders { 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() - } - /** used from classfile parser to avoid cyclies */ var parentsLevel = 0 var pendingLoadActions: List[() => Unit] = Nil diff --git a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala deleted file mode 100644 index 624db027f19d..000000000000 --- a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala +++ /dev/null @@ -1,132 +0,0 @@ -/* NSC -- new scala compiler - * Copyright 2004-2013 LAMP/EPFL - */ - - -package scala.tools.nsc -package symtab -package clr - -import ch.epfl.lamp.compiler.msil._ -import scala.collection.{ mutable, immutable } - -/** - * Collects all types from all reference assemblies. - */ -abstract class CLRTypes { - - val global: Global - import global.Symbol - - //########################################################################## - - 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 deleted file mode 100644 index 8992ad1f8bff..000000000000 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ /dev/null @@ -1,848 +0,0 @@ -/* NSC -- new scala compiler - * Copyright 2004-2013 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 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 with FlagAgnosticCompleter { - 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(nme.CONSTRUCTOR, NoPosition, 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) - 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(name, NoPosition, 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: TermName = 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(name, NoPosition, 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: TermName = 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(name, NoPosition, 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(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(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(getName(method), NoPosition, 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: TermName, 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: TermName, flags: Long, mtype: Symbol => Type, method: MethodInfo, statik: Boolean): Symbol = { - val methodSym: Symbol = (if (statik) statics else clazz).newMethod(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) - 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) - 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): TermName = { - - 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 - operatorOverload(name, paramsArity) foreach (x => return x.toTermName) - } - 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 = rootMirror.getClassByName(typ.FullName.replace('+', '.') : TypeName).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/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 3af9c6d74dd7..765ef39e6bec 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -69,12 +69,6 @@ abstract class CleanUp extends Transform with ast.TreeDSL { case "mono-cache" => MONO_CACHE case "poly-cache" => POLY_CACHE } - - def shouldRewriteTry(tree: Try) = { - val sym = tree.tpe.typeSymbol - forMSIL && (sym != UnitClass) && (sym != NothingClass) - } - private def typedWithPos(pos: Position)(tree: Tree) = localTyper.typedPos(pos)(tree) @@ -543,10 +537,9 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * constructor. */ case Template(parents, self, body) => localTyper = typer.atOwner(tree, currentClass) - if (forMSIL) savingStatics( transformTemplate(tree) ) - else transformTemplate(tree) + transformTemplate(tree) - case Literal(c) if (c.tag == ClazzTag) && !forMSIL=> + case Literal(c) if c.tag == ClazzTag => val tpe = c.typeValue typedWithPos(tree.pos) { if (isPrimitiveValueClass(tpe.typeSymbol)) { @@ -559,24 +552,6 @@ abstract class CleanUp extends Transform with ast.TreeDSL { else tree } - /* MSIL requires that the stack is empty at the end of a try-block. - * Hence, we here rewrite all try blocks with a result != {Unit, All} such that they - * store their result in a local variable. The catch blocks are adjusted as well. - * The try tree is subsituted by a block whose result expression is read of that variable. */ - case theTry @ Try(block, catches, finalizer) if shouldRewriteTry(theTry) => - def transformTry = { - val tpe = theTry.tpe.widen - val tempVar = currentOwner.newVariable(mkTerm(nme.EXCEPTION_RESULT_PREFIX), theTry.pos).setInfo(tpe) - def assignBlock(rhs: Tree) = super.transform(BLOCK(Ident(tempVar) === transform(rhs))) - - val newBlock = assignBlock(block) - val newCatches = for (CaseDef(pattern, guard, body) <- catches) yield - (CASE(super.transform(pattern)) IF (super.transform(guard))) ==> assignBlock(body) - val newTry = Try(newBlock, newCatches, super.transform(finalizer)) - - typedWithPos(theTry.pos)(BLOCK(VAL(tempVar) === EmptyTree, newTry, Ident(tempVar))) - } - transformTry /* * This transformation should identify Scala symbol invocations in the tree and replace them * with references to a static member. Also, whenever a class has at least a single symbol invocation diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index f78a5133a63c..3772a58c147c 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -513,7 +513,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * - create a new method definition that also has a `self` parameter * (which comes first) Iuli: this position is assumed by tail call elimination * on a different receiver. Storing a new 'this' assumes it is located at - * index 0 in the local variable table. See 'STORE_THIS' and GenJVM/GenMSIL. + * index 0 in the local variable table. See 'STORE_THIS' and GenASM. * - Map implementation class types in type-apply's to their interfaces * - Remove all fields in implementation classes */ diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 6ab99eaec60c..7cad2b39868e 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -149,7 +149,7 @@ abstract class TailCalls extends Transform { def enclosingType = method.enclClass.typeOfThis def isEligible = method.isEffectivelyFinal // @tailrec annotation indicates mandatory transformation - def isMandatory = method.hasAnnotation(TailrecClass) && !forMSIL + def isMandatory = method.hasAnnotation(TailrecClass) def isTransformed = isEligible && accessed(label) def tailrecFailure() = unit.error(failPos, "could not optimize @tailrec annotated " + method + ": " + failReason) @@ -229,7 +229,6 @@ abstract class TailCalls extends Transform { } else if (!matchesTypeArgs) failHere("it is called recursively with different type arguments") else if (receiver == EmptyTree) rewriteTailCall(This(currentClass)) - else if (forMSIL) fail("it cannot be optimized on MSIL") else if (!receiverIsSame) failHere("it changes type of 'this' on a polymorphic recursive call") else rewriteTailCall(receiver) } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index d8658085ed97..19b9c188b013 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -61,24 +61,6 @@ abstract class UnCurry extends InfoTransform // uncurry and uncurryType expand type aliases - /** Traverse tree omitting local method definitions. - * If a `return` is encountered, set `returnFound` to true. - * Used for MSIL only. - */ - private object lookForReturns extends Traverser { - var returnFound = false - override def traverse(tree: Tree): Unit = tree match { - case Return(_) => returnFound = true - case DefDef(_, _, _, _, _, _) => ; - case _ => super.traverse(tree) - } - def found(tree: Tree) = { - returnFound = false - traverse(tree) - returnFound - } - } - class UnCurryTransformer(unit: CompilationUnit) extends TypingTransformer(unit) { private var needTryLift = false private var inPattern = false @@ -537,13 +519,6 @@ abstract class UnCurry extends InfoTransform finally needTryLift = saved } - /** A try or synchronized needs to be lifted anyway for MSIL if it contains - * return statements. These are disallowed in the CLR. By lifting - * such returns will be converted to throws. - */ - def shouldBeLiftedAnyway(tree: Tree) = false && // buggy, see #1981 - forMSIL && lookForReturns.found(tree) - /** Transform tree `t` to { def f = t; f } where `f` is a fresh name */ def liftTree(tree: Tree) = { @@ -618,13 +593,10 @@ abstract class UnCurry extends InfoTransform treeCopy.UnApply(tree, fn1, args1) case Apply(fn, args) => - if (fn.symbol == Object_synchronized && shouldBeLiftedAnyway(args.head)) - transform(treeCopy.Apply(tree, fn, List(liftTree(args.head)))) - else - withNeedLift(true) { - val formals = fn.tpe.paramTypes - treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, fn.symbol, args, formals))) - } + withNeedLift(true) { + val formals = fn.tpe.paramTypes + treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, fn.symbol, args, formals))) + } case Assign(_: RefTree, _) => withNeedLift(true) { super.transform(tree) } @@ -643,7 +615,7 @@ abstract class UnCurry extends InfoTransform super.transform(tree) case Try(block, catches, finalizer) => - if (needTryLift || shouldBeLiftedAnyway(tree)) transform(liftTree(tree)) + if (needTryLift) transform(liftTree(tree)) else super.transform(tree) case CaseDef(pat, guard, body) => diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index f7079f63faa8..4d1ab98fa03f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -470,9 +470,6 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { * Is also capable of detecting REPL and reusing its classloader. */ lazy val macroClassloader: ClassLoader = { - if (global.forMSIL) - throw new UnsupportedOperationException("Scala reflection not available on this platform") - val classpath = global.classPath.asURLs macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath)) val loader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index ee128c0e57a0..18bc95af39e8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -203,8 +203,7 @@ trait MethodSynthesis { ) def beanAccessors(vd: ValDef): List[DerivedFromValDef] = { val setter = if (vd.mods.isMutable) List(BeanSetter(vd)) else Nil - if (forMSIL) Nil - else if (vd.symbol hasAnnotation BeanPropertyAttr) + if (vd.symbol hasAnnotation BeanPropertyAttr) BeanGetter(vd) :: setter else if (vd.symbol hasAnnotation BooleanBeanPropertyAttr) BooleanBeanGetter(vd) :: setter @@ -523,9 +522,6 @@ trait MethodSynthesis { } protected def enterBeans(tree: ValDef) { - if (forMSIL) - return - val ValDef(mods, name, _, _) = tree val beans = beanAccessorsFromNames(tree) if (beans.nonEmpty) { diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 0ae225ccee12..16680c3f13c9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1116,8 +1116,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def isUnit(s: Symbol) = unboxedValueClass(s) == UnitClass def isNumeric(s: Symbol) = isNumericValueClass(unboxedValueClass(s)) || isAnyNumber(s) def isScalaNumber(s: Symbol) = s isSubClass ScalaNumberClass - // test is behind a platform guard - def isJavaNumber(s: Symbol) = !forMSIL && (s isSubClass JavaNumberClass) + def isJavaNumber(s: Symbol) = s isSubClass JavaNumberClass // includes java.lang.Number if appropriate [SI-5779] def isAnyNumber(s: Symbol) = isScalaNumber(s) || isJavaNumber(s) def isMaybeAnyValue(s: Symbol) = isPrimitiveValueClass(unboxedValueClass(s)) || isMaybeValue(s) @@ -1160,7 +1159,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans nonSensiblyNeq() } else if (isNumeric(receiver)) { - if (!isNumeric(actual) && !forMSIL) + if (!isNumeric(actual)) if (isUnit(actual) || isBoolean(actual) || !isMaybeValue(actual)) // 5 == "abc" nonSensiblyNeq() } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e534e36a0d41..8d606a8fd595 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1130,13 +1130,6 @@ trait Typers extends Modes with Adaptations with Tags { // (14); the condition prevents chains of views debuglog("inferring view from " + tree.tpe + " to " + pt) val coercion = inferView(tree, tree.tpe, pt, true) - // convert forward views of delegate types into closures wrapped around - // the delegate's apply method (the "Invoke" method, which was translated into apply) - if (forMSIL && coercion != null && isCorrespondingDelegate(tree.tpe, pt)) { - val meth: Symbol = tree.tpe.member(nme.apply) - debuglog("replacing forward delegate view with: " + meth + ":" + meth.tpe) - return typed(Select(tree, meth), mode, pt) - } if (coercion != EmptyTree) { def msg = "inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe if (settings.logImplicitConv.value) @@ -3037,26 +3030,6 @@ trait Typers extends Modes with Adaptations with Tags { case _ => tp } - // Replace the Delegate-Chainer methods += and -= with corresponding - // + and - calls, which are translated in the code generator into - // Combine and Remove - if (forMSIL) { - fun match { - case Select(qual, name) => - if (isSubType(qual.tpe, DelegateClass.tpe) - && (name == encode("+=") || name == encode("-="))) { - val n = if (name == encode("+=")) nme.PLUS else nme.MINUS - val f = Select(qual, n) - // the compiler thinks, the PLUS method takes only one argument, - // but he thinks it's an instance method -> still two ref's on the stack - // -> translated by backend - val rhs = treeCopy.Apply(tree, f, args) - return typed(Assign(qual, rhs)) - } - case _ => () - } - } - /** * This is translating uses of List() into Nil. This is less * than ideal from a consistency standpoint, but it shouldn't be @@ -4162,24 +4135,7 @@ trait Typers extends Modes with Adaptations with Tags { else adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType)) case MethodType(formals, _) => if (isFunctionType(pt)) expr1 - else expr1 match { - case Select(qual, name) if (forMSIL && - pt != WildcardType && - pt != ErrorType && - isSubType(pt, DelegateClass.tpe)) => - val scalaCaller = newScalaCaller(pt) - addScalaCallerInfo(scalaCaller, expr1.symbol) - val n: Name = scalaCaller.name - val del = Ident(DelegateClass) setType DelegateClass.tpe - val f = Select(del, n) - //val f1 = TypeApply(f, List(Ident(pt.symbol) setType pt)) - val args: List[Tree] = if(expr1.symbol.isStatic) List(Literal(Constant(null))) - else List(qual) // where the scala-method is located - val rhs = Apply(f, args) - typed(rhs) - case _ => - adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType)) - } + else adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType)) case ErrorType => expr1 case _ => diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index ee66801c4546..cbf6ef69d79b 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -184,8 +184,7 @@ abstract class ClassPath[T] { def sourcepaths: IndexedSeq[AbstractFile] /** - * Represents classes which can be loaded with a ClassfileLoader/MsilFileLoader - * and / or a SourcefileLoader. + * Represents classes which can be loaded with a ClassfileLoader and/or SourcefileLoader. */ case class ClassRep(binary: Option[T], source: Option[AbstractFile]) { def name: String = binary match { diff --git a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala deleted file mode 100644 index 2f209c550db2..000000000000 --- a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala +++ /dev/null @@ -1,166 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2006-2013 LAMP/EPFL - * @author Martin Odersky - */ - -// $Id$ - -package scala.tools.nsc -package util - -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) { } diff --git a/src/eclipse/README.md b/src/eclipse/README.md index 39a3f457a013..d135f99418df 100644 --- a/src/eclipse/README.md +++ b/src/eclipse/README.md @@ -44,7 +44,7 @@ If you want to go back to normal (for instance, to commit your changes to projec DETAILS ======= -The compiler project depends on the library, reflect, asm and fjbg projects. The +The compiler project depends on the library, reflect, and asm projects. The builder will take care of the correct ordering, and changes in one project will be picked up by the dependent projects. diff --git a/src/eclipse/fjbg/.classpath b/src/eclipse/fjbg/.classpath deleted file mode 100644 index 3e2f55f48a7e..000000000000 --- a/src/eclipse/fjbg/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/eclipse/fjbg/.project b/src/eclipse/fjbg/.project deleted file mode 100644 index 8acea9f5fe55..000000000000 --- a/src/eclipse/fjbg/.project +++ /dev/null @@ -1,30 +0,0 @@ - - - fjbg - - - - - - org.scala-ide.sdt.core.scalabuilder - - - - - - org.scala-ide.sdt.core.scalanature - org.eclipse.jdt.core.javanature - - - - fjbg - 2 - SCALA_BASEDIR/src/fjbg - - - libs-classes-fjbg - 2 - SCALA_BASEDIR/build/libs/classes/fjbg - - - diff --git a/src/eclipse/partest/.classpath b/src/eclipse/partest/.classpath index b14e465aa6bd..39a2c67f7c08 100644 --- a/src/eclipse/partest/.classpath +++ b/src/eclipse/partest/.classpath @@ -8,7 +8,6 @@ - diff --git a/src/eclipse/scala-compiler/.classpath b/src/eclipse/scala-compiler/.classpath index 40a4ed999618..3d851de53a2d 100644 --- a/src/eclipse/scala-compiler/.classpath +++ b/src/eclipse/scala-compiler/.classpath @@ -3,11 +3,9 @@ - - diff --git a/src/eclipse/scalap/.classpath b/src/eclipse/scalap/.classpath index 2b44ad19b2ff..3863097a6531 100644 --- a/src/eclipse/scalap/.classpath +++ b/src/eclipse/scalap/.classpath @@ -7,6 +7,5 @@ - diff --git a/src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java b/src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java deleted file mode 100644 index 9856dc7311d8..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/FJBGContext.java +++ /dev/null @@ -1,195 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.IOException; - -/** - * Context in which FJBG executes. Used both as a factory for most - * FJBG classes and as a repository for other factories. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class FJBGContext { - /** Class file major version */ - final int MAJOR_VERSION; - - /** Class file minor version */ - final int MINOR_VERSION; - - public FJBGContext() { - this(45, 3); - } - - public FJBGContext(int major, int minor) { - MAJOR_VERSION = major; - MINOR_VERSION = minor; - } - - // Factory methods - ////////////////////////////////////////////////////////////////////// - - public JClass JClass(int accessFlags, - String name, - String superclassName, - String[] interfaceNames, - String sourceFileName) { - return new JClass(this, - accessFlags, - name, - superclassName, - interfaceNames, - sourceFileName); - } - - public JClass JClass(DataInputStream stream) - throws IOException { - return new JClass(this, stream); - } - - public JConstantPool JConstantPool() { - return new JConstantPool(this); - } - - public JConstantPool JConstantPool(DataInputStream stream) - throws IOException { - return new JConstantPool(this, stream); - } - - public JField JField(JClass owner, - int accessFlags, - String name, - JType type) { - return new JField(this, - owner, - accessFlags, - name, - type); - } - - public JField JField(JClass owner, DataInputStream stream) - throws IOException { - return new JField(this, owner, stream); - } - - public JMethod JMethod(JClass owner, - int accessFlags, - String name, - JType returnType, - JType[] argTypes, - String[] argNames) { - return new JMethod(this, - owner, - accessFlags, - name, - returnType, - argTypes, - argNames); - } - - public JMethod JMethod(JClass owner, - int accessFlags, - String name, - JMethodType type, - String[] argNames) { - return JMethod(owner, - accessFlags, - name, - type.getReturnType(), - type.getArgumentTypes(), - argNames); - } - - public JMethod JMethod(JClass owner, DataInputStream stream) - throws IOException { - return new JMethod(this, owner, stream); - } - - public JLocalVariable JLocalVariable(JMethod owner, - JType type, - String name, - int index) { - return new JLocalVariable(this, owner, type, name, index); - } - - public JCode JCode(JClass clazz, JMethod owner) { - return new JExtendedCode(this, clazz, owner); - } - - public JCode JCode(JClass clazz, JMethod owner, DataInputStream stream) - throws IOException { - return new JCode(this, clazz, owner, stream); - } - - public JAttributeFactory JAttributeFactory() { - return new JAttributeFactory(this); - } - - // Attributes - public JCodeAttribute JCodeAttribute(JClass clazz, JMethod owner) { - return new JCodeAttribute(this, clazz, owner); - } - - public JEnclosingMethodAttribute JEnclosingMethodAttribute(JClass clazz, - String className, - String methodName, - JType methodType) { - return new JEnclosingMethodAttribute(this, clazz, className, methodName, methodType); - } - - public JExceptionsAttribute JExceptionsAttribute(JClass clazz, - JMethod owner) { - return new JExceptionsAttribute(this, clazz, owner); - } - - public JLineNumberTableAttribute JLineNumberTableAttribute(JClass clazz, - JCode owner) { - return new JLineNumberTableAttribute(this, clazz, owner); - } - - public JLocalVariableTableAttribute JLocalVariableTableAttribute(JClass clazz, - JCode owner) { - return new JLocalVariableTableAttribute(this, clazz, owner); - } - - public JOtherAttribute JOtherAttribute(JClass clazz, - Object owner, - String name, - byte[] contents, - int length) { - return new JOtherAttribute(this, clazz, owner, name, contents, length); - } - - public JOtherAttribute JOtherAttribute(JClass clazz, - Object owner, - String name, - byte[] contents) { - return JOtherAttribute(clazz, owner, name, contents, contents.length); - } - - public JSourceFileAttribute JSourceFileAttribute(JClass clazz, - String sourceFileName) { - return new JSourceFileAttribute(this, clazz, sourceFileName); - } - - public JStackMapTableAttribute JStackMapTableAttribute(JClass clazz, - JCode owner) { - return new JStackMapTableAttribute(this, clazz, owner); - } - - /// Repository - ////////////////////////////////////////////////////////////////////// - - protected JAttributeFactory jAttributeFactory = null; - public JAttributeFactory getJAttributeFactory() { - if (jAttributeFactory == null) - jAttributeFactory = JAttributeFactory(); - return jAttributeFactory; - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JAccessFlags.java b/src/fjbg/ch/epfl/lamp/fjbg/JAccessFlags.java deleted file mode 100644 index 01d8cc9a7eff..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JAccessFlags.java +++ /dev/null @@ -1,35 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Definition of access flags for fields, methods and classes. - * - * @author Michel Schinz - * @version 1.0 - */ - -public interface JAccessFlags { - public static int ACC_PUBLIC = 0x0001; - public static int ACC_PRIVATE = 0x0002; - public static int ACC_PROTECTED = 0x0004; - public static int ACC_STATIC = 0x0008; - public static int ACC_FINAL = 0x0010; - public static int ACC_SUPER = 0x0020; - public static int ACC_VOLATILE = 0x0040; - public static int ACC_TRANSIENT = 0x0080; - public static int ACC_NATIVE = 0x0100; - public static int ACC_INTERFACE = 0x0200; - public static int ACC_ABSTRACT = 0x0400; - public static int ACC_STRICT = 0x0800; - public static int ACC_SYNTHETIC = 0x1000; - public static int ACC_ANNOTATION= 0x2000; - public static int ACC_ENUM = 0x4000; - - // 1.5 specifics - public static int ACC_BRIDGE = 0x0040; - public static int ACC_VARARGS = 0x0080; -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JArrayType.java b/src/fjbg/ch/epfl/lamp/fjbg/JArrayType.java deleted file mode 100644 index 61a04523caa5..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JArrayType.java +++ /dev/null @@ -1,62 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Types for Java arrays. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JArrayType extends JReferenceType { - protected final JType elementType; - protected String signature = null; - - public JArrayType(JType elementType) { - this.elementType = elementType; - } - - public int getSize() { return 1; } - - public String getSignature() { - if (signature == null) - signature = "[" + elementType.getSignature(); - return signature; - } - - public String getDescriptor() { - return getSignature(); - } - - public int getTag() { return T_ARRAY; } - - public JType getElementType() { return elementType; } - - public String toString() { - return elementType.toString() + "[]"; - } - - public boolean isArrayType() { return true; } - - public boolean isCompatibleWith(JType other) { - if (other instanceof JObjectType) - return (JObjectType)other == JObjectType.JAVA_LANG_OBJECT; - else if (other instanceof JArrayType) - return elementType.isCompatibleWith(((JArrayType)other).elementType); - else return other == JType.REFERENCE; - } - - public static JArrayType BOOLEAN = new JArrayType(JType.BOOLEAN); - public static JArrayType BYTE = new JArrayType(JType.BYTE); - public static JArrayType CHAR = new JArrayType(JType.CHAR); - public static JArrayType SHORT = new JArrayType(JType.SHORT); - public static JArrayType INT = new JArrayType(JType.INT); - public static JArrayType FLOAT = new JArrayType(JType.FLOAT); - public static JArrayType LONG = new JArrayType(JType.LONG); - public static JArrayType DOUBLE = new JArrayType(JType.DOUBLE); - public static JArrayType REFERENCE = new JArrayType(JType.REFERENCE); -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JAttribute.java deleted file mode 100644 index 6a825beb18dd..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JAttribute.java +++ /dev/null @@ -1,84 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.*; - -/** - * Abstract superclass for attributes which can be attached to various - * parts of a class file. - * - * Attributes are used for classes (section 4.2), fields (section 4.6), - * methods (section 4.7) and the Code attribute (section 4.8.3). - * See sections 4.2 and later of the JVM specification. - * - * @author Michel Schinz - * @version 1.0 - */ - -public abstract class JAttribute { - protected final int nameIdx; - - static public void writeTo(List/**/ attrs, DataOutputStream stream) - throws IOException { - stream.writeShort(attrs.size()); - Iterator attrsIt = attrs.iterator(); - while (attrsIt.hasNext()) { - JAttribute attr = (JAttribute)attrsIt.next(); - attr.writeTo(stream); - } - } - - static public List/**/ readFrom(FJBGContext context, - JClass clazz, - Object owner, - DataInputStream stream) - throws IOException { - JAttributeFactory factory = context.getJAttributeFactory(); - int count = stream.readShort(); - ArrayList list = new ArrayList(count); - for (int i = 0; i < count; ++i) - list.add(factory.newInstance(clazz, owner, stream)); - return list; - } - - public JAttribute(FJBGContext context, JClass clazz) { - this.nameIdx = clazz.getConstantPool().addUtf8(getName()); - } - - public JAttribute(FJBGContext context, JClass clazz, String name) { - this.nameIdx = clazz.getConstantPool().addUtf8(name); - } - - abstract public String getName(); - - /** - * Write the attribute to a stream. - */ - public void writeTo(DataOutputStream stream) throws IOException { - int contentsSize = getSize(); - - stream.writeShort(nameIdx); - stream.writeInt(contentsSize); - int streamSizeBefore = stream.size(); - writeContentsTo(stream); - int streamSizeDiff = stream.size() - streamSizeBefore; - - assert contentsSize == streamSizeDiff - : "invalid size for attribute " + getName() - + " given: " + contentsSize - + " actual: " + streamSizeDiff; - } - - // Note: it is not legal to add data to the constant pool during - // the execution of any of the following two methods. - protected abstract int getSize(); - protected abstract void writeContentsTo(DataOutputStream stream) - throws IOException; -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JAttributeFactory.java b/src/fjbg/ch/epfl/lamp/fjbg/JAttributeFactory.java deleted file mode 100644 index 33cdce2760fd..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JAttributeFactory.java +++ /dev/null @@ -1,101 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; - -/** - * Extensible factory to build subclasses of JAttribute based on an - * attribute name. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JAttributeFactory { - protected FJBGContext context; - protected HashMap/**/ constructors = new HashMap(); - - protected final static Class[] CONSTRUCTOR_ARGS = new Class[] { - FJBGContext.class, - JClass.class, - Object.class, - String.class, - int.class, - DataInputStream.class - }; - - protected final static Constructor defaultDefaultConstructor; - static { - try { - defaultDefaultConstructor = - JOtherAttribute.class.getConstructor(CONSTRUCTOR_ARGS); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - protected final Constructor defaultConstructor; - - public JAttributeFactory(FJBGContext context, - Constructor defaultConstructor) { - this.context = context; - this.defaultConstructor = defaultConstructor; - registerClass("Code", JCodeAttribute.class); - registerClass("ConstantValue", JConstantValueAttribute.class); - registerClass("EnclosingMethod", JEnclosingMethodAttribute.class); - registerClass("Exceptions", JExceptionsAttribute.class); - registerClass("InnerClasses", JInnerClassesAttribute.class); - registerClass("LineNumberTable", JLineNumberTableAttribute.class); - registerClass("LocalVariableTable", JLocalVariableTableAttribute.class); - registerClass("SourceFile", JSourceFileAttribute.class); - registerClass("StackMapTable", JStackMapTableAttribute.class); - } - - public JAttributeFactory(FJBGContext context) { - this(context, defaultDefaultConstructor); - } - - public void registerClass(String attributeName, - Class clazz) { - if (! JAttribute.class.isAssignableFrom(clazz)) - throw new IllegalArgumentException("Not a subclass of JAttribute: " - + clazz); - - try { - Constructor constr = clazz.getConstructor(CONSTRUCTOR_ARGS); - constructors.put(attributeName, constr); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("No appropriate constructor for " - + clazz); - } - } - - public JAttribute newInstance(JClass clazz, - Object owner, - DataInputStream stream) - throws IOException { - String name = clazz.getConstantPool().lookupUtf8(stream.readShort()); - Integer size = new Integer(stream.readInt()); - Constructor constr = (Constructor)constructors.get(name); - if (constr == null) constr = defaultConstructor; - - Object[] args = new Object[] { context, clazz, owner, name, size, stream }; - try { - return (JAttribute)constr.newInstance(args); - } catch (InstantiationException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JClass.java b/src/fjbg/ch/epfl/lamp/fjbg/JClass.java deleted file mode 100644 index bb1538ec238c..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JClass.java +++ /dev/null @@ -1,420 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.util.*; -import java.io.*; - -/** - * Representation of a Java class. - * - * @author Michel Schinz, Stephane Micheloud - * @version 1.1 - */ -public class JClass extends JMember { - - /** Magic number for Java class files. */ - public final static int MAGIC_NUMBER = 0xCAFEBABE; - - protected final JAttributeFactory attributeFactory; - - protected final String superclassName; - protected final String[] interfaceNames; - protected final String sourceFileName; - protected final JConstantPool pool; - - public final static String[] NO_INTERFACES = new String[0]; - - protected final LinkedList/**/ methods = new LinkedList(); - protected final LinkedList/**/ fields = new LinkedList(); - - protected JInnerClassesAttribute innerClasses; - - protected int major; - protected int minor; - - /** - * Creates a new class with its access flags, name, superclass name, - * interfaces names and source file name initialized to a given value. - * The constructor also initializes the pool and adds a sourceFileName - * attribute to the class. - * @param accessFlags the int representing the access flags of the class. - * @param name the string representing the name of the class. - * @param superclassName the string representing the name of the class' - * superclass. - * @param interfaceNames the list of strings representing the names of the - * interfaces implemented by the class. - * @param sourceFileName name of the file from which the class was compiled. - */ - protected JClass(FJBGContext context, - int accessFlags, - String name, - String superclassName, - String[] interfaceNames, - String sourceFileName) { - super(context, accessFlags, name); - this.attributeFactory = context.getJAttributeFactory(); - - this.major = context.MAJOR_VERSION; - this.minor = context.MINOR_VERSION; - - this.superclassName = superclassName; - this.interfaceNames = interfaceNames; - this.sourceFileName = sourceFileName; - this.pool = context.JConstantPool(); - if (sourceFileName != null) - addAttribute(context.JSourceFileAttribute(this, sourceFileName)); - } - - protected JClass(FJBGContext context, DataInputStream stream) - throws IOException { - super(context); - this.attributeFactory = context.getJAttributeFactory(); - - int magic = stream.readInt(); - if (magic != MAGIC_NUMBER) - throw new IllegalArgumentException("invalid magic number: "+magic); - - minor = stream.readShort(); - major = stream.readShort(); - pool = context.JConstantPool(stream); - accessFlags = stream.readShort(); - - // This class, super class and interfaces - name = pool.lookupClass(stream.readShort()); - superclassName = pool.lookupClass(stream.readShort()); - interfaceNames = new String[stream.readShort()]; - for (int i = 0; i < interfaceNames.length; ++i) - interfaceNames[i] = pool.lookupClass(stream.readShort()); - - // Fields, methods and attributes - int fieldsCount = stream.readShort(); - for (int i = 0; i < fieldsCount; ++i) - addField(context.JField(this, stream)); - - int methodsCount = stream.readShort(); - for (int i = 0; i < methodsCount; ++i) - addMethod(context.JMethod(this, stream)); - - String fileName = null; - int attributesCount = stream.readShort(); - for (int i = 0; i < attributesCount; ++i) { - JAttribute attr = attributeFactory.newInstance(this, this, stream); - if (attr instanceof JSourceFileAttribute) - fileName = ((JSourceFileAttribute)attr).getFileName(); - else if (attr instanceof JInnerClassesAttribute) - innerClasses = (JInnerClassesAttribute)attr; - addAttribute(attr); - } - sourceFileName = fileName; - } - - /** - * Gets the name of the class' superclass. - * @return The string representing the name of the class' superclass. - */ - public String getSuperclassName() { return superclassName; } - - /** - * Gets the names of the interfaces implemented by the class. - * @return The array containing the string representations of the - * names of the interfaces implemented by the class. - */ - public String[] getInterfaceNames() { return interfaceNames; } - - /** - * Gets the source file name of this class. - * @return The string representing the source file name of this class. - */ - public String getSourceFileName() { return sourceFileName; } - - /** - * Gets the type of the objects that are instances of the class. - * @return The type of the instances of the class. - */ - public JType getType() { return new JObjectType(name); } - - public JClass getJClass() { return this; } - - public boolean isPublic() { - return (accessFlags & JAccessFlags.ACC_PUBLIC) != 0; - } - - public boolean isPrivate() { - return (accessFlags & JAccessFlags.ACC_PRIVATE) != 0; - } - - public boolean isProtected() { - return (accessFlags & JAccessFlags.ACC_PROTECTED) != 0; - } - - public boolean isStatic() { - return (accessFlags & JAccessFlags.ACC_STATIC) != 0; - } - - public boolean isFinal() { - return (accessFlags & JAccessFlags.ACC_FINAL) != 0; - } - - public boolean isAbstract() { - return (accessFlags & JAccessFlags.ACC_ABSTRACT) != 0; - } - - /** - * Gets the version number of the class. - * @param major The int representing the major part of the version number - * of the class. - * @param minor The int representing the minor part of the version number - * of the class. - */ - public void setVersion(int major, int minor) { - assert !frozen; - this.major = major; - this.minor = minor; - } - - /** - * Gets the major part of the number describing the version of the class. - * @return The int representing the major part of the version number of - * the class. - */ - public int getMajorVersion() { return major; } - - /** - * Gets the minor part of the number describing the version of the class. - * @return The int representing the minor part of the version number of - * the class. - */ - public int getMinorVersion() { return minor; } - - /** - * Gets the constant pool of the class. - * @return The constant pool of the class. - */ - public JConstantPool getConstantPool() { return pool; } - - public JInnerClassesAttribute getInnerClasses() { - if (innerClasses == null) { - innerClasses = new JInnerClassesAttribute(context, this); - addAttribute(innerClasses); - } - return innerClasses; - } - - /** - * Decides if the class is an interface. - * @return The boolean representing if the class is an interface or not. - */ - public boolean isInterface() { - return (accessFlags & JAccessFlags.ACC_INTERFACE) != 0; - } - - public void addField(JField field) { - assert !frozen; - fields.add(field); - } - - /** - * Create and add a new field to the class. - */ - public JField addNewField(int accessFlags, String name, JType type) { - assert !frozen; - JField f = context.JField(this, accessFlags, name, type); - addField(f); - return f; - } - - protected void addMethod(JMethod method) { - assert !frozen; - methods.add(method); - } - - /** - * Create and add a new method to the class. - */ - public JMethod addNewMethod(int accessFlags, - String name, - JType returnType, - JType[] argTypes, - String[] argNames) { - assert !frozen; - JMethod m = context.JMethod(this, - accessFlags, - name, - returnType, - argTypes, - argNames); - addMethod(m); - return m; - } - - /** - * Remove a previously-added method. This makes no attempt at - * minimising the constant pool by removing all constants which - * were used only by this method. - */ - public void removeMethod(JMethod m) { - assert !frozen; - methods.remove(m); - } - - public JField[] getFields() { - return (JField[])fields.toArray(new JField[fields.size()]); - } - - public JMethod[] getMethods() { - return (JMethod[])methods.toArray(new JMethod[methods.size()]); - } - - /** - * Freeze the contents of this class so that it can be written to - * a file. - */ - public void freeze() { - assert !frozen; - frozen = true; - } - - /** - * Writes the contents of the class to a file referenced by its name. - * @param fileName The name of the file in which the class must be written. - */ - public void writeTo(String fileName) throws IOException { - writeTo(new File(fileName)); - } - - /** - * Writes the contents of the class to a file. - * @param file The file in which the class must be written. - */ - public void writeTo(File file) throws IOException { - File parent = file.getParentFile(); - if (parent != null && !parent.isDirectory()) - if (!parent.mkdirs()) - throw new IOException("cannot create directory " + parent); - - FileOutputStream fStream = new FileOutputStream(file); - BufferedOutputStream bStream = new BufferedOutputStream(fStream); - DataOutputStream dStream = new DataOutputStream(bStream); - writeTo(dStream); - dStream.close(); - bStream.close(); - fStream.close(); - } - - /** - * Writes the contents of the class to a data stream. - * @param stream The data stream in which the class must be written. - */ - public void writeTo(DataOutputStream stream) throws IOException { - if (!frozen) freeze(); - - int thisClassIdx = pool.addClass(name); - int superClassIdx = pool.addClass(superclassName); - int[] interfacesIdx = new int[interfaceNames.length]; - - for (int i = 0; i < interfaceNames.length; ++i) - interfacesIdx[i] = pool.addClass(interfaceNames[i]); - - pool.freeze(); - - // Magic number. - stream.writeInt(MAGIC_NUMBER); - // Version - stream.writeShort(minor); - stream.writeShort(major); - // Constant pool - pool.writeTo(stream); - // Access flags - stream.writeShort(accessFlags); - - // This class, super class and interfaces - stream.writeShort(thisClassIdx); - stream.writeShort(superClassIdx); - stream.writeShort(interfacesIdx.length); - for (int i = 0; i < interfacesIdx.length; ++i) - stream.writeShort(interfacesIdx[i]); - - // Fields and methods - stream.writeShort(fields.size()); - Iterator fieldsIt = fields.iterator(); - while (fieldsIt.hasNext()) - ((JField)fieldsIt.next()).writeTo(stream); - - stream.writeShort(methods.size()); - Iterator methodsIt = methods.iterator(); - while (methodsIt.hasNext()) - ((JMethod)methodsIt.next()).writeTo(stream); - - // Attributes - JAttribute.writeTo(attributes, stream); - } - - // Follows javap output format for ClassFile. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(); - if (sourceFileName != null) { - buf.append("Compiled from \""); - buf.append(sourceFileName); - buf.append("\"\n"); - } - buf.append(getMemberName()); - buf.append(toExternalName(getName())); - if (!isInterface()) { - buf.append(" extends "); - buf.append(toExternalName(getSuperclassName())); - } - if (interfaceNames.length > 0) { - if (isInterface()) buf.append(" extends "); - else buf.append(" implements "); - for (int i = 0; i < interfaceNames.length; ++i) { - if (i > 0) buf.append(","); - buf.append(toExternalName(interfaceNames[i])); - } - } - buf.append("\n"); - Iterator attrsIt = attributes.iterator(); - while (attrsIt.hasNext()) { - JAttribute attr = (JAttribute)attrsIt.next(); - buf.append(attr); - } - buf.append(" minor version: "); - buf.append(minor); - buf.append("\n major version: "); - buf.append(major); - buf.append("\n"); - buf.append(pool); - buf.append("\n{\n"); - JField[] jfields = getFields(); - for (int i = 0; i < jfields.length; ++i) { - if (i > 0) buf.append("\n"); - buf.append(jfields[i]); - } - buf.append("\n"); - JMethod[] jmethods = getMethods(); - for (int i = 0; i < jmethods.length; ++i) { - if (i > 0) buf.append("\n"); - buf.append(jmethods[i]); - } - buf.append("\n}\n"); - return buf.toString(); - } - - private String getMemberName() { - StringBuffer buf = new StringBuffer(); - if (isPublic()) buf.append("public "); - else if (isProtected()) buf.append("protected "); - else if (isPrivate()) buf.append("private "); - if (isInterface()) - buf.append("interface "); - else { - if (isAbstract()) buf.append("abstract "); - else if (isFinal()) buf.append("final "); - buf.append("class "); - } - return buf.toString(); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JCode.java b/src/fjbg/ch/epfl/lamp/fjbg/JCode.java deleted file mode 100644 index ab6934ab30ad..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JCode.java +++ /dev/null @@ -1,1308 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.*; - -import ch.epfl.lamp.util.ByteArray; - -/** - * List of instructions, to which Java byte-code instructions can be added. - * - * @author Michel Schinz, Thomas Friedli - * @version 1.0 - */ - -public class JCode { - protected boolean frozen = false; - - public static int MAX_CODE_SIZE = 65535; - - protected final FJBGContext context; - protected final JMethod owner; - - protected final ByteArray codeArray; - - protected final LinkedList/**/ exceptionHandlers = - new LinkedList(); - - protected final JConstantPool pool; - - protected final ArrayList/**/ offsetToPatch = - new ArrayList(); - - protected static int UNKNOWN_STACK_SIZE = Integer.MIN_VALUE; - protected int maxStackSize = UNKNOWN_STACK_SIZE; - protected int[] stackProduction = null; - protected int[] stackSizes; - - protected JCode(FJBGContext context, JClass clazz, JMethod owner) { - this.context = context; - this.pool = clazz.getConstantPool(); - this.owner = owner; - this.codeArray = new ByteArray(); - } - - protected JCode(FJBGContext context, - JClass clazz, - JMethod owner, - DataInputStream stream) - throws IOException { - this.context = context; - this.pool = clazz.getConstantPool(); - this.owner = owner; - owner.setCode(this); - int size = stream.readInt(); - if (size > MAX_CODE_SIZE) // section 4.10 - throw new Error("code size must be less than " + MAX_CODE_SIZE + ": " + size); - this.codeArray = new ByteArray(stream, size); - } - - /** - * Gets the program counter, which is defined as the address of the - * next instruction. - * @return The int representing the value of the program counter - */ - public int getPC() { - return codeArray.getSize(); - } - - /** - * Gets the size of the code - * @return The number of bytes of the code - */ - public int getSize() { - return codeArray.getSize(); - } - - /** - * Gets the method to which the code belongs - * @return The method to which the code belongs - */ - public JMethod getOwner() { - return owner; - } - - // Stack size - public int getMaxStackSize() { - if (maxStackSize == UNKNOWN_STACK_SIZE) - maxStackSize = computeMaxStackSize(); - return maxStackSize; - } - - // Freezing - ////////////////////////////////////////////////////////////////////// - - public static class CodeSizeTooBigException extends OffsetTooBigException { - public int codeSize; - - public CodeSizeTooBigException(int size) { - codeSize = size; - } - } - - public void freeze() throws OffsetTooBigException { - assert !frozen; - - if (getSize() > MAX_CODE_SIZE) throw new CodeSizeTooBigException(getSize()); - - patchAllOffset(); - codeArray.freeze(); - frozen = true; - } - - // Attributes - ////////////////////////////////////////////////////////////////////// - - protected final LinkedList/**/ attributes = new LinkedList(); - - public void addAttribute(JAttribute attr) { - attributes.add(attr); - } - - public List/**/ getAttributes() { - return attributes; - } - - // Emitting code - ////////////////////////////////////////////////////////////////////// - - public void emit(JOpcode opcode) { - setStackProduction(getPC(), opcode); - codeArray.addU1(opcode.code); - } - - public void emitNOP() { emit(JOpcode.NOP); } - - // Constant loading. - public void emitACONST_NULL() { emit(JOpcode.ACONST_NULL); } - public void emitICONST_M1() { emit(JOpcode.ICONST_M1); } - public void emitICONST_0() { emit(JOpcode.ICONST_0); } - public void emitICONST_1() { emit(JOpcode.ICONST_1); } - public void emitICONST_2() { emit(JOpcode.ICONST_2); } - public void emitICONST_3() { emit(JOpcode.ICONST_3); } - public void emitICONST_4() { emit(JOpcode.ICONST_4); } - public void emitICONST_5() { emit(JOpcode.ICONST_5); } - public void emitLCONST_0() { emit(JOpcode.LCONST_0); } - public void emitLCONST_1() { emit(JOpcode.LCONST_1); } - public void emitFCONST_0() { emit(JOpcode.FCONST_0); } - public void emitFCONST_1() { emit(JOpcode.FCONST_1); } - public void emitFCONST_2() { emit(JOpcode.FCONST_2); } - public void emitDCONST_0() { emit(JOpcode.DCONST_0); } - public void emitDCONST_1() { emit(JOpcode.DCONST_1); } - - public void emitBIPUSH(int b) { emitU1(JOpcode.BIPUSH, b); } - public void emitSIPUSH(int s) { emitU2(JOpcode.SIPUSH, s); } - public void emitLDC(int value) { - emitU1(JOpcode.LDC, pool.addInteger(value)); - } - public void emitLDC(float value) { - emitU1(JOpcode.LDC, pool.addFloat(value)); - } - public void emitLDC(String value) { - emitU1(JOpcode.LDC, pool.addString(value)); - } - public void emitLDC_W(int value) { - emitU1(JOpcode.LDC_W, pool.addInteger(value)); - } - public void emitLDC_W(float value) { - emitU1(JOpcode.LDC_W, pool.addFloat(value)); - } - public void emitLDC_W(String value) { - emitU1(JOpcode.LDC_W, pool.addString(value)); - } - public void emitLDC2_W(long value) { - emitU2(JOpcode.LDC2_W, pool.addLong(value)); - } - public void emitLDC2_W(double value) { - emitU2(JOpcode.LDC2_W, pool.addDouble(value)); - } - - // Loading variables. - public void emitILOAD(int index) { emitU1(JOpcode.ILOAD, index); } - public void emitLLOAD(int index) { emitU1(JOpcode.LLOAD, index); } - public void emitFLOAD(int index) { emitU1(JOpcode.FLOAD, index); } - public void emitDLOAD(int index) { emitU1(JOpcode.DLOAD, index); } - public void emitALOAD(int index) { emitU1(JOpcode.ALOAD, index); } - - public void emitILOAD_0() { emit(JOpcode.ILOAD_0); } - public void emitILOAD_1() { emit(JOpcode.ILOAD_1); } - public void emitILOAD_2() { emit(JOpcode.ILOAD_2); } - public void emitILOAD_3() { emit(JOpcode.ILOAD_3); } - public void emitLLOAD_0() { emit(JOpcode.LLOAD_0); } - public void emitLLOAD_1() { emit(JOpcode.LLOAD_1); } - public void emitLLOAD_2() { emit(JOpcode.LLOAD_2); } - public void emitLLOAD_3() { emit(JOpcode.LLOAD_3); } - public void emitFLOAD_0() { emit(JOpcode.FLOAD_0); } - public void emitFLOAD_1() { emit(JOpcode.FLOAD_1); } - public void emitFLOAD_2() { emit(JOpcode.FLOAD_2); } - public void emitFLOAD_3() { emit(JOpcode.FLOAD_3); } - public void emitDLOAD_0() { emit(JOpcode.DLOAD_0); } - public void emitDLOAD_1() { emit(JOpcode.DLOAD_1); } - public void emitDLOAD_2() { emit(JOpcode.DLOAD_2); } - public void emitDLOAD_3() { emit(JOpcode.DLOAD_3); } - public void emitALOAD_0() { emit(JOpcode.ALOAD_0); } - public void emitALOAD_1() { emit(JOpcode.ALOAD_1); } - public void emitALOAD_2() { emit(JOpcode.ALOAD_2); } - public void emitALOAD_3() { emit(JOpcode.ALOAD_3); } - - public void emitIALOAD() { emit(JOpcode.IALOAD); } - public void emitLALOAD() { emit(JOpcode.LALOAD); } - public void emitFALOAD() { emit(JOpcode.FALOAD); } - public void emitDALOAD() { emit(JOpcode.DALOAD); } - public void emitAALOAD() { emit(JOpcode.AALOAD); } - public void emitBALOAD() { emit(JOpcode.BALOAD); } - public void emitCALOAD() { emit(JOpcode.CALOAD); } - public void emitSALOAD() { emit(JOpcode.SALOAD); } - - // Storing variables. - public void emitISTORE(int index) { emitU1(JOpcode.ISTORE, index); } - public void emitLSTORE(int index) { emitU1(JOpcode.LSTORE, index); } - public void emitFSTORE(int index) { emitU1(JOpcode.FSTORE, index); } - public void emitDSTORE(int index) { emitU1(JOpcode.DSTORE, index); } - public void emitASTORE(int index) { emitU1(JOpcode.ASTORE, index); } - - public void emitISTORE_0() { emit(JOpcode.ISTORE_0); } - public void emitISTORE_1() { emit(JOpcode.ISTORE_1); } - public void emitISTORE_2() { emit(JOpcode.ISTORE_2); } - public void emitISTORE_3() { emit(JOpcode.ISTORE_3); } - public void emitLSTORE_0() { emit(JOpcode.LSTORE_0); } - public void emitLSTORE_1() { emit(JOpcode.LSTORE_1); } - public void emitLSTORE_2() { emit(JOpcode.LSTORE_2); } - public void emitLSTORE_3() { emit(JOpcode.LSTORE_3); } - public void emitFSTORE_0() { emit(JOpcode.FSTORE_0); } - public void emitFSTORE_1() { emit(JOpcode.FSTORE_1); } - public void emitFSTORE_2() { emit(JOpcode.FSTORE_2); } - public void emitFSTORE_3() { emit(JOpcode.FSTORE_3); } - public void emitDSTORE_0() { emit(JOpcode.DSTORE_0); } - public void emitDSTORE_1() { emit(JOpcode.DSTORE_1); } - public void emitDSTORE_2() { emit(JOpcode.DSTORE_2); } - public void emitDSTORE_3() { emit(JOpcode.DSTORE_3); } - public void emitASTORE_0() { emit(JOpcode.ASTORE_0); } - public void emitASTORE_1() { emit(JOpcode.ASTORE_1); } - public void emitASTORE_2() { emit(JOpcode.ASTORE_2); } - public void emitASTORE_3() { emit(JOpcode.ASTORE_3); } - - public void emitIASTORE() { emit(JOpcode.IASTORE); } - public void emitLASTORE() { emit(JOpcode.LASTORE); } - public void emitFASTORE() { emit(JOpcode.FASTORE); } - public void emitDASTORE() { emit(JOpcode.DASTORE); } - public void emitAASTORE() { emit(JOpcode.AASTORE); } - public void emitBASTORE() { emit(JOpcode.BASTORE); } - public void emitCASTORE() { emit(JOpcode.CASTORE); } - public void emitSASTORE() { emit(JOpcode.SASTORE); } - - // Stack manipulation. - public void emitPOP() { emit(JOpcode.POP); } - public void emitPOP2() { emit(JOpcode.POP2); } - public void emitDUP() { emit(JOpcode.DUP); } - public void emitDUP_X1() { emit(JOpcode.DUP_X1); } - public void emitDUP_X2() { emit(JOpcode.DUP_X2); } - public void emitDUP2() { emit(JOpcode.DUP2); } - public void emitDUP2_X1() { emit(JOpcode.DUP2_X1); } - public void emitDUP2_X2() { emit(JOpcode.DUP2_X2); } - public void emitSWAP() { emit(JOpcode.SWAP); } - - // Artithmetic and logic operations. - public void emitIADD() { emit(JOpcode.IADD); } - public void emitLADD() { emit(JOpcode.LADD); } - public void emitFADD() { emit(JOpcode.FADD); } - public void emitDADD() { emit(JOpcode.DADD); } - - public void emitISUB() { emit(JOpcode.ISUB); } - public void emitLSUB() { emit(JOpcode.LSUB); } - public void emitFSUB() { emit(JOpcode.FSUB); } - public void emitDSUB() { emit(JOpcode.DSUB); } - - public void emitIMUL() { emit(JOpcode.IMUL); } - public void emitLMUL() { emit(JOpcode.LMUL); } - public void emitFMUL() { emit(JOpcode.FMUL); } - public void emitDMUL() { emit(JOpcode.DMUL); } - - public void emitIDIV() { emit(JOpcode.IDIV); } - public void emitLDIV() { emit(JOpcode.LDIV); } - public void emitFDIV() { emit(JOpcode.FDIV); } - public void emitDDIV() { emit(JOpcode.DDIV); } - - public void emitIREM() { emit(JOpcode.IREM); } - public void emitLREM() { emit(JOpcode.LREM); } - public void emitFREM() { emit(JOpcode.FREM); } - public void emitDREM() { emit(JOpcode.DREM); } - - public void emitINEG() { emit(JOpcode.INEG); } - public void emitLNEG() { emit(JOpcode.LNEG); } - public void emitFNEG() { emit(JOpcode.FNEG); } - public void emitDNEG() { emit(JOpcode.DNEG); } - - public void emitISHL() { emit(JOpcode.ISHL); } - public void emitLSHL() { emit(JOpcode.LSHL); } - - public void emitISHR() { emit(JOpcode.ISHR); } - public void emitLSHR() { emit(JOpcode.LSHR); } - - public void emitIUSHR() { emit(JOpcode.IUSHR); } - public void emitLUSHR() { emit(JOpcode.LUSHR); } - - public void emitIAND() { emit(JOpcode.IAND); } - public void emitLAND() { emit(JOpcode.LAND); } - - public void emitIOR() { emit(JOpcode.IOR); } - public void emitLOR() { emit(JOpcode.LOR); } - - public void emitIXOR() { emit(JOpcode.IXOR); } - public void emitLXOR() { emit(JOpcode.LXOR); } - - public void emitIINC(int index, int increment) { - emitU1U1(JOpcode.IINC, index, increment); - } - - // (Numeric) type conversions. - public void emitI2L() { emit(JOpcode.I2L); } - public void emitI2F() { emit(JOpcode.I2F); } - public void emitI2D() { emit(JOpcode.I2D); } - public void emitL2I() { emit(JOpcode.L2I); } - public void emitL2F() { emit(JOpcode.L2F); } - public void emitL2D() { emit(JOpcode.L2D); } - public void emitF2I() { emit(JOpcode.F2I); } - public void emitF2L() { emit(JOpcode.F2L); } - public void emitF2D() { emit(JOpcode.F2D); } - public void emitD2I() { emit(JOpcode.D2I); } - public void emitD2L() { emit(JOpcode.D2L); } - public void emitD2F() { emit(JOpcode.D2F); } - public void emitI2B() { emit(JOpcode.I2B); } - public void emitI2C() { emit(JOpcode.I2C); } - public void emitI2S() { emit(JOpcode.I2S); } - - // Comparisons and tests. - public void emitLCMP() { emit(JOpcode.LCMP); } - public void emitFCMPL() { emit(JOpcode.FCMPL); } - public void emitFCMPG() { emit(JOpcode.FCMPG); } - public void emitDCMPL() { emit(JOpcode.DCMPL); } - public void emitDCMPG() { emit(JOpcode.DCMPG); } - - protected void emitGenericIF(JOpcode opcode, Label label) - throws OffsetTooBigException { - emitU2(opcode, label.getOffset16(getPC() + 1, getPC())); - } - - public void emitIFEQ(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFEQ, label); - } - public void emitIFEQ(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFEQ, targetPC - getPC()); - } - public void emitIFEQ() { - emitU2(JOpcode.IFEQ, 0); - } - - public void emitIFNE(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFNE, label); - } - public void emitIFNE(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFNE, targetPC - getPC()); - } - public void emitIFNE() { - emitU2(JOpcode.IFNE, 0); - } - - public void emitIFLT(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFLT, label); - } - public void emitIFLT(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFLT, targetPC - getPC()); - } - public void emitIFLT() { - emitU2(JOpcode.IFLT, 0); - } - - public void emitIFGE(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFGE, label); - } - public void emitIFGE(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFGE, targetPC - getPC()); - } - public void emitIFGE() { - emitU2(JOpcode.IFGE, 0); - } - - public void emitIFGT(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFGT, label); - } - public void emitIFGT(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFGT, targetPC - getPC()); - } - public void emitIFGT() { - emitU2(JOpcode.IFGT, 0); - } - - public void emitIFLE(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFLE, label); - } - public void emitIFLE(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFLE, targetPC - getPC()); - } - public void emitIFLE() { - emitU2(JOpcode.IFLE, 0); - } - - public void emitIF_ICMPEQ(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ICMPEQ, label); - } - public void emitIF_ICMPEQ(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ICMPEQ, targetPC - getPC()); - } - public void emitIF_ICMPEQ() { - emitU2(JOpcode.IF_ICMPEQ, 0); - } - - public void emitIF_ICMPNE(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ICMPNE, label); - } - public void emitIF_ICMPNE(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ICMPNE, targetPC - getPC()); - } - public void emitIF_ICMPNE() { - emitU2(JOpcode.IF_ICMPNE, 0); - } - - public void emitIF_ICMPLT(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ICMPLT, label); - } - public void emitIF_ICMPLT(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ICMPLT, targetPC - getPC()); - } - public void emitIF_ICMPLT() { - emitU2(JOpcode.IF_ICMPLT, 0); - } - - public void emitIF_ICMPGE(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ICMPGE, label); - } - public void emitIF_ICMPGE(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ICMPGE, targetPC - getPC()); - } - public void emitIF_ICMPGE() { - emitU2(JOpcode.IF_ICMPGE, 0); - } - - public void emitIF_ICMPGT(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ICMPGT, label); - } - public void emitIF_ICMPGT(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ICMPGT, targetPC - getPC()); - } - public void emitIF_ICMPGT() { - emitU2(JOpcode.IF_ICMPGT, 0); - } - - public void emitIF_ICMPLE(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ICMPLE, label); - } - public void emitIF_ICMPLE(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ICMPLE, targetPC - getPC()); - } - public void emitIF_ICMPLE() { - emitU2(JOpcode.IF_ICMPLE, 0); - } - - public void emitIF_ACMPEQ(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ACMPEQ, label); - } - public void emitIF_ACMPEQ(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ACMPEQ, targetPC - getPC()); - } - public void emitIF_ACMPEQ() { - emitU2(JOpcode.IF_ACMPEQ, 0); - } - - public void emitIF_ACMPNE(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IF_ACMPNE, label); - } - public void emitIF_ACMPNE(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IF_ACMPNE, targetPC - getPC()); - } - public void emitIF_ACMPNE() { - emitU2(JOpcode.IF_ACMPNE, 0); - } - - public void emitIFNULL(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFNULL, label); - } - public void emitIFNULL(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFNULL, targetPC - getPC()); - } - public void emitIFNULL() { - emitU2(JOpcode.IFNULL, 0); - } - - public void emitIFNONNULL(Label label) throws OffsetTooBigException { - emitGenericIF(JOpcode.IFNONNULL, label); - } - public void emitIFNONNULL(int targetPC) throws OffsetTooBigException { - emitU2(JOpcode.IFNONNULL, targetPC - getPC()); - } - public void emitIFNONNULL() { - emitU2(JOpcode.IFNONNULL, 0); - } - - public void emitGOTO(Label label) throws OffsetTooBigException { - emitU2(JOpcode.GOTO, label.getOffset16(getPC() + 1, getPC())); - } - public void emitGOTO(int targetPC) throws OffsetTooBigException { - int offset = targetPC - getPC(); - checkOffset16(offset); - emitU2(JOpcode.GOTO, offset); - } - public void emitGOTO() { - emitU2(JOpcode.GOTO, 0); - } - - public void emitGOTO_W(Label label) { - emitU4(JOpcode.GOTO_W, label.getOffset32(getPC() + 1, getPC())); - } - public void emitGOTO_W(int targetPC) { - emitU4(JOpcode.GOTO_W, targetPC - getPC()); - } - public void emitGOTO_W() { - emitU4(JOpcode.GOTO_W, 0); - } - - public void emitJSR(Label label) throws OffsetTooBigException { - emitU2(JOpcode.JSR, label.getOffset16(getPC() + 1, getPC())); - } - public void emitJSR(int targetPC) { - emitU2(JOpcode.JSR, targetPC - getPC()); - } - public void emitJSR() { - emitU2(JOpcode.JSR, 0); - } - - public void emitJSR_W(Label label) { - emitU4(JOpcode.JSR_W, label.getOffset32(getPC() + 1, getPC())); - } - public void emitJSR_W(int targetPC) { - emitU4(JOpcode.JSR_W, targetPC - getPC()); - } - public void emitJSR_W() { - emitU4(JOpcode.JSR_W, 0); - } - - /* - public void emitRET(Label label) throws OffsetTooBigException { - emitU2(JOpcode.RET, label.getOffset16(getPC() + 1, getPC())); - } - public void emitRET(int targetPC) { - emitU1(JOpcode.RET, targetPC); - } - public void emitRET() { - emitU1(JOpcode.RET, 0); - } - */ - - public void emitRET(int index) { - emitU1(JOpcode.RET, index); - } - - public void emitRET(JLocalVariable var) { - emitRET(var.getIndex()); - } - - public void emitTABLESWITCH(int[] keys, - Label[] branches, - Label defaultBranch) { - assert keys.length == branches.length; - - int low = keys[0], high = keys[keys.length - 1]; - int instrPC = getPC(); - - setStackProduction(instrPC, JOpcode.TABLESWITCH); - codeArray.addU1(JOpcode.cTABLESWITCH); - while (getPC() % 4 != 0) codeArray.addU1(0); - - codeArray.addU4(defaultBranch.getOffset32(getPC(), instrPC)); - codeArray.addU4(low); - codeArray.addU4(high); - for (int i = 0; i < branches.length; i++) { - assert keys[i] == low + i; - codeArray.addU4(branches[i].getOffset32(getPC(), instrPC)); - } - } - - public void emitLOOKUPSWITCH(int[] keys, - Label[] branches, - Label defaultBranch) { - assert keys.length == branches.length; - - int instrPC = getPC(); - setStackProduction(getPC(), JOpcode.LOOKUPSWITCH); - codeArray.addU1(JOpcode.cLOOKUPSWITCH); - while (getPC() % 4 != 0) codeArray.addU1(0); - - codeArray.addU4(defaultBranch.getOffset32(getPC(), instrPC)); - codeArray.addU4(branches.length); - for (int i = 0; i < branches.length; i++) { - codeArray.addU4(keys[i]); - codeArray.addU4(branches[i].getOffset32(getPC(), instrPC)); - } - } - - public void emitIRETURN() { emit(JOpcode.IRETURN); } - public void emitLRETURN() { emit(JOpcode.LRETURN); } - public void emitFRETURN() { emit(JOpcode.FRETURN); } - public void emitDRETURN() { emit(JOpcode.DRETURN); } - public void emitARETURN() { emit(JOpcode.ARETURN); } - public void emitRETURN() { emit(JOpcode.RETURN); } - - // Field access - public void emitGETSTATIC(String className, String name, JType type) { - setStackProduction(getPC(), type.getSize()); - int index = pool.addFieldRef(className, name, type.getSignature()); - emitU2(JOpcode.GETSTATIC, index); - } - public void emitPUTSTATIC(String className, String name, JType type) { - setStackProduction(getPC(), -type.getSize()); - int index = pool.addFieldRef(className, name, type.getSignature()); - emitU2(JOpcode.PUTSTATIC, index); - } - public void emitGETFIELD(String className, String name, JType type) { - setStackProduction(getPC(), type.getSize() - 1); - int index = pool.addFieldRef(className, name, type.getSignature()); - emitU2(JOpcode.GETFIELD, index); - } - public void emitPUTFIELD(String className, String name, JType type) { - setStackProduction(getPC(), -(type.getSize() + 1)); - int index = pool.addFieldRef(className, name, type.getSignature()); - emitU2(JOpcode.PUTFIELD, index); - } - - // Method invocation - public void emitINVOKEVIRTUAL(String className, - String name, - JMethodType type) { - setStackProduction(getPC(), type.getProducedStack() - 1); - int index = - pool.addClassMethodRef(className, name, type.getSignature()); - emitU2(JOpcode.INVOKEVIRTUAL, index); - } - public void emitINVOKESPECIAL(String className, - String name, - JMethodType type) { - setStackProduction(getPC(), type.getProducedStack() - 1); - int index = - pool.addClassMethodRef(className, name, type.getSignature()); - emitU2(JOpcode.INVOKESPECIAL, index); - } - public void emitINVOKESTATIC(String className, - String name, - JMethodType type) { - setStackProduction(getPC(), type.getProducedStack()); - int index = - pool.addClassMethodRef(className, name, type.getSignature()); - emitU2(JOpcode.INVOKESTATIC, index); - } - public void emitINVOKEINTERFACE(String className, - String name, - JMethodType type) { - setStackProduction(getPC(), type.getProducedStack() - 1); - int index = - pool.addInterfaceMethodRef(className, name, type.getSignature()); - emitU2U1U1(JOpcode.INVOKEINTERFACE, index, type.getArgsSize() + 1, 0); - } - - // Object creation - public void emitNEW(String className) { - emitU2(JOpcode.NEW, pool.addClass(className)); - } - public void emitNEWARRAY(JType elemType) { - emitU1(JOpcode.NEWARRAY, elemType.getTag()); - } - public void emitANEWARRAY(JReferenceType elemType) { - emitU2(JOpcode.ANEWARRAY, pool.addDescriptor(elemType)); - } - public void emitMULTIANEWARRAY(JReferenceType elemType, int dimensions) { - setStackProduction(getPC(), -dimensions + 1); - emitU2U1(JOpcode.MULTIANEWARRAY, - pool.addDescriptor(elemType), - dimensions); - } - public void emitARRAYLENGTH() { emit(JOpcode.ARRAYLENGTH); } - - // Exception throwing - public void emitATHROW() { emit(JOpcode.ATHROW); } - - // Dynamic typing - public void emitCHECKCAST(JReferenceType type) { - emitU2(JOpcode.CHECKCAST, pool.addDescriptor(type)); - } - public void emitINSTANCEOF(JReferenceType type) { - emitU2(JOpcode.INSTANCEOF, pool.addDescriptor(type)); - } - - // Monitors - public void emitMONITORENTER() { emit(JOpcode.MONITORENTER); } - public void emitMONITOREXIT() { emit(JOpcode.MONITOREXIT); } - - // Wide variants - // FIXME setStackProd. will here raise an exception - public void emitWIDE(JOpcode opcode, int index) { - assert (opcode.code == JOpcode.cILOAD) - || (opcode.code == JOpcode.cLLOAD) - || (opcode.code == JOpcode.cFLOAD) - || (opcode.code == JOpcode.cDLOAD) - || (opcode.code == JOpcode.cALOAD) - || (opcode.code == JOpcode.cISTORE) - || (opcode.code == JOpcode.cLSTORE) - || (opcode.code == JOpcode.cFSTORE) - || (opcode.code == JOpcode.cDSTORE) - || (opcode.code == JOpcode.cASTORE) - || (opcode.code == JOpcode.cRET) - : "invalide opcode for WIDE: " + opcode; - - setStackProduction(getPC(), opcode); - codeArray.addU1(JOpcode.WIDE.code); - codeArray.addU1(opcode.code); - codeArray.addU2(index); - } - public void emitWIDE(JOpcode opcode, int index, int constant) { - assert opcode.code == JOpcode.cIINC - : "invalid opcode for WIDE: " + opcode; - - setStackProduction(getPC(), opcode); - codeArray.addU1(JOpcode.cWIDE); - codeArray.addU1(opcode.code); - codeArray.addU2(index); - codeArray.addU2(constant); - } - - protected void emitU1(JOpcode opcode, int i1) { - setStackProduction(getPC(), opcode); - codeArray.addU1(opcode.code); - codeArray.addU1(i1); - } - - protected void emitU1U1(JOpcode opcode, int i1, int i2) { - setStackProduction(getPC(), opcode); - codeArray.addU1(opcode.code); - codeArray.addU1(i1); - codeArray.addU1(i2); - } - - protected void emitU2(JOpcode opcode, int i1) { - setStackProduction(getPC(), opcode); - codeArray.addU1(opcode.code); - codeArray.addU2(i1); - } - - protected void emitU2U1(JOpcode opcode, int i1, int i2) { - setStackProduction(getPC(), opcode); - codeArray.addU1(opcode.code); - codeArray.addU2(i1); - codeArray.addU1(i2); - } - - protected void emitU2U1U1(JOpcode opcode, int i1, int i2, int i3) { - setStackProduction(getPC(), opcode); - codeArray.addU1(opcode.code); - codeArray.addU2(i1); - codeArray.addU1(i2); - codeArray.addU1(i3); - } - - protected void emitU4(JOpcode opcode, int i1) { - setStackProduction(getPC(), opcode); - codeArray.addU1(opcode.code); - codeArray.addU4(i1); - } - - protected int getU1(int sourcePos) { - return codeArray.getU1(sourcePos); - } - - protected int getU2(int sourcePos) { - return codeArray.getU2(sourcePos); - } - - protected int getU4(int sourcePos) { - return codeArray.getU4(sourcePos); - } - - protected int getS1(int sourcePos) { - return codeArray.getS1(sourcePos); - } - - protected int getS2(int sourcePos) { - return codeArray.getS2(sourcePos); - } - - protected int getS4(int sourcePos) { - return codeArray.getS4(sourcePos); - } - - // Stack size computation - ////////////////////////////////////////////////////////////////////// - - protected int getStackProduction(int pc) { - if (stackProduction == null || pc >= stackProduction.length) - return UNKNOWN_STACK_SIZE; - else - return stackProduction[pc]; - } - - protected void setStackProduction(int pc, int production) { - if (stackProduction == null) { - stackProduction = new int[256]; - Arrays.fill(stackProduction, UNKNOWN_STACK_SIZE); - } else { - while (pc >= stackProduction.length) { - int[] newStackProduction = new int[stackProduction.length * 2]; - System.arraycopy(stackProduction, 0, - newStackProduction, 0, - stackProduction.length); - Arrays.fill(newStackProduction, - stackProduction.length, - newStackProduction.length, - UNKNOWN_STACK_SIZE); - stackProduction = newStackProduction; - } - } - stackProduction[pc] = production; - } - - protected void setStackProduction(int pc, JOpcode opcode) { - // TODO we should instead check whether the opcode has known - // stack consumption/production. - if (getStackProduction(pc) == UNKNOWN_STACK_SIZE) -// && opcode.hasKnownProducedDataSize() -// && opcode.hasKnownConsumedDataSize()) - setStackProduction(pc, - opcode.getProducedDataSize() - - opcode.getConsumedDataSize()); - } - - protected int computeMaxStackSize() { - if (stackSizes == null) { - stackSizes = new int[getSize()]; - Arrays.fill(stackSizes, UNKNOWN_STACK_SIZE); - stackSizes[0] = 0; - } - int size = computeMaxStackSize(0, 0, 0); - - // compute stack sizes for exception handlers too - ExceptionHandler exh = null; - for (Iterator it = exceptionHandlers.iterator(); - it.hasNext();) { - exh = (ExceptionHandler)it.next(); - int exhSize = computeMaxStackSize(exh.getHandlerPC(), 1, 1); - if (size < exhSize) - size = exhSize; - } - - return size; - } - - protected int computeMaxStackSize(int pc, int stackSize, int maxStackSize) { - JCodeIterator iterator = new JCodeIterator(this, pc); - for (;;) { - int successors = iterator.getSuccessorCount(); - if (successors == 0) - return maxStackSize; - else { - assert stackProduction[iterator.getPC()] != UNKNOWN_STACK_SIZE - : "unknown stack production, pc=" + iterator.getPC() - + " in method " + owner.getName(); - stackSize += stackProduction[iterator.getPC()]; - if (stackSize > maxStackSize) - maxStackSize = stackSize; - int nextPC = -1; - for (int i = 0; i < successors; ++i) { - int succPC = iterator.getSuccessorPC(i); - assert succPC >= 0 && succPC < stackSizes.length - : iterator.getPC() + ": invalid pc: " + succPC - + " op: " + iterator.getOpcode(); - if (stackSizes[succPC] == UNKNOWN_STACK_SIZE) { - stackSizes[succPC] = stackSize; - if (nextPC == -1) - nextPC = succPC; - else - maxStackSize = computeMaxStackSize(succPC, - stackSize, - maxStackSize); - } - } - if (nextPC == -1) - return maxStackSize; - else - iterator.moveTo(nextPC); - } - } - } - - // Labels - ////////////////////////////////////////////////////////////////////// - - public static class OffsetTooBigException extends Exception { - public OffsetTooBigException() { super(); } - public OffsetTooBigException(String message) { super(message); } - } - - protected void checkOffset16(int offset) throws OffsetTooBigException { - if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) - throw new OffsetTooBigException("offset too big to fit" - + " in 16 bits: " + offset); - } - - public class Label { - protected boolean anchored = false; - protected int targetPC = 0; - - public void anchorToNext() { - assert !anchored; - this.targetPC = getPC(); - anchored = true; - } - - public int getAnchor() { - assert anchored; - return targetPC; - } - - protected int getOffset16(int pc, int instrPC) - throws OffsetTooBigException { - if (anchored) { - int offset = targetPC - instrPC; - checkOffset16(offset); - return offset; - } else { - recordOffsetToPatch(pc, 16, instrPC, this); - return 0; - } - } - - protected int getOffset32(int pc, int instrPC) { - if (anchored) - return targetPC - instrPC; - else { - recordOffsetToPatch(pc, 32, instrPC, this); - return 0; - } - } - } - - public Label newLabel() { - return new Label(); - } - - public Label[] newLabels(int count) { - Label[] labels = new Label[count]; - for (int i = 0; i < labels.length; ++i) - labels[i] = newLabel(); - return labels; - } - - protected static class OffsetToPatch { - public final int pc; - public final int size; - public final int instrPC; - public final Label label; - - public OffsetToPatch(int pc, int size, int instrPC, Label label) { - this.pc = pc; - this.size = size; - this.instrPC = instrPC; - this.label = label; - } - } - - protected void recordOffsetToPatch(int offsetPC, - int size, - int instrPC, - Label label) { - offsetToPatch.add(new OffsetToPatch(offsetPC, size, instrPC, label)); - } - - protected void patchAllOffset() throws OffsetTooBigException { - Iterator offsetIt = offsetToPatch.iterator(); - while (offsetIt.hasNext()) { - OffsetToPatch offset = (OffsetToPatch)offsetIt.next(); - int offsetValue = offset.label.getAnchor() - offset.instrPC; - if (offset.size == 16) { - checkOffset16(offsetValue); - codeArray.putU2(offset.pc, offsetValue); - } else - codeArray.putU4(offset.pc, offsetValue); - } - } - - // Exception handling - ////////////////////////////////////////////////////////////////////// - - public class ExceptionHandler { - protected int startPC, endPC, handlerPC; - protected final String catchType; - protected final int catchTypeIndex; - - public void setStartPC(int pc) { - this.startPC = pc; - } - - public int getStartPC() { - return this.startPC; - } - - public void setEndPC(int pc) { - this.endPC = pc; - } - - public int getEndPC() { - return this.endPC; - } - - public void setHandlerPC(int pc) { - this.handlerPC = pc; - } - - public int getHandlerPC() { - return this.handlerPC; - } - - public ExceptionHandler(String catchType) { - this(0, 0, 0, catchType); - } - - public ExceptionHandler(int startPC, - int endPC, - int handlerPC, - String catchType) { - this.startPC = startPC; - this.endPC = endPC; - this.handlerPC = handlerPC; - this.catchType = catchType; - this.catchTypeIndex = (catchType == null - ? 0 - : pool.addClass(catchType)); - } - - public ExceptionHandler(DataInputStream stream) throws IOException { - this.startPC = stream.readShort(); - this.endPC = stream.readShort(); - this.handlerPC = stream.readShort(); - this.catchTypeIndex = stream.readShort(); - this.catchType = (catchTypeIndex == 0 - ? null - : pool.lookupClass(catchTypeIndex)); - } - - public void writeTo(DataOutputStream stream) throws IOException { - stream.writeShort(startPC); - stream.writeShort(endPC); - stream.writeShort(handlerPC); - stream.writeShort(catchTypeIndex); - } - - // Follows javap output format for exception handlers. - /*@Override*/public String toString() { - StringBuffer buf = new StringBuffer(" "); - if (startPC < 10) buf.append(" "); - buf.append(startPC); - buf.append(" "); - if (endPC < 10) buf.append(" "); - buf.append(endPC); - buf.append(" "); - buf.append(handlerPC); - buf.append(" "); - if (catchType != null) { - buf.append("Class "); - buf.append(catchType); - } - else - buf.append("any"); - return buf.toString(); - } - - } - - public void addExceptionHandler(ExceptionHandler handler) { - assert !frozen; - exceptionHandlers.add(handler); - } - - public void addExceptionHandler(int startPC, - int endPC, - int handlerPC, - String catchType) { - addExceptionHandler(new ExceptionHandler(startPC, - endPC, - handlerPC, - catchType)); - } - - public void addFinallyHandler(int startPC, int endPC, int handlerPC) { - assert !frozen; - addExceptionHandler(startPC, endPC, handlerPC, null); - } - - public List/**/ getExceptionHandlers() { - return exceptionHandlers; - } - - // Line numbers - ////////////////////////////////////////////////////////////////////// - - protected int[] lineNumbers = null; - protected void ensureLineNumberCapacity(int endPC) { - assert !frozen; - if (lineNumbers == null) { - lineNumbers = new int[endPC]; - addAttribute(context.JLineNumberTableAttribute(owner.getOwner(), - this)); - } else if (lineNumbers.length < endPC) { - int[] newLN = new int[Math.max(endPC, lineNumbers.length * 2)]; - System.arraycopy(lineNumbers, 0, newLN, 0, lineNumbers.length); - lineNumbers = newLN; - } - } - - /** - * Set all line numbers in the interval [startPC, endPC) to - * line, overwriting existing line numbers. - */ - public void setLineNumber(int startPC, int endPC, int line) { - ensureLineNumberCapacity(endPC); - Arrays.fill(lineNumbers, startPC, endPC, line); - } - - public void setLineNumber(int instrPC, int line) { - setLineNumber(instrPC, instrPC + 1, line); - } - - /** Sets all non-filled line numbers in the interval [startPC, endPC) - * to 'line'. - */ - public void completeLineNumber(int startPC, int endPC, int line) { - ensureLineNumberCapacity(endPC); - for (int pc = startPC; pc < endPC; ++pc) - if (lineNumbers[pc] == 0) lineNumbers[pc] = line; - } - - public int[] getLineNumbers() { - assert frozen; - if (lineNumbers == null) return new int[0]; - else if (lineNumbers.length == getPC()) return lineNumbers; - else { - int[] trimmedLN = new int[getPC()]; - System.arraycopy(lineNumbers, 0, - trimmedLN, 0, - Math.min(lineNumbers.length, trimmedLN.length)); - return trimmedLN; - } - } - - // Output - ////////////////////////////////////////////////////////////////////// - - public void writeTo(DataOutputStream stream) throws IOException { - assert frozen; - stream.writeInt(getSize()); - codeArray.writeTo(stream); - } - - // Follows javap output format for opcodes. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(); - JOpcode opcode = null; - int pc = 0, addr = 0; - while (pc < codeArray.getSize()) { - buf.append("\n "); - buf.append(pc); - buf.append(":\t"); - opcode = JOpcode.OPCODES[codeArray.getU1(pc)]; - buf.append(decode(opcode, pc)); - if (opcode.code == JOpcode.cTABLESWITCH || - opcode.code == JOpcode.cLOOKUPSWITCH) { - addr = ((pc / 4 + 1) + 1) * 4; // U4 aligned data - int low = codeArray.getU4(addr); - int high = codeArray.getU4(addr+4); - pc = addr + (2/*low+high*/ + (high - low + 1)/*targets*/) * 4; - } else - pc += opcode.getSize(); - } - if (exceptionHandlers.size() > 0) { - buf.append("\n Exception table:\n from to target type\n"); - Iterator it = exceptionHandlers.iterator(); - while (it.hasNext()) { - ExceptionHandler exh = (ExceptionHandler)it.next(); - buf.append(exh); - buf.append("\n"); - } - } - return buf.toString(); - } - - private String decode(JOpcode opcode, int pc) { - String ownerClassName = owner.getOwner().getName(); - int data, data2; - StringBuilder buf = new StringBuilder(); - buf.append(opcode.name.toLowerCase()); - switch (opcode.code) { - case JOpcode.cALOAD: case JOpcode.cASTORE: case JOpcode.cBIPUSH: - case JOpcode.cDLOAD: case JOpcode.cDSTORE: - case JOpcode.cFLOAD: case JOpcode.cFSTORE: - case JOpcode.cILOAD: case JOpcode.cISTORE: - case JOpcode.cLLOAD: case JOpcode.cLSTORE: - data = codeArray.getU1(pc+1); - buf.append("\t"); - buf.append(data); - break; - case JOpcode.cLDC: - data = codeArray.getU1(pc+1); - buf.append("\t#"); - buf.append(data); - buf.append("; "); - buf.append(pool.lookupEntry(data).toComment(ownerClassName)); - break; - case JOpcode.cNEWARRAY: - data = codeArray.getU1(pc+1); - buf.append(" "); - buf.append(JType.tagToString(data)); - break; - case JOpcode.cIINC: - data = codeArray.getU1(pc+1); - data2 = codeArray.getU1(pc+2); - buf.append("\t"); - buf.append(data); - buf.append(", "); - buf.append(data2); - break; - case JOpcode.cSIPUSH: - data = codeArray.getU2(pc+1); - buf.append("\t"); - buf.append(data); - break; - case JOpcode.cANEWARRAY: case JOpcode.cCHECKCAST: - case JOpcode.cGETFIELD: case JOpcode.cGETSTATIC: - case JOpcode.cINSTANCEOF: - case JOpcode.cINVOKESPECIAL: case JOpcode.cINVOKESTATIC: - case JOpcode.cINVOKEVIRTUAL: - case JOpcode.cLDC_W: case JOpcode.cLDC2_W: case JOpcode.cNEW: - case JOpcode.cPUTFIELD: case JOpcode.cPUTSTATIC: - data = codeArray.getU2(pc+1); - buf.append("\t#"); - buf.append(data); - buf.append("; "); - buf.append(pool.lookupEntry(data).toComment(ownerClassName)); - break; - case JOpcode.cIF_ACMPEQ: case JOpcode.cIF_ACMPNE: - case JOpcode.cIFEQ: case JOpcode.cIFGE: case JOpcode.cIFGT: - case JOpcode.cIFLE: case JOpcode.cIFLT: case JOpcode.cIFNE: - case JOpcode.cIFNONNULL: case JOpcode.cIFNULL: - case JOpcode.cIF_ICMPEQ: case JOpcode.cIF_ICMPGE: - case JOpcode.cIF_ICMPGT: case JOpcode.cIF_ICMPLE: - case JOpcode.cIF_ICMPLT: case JOpcode.cIF_ICMPNE: - data = codeArray.getU2(pc+1); // maybe S2 offset - buf.append("\t"); - buf.append(pc+data); - break; - case JOpcode.cGOTO: - data = codeArray.getS2(pc+1); // always S2 offset - buf.append("\t"); - buf.append(pc+data); - break; - case JOpcode.cINVOKEINTERFACE: - data = codeArray.getU2(pc+1); - data2 = codeArray.getU1(pc+3); - buf.append("\t#"); - buf.append(data); - buf.append(", "); - buf.append(data2); - buf.append("; "); - buf.append(pool.lookupEntry(data).toComment(ownerClassName)); - break; - case JOpcode.cTABLESWITCH: - buf.append("{ //"); - int addr = ((pc / 4 + 1) + 1) * 4; // U4 aligned data - int low = codeArray.getU4(addr); - int high = codeArray.getU4(addr+4); - buf.append(low); - buf.append(" to "); - buf.append(high); - for (int i = low; i <= high; ++i) { - buf.append("\n\t\t"); - buf.append(i); - buf.append(": "); - buf.append(pc+codeArray.getU4(addr+(i-1)*4)); - buf.append(";"); - } - buf.append("\n\t\tdefault: "); - buf.append(pc+codeArray.getU4(addr-4)); - buf.append(" }"); - default: - } - return buf.toString(); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JCodeAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JCodeAttribute.java deleted file mode 100644 index 9f3fcf8c6a7d..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JCodeAttribute.java +++ /dev/null @@ -1,125 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.Iterator; -import java.util.List; - -/** - * Code attribute, containing code of methods. - * - * A Code attribute contains the JVM instructions and auxiliary information - * for a single method, instance initialization method, or class or interface - * initialization method. See section 4.8.3 of the JVM specification. - * - * @author Michel Schinz, Stephane Micheloud - * @version 1.1 - */ - -public class JCodeAttribute extends JAttribute { - protected final JCode code; - protected final JMethod owner; - protected static int UNKNOWN_STACK_SIZE = Integer.MIN_VALUE; - protected final int maxStackSize; - protected final int maxLocals; - - public JCodeAttribute(FJBGContext context, JClass clazz, JMethod owner) { - super(context, clazz); - this.owner = owner; - - this.maxStackSize = UNKNOWN_STACK_SIZE; - this.maxLocals = 0; // unknown - this.code = owner.getCode(); - - assert clazz == owner.getOwner(); - } - - public JCodeAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.owner = (JMethod)owner; - - this.maxStackSize = stream.readShort(); - this.maxLocals = stream.readShort(); - this.code = context.JCode(clazz, (JMethod)owner, stream); - - int handlersCount = stream.readShort(); - for (int i = 0; i < handlersCount; ++i) - code.addExceptionHandler(code.new ExceptionHandler(stream)); - List/**/ attributes = - JAttribute.readFrom(context, clazz, code, stream); - Iterator attrIt = attributes.iterator(); - while (attrIt.hasNext()) - code.addAttribute((JAttribute)attrIt.next()); - - assert name.equals(getName()); - } - - public String getName() { return "Code"; } - - // Follows javap output format for Code attribute. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" Code:"); - buf.append("\n Stack="); - buf.append(maxStackSize); - buf.append(", Locals="); - buf.append(maxLocals); - buf.append(", Args_size="); - buf.append(owner.getArgsSize()); - buf.append(code); - buf.append("\n"); - Iterator it = code.getAttributes().iterator(); - while (it.hasNext()) { - JAttribute attr = (JAttribute)it.next(); - buf.append(attr); - buf.append("\n"); - } - return buf.toString(); - } - - protected int getSize() { - int handlersNum = code.getExceptionHandlers().size(); - - int attrsSize = 0; - Iterator attrsIt = code.getAttributes().iterator(); - while (attrsIt.hasNext()) { - JAttribute attr = (JAttribute)attrsIt.next(); - attrsSize += attr.getSize() + 6; - } - - return 2 // max stack - + 2 // max locals - + 4 // code size - + code.getSize() // code - + 2 // exception table size - + 8 * handlersNum // exception table - + 2 // attributes count - + attrsSize; // attributes - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - List/**/ handlers = code.getExceptionHandlers(); - - stream.writeShort(code.getMaxStackSize()); - stream.writeShort(owner.getMaxLocals()); - - code.writeTo(stream); - - stream.writeShort(handlers.size()); - Iterator handlerIt = handlers.iterator(); - while (handlerIt.hasNext()) - ((JCode.ExceptionHandler)handlerIt.next()).writeTo(stream); - JAttribute.writeTo(code.getAttributes(), stream); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java b/src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java deleted file mode 100644 index d09dfd19a4f8..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JCodeIterator.java +++ /dev/null @@ -1,377 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import ch.epfl.lamp.util.ByteArray; - -/** - * Iterator used to examine the contents of an instruction list. - * - * @author Michel Schinz, Thomas Friedli - * @version 1.0 - */ - -public class JCodeIterator { - protected final JCode code; - protected final JConstantPool pool; - protected final ByteArray codeArray; - - protected int pc; - protected JOpcode opcode; - - /** - * Creates a new code iterator with its instruction list - * and its pc initialized to a given value. - */ - public JCodeIterator(JCode code, int pc) { - this.code = code; - this.pool = code.getOwner().getOwner().getConstantPool(); - this.codeArray = code.codeArray; - this.pc = pc; - setOpcode(); - } - - public JCodeIterator(JCode code) { - this(code, 0); - } - - /** - * Get the current program counter. - * @return The current program counter. - */ - public int getPC() { return pc; } - - /** - * Searches the type of the instruction positionned at the - * current address and updates the current instruction. - */ - protected void setOpcode() { - // TODO : check if the current pc is the beginning - // of an instruction - opcode = isValid() ? JOpcode.OPCODES[codeArray.getU1(pc)] : null; - } - - /** - * Returns the opcode of the current instruction. - * @return The opcode of the current instruction. - */ - public JOpcode getOpcode() { - return opcode; - } - - /** - * Updates the program counter to an given value. - * @param pc The new value of the program counter. - */ - public void moveTo(int pc) { - this.pc = pc; - setOpcode(); - } - - /** - * Check the validity of the iterator. - * @return true iff the iterator points to a valid address. - */ - public boolean isValid() { - return pc < codeArray.getSize(); - } - - /** - * Updates the current instruction with the next one in the - * sense of their position in the code. - */ - public void moveToNext() { - moveTo(pc + getInstructionSize()); - } - - /** - * Updates the current instruction with a specific successor - * of it. - * @param succ The index of the wanted successor in the list of - * the successors of the current instruction. - */ - public void moveToSuccessor(int succ) { - moveTo(getSuccessorPC(succ)); - } - - /** - * Updates the current instruction with the one positionned - * at a given index relatively to the actual program counter - * @param offset The relative position of the instruction - * compared with the position of the current one - */ - public void moveRelatively(int offset) { - moveTo(pc + offset); - } - - /** - * Returns the size in bytes of the current instruction. - * @return The size in bytes of the current instruction. - */ - public int getInstructionSize() { - if (opcode.size != JOpcode.UNKNOWN) { - return opcode.size; - } else if (opcode == JOpcode.TABLESWITCH) { - int lowOffset = 1 + pad4(pc + 1) + 4; - int low = codeArray.getS4(pc + lowOffset); - int high = codeArray.getS4(pc + lowOffset + 4); - return lowOffset + 8 + 4 * (high - low + 1); - } else if (opcode == JOpcode.LOOKUPSWITCH) { - int npairsOffset = 1 + pad4(pc + 1) + 4; - int npairs = codeArray.getS4(pc + npairsOffset); - return npairsOffset + 4 + 8 * npairs; - } else if (opcode == JOpcode.WIDE) { - if (codeArray.getU1(pc + 1) == JOpcode.cIINC) - return 6; - else - return 4; - } else - throw new Error("Unknown size for instruction " + opcode); - } - - /** - * Returns the number of successors of the current instruction. - * @return The number of successors of the current instruction. - */ - public int getSuccessorCount() { - if (opcode.successorCount != JOpcode.UNKNOWN) { - return opcode.successorCount; - } else if (opcode == JOpcode.TABLESWITCH) { - int lowPos = pc + 1 + pad4(pc + 1) + 4; - return 1 // default case - + codeArray.getS4(lowPos + 4) // value of HIGH field - - codeArray.getS4(lowPos) + 1; // value of LOW field - } else if (opcode == JOpcode.LOOKUPSWITCH) { - int npairsPos = pc + 1 + pad4(pc + 1) + 4; - return 1 + codeArray.getS4(npairsPos); - } else - throw new Error("Unknown successors for instruction " + opcode); - } - - /** - * Returns the address of the successor of the current instruction - * given its index in the list of successors of the current - * instruction. - * @param index The index of the wanted successor in the list of - * the successors of the current instruction. - * @return The address of the specific successor. - */ - public int getSuccessorPC(int index) { - assert (index >= 0) && (index < getSuccessorCount()) : index; - - switch (opcode.jumpKind) { - case JOpcode.JMP_NEXT: - return pc + getInstructionSize(); - case JOpcode.JMP_ALWAYS_S2_OFFSET: - return pc + codeArray.getS2(pc + 1); - case JOpcode.JMP_ALWAYS_S4_OFFSET: - return pc + codeArray.getS4(pc + 1); - case JOpcode.JMP_MAYBE_S2_OFFSET: - if (index == 0) - return pc + getInstructionSize(); - else - return pc + codeArray.getS2(pc + 1); - case JOpcode.JMP_TABLE: { - int defaultPos = pc + 1 + pad4(pc + 1); - if (index == 0) - return pc + codeArray.getS4(defaultPos); - else - return pc + codeArray.getS4(defaultPos + 3*4 + 4 * (index - 1)); - } - case JOpcode.JMP_LOOKUP: { - int defaultPos = pc + 1 + pad4(pc + 1); - if (index == 0) - return pc + codeArray.getS4(defaultPos); - else - return pc + codeArray.getS4(defaultPos + 2*4 + 4 + 8 * (index - 1)); - } - default: - throw new Error(); - } - } - - /** - * Returns the total size of data words put on the stack by the current - * instruction. - * @return The total size of data words put on the stack by the current - * instruction. - */ - public int getProducedDataSize() { - if (opcode.getProducedDataTypes() == JOpcode.UNKNOWN_TYPE) { - switch (opcode.code) { - case JOpcode.cLDC: case JOpcode.cLDC_W: case JOpcode.cBALOAD: - return 1; - case JOpcode.cLDC2_W: case JOpcode.cDUP: case JOpcode.cSWAP: - return 2; - case JOpcode.cDUP_X1: - return 3; - case JOpcode.cDUP_X2: case JOpcode.cDUP2: - return 4; - case JOpcode.cDUP2_X1: - return 5; - case JOpcode.cDUP2_X2: - return 6; - case JOpcode.cGETSTATIC: case JOpcode.cGETFIELD: { - JConstantPool.FieldOrMethodRefEntry entry = - (JConstantPool.FieldOrMethodRefEntry) - pool.lookupEntry(codeArray.getU2(pc + 1)); - return JType.parseSignature(entry.getSignature()).getSize(); - } - case JOpcode.cWIDE : { - int op = codeArray.getU1(pc + 1); - if (op >= JOpcode.cILOAD && op <= JOpcode.cALOAD) { - JOpcode opcode2 = JOpcode.OPCODES[op]; - return JType.getTotalSize(opcode2.getProducedDataTypes()); - } else if (op >= JOpcode.cISTORE && op <= JOpcode.cASTORE) - return 0; - else return 0; // (IINC) - } - default : - throw new Error(opcode.toString()); - } - } else - return JType.getTotalSize(opcode.getProducedDataTypes()); - } - - /** - * Returns the total size of data words taken from the stack by the current - * instruction. - * @return The total size of data words taken from the stack by the current - * instruction. - */ - public int getConsumedDataSize() { - if (opcode.getConsumedDataTypes() != JOpcode.UNKNOWN_TYPE) - return JType.getTotalSize(opcode.getConsumedDataTypes()); - else { - switch (opcode.code) { - case JOpcode.cPOP: case JOpcode.cDUP: - return 1; - case JOpcode.cPOP2: case JOpcode.cSWAP: - case JOpcode.cDUP_X1: case JOpcode.cDUP2: - return 2; - case JOpcode.cDUP_X2: case JOpcode.cDUP2_X1: - return 3; - case JOpcode.cDUP2_X2: - return 4; - case JOpcode.cPUTSTATIC: case JOpcode.cPUTFIELD: { - JConstantPool.FieldOrMethodRefEntry entry = - (JConstantPool.FieldOrMethodRefEntry) - pool.lookupEntry(codeArray.getU2(pc + 1)); - return JType.parseSignature(entry.getSignature()).getSize(); - } - case JOpcode.cINVOKEVIRTUAL: case JOpcode.cINVOKESPECIAL: - case JOpcode.cINVOKESTATIC: case JOpcode.cINVOKEINTERFACE : { - JConstantPool.FieldOrMethodRefEntry entry = - (JConstantPool.FieldOrMethodRefEntry) - pool.lookupEntry(codeArray.getU2(pc + 1)); - JMethodType tp = (JMethodType) - JType.parseSignature(entry.getSignature()); - return tp.getArgsSize() - + (opcode == JOpcode.INVOKESTATIC ? 0 : 1); - } - case JOpcode.cWIDE : { - int op = codeArray.getU1(pc + 1); - if (op >= JOpcode.cILOAD && op <= JOpcode.cALOAD) - return 0; - else if (op >= JOpcode.cISTORE && op <= JOpcode.cASTORE) { - JOpcode opcode2 = JOpcode.OPCODES[op]; - return JType.getTotalSize(opcode2.getConsumedDataTypes()); - } else - return 0; // (IINC) - } - case JOpcode.cMULTIANEWARRAY : - return codeArray.getU1(pc + 3); - default: - throw new Error(opcode.toString()); - } - } - } - - /** - * Returns the number of data types put on the stack by the current - * instruction. - * @return The number of data types put on the stack by the current - * instruction. - */ - public int getProducedDataTypesNumber() { - if (opcode.getProducedDataTypes() != JOpcode.UNKNOWN_TYPE) - return opcode.getProducedDataTypes().length; - else { - switch (opcode.code) { - case JOpcode.cLDC: case JOpcode.cLDC_W: case JOpcode.cLDC2_W: - case JOpcode.cBALOAD: case JOpcode.cGETSTATIC: - case JOpcode.cGETFIELD: - return 1; - case JOpcode.cDUP: case JOpcode.cSWAP: - return 2; - case JOpcode.cDUP_X1: - return 3; - case JOpcode.cWIDE: { - int op = codeArray.getU1(pc + 1); - if (op >= JOpcode.cILOAD && op <= JOpcode.cALOAD) - return 1; - else if (op >= JOpcode.cISTORE && op <= JOpcode.cASTORE) - return 0; - else - return 0; // (IINC) - } - default: - throw new Error("JOpcode implementation error"); - } - } - } - - /** - * Returns the number of data types taken from the stack by the current - * instruction. - * @return The number of data types taken from the stack by the current - * instruction. - */ -// public int getConsumedDataTypesNumber() { -// if (opcode.getConsumedDataTypes() == JOpcode.UNKNOWN_TYPE) { -// switch (opcode.code) { -// case 87 : return 1; // POP -// case 88 : return 2; // POP2 -// case 89 : return 1; // DUP -// case 90 : return 2; // DUP_X1 -// case 91 : // DUP_X2 -// case 92 : // DUP2 -// case 93 : // DUP2_X1 -// case 94 : // DUP2_X2 -// throw new UnsupportedOperationException("Opcode " + opcode.name -// + " has a stack-dependant" -// + " data types consumption"); -// case 95 : return 2; // SWAP -// case 179 : return 1; // PUTSTATIC -// case 181 : return 1; // PUTFIELD -// case 182 : // INVOKEVIRTUAL -// case 183 : // INVOKESPECIAL -// case 185 : // INVOKEINTERFACE -// s = epool.getClassMethodRef(codeArray.getU2(pc + 1)).split(" ")[3]; -// return ((JMethodType)JType.parseSignature(s)).argTypes.length + 1; -// case 184 : // INVOKESTATIC -// s = epool.getClassMethodRef(codeArray.getU2(pc + 1)).split(" ")[3]; -// return ((JMethodType)JType.parseSignature(s)).argTypes.length; -// case 196 : // WIDE -// int op = codeArray.getU1(pc + 1); -// if (op >= 21 && op <= 25) return 0; // (xLOAD) -// else if (op >= 54 && op <= 58) // (xSTORE) -// return JOpcode.OPCODES[op].getConsumedDataTypes().length; -// else return 0; // (IINC) -// case 197 : return codeArray.getU1(pc + 3); // MULTIANEWARRAY -// default : throw new Error("JOpcode implementation error"); -// } -// } else return opcode.getConsumedDataTypes().length; -// } - - - // Return the number between 0 and 3 which, if added to the given - // value, would yield a multiple of 4. - protected int[] padding = { 0, 3, 2, 1 }; - protected int pad4(int value) { - return padding[value % 4]; - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java b/src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java deleted file mode 100644 index 9867e01b2521..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JConstantPool.java +++ /dev/null @@ -1,771 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.HashMap; - -/** - * Constant pool, holding constants for a Java class file. - * - * @author Michel Schinz - * @version 2.0 - */ - -public class JConstantPool { - protected boolean frozen = false; - - protected HashMap/**/ entryToIndex = new HashMap(); - protected Entry[] indexToEntry; - protected int currIndex; - - public static final short CONSTANT_Utf8 = 1; - public static final short CONSTANT_Integer = 3; - public static final short CONSTANT_Float = 4; - public static final short CONSTANT_Long = 5; - public static final short CONSTANT_Double = 6; - public static final short CONSTANT_Class = 7; - public static final short CONSTANT_String = 8; - public static final short CONSTANT_Fieldref = 9; - public static final short CONSTANT_Methodref = 10; - public static final short CONSTANT_InterfaceMethodref = 11; - public static final short CONSTANT_NameAndType = 12; - - protected JConstantPool(FJBGContext context) { - indexToEntry = new Entry[8]; - currIndex = 1; - } - - protected JConstantPool(FJBGContext context, DataInputStream stream) - throws IOException { - int count = stream.readShort(); - indexToEntry = new EntryIndex[count]; - - currIndex = 1; - while (currIndex < count) { - EntryIndex e; - int tag = stream.readByte(); - - switch (tag) { - case CONSTANT_Utf8: - e = new Utf8Entry(stream); - // no duplicates - entryToIndex.put(e, new Integer(currIndex)); - break; - case CONSTANT_Integer: - e = new IntegerEntry(stream); - break; - case CONSTANT_Float: - e = new FloatEntry(stream); - break; - case CONSTANT_Long: - e = new LongEntry(stream); - break; - case CONSTANT_Double: - e = new DoubleEntry(stream); - break; - case CONSTANT_Class: - e = new DescriptorEntryIndex(stream); - break; - case CONSTANT_String: - e = new StringEntryIndex(stream); - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - e = new FieldOrMethodRefEntryIndex(tag, stream); - break; - case CONSTANT_NameAndType: - e = new NameAndTypeEntryIndex(stream); - break; - default: - throw new IllegalArgumentException("unknown entry in pool: " + tag); - } - indexToEntry[currIndex] = e; - currIndex += e.getSize(); - } - } - - public void freeze() { frozen = true; } - - /** - * Returns a string representing the type of an entry - * knowing its tag - * @param tag The tag representing the type of the - * constant pool entry - */ - public String getEntryType(int tag) { - switch (tag) { - case CONSTANT_Utf8 : return "Utf8"; - case CONSTANT_Integer : return "Integer"; - case CONSTANT_Float : return "Float"; - case CONSTANT_Long : return "Long"; - case CONSTANT_Double : return "Double"; - case CONSTANT_Class : return "Class"; - case CONSTANT_String : return "String"; - case CONSTANT_Fieldref : return "Field"; - case CONSTANT_Methodref : return "Method"; - case CONSTANT_InterfaceMethodref : return "InterfaceMethod"; - case CONSTANT_NameAndType : return "NameAndType"; - default : throw new Error("invalid constant pool tag : " + tag); - } - } - - public int addClass(String className) { - return addDescriptor(className.replace('.', '/')); - } - - public int addDescriptor(JReferenceType type) { - return addDescriptor(type.getDescriptor()); - } - - protected int addDescriptor(String name) { - return addEntry(new DescriptorEntryValue(name)); - } - - public int addClassMethodRef(String className, - String methodName, - String signature) { - return addMethodRef(true, className, methodName, signature); - } - - public int addInterfaceMethodRef(String className, - String methodName, - String signature) { - return addMethodRef(false, className, methodName, signature); - } - - public int addMethodRef(boolean isClass, - String className, - String methodName, - String signature) { - return addEntry(new FieldOrMethodRefEntryValue(isClass - ? CONSTANT_Methodref - : CONSTANT_InterfaceMethodref, - className, - methodName, - signature)); - } - - public int addFieldRef(String className, - String fieldName, - String signature) { - return addEntry(new FieldOrMethodRefEntryValue(CONSTANT_Fieldref, - className, - fieldName, - signature)); - } - - public int addInteger(int value) { - return addEntry(new IntegerEntry(value)); - } - - public int addFloat(float value) { - return addEntry(new FloatEntry(value)); - } - - public int addLong(long value) { - return addEntry(new LongEntry(value)); - } - - public int addDouble(double value) { - return addEntry(new DoubleEntry(value)); - } - - public int addString(String value) { - return addEntry(new StringEntryValue(value)); - } - - public int addNameAndType(String name, String descriptor) { - return addEntry(new NameAndTypeEntryValue(name, descriptor)); - } - - public int addUtf8(String value) { - return addEntry(new Utf8Entry(value)); - } - - public int addUtf8(byte[] value) { - return addEntry(new Utf8Entry(value)); - } - - protected int addEntry(EntryValue e) { - assert !frozen; - Integer idx = (Integer)entryToIndex.get(e); - if (idx != null) - return idx.intValue(); - - e.addChildren(); - - int index = currIndex; - currIndex += e.getSize(); - - entryToIndex.put(e, new Integer(index)); - if (index >= indexToEntry.length) { - Entry[] newI2E = new Entry[indexToEntry.length * 2]; - System.arraycopy(indexToEntry, 0, newI2E, 0, indexToEntry.length); - indexToEntry = newI2E; - } - indexToEntry[index] = e; - return index; - } - - /// Lookup methods - ////////////////////////////////////////////////////////////////////// - - public Entry lookupEntry(int index) { - assert index > 0 && index < currIndex - : "invalid index: " + index; - assert indexToEntry[index] != null - : "invalid index (null contents): " + index; - return indexToEntry[index]; - } - - public String lookupClass(int index) { - DescriptorEntry entry = (DescriptorEntry)lookupEntry(index); - return entry.getValue(); - } - - public String lookupNameAndType(int index) { - NameAndTypeEntry entry = (NameAndTypeEntry)lookupEntry(index); - return entry.getName()+":"+entry.getDescriptor(); - } - - public String lookupUtf8(int index) { - Utf8Entry entry = (Utf8Entry)lookupEntry(index); - return entry.getValue(); - } - - /// Output - ////////////////////////////////////////////////////////////////////// - - public void writeTo(DataOutputStream stream) throws IOException { - if (! frozen) freeze(); - - stream.writeShort(currIndex); - for (int i = 0; i < currIndex; ++i) { - Entry entry = indexToEntry[i]; - if (entry != null) { - stream.writeByte(entry.getTag()); - entry.writeContentsTo(stream); - } - } - } - - // Follows javap output format for constant pool. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" Constant pool:"); - for (int i = 0; i < currIndex; ++i) { - Entry entry = indexToEntry[i]; - if (entry != null) { - if (i > 0) buf.append("\n"); - buf.append("const #"); - buf.append(i); - buf.append(" = "); - buf.append(entry); - } - } - buf.append("\n"); - return buf.toString(); - } - - /// Classes for the various kinds of entries - ////////////////////////////////////////////////////////////////////// - - public interface Entry { - public int getTag(); - - int getSize(); - void writeContentsTo(DataOutputStream stream) throws IOException; - String toComment(String ownerClassName); - } - - protected interface EntryValue extends Entry { - abstract void addChildren(); - } - - protected interface EntryIndex extends Entry { - abstract void fetchChildren(); - } - - abstract protected class ChildlessEntry implements EntryValue, EntryIndex { - public void addChildren() {} - public void fetchChildren() {} - } - - public class IntegerEntry extends ChildlessEntry implements Entry { - private final int value; - public IntegerEntry(int value) { this.value = value; } - public IntegerEntry(DataInputStream stream) throws IOException { - this(stream.readInt()); - } - - public int hashCode() { return value; } - public boolean equals(Object o) { - return o instanceof IntegerEntry && ((IntegerEntry)o).value == value; - } - - public int getTag() { return CONSTANT_Integer; } - public int getValue() { return value; } - - public int getSize() { return 1; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeInt(value); - } - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer("int\t"); - buf.append(getValue()); - buf.append(";"); - return buf.toString(); - } - public String toComment(String ownerClassname) { - return "//int "+getValue(); - } - } - - public class FloatEntry extends ChildlessEntry implements Entry { - private final float value; - public FloatEntry(float value) { this.value = value; } - public FloatEntry(DataInputStream stream) throws IOException { - this(stream.readFloat()); - } - - public int hashCode() { return (int)value; } - public boolean equals(Object o) { - return o instanceof FloatEntry && ((FloatEntry)o).value == value; - } - - public int getTag() { return CONSTANT_Float; } - public float getValue() { return value; } - - public int getSize() { return 1; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeFloat(value); - } - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer("float\t"); - buf.append(getValue()); - buf.append("f"); - return buf.toString(); - } - public String toComment(String ownerClassname) { - return "//float "+getValue()+"f"; - } - } - - public class LongEntry extends ChildlessEntry implements Entry { - private final long value; - public LongEntry(long value) { this.value = value; } - public LongEntry(DataInputStream stream) throws IOException { - this(stream.readLong()); - } - - public int hashCode() { return (int)value; } - public boolean equals(Object o) { - return o instanceof LongEntry && ((LongEntry)o).value == value; - } - - public int getTag() { return CONSTANT_Long; } - public long getValue() { return value; } - - public int getSize() { return 2; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeLong(value); - } - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer("long\t"); - buf.append(getValue()); - buf.append("l;"); - return buf.toString(); - } - public String toComment(String ownerClassname) { - return "//long "+getValue()+"l"; - } - } - - public class DoubleEntry extends ChildlessEntry implements Entry { - private final double value; - public DoubleEntry(double value) { this.value = value; } - public DoubleEntry(DataInputStream stream) throws IOException { - this(stream.readDouble()); - } - - public int hashCode() { return (int)value; } - public boolean equals(Object o) { - return o instanceof DoubleEntry && ((DoubleEntry)o).value == value; - } - - public int getTag() { return CONSTANT_Double; } - public double getValue() { return value; } - - public int getSize() { return 2; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeDouble(value); - } - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer("double\t"); - buf.append(getValue()); - return buf.toString(); - } - public String toComment(String ownerClassname) { - return "//double "+getValue(); - } - } - - public class Utf8Entry extends ChildlessEntry implements Entry { - private final String value; - private final byte[] bytes; - public Utf8Entry(String value) { - this.value = value.intern(); - this.bytes = null; - } - public Utf8Entry(DataInputStream stream) throws IOException { - this(stream.readUTF()); - } - public Utf8Entry(byte[] bytes) { - this.bytes = bytes; - this.value = null; - } - - public int hashCode() { - if (bytes != null) return bytes.hashCode(); - return value.hashCode(); - } - public boolean equals(Object o) { - boolean isEqual = o instanceof Utf8Entry; - if (bytes != null) { - isEqual = isEqual && ((Utf8Entry)o).bytes == bytes; - } - else { - isEqual = isEqual && ((Utf8Entry)o).value == value; - } - return isEqual; - } - - public int getTag() { return CONSTANT_Utf8; } - public String getValue() { return value; } - public byte[] getBytes() { return bytes; } - - public int getSize() { return 1; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - if (bytes != null) { - if (bytes.length > 65535) { - throw new IOException("String literal of length " + bytes.length + " does not fit in Classfile"); - } - stream.writeShort(bytes.length); - stream.write(bytes); - } - else - stream.writeUTF(value); - } - // Follows javap output format for Utf8 pool entries. - public String toString() { return "Asciz\t"+escaped(getValue())+";"; } - public String toComment(String ownerClassname) { - return "//Asciz "+escaped(getValue()); - } - private String escaped(String s) { - return s.replace("\n", "\\n"); - } - } - - abstract public class StringEntry implements Entry { - protected String value; - protected int valueIndex; - - public int hashCode() { - assert value != null; - return value.hashCode(); - } - public boolean equals(Object o) { - return o instanceof StringEntry && ((StringEntry)o).value == value; - } - - public int getTag() { return CONSTANT_String; } - public String getValue() { return value; } - - public int getSize() { return 1; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(valueIndex); - } - // Follows javap output format for String pool entries. - public String toString() { - return "String\t#"+valueIndex+";\t// "+escaped(getValue()); - } - public String toComment(String ownerClassname) { - return "//String "+escaped(getValue()); - } - private String escaped(String s) { - return s.replace("\n", "\\n"); - } - } - - public class StringEntryValue extends StringEntry implements EntryValue { - public StringEntryValue(String value) { - this.value = value.intern(); - } - public void addChildren() { - valueIndex = addUtf8(value); - } - } - - public class StringEntryIndex extends StringEntry implements EntryIndex { - public StringEntryIndex(int valueIndex) { - this.valueIndex = valueIndex; - } - public StringEntryIndex(DataInputStream stream) throws IOException { - this(stream.readShort()); - } - public String getValue() { - if (value == null) fetchChildren(); - return super.getValue(); - } - public void fetchChildren() { - value = lookupUtf8(valueIndex); - } - } - - abstract public class DescriptorEntry implements Entry { - protected String name; - protected int nameIndex; - - public int hashCode() { - assert name != null; - return name.hashCode(); - } - public boolean equals(Object o) { - return o instanceof DescriptorEntry && ((DescriptorEntry)o).name == name; - } - - public int getTag() { return CONSTANT_Class; } - public String getValue() { return name; } - - public int getSize() { return 1; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(nameIndex); - } - // Follows javap output format for class pool entries. - public String toString() { - StringBuffer buf = new StringBuffer("class\t#"); - buf.append(nameIndex); - buf.append(";\t// "); - buf.append(getClassName()); - return buf.toString(); - } - public String toComment(String ownerClassname) { - return "//class "+getClassName(); - } - private String getClassName() { - StringBuffer buf = new StringBuffer(); - String value = getValue(); - if (value.startsWith("[")) buf.append("\""); - buf.append(value); - if (value.startsWith("[")) buf.append("\""); - return buf.toString(); - } - } - - protected class DescriptorEntryValue - extends DescriptorEntry - implements EntryValue { - public DescriptorEntryValue(String name) { this.name = name.intern(); } - public void addChildren() { - nameIndex = addUtf8(name); - } - } - - protected class DescriptorEntryIndex - extends DescriptorEntry - implements EntryIndex { - public DescriptorEntryIndex(int nameIndex) { this.nameIndex = nameIndex; } - public DescriptorEntryIndex(DataInputStream stream) throws IOException { - this(stream.readShort()); - } - public String getValue() { - if (name == null) fetchChildren(); - return super.getValue(); - } - public void fetchChildren() { - name = lookupUtf8(nameIndex); - } - } - - abstract public class FieldOrMethodRefEntry implements Entry { - private final int tag; - protected String className, thingName, signature; - protected int classIndex, nameAndTypeIndex; - - public FieldOrMethodRefEntry(int tag) { - assert tag == CONSTANT_Fieldref - || tag == CONSTANT_Methodref - || tag == CONSTANT_InterfaceMethodref; - - this.tag = tag; - } - - public int hashCode() { - return tag - + className.hashCode() - + thingName.hashCode() - + signature.hashCode(); - } - public boolean equals(Object o) { - return o instanceof FieldOrMethodRefEntry - && ((FieldOrMethodRefEntry)o).tag == tag - && ((FieldOrMethodRefEntry)o).className == className - && ((FieldOrMethodRefEntry)o).thingName == thingName - && ((FieldOrMethodRefEntry)o).signature == signature; - } - - public int getTag() { return tag; } - public String getClassName() { return className; } - public String getFieldOrMethodName() { return thingName; } - public String getSignature() { return signature; } - - public int getSize() { return 1; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(classIndex); - stream.writeShort(nameAndTypeIndex); - } - // Follows javap output format for field/method pool entries. - public String toString() { - return getEntryType(tag)+"\t#"+classIndex+".#"+nameAndTypeIndex+ - ";\t// "+getName("")+":"+signature; - } - public String toComment(String ownerClassName) { - return "//"+getEntryType(tag)+" "+getName(ownerClassName)+":"+signature; - } - private String getName(String ownerClassName) { - String name = getFieldOrMethodName(); - if (JMethod.INSTANCE_CONSTRUCTOR_NAME.equals(name)) - name = "\""+name+"\""; - if (!getClassName().equals(ownerClassName)) - name = getClassName()+"."+name; - return name; - } - } - - protected class FieldOrMethodRefEntryValue - extends FieldOrMethodRefEntry - implements EntryValue { - public FieldOrMethodRefEntryValue(int tag, - String className, - String thingName, - String signature) { - super(tag); - this.className = className.intern(); - this.thingName = thingName.intern(); - this.signature = signature.intern(); - } - - public void addChildren() { - classIndex = addClass(className); - nameAndTypeIndex = addNameAndType(thingName, signature); - } - } - - protected class FieldOrMethodRefEntryIndex - extends FieldOrMethodRefEntry - implements EntryIndex { - public FieldOrMethodRefEntryIndex(int tag, - int classIndex, - int nameAndTypeIndex) { - super(tag); - this.classIndex = classIndex; - this.nameAndTypeIndex = nameAndTypeIndex; - } - public FieldOrMethodRefEntryIndex(int tag, DataInputStream stream) - throws IOException { - this(tag, stream.readShort(), stream.readShort()); - } - public String getClassName() { - if (className == null) fetchChildren(); - return super.getClassName(); - } - public String getFieldOrMethodName() { - if (thingName == null) fetchChildren(); - return super.getFieldOrMethodName(); - } - public String getSignature() { - if (signature == null) fetchChildren(); - return super.getSignature(); - } - public void fetchChildren() { - className = lookupClass(classIndex); - NameAndTypeEntry nat = (NameAndTypeEntry)lookupEntry(nameAndTypeIndex); - thingName = nat.getName(); - signature = nat.getDescriptor(); - } - } - - abstract public class NameAndTypeEntry implements Entry { - protected String name, descriptor; - protected int nameIndex, descriptorIndex; - - public int hashCode() { return name.hashCode() + descriptor.hashCode(); } - public boolean equals(Object o) { - return o instanceof NameAndTypeEntry - && ((NameAndTypeEntry)o).name == name - && ((NameAndTypeEntry)o).descriptor == descriptor; - } - - public int getTag() { return CONSTANT_NameAndType; } - public String getName() { return name; } - public String getDescriptor() { return descriptor; } - - public int getSize() { return 1; } - public void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(nameIndex); - stream.writeShort(descriptorIndex); - } - // Follows javap output format for name/type pool entries. - public String toString() { - String natName = getName(); - if (JMethod.INSTANCE_CONSTRUCTOR_NAME.equals(natName)) - natName = "\""+natName+"\""; - return "NameAndType\t#"+nameIndex+":#"+descriptorIndex+ - ";// "+natName+":"+getDescriptor(); - } - public String toComment(String ownerClassname) { return ""; } - } - - protected class NameAndTypeEntryValue - extends NameAndTypeEntry - implements EntryValue { - public NameAndTypeEntryValue(String name, String descriptor) { - this.name = name.intern(); - this.descriptor = descriptor.intern(); - } - public void addChildren() { - nameIndex = addUtf8(name); - descriptorIndex = addUtf8(descriptor); - } - } - - protected class NameAndTypeEntryIndex - extends NameAndTypeEntry - implements EntryIndex { - public NameAndTypeEntryIndex(int nameIndex, int descriptorIndex) { - this.nameIndex = nameIndex; - this.descriptorIndex = descriptorIndex; - } - public NameAndTypeEntryIndex(DataInputStream stream) throws IOException { - this(stream.readShort(), stream.readShort()); - } - public String getName() { - if (name == null) fetchChildren(); - return super.getName(); - } - public String getDescriptor() { - if (descriptor == null) fetchChildren(); - return super.getDescriptor(); - } - public void fetchChildren() { - name = lookupUtf8(nameIndex); - descriptor = lookupUtf8(descriptorIndex); - } - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JConstantValueAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JConstantValueAttribute.java deleted file mode 100644 index 6ee05e43c7e7..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JConstantValueAttribute.java +++ /dev/null @@ -1,69 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * ConstantValue attribute representing the value of a constant field. - * - * There can be no more than one ConstantValue attribute in the attributes - * table of a given field_info structure.. See section 4.8.2 of the JVM - * specification. - * - * @author Stephane Micheloud - * @version 1.0 - */ - -public class JConstantValueAttribute extends JAttribute { - /** Constant pool of the current classfile. */ - private JConstantPool pool; - - protected int constantValueIndex; - - public JConstantValueAttribute(FJBGContext context, - JClass clazz, - JField field) { - super(context, clazz); - this.pool = clazz.pool; - - assert field.getOwner() == clazz; - } - - public JConstantValueAttribute(FJBGContext context, - JClass clazz, - Object owner, // JField - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.pool = clazz.pool; - - this.constantValueIndex = stream.readShort(); - - assert name.equals(getName()); - } - - public String getName() { return "ConstantValue"; } - - // Follows javap output format for ConstantValue attribute. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" Constant value: "); - buf.append(pool.lookupEntry(constantValueIndex)); - return buf.toString(); - } - - protected int getSize() { - return 2; // Short.SIZE - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(constantValueIndex); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JEnclosingMethodAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JEnclosingMethodAttribute.java deleted file mode 100644 index f663f00ae1df..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JEnclosingMethodAttribute.java +++ /dev/null @@ -1,83 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * EclosingMethod attribute - - * A class must have an EnclosingMethod attribute if and only if it is a - * local class or an anonymous class. A class may have no more than one - * EnclosingMethod attribute. See section 4.8.6 of the JVM specification. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JEnclosingMethodAttribute extends JAttribute { - /** Constant pool of the current classfile. */ - private JConstantPool pool; - - protected final int classIdx; - protected final int nameAndTypeIdx; - - public JEnclosingMethodAttribute(FJBGContext context, - JClass clazz, - String className, - String methodName, - JType methodType) { - super(context, clazz); - this.pool = clazz.pool; - - this.classIdx = pool.addClass(className); - this.nameAndTypeIdx = pool.addNameAndType(methodName, methodType.getSignature()); - } - - public JEnclosingMethodAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.pool = clazz.pool; - - this.classIdx = stream.readShort(); - this.nameAndTypeIdx = stream.readShort(); - - assert name.equals(getName()); - } - - public String getName() { return "EnclosingMethod"; } - - // Follows javap output format for EnclosingMethod attribute. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" EnclosingMethod:"); - buf.append("\n #"); - buf.append(classIdx); - if (nameAndTypeIdx != 0) { - buf.append(" of #"); - buf.append(nameAndTypeIdx); - } - buf.append(";\t// "); - buf.append(pool.lookupEntry(classIdx)); - buf.append("\n"); - return buf.toString(); - } - - protected int getSize() { - return 4; // 2 * Short.SIZE - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(classIdx); - stream.writeShort(nameAndTypeIdx); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JExceptionsAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JExceptionsAttribute.java deleted file mode 100644 index b91d0f2e93da..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JExceptionsAttribute.java +++ /dev/null @@ -1,90 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * Exceptions attribute - - * This table is used by compilers to indicate which Exceptions a method - * is declared to throw. See section 2.6.4 of the JVM specification. - * - * @author Stephane Micheloud - * @version 1.0 - */ - -public class JExceptionsAttribute extends JAttribute { - /** Constant pool of the current classfile. */ - private JConstantPool pool; - - protected int[] indexTable; - protected int count; - - public JExceptionsAttribute(FJBGContext context, - JClass clazz, - JMethod owner) { - super(context, clazz); - this.pool = clazz.pool; - - this.count = 0; - this.indexTable = new int[8]; // some size > count - - assert clazz == owner.getOwner(); - } - - public JExceptionsAttribute(FJBGContext context, - JClass clazz, - Object owner, //JMethod - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.pool = clazz.pool; - - this.count = stream.readShort(); - this.indexTable = new int[count]; - for (int i = 0; i < count; ++i) - indexTable[i] = stream.readShort(); - - assert name.equals(getName()); - } - - public void addEntry(int classIndex) { - if (count >= indexTable.length) { - int[] newIT = new int[indexTable.length * 2]; - System.arraycopy(indexTable, 0, newIT, 0, indexTable.length); - indexTable = newIT; - } - indexTable[count++] = classIndex; - } - - public String getName() { return "Exceptions"; } - - // Follows javap output format for Exceptions attribute. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" Exceptions: "); - for (int i = 0; i < indexTable.length; ++i) { - buf.append("\n throws "); - buf.append(JClass.toExternalName(pool.lookupClass(indexTable[i]))); - } - buf.append("\n"); - return buf.toString(); - } - - protected int getSize() { - return 2 + indexTable.length * 2; - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(count); - for (int i = 0; i < count; ++i) - stream.writeShort(indexTable[i]); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java b/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java deleted file mode 100644 index d82db8289fff..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JExtendedCode.java +++ /dev/null @@ -1,667 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Extended list of instructions, providing pseudo-instructions which - * are easier to use than the standard ones. - * - * @author Michel Schinz, Thomas Friedli - * @version 1.0 - */ - -public class JExtendedCode extends JCode { - public final static int COND_EQ = 0; - public final static int COND_NE = 1; - public final static int COND_LT = 2; - public final static int COND_GE = 3; - public final static int COND_GT = 4; - public final static int COND_LE = 5; - - private final JOpcode[] forbidden = new JOpcode[0]; - private final JOpcode[] nothingToDo = new JOpcode[0]; - - private final JOpcode[][][] typeConversions = { - { - /* T_BOOLEAN -> T_BOOLEAN */ nothingToDo, - /* T_BOOLEAN -> T_CHAR */ forbidden, - /* T_BOOLEAN -> T_FLOAT */ forbidden, - /* T_BOOLEAN -> T_DOUBLE */ forbidden, - /* T_BOOLEAN -> T_BYTE */ forbidden, - /* T_BOOLEAN -> T_SHORT */ forbidden, - /* T_BOOLEAN -> T_INT */ forbidden, - /* T_BOOLEAN -> T_LONG */ forbidden - }, - { - /* T_CHAR -> T_BOOLEAN */ forbidden, - /* T_CHAR -> T_CHAR */ nothingToDo, - /* T_CHAR -> T_FLOAT */ {JOpcode.I2F}, - /* T_CHAR -> T_DOUBLE */ {JOpcode.I2D}, - /* T_CHAR -> T_BYTE */ {JOpcode.I2B}, - /* T_CHAR -> T_SHORT */ {JOpcode.I2S}, - /* T_CHAR -> T_INT */ nothingToDo, - /* T_CHAR -> T_LONG */ {JOpcode.I2L} - }, - { - /* T_FLOAT -> T_BOOLEAN */ forbidden, - /* T_FLOAT -> T_CHAR */ {JOpcode.F2I, JOpcode.I2C}, - /* T_FLOAT -> T_FLOAT */ nothingToDo, - /* T_FLOAT -> T_DOUBLE */ {JOpcode.F2D}, - /* T_FLOAT -> T_BYTE */ {JOpcode.F2I, JOpcode.I2B}, - /* T_FLOAT -> T_SHORT */ {JOpcode.F2I, JOpcode.I2S}, - /* T_FLOAT -> T_INT */ {JOpcode.F2I}, - /* T_FLOAT -> T_LONG */ {JOpcode.F2L} - }, - { - /* T_DOUBLE -> T_BOOLEAN */ forbidden, - /* T_DOUBLE -> T_CHAR */ {JOpcode.D2I, JOpcode.I2C}, - /* T_DOUBLE -> T_FLOAT */ {JOpcode.D2F}, - /* T_DOUBLE -> T_DOUBLE */ nothingToDo, - /* T_DOUBLE -> T_BYTE */ {JOpcode.D2I, JOpcode.I2B}, - /* T_DOUBLE -> T_SHORT */ {JOpcode.D2I, JOpcode.I2S}, - /* T_DOUBLE -> T_INT */ {JOpcode.D2I}, - /* T_DOUBLE -> T_LONG */ {JOpcode.D2L} - }, - { - /* T_BYTE -> T_BOOLEAN */ forbidden, - /* T_BYTE -> T_CHAR */ {JOpcode.I2C}, - /* T_BYTE -> T_FLOAT */ {JOpcode.I2F}, - /* T_BYTE -> T_DOUBLE */ {JOpcode.I2D}, - /* T_BYTE -> T_BYTE */ nothingToDo, - /* T_BYTE -> T_SHORT */ nothingToDo, - /* T_BYTE -> T_INT */ nothingToDo, - /* T_BYTE -> T_LONG */ {JOpcode.I2L} - }, - { - /* T_SHORT -> T_BOOLEAN */ forbidden, - /* T_SHORT -> T_CHAR */ {JOpcode.I2C}, - /* T_SHORT -> T_FLOAT */ {JOpcode.I2F}, - /* T_SHORT -> T_DOUBLE */ {JOpcode.I2D}, - /* T_SHORT -> T_BYTE */ {JOpcode.I2B}, - /* T_SHORT -> T_SHORT */ nothingToDo, - /* T_SHORT -> T_INT */ nothingToDo, - /* T_SHORT -> T_LONG */ {JOpcode.I2L} - }, - { - /* T_INT -> T_BOOLEAN */ forbidden, - /* T_INT -> T_CHAR */ {JOpcode.I2C}, - /* T_INT -> T_FLOAT */ {JOpcode.I2F}, - /* T_INT -> T_DOUBLE */ {JOpcode.I2D}, - /* T_INT -> T_BYTE */ {JOpcode.I2B}, - /* T_INT -> T_SHORT */ {JOpcode.I2S}, - /* T_INT -> T_INT */ nothingToDo, - /* T_INT -> T_LONG */ {JOpcode.I2L} - }, - { - /* T_LONG -> T_BOOLEAN */ forbidden, - /* T_LONG -> T_CHAR */ {JOpcode.L2I, JOpcode.I2C}, - /* T_LONG -> T_FLOAT */ {JOpcode.L2F}, - /* T_LONG -> T_DOUBLE */ {JOpcode.L2D}, - /* T_LONG -> T_BYTE */ {JOpcode.L2I, JOpcode.I2B}, - /* T_LONG -> T_SHORT */ {JOpcode.L2I, JOpcode.I2S}, - /* T_LONG -> T_INT */ {JOpcode.L2I}, - /* T_LONG -> T_LONG */ nothingToDo - } - }; - - public JExtendedCode(FJBGContext context, - JClass clazz, - JMethod owner) { - super(context, clazz, owner); - } - - public void emitPUSH(boolean value) { emitPUSH(value ? 1 : 0); } - public void emitPUSH(Boolean value) { emitPUSH(value.booleanValue()); } - - public void emitPUSH(byte value) { - switch (value) { - case -1: emitICONST_M1(); break; - case 0: emitICONST_0(); break; - case 1: emitICONST_1(); break; - case 2: emitICONST_2(); break; - case 3: emitICONST_3(); break; - case 4: emitICONST_4(); break; - case 5: emitICONST_5(); break; - default: - emitBIPUSH(value); - } - } - public void emitPUSH(Byte value) { emitPUSH(value.byteValue()); } - - public void emitPUSH(short value) { - switch (value) { - case -1: emitICONST_M1(); break; - case 0: emitICONST_0(); break; - case 1: emitICONST_1(); break; - case 2: emitICONST_2(); break; - case 3: emitICONST_3(); break; - case 4: emitICONST_4(); break; - case 5: emitICONST_5(); break; - default: - if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) - emitBIPUSH((byte)value); - else - emitSIPUSH(value); - } - } - public void emitPUSH(Short value) { emitPUSH(value.shortValue()); } - - // TODO check that we do the right thing here - public void emitPUSH(char value) { emitPUSH((int)value); } - public void emitPUSH(Character value) { emitPUSH(value.charValue()); } - - public void emitPUSH(int value) { - switch (value) { - case -1: emitICONST_M1(); break; - case 0: emitICONST_0(); break; - case 1: emitICONST_1(); break; - case 2: emitICONST_2(); break; - case 3: emitICONST_3(); break; - case 4: emitICONST_4(); break; - case 5: emitICONST_5(); break; - default: - if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) - emitBIPUSH((byte)value); - else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) - emitSIPUSH((short)value); - else - emitPUSH_index(pool.addInteger(value)); - break; - } - } - public void emitPUSH(Integer value) { emitPUSH(value.intValue()); } - - public void emitPUSH(long value) { - if (value == 0L) - emitLCONST_0(); - else if (value == 1L) - emitLCONST_1(); - else - emitLDC2_W(value); - } - public void emitPUSH(Long value) { emitPUSH(value.longValue()); } - - private static final Float ZEROF = Float.valueOf(0f); - private static final Float ONEF = Float.valueOf(1f); - private static final Float TWOF = Float.valueOf(2f); - public void emitPUSH(Float value) { - if (ZEROF.equals(value)) - emitFCONST_0(); - else if (ONEF.equals(value)) - emitFCONST_1(); - else if (TWOF.equals(value)) - emitFCONST_2(); - else - emitPUSH_index(pool.addFloat(value.floatValue())); - } - public void emitPUSH(float value) { emitPUSH(Float.valueOf(value)); } - - private static final Double ZEROD = Double.valueOf(0d); - private static final Double ONED = Double.valueOf(1d); - public void emitPUSH(Double value) { - if (ZEROD.equals(value)) - emitDCONST_0(); - else if (ONED.equals(value)) - emitDCONST_1(); - else - emitLDC2_W(value.doubleValue()); - } - public void emitPUSH(double value) { emitPUSH(Double.valueOf(value)); } - - public void emitPUSH(String s) { - emitPUSH_index(pool.addString(s)); - } - - /** Pushes a class literal on the stack */ - public void emitPUSH(JReferenceType type) { - assert owner.owner.major >= 49; - emitPUSH_index(pool.addClass(type.getDescriptor())); - } - - protected void emitPUSH_index(int index) { - if (index <= 0xFF) - emitU1(JOpcode.LDC, index); - else - emitU2(JOpcode.LDC_W, index); - } - - public void emitLOAD(int index, JType type) { - JOpcode opcode; - - switch (type.getTag()) { - case JType.T_BOOLEAN: case JType.T_BYTE: case JType.T_CHAR: - case JType.T_SHORT: case JType.T_INT: - switch (index) { - case 0: emitILOAD_0(); return; - case 1: emitILOAD_1(); return; - case 2: emitILOAD_2(); return; - case 3: emitILOAD_3(); return; - default: opcode = JOpcode.ILOAD; - } break; - case JType.T_FLOAT: - switch (index) { - case 0: emitFLOAD_0(); return; - case 1: emitFLOAD_1(); return; - case 2: emitFLOAD_2(); return; - case 3: emitFLOAD_3(); return; - default: opcode = JOpcode.FLOAD; - } break; - case JType.T_LONG: - switch (index) { - case 0: emitLLOAD_0(); return; - case 1: emitLLOAD_1(); return; - case 2: emitLLOAD_2(); return; - case 3: emitLLOAD_3(); return; - default: opcode = JOpcode.LLOAD; - } break; - case JType.T_DOUBLE: - switch (index) { - case 0: emitDLOAD_0(); return; - case 1: emitDLOAD_1(); return; - case 2: emitDLOAD_2(); return; - case 3: emitDLOAD_3(); return; - default: opcode = JOpcode.DLOAD; - } break; - case JType.T_ARRAY: case JType.T_OBJECT: - switch (index) { - case 0: emitALOAD_0(); return; - case 1: emitALOAD_1(); return; - case 2: emitALOAD_2(); return; - case 3: emitALOAD_3(); return; - default: opcode = JOpcode.ALOAD; - } break; - default: - throw new IllegalArgumentException("invalid type for load "+type); - } - - if (index > 0xFF) - emitWIDE(opcode, index); - else - emitU1(opcode, index); - } - public void emitLOAD(JLocalVariable var) { - emitLOAD(var.index, var.type); - } - - public void emitSTORE(int index, JType type) { - JOpcode opcode; - - switch (type.getTag()) { - case JType.T_BOOLEAN: case JType.T_BYTE: case JType.T_CHAR: - case JType.T_SHORT: case JType.T_INT: - switch (index) { - case 0: emitISTORE_0(); return; - case 1: emitISTORE_1(); return; - case 2: emitISTORE_2(); return; - case 3: emitISTORE_3(); return; - default: opcode = JOpcode.ISTORE; - } break; - case JType.T_FLOAT: - switch (index) { - case 0: emitFSTORE_0(); return; - case 1: emitFSTORE_1(); return; - case 2: emitFSTORE_2(); return; - case 3: emitFSTORE_3(); return; - default: opcode = JOpcode.FSTORE; - } break; - case JType.T_LONG: - switch (index) { - case 0: emitLSTORE_0(); return; - case 1: emitLSTORE_1(); return; - case 2: emitLSTORE_2(); return; - case 3: emitLSTORE_3(); return; - default: opcode = JOpcode.LSTORE; - } break; - case JType.T_DOUBLE: - switch (index) { - case 0: emitDSTORE_0(); return; - case 1: emitDSTORE_1(); return; - case 2: emitDSTORE_2(); return; - case 3: emitDSTORE_3(); return; - default: opcode = JOpcode.DSTORE; - } break; - case JType.T_ARRAY: case JType.T_OBJECT: case JType.T_ADDRESS: - switch (index) { - case 0: emitASTORE_0(); return; - case 1: emitASTORE_1(); return; - case 2: emitASTORE_2(); return; - case 3: emitASTORE_3(); return; - default: opcode = JOpcode.ASTORE; - } break; - default: - throw new IllegalArgumentException("invalid type for store "+type); - } - - if (index > 0xFF) - emitWIDE(opcode, index); - else - emitU1(opcode, index); - } - public void emitSTORE(JLocalVariable var) { - emitSTORE(var.index, var.type); - } - - public void emitALOAD(JType type) { - switch (type.getTag()) { - case JType.T_BOOLEAN: - case JType.T_BYTE: - emitBALOAD(); - break; - case JType.T_CHAR: - emitCALOAD(); - break; - case JType.T_SHORT: - emitSALOAD(); - break; - case JType.T_INT: - emitIALOAD(); - break; - case JType.T_FLOAT: - emitFALOAD(); - break; - case JType.T_LONG: - emitLALOAD(); - break; - case JType.T_DOUBLE: - emitDALOAD(); - break; - case JType.T_ARRAY: - case JType.T_OBJECT: - emitAALOAD(); - break; - default: - throw new IllegalArgumentException("invalid type for aload " + type); - } - } - - public void emitASTORE(JType type) { - switch (type.getTag()) { - case JType.T_BOOLEAN: - case JType.T_BYTE: - emitBASTORE(); - break; - case JType.T_CHAR: - emitCASTORE(); - break; - case JType.T_SHORT: - emitSASTORE(); - break; - case JType.T_INT: - emitIASTORE(); - break; - case JType.T_FLOAT: - emitFASTORE(); - break; - case JType.T_LONG: - emitLASTORE(); - break; - case JType.T_DOUBLE: - emitDASTORE(); - break; - case JType.T_ARRAY: - case JType.T_OBJECT: - emitAASTORE(); - break; - default: - throw new IllegalArgumentException("invalid type for astore " + type); - } - } - - public void emitRETURN(JType type) { - if (type.isValueType()) { - switch (type.getTag()) { - case JType.T_BOOLEAN: - case JType.T_BYTE: - case JType.T_CHAR: - case JType.T_SHORT: - case JType.T_INT: - emitIRETURN(); - break; - case JType.T_FLOAT: - emitFRETURN(); - break; - case JType.T_LONG: - emitLRETURN(); - break; - case JType.T_DOUBLE: - emitDRETURN(); - break; - } - } else if (type.isArrayType() || type.isObjectType()) - emitARETURN(); - else if (type == JType.VOID) - emitRETURN(); - else - throw new IllegalArgumentException("invalid type for RETURN " + type); - } - - public void emitADD(JType type) { - switch (type.getTag()) { - case JType.T_BOOLEAN: case JType.T_BYTE: case JType.T_CHAR: - case JType.T_SHORT: case JType.T_INT: - emitIADD(); break; - case JType.T_FLOAT: - emitFADD(); break; - case JType.T_LONG: - emitLADD(); break; - case JType.T_DOUBLE: - emitDADD(); break; - } - } - - /** - * Emits a basic type conversion instruction choosen according to the - * types given in parameter. - * - * @param fromType The type of the value to be cast into another type. - * @param toType The type the value will be cast into. - */ - public void emitT2T(JType fromType, JType toType) { - assert fromType.getTag() >= JType.T_BOOLEAN - && fromType.getTag() <= JType.T_LONG - && toType.getTag() >= JType.T_BOOLEAN - && toType.getTag() <= JType.T_LONG; - - JOpcode[] conv = typeConversions[fromType.getTag() - 4][toType.getTag() - 4]; - if (conv == forbidden) { - throw new Error("inconvertible types : " + fromType.toString() - + " -> " + toType.toString()); - } else if (conv != nothingToDo) { - for (int i = 0; i < conv.length; i++) { - emit(conv[i]); - } - } - } - - public void emitIF(int cond, Label label) throws OffsetTooBigException { - assert cond >= COND_EQ && cond <= COND_LE; - emitU2(JOpcode.OPCODES[153 + cond], label.getOffset16(getPC() + 1, getPC())); - } - public void emitIF(int cond, int targetPC) throws OffsetTooBigException { - int offset = targetPC - getPC(); - emitU2(JOpcode.OPCODES[153 + cond], offset); - } - public void emitIF(int cond) throws OffsetTooBigException { - emitIF(cond, 0); - } - - public void emitIF_ICMP(int cond, Label label) throws OffsetTooBigException { - assert cond >= COND_EQ && cond <= COND_LE; - emitU2(JOpcode.OPCODES[159 + cond], label.getOffset16(getPC() + 1, getPC())); - } - public void emitIF_ICMP(int cond, int targetPC) throws OffsetTooBigException { - int offset = targetPC - getPC(); - emitU2(JOpcode.OPCODES[159 + cond], offset); - } - public void emitIF_ICMP(int cond) throws OffsetTooBigException { - emitIF_ICMP(cond, 0); - } - - public void emitIF_ACMP(int cond, Label label) throws OffsetTooBigException { - assert cond == COND_EQ || cond == COND_NE; - emitU2(JOpcode.OPCODES[165 + cond], label.getOffset16(getPC() + 1, getPC())); - } - public void emitIF_ACMP(int cond, int targetPC) throws OffsetTooBigException { - int offset = targetPC - getPC(); - emitU2(JOpcode.OPCODES[165 + cond], offset); - } - public void emitIF_ACMP(int cond) throws OffsetTooBigException { - emitIF_ACMP(cond, 0); - } - - public void emitGOTO_maybe_W(Label label, boolean defaultToWide) { - if (label.anchored) - emitGOTO_maybe_W(label.targetPC); - else { - if (defaultToWide) - emitGOTO_W(label); - else { - try { - emitGOTO(label); - } catch (OffsetTooBigException e) { - throw new Error(e); - } - } - } - } - - public void emitGOTO_maybe_W(int targetPC) { - int offset = targetPC - (getPC() + 1); - if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) - emitGOTO_W(targetPC); - else { - try { - emitGOTO(targetPC); - } catch (OffsetTooBigException e) { - throw new Error(e); - } - } - } - - /** - * Emits a switch instruction choosen according to the caracteristics - * of the given list of keys and a default maxRate. - * - * @param keySets The array of all keys that must be compared to the - * value on stack. - * @param branches The labels representing the jump addresses linked - * with the corresponding keys. - * @param defaultBranch The label representing the default branch - * address. - */ - public void emitSWITCH(int[][] keySets, - Label[] branches, - Label defaultBranch, - double minDensity) { - assert keySets.length == branches.length; - - int flatSize = 0; - for (int i = 0; i < keySets.length; ++i) - flatSize += keySets[i].length; - - int[] flatKeys = new int[flatSize]; - Label[] flatBranches = new Label[flatSize]; - int flatI = 0; - for (int i = 0; i < keySets.length; ++i) { - Label branch = branches[i]; - int[] keys = keySets[i]; - for (int j = 0; j < keys.length; ++j) { - flatKeys[flatI] = keys[j]; - flatBranches[flatI] = branch; - } - ++flatI; - } - assert flatI == flatSize; - emitSWITCH(flatKeys, flatBranches, defaultBranch, minDensity); - } - - /** - * Emits a switch instruction choosen according to the caracteristics - * of the given list of keys and a given maxRate. - * - * @param keys The array of all keys that must be compared to the - * value on stack. - * @param branches The labels representing the jump addresses linked - * with the corresponding keys. - * @param defaultBranch The label representing the default branch - * address. - * @param minDensity The minimum density to use for TABLESWITCH. - */ - public void emitSWITCH(int[] keys, - Label[] branches, - Label defaultBranch, - double minDensity) { - assert keys.length == branches.length; - - //The special case for empty keys. It makes sense to allow - //empty keys and generate LOOKUPSWITCH with defaultBranch - //only. This is exactly what javac does for switch statement - //that has only a default case. - if (keys.length == 0) { - emitLOOKUPSWITCH(keys, branches, defaultBranch); - return; - } - //the rest of the code assumes that keys.length > 0 - - // sorting the tables - // FIXME use quicksort - for (int i = 1; i < keys.length; i++) { - for (int j = 1; j <= keys.length - i; j++) { - if (keys[j] < keys[j - 1]) { - int tmp = keys[j]; - keys[j] = keys[j - 1]; - keys[j - 1] = tmp; - - Label tmp_l = branches[j]; - branches[j] = branches[j - 1]; - branches[j - 1] = tmp_l; - } - } - } - - int keyMin = keys[0], keyMax = keys[keys.length - 1]; - /** Calculate in long to guard against overflow. */ - long keyRange = (long)keyMax - keyMin + 1; - if ((double)keys.length / (double)keyRange >= minDensity) { - // Keys are dense enough, use a table in which holes are - // filled with defaultBranch. - int[] newKeys = new int[(int)keyRange]; - Label[] newBranches = new Label[(int)keyRange]; - int oldPos = 0; - for (int i = 0; i < keyRange; ++i) { - int key = keyMin + i; - newKeys[i] = key; - if (keys[oldPos] == key) { - newBranches[i] = branches[oldPos]; - ++oldPos; - } else - newBranches[i] = defaultBranch; - } - assert oldPos == keys.length; - emitTABLESWITCH(newKeys, newBranches, defaultBranch); - } else - emitLOOKUPSWITCH(keys, branches, defaultBranch); - } - - /** - * Emits a method invocation instruction choosen according to - * the caracteristics of the given method. - * - * @param method The method to be invoked. - */ - public void emitINVOKE(JMethod method) { - String mName = method.getName(); - String cName = method.getOwner().getName(); - JMethodType mType = (JMethodType)method.getType(); - if (method.isStatic()) - emitINVOKESTATIC(cName, mName, mType); - else if (method.getOwner().isInterface()) - emitINVOKEINTERFACE(cName, mName, mType); - else - emitINVOKEVIRTUAL(cName, mName, mType); - } - -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JField.java b/src/fjbg/ch/epfl/lamp/fjbg/JField.java deleted file mode 100644 index 29d826ba99b7..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JField.java +++ /dev/null @@ -1,62 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.IOException; - -/** - * Java class field. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JField extends JFieldOrMethod { - - protected JField(FJBGContext context, - JClass owner, - int accessFlags, - String name, - JType type) { - super(context, owner, accessFlags, name, type); - } - - protected JField(FJBGContext context, - JClass owner, - DataInputStream stream) - throws IOException { - super(context, owner, stream); - } - - // Follows javap output format for fields. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(flagsToString()); - buf.append(toExternalName(getType())); - buf.append(" "); - buf.append(getName()); - buf.append(";\n"); - java.util.Iterator attrsIt = attributes.iterator(); - while (attrsIt.hasNext()) { - JAttribute attrs = (JAttribute)attrsIt.next(); - buf.append(attrs); - } - return buf.toString(); - } - - private String flagsToString() { - StringBuffer buf = new StringBuffer(); - if (isPublic()) buf.append("public "); - else if (isProtected()) buf.append("protected "); - else if (isPrivate()) buf.append("private "); - if (isStatic()) buf.append("static "); - else if (isTransient()) buf.append("transient "); - else if (isVolatile()) buf.append("volatile "); - if (isAbstract()) buf.append("abstract "); - else if (isFinal()) buf.append("final "); - return buf.toString(); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java b/src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java deleted file mode 100644 index 794c0f13b51f..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JFieldOrMethod.java +++ /dev/null @@ -1,138 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * Abstract superclass for a Java field or method. - * - * No two methods of fields in one class file may have the same name and - * descriptor. See sections 4.6 and 4.7 of the JVM specification. - * - * @author Michel Schinz - * @version 1.0 - */ - -abstract public class JFieldOrMethod extends JMember { - - protected final JClass owner; - protected final JType type; - - protected final int nameIndex, signatureIndex; - - protected JFieldOrMethod(FJBGContext context, - JClass owner, - int accessFlags, - String name, - JType type) { - super(context, accessFlags, name); - this.owner = owner; - this.type = type; - - nameIndex = owner.pool.addUtf8(name); - signatureIndex = owner.pool.addUtf8(type.getSignature()); - } - - protected JFieldOrMethod(FJBGContext context, - JClass owner, - DataInputStream stream) - throws IOException { - super(context); - this.owner = owner; - this.accessFlags = stream.readShort(); - this.nameIndex = stream.readShort(); - this.name = owner.pool.lookupUtf8(nameIndex); - this.signatureIndex = stream.readShort(); - this.type = JType.parseSignature(owner.pool.lookupUtf8(signatureIndex)); - this.attributes.addAll(JAttribute.readFrom(context, owner, this, stream)); - } - - public void freeze() throws JCode.OffsetTooBigException { - assert !frozen; - frozen = true; - } - - public JClass getOwner() { return owner; } - - public JType getType() { return type; } - - public JClass getJClass() { return owner; } - - public boolean isPublic() { - return (accessFlags & JAccessFlags.ACC_PUBLIC) != 0; - } - - public boolean isPrivate() { - return (accessFlags & JAccessFlags.ACC_PRIVATE) != 0; - } - - public boolean isProtected() { - return (accessFlags & JAccessFlags.ACC_PROTECTED) != 0; - } - - public boolean isStatic() { - return (accessFlags & JAccessFlags.ACC_STATIC) != 0; - } - - public boolean isFinal() { - return (accessFlags & JAccessFlags.ACC_FINAL) != 0; - } - - public boolean isSuper() { - return (accessFlags & JAccessFlags.ACC_SUPER) != 0; - } - - public boolean isVolatile() { - return (accessFlags & JAccessFlags.ACC_VOLATILE) != 0; - } - - public boolean isTransient() { - return (accessFlags & JAccessFlags.ACC_TRANSIENT) != 0; - } - - public boolean isNative() { - return (accessFlags & JAccessFlags.ACC_NATIVE) != 0; - } - - public boolean isInterface() { - return (accessFlags & JAccessFlags.ACC_INTERFACE) != 0; - } - - public boolean isAbstract() { - return (accessFlags & JAccessFlags.ACC_ABSTRACT) != 0; - } - - public boolean isStrict() { - return (accessFlags & JAccessFlags.ACC_STRICT) != 0; - } - - // 1.5 specifics - public boolean isBridge() { - return (accessFlags & JAccessFlags.ACC_BRIDGE) != 0; - } - - public boolean hasVarargs() { - return (accessFlags & JAccessFlags.ACC_VARARGS) != 0; - } - - public void writeTo(DataOutputStream stream) throws IOException { - if (! frozen) { - try { - freeze(); - } - catch (JCode.OffsetTooBigException e) { - throw new Error(e); - } - } - stream.writeShort(accessFlags); - stream.writeShort(nameIndex); - stream.writeShort(signatureIndex); - JAttribute.writeTo(getAttributes(), stream); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JInnerClassesAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JInnerClassesAttribute.java deleted file mode 100644 index 1c1ced500dbc..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JInnerClassesAttribute.java +++ /dev/null @@ -1,201 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * InnerClasses attribute. - * - * The ClassFile structure of a class/interface C must have exactly one - * InnerClasses attribute in its attributes table if the constant pool of C - * contains a CONSTANT_Class_info entry which represents a class or interface - * that is not a member of a package. See section 4.8.5 of the JVM Specification. - * - * @author Iulian Dragos, Stephane Micheloud - * @version 1.1 - */ -public class JInnerClassesAttribute extends JAttribute { - /** Constant pool of the current classfile. */ - private JConstantPool pool; - - /** InnerClass entries */ - private Map/**/ entries = new LinkedHashMap(); - - public JInnerClassesAttribute(FJBGContext context, JClass clazz) { - super(context, clazz); - this.pool = clazz.pool; - } - - public JInnerClassesAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.pool = clazz.pool; - - String inner = null; - int count = stream.readShort(); - for (int i = 0; i < count; ++i) { - int innerIdx = stream.readShort(); - int outerIdx = stream.readShort(); - int nameIdx = stream.readShort(); - int flags = stream.readShort(); - inner = pool.lookupClass(innerIdx); - entries.put(inner, new Entry(innerIdx, outerIdx, nameIdx, flags)); - } - - assert name.equals(getName()); - } - - public void addEntry(String inner, String outer, String name, int flags) { - int innerIdx = pool.addClass(inner); - int outerIdx = 0; - if (outer != null) outerIdx = pool.addClass(outer); - int nameIdx = 0; - if (name != null) nameIdx = pool.addUtf8(name); - - Entry e = new Entry(innerIdx, outerIdx, nameIdx, flags); - - if (entries.containsKey(inner)) { - Entry other = (Entry) entries.get(inner); - assert other.outerInfo == e.outerInfo && other.originalName == e.originalName && other.innerFlags == e.innerFlags - : inner + " already declared as " + other; - } else - entries.put(inner, e); - } - - public String getName() { return "InnerClasses"; } - - // Follows javap output format for the InnerClass attribute. - /*@Override*/ public String toString() { - // Here we intentionally use "InnerClass" as javap :-( - StringBuffer buf = new StringBuffer(" InnerClass: "); - for (Iterator it = entries.values().iterator(); it.hasNext(); ) { - Entry e = (Entry)it.next(); - buf.append("\n "); - buf.append(e.innerFlagsToString()); - buf.append("#"); - if (e.originalName != 0) { - buf.append(e.originalName); - buf.append("= #"); - } - buf.append(e.innerInfo); - if (e.outerInfo != 0) { - buf.append(" of #"); - buf.append(e.outerInfo); - } - buf.append("; //"); - if (e.originalName != 0) { - buf.append(pool.lookupUtf8(e.originalName)); - buf.append("="); - } - buf.append("class "); - buf.append(pool.lookupClass(e.innerInfo)); - if (e.outerInfo != 0) { - buf.append(" of class "); - buf.append(pool.lookupClass(e.outerInfo)); - } - } - buf.append("\n"); - return buf.toString(); - } - - protected int getSize() { - return 2 + entries.size() * 8; - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(entries.size()); - for (Iterator it = entries.values().iterator(); it.hasNext(); ) { - Entry e = (Entry)it.next(); - stream.writeShort(e.innerInfo); - stream.writeShort(e.outerInfo); - stream.writeShort(e.originalName); - stream.writeShort(e.innerFlags); - } - } - - /** An entry in the InnerClasses attribute, as defined by the JVM Spec. */ - private class Entry { - /** CONSTANT_Class_info index in the pool for the inner class (mangled). */ - int innerInfo; - - /** CONSTANT_Class_info index in the pool for the outer class (mangled). */ - int outerInfo; - - /** CONSTANT_Utf8_info index in the pool for the original name of the inner class. */ - int originalName; - - /** Short int for modifier flags. */ - int innerFlags; - - public Entry(int iI, int oI, int oN, int f) { - this.innerInfo = iI; - this.outerInfo = oI; - this.originalName = oN; - this.innerFlags = f; - } - - public Entry(String innerClass, String outerClass, String name, int flags) { - this(pool.addClass(innerClass), pool.addClass(outerClass), pool.addUtf8(name), flags); - } - - /** Two entries are equal if they refer to the same inner class. - * innerInfo represents a unique name (mangled). - */ - public boolean equals(Object other) { - if (other instanceof Entry) { - Entry otherEntry = (Entry) other; - return otherEntry.innerInfo == this.innerInfo; - } - return false; - } - - public String innerFlagsToString() { - StringBuffer buf = new StringBuffer(); - if (isPublic()) buf.append("public "); - else if (isProtected()) buf.append("protected "); - else if (isPrivate()) buf.append("private "); - //if (isStatic()) buf.append("static "); // as javap - if (isAbstract()) buf.append("abstract "); - else if (isFinal()) buf.append("final "); - return buf.toString(); - } - - private boolean isPublic() { - return (innerFlags & JAccessFlags.ACC_PUBLIC) != 0; - } - - private boolean isPrivate() { - return (innerFlags & JAccessFlags.ACC_PRIVATE) != 0; - } - - private boolean isProtected() { - return (innerFlags & JAccessFlags.ACC_PROTECTED) != 0; - } - - private boolean isStatic() { - return (innerFlags & JAccessFlags.ACC_STATIC) != 0; - } - - private boolean isFinal() { - return (innerFlags & JAccessFlags.ACC_FINAL) != 0; - } - - private boolean isAbstract() { - return (innerFlags & JAccessFlags.ACC_ABSTRACT) != 0; - } - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JLabel.java b/src/fjbg/ch/epfl/lamp/fjbg/JLabel.java deleted file mode 100644 index 96f3b4ebefe5..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JLabel.java +++ /dev/null @@ -1,30 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Labels which can be attached to instructions. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JLabel { - public final static int UNDEFINED_ANCHOR = -1; - protected int anchor = UNDEFINED_ANCHOR; - - public boolean isAnchored() { return anchor != UNDEFINED_ANCHOR; } - - public int getAnchor() { - assert isAnchored(); - return anchor; - } - - public void setAnchor(int anchor) { - assert !isAnchored(); - this.anchor = anchor; - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JLineNumberTableAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JLineNumberTableAttribute.java deleted file mode 100644 index f8c09b8ef8fa..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JLineNumberTableAttribute.java +++ /dev/null @@ -1,121 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * Attribute storing correspondance between instructions and source - * line numbers. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JLineNumberTableAttribute extends JAttribute { - protected final JCode code; - - public JLineNumberTableAttribute(FJBGContext context, - JClass clazz, - JCode owner) { - super(context, clazz); - this.code = owner; - - assert owner.getOwner().getOwner() == clazz; - } - - public JLineNumberTableAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.code = (JCode)owner; - - int[] mapping = new int[code.getSize()]; - - int count = stream.readShort(); - for (int i = 0; i < count; ++i) { - int startPC = stream.readShort(); - int lineNum = stream.readShort(); - mapping[startPC] = lineNum; - } - - // Avoids duplication of LineNumberTable attribute - // (see method ensureLineNumberCapacity in class JCode). - assert code.lineNumbers == null; - code.lineNumbers = new int[0]; - - int lineNum = 0; - for (int pc = 0; pc < mapping.length; ++pc) { - if (mapping[pc] != 0) lineNum = mapping[pc]; - if (lineNum != 0) code.setLineNumber(pc, lineNum); - } - - assert name.equals(getName()); - } - - public String getName() { return "LineNumberTable"; } - - // Follows javap output format for LineNumberTable attribute. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" LineNumberTable: "); - int[] encoding = encode(); - for (int i = 0; i < encoding.length/2; ++i) { - buf.append("\n line "); - buf.append(encoding[i * 2 + 1]); - buf.append(": "); - buf.append(encoding[i * 2]); - } - buf.append("\n"); - return buf.toString(); - } - - protected int[] encoding; - protected int[] encode() { - if (encoding == null) { - int[] lineNumbers = code.getLineNumbers(); - int[] preEncoding = new int[lineNumbers.length * 2]; - int prevLineNum = 0; - - int i = 0; - for (int pc = 0; pc < lineNumbers.length; ++pc) { - int lineNum = lineNumbers[pc]; - if (lineNum != 0 & lineNum != prevLineNum) { - preEncoding[i++] = pc; - preEncoding[i++] = lineNum; - prevLineNum = lineNum; - } - } - if (i == preEncoding.length) - encoding = preEncoding; - else { - encoding = new int[i]; - System.arraycopy(preEncoding, 0, encoding, 0, i); - } - } - return encoding; - } - - protected int getSize() { - int[] encoding = encode(); - return 2 + encoding.length * 2; - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - int[] encoding = encode(); - int entries = encoding.length / 2; - stream.writeShort(entries); - for (int i = 0; i < entries; ++i) { - stream.writeShort(encoding[i * 2]); - stream.writeShort(encoding[i * 2 + 1]); - } - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JLocalVariable.java b/src/fjbg/ch/epfl/lamp/fjbg/JLocalVariable.java deleted file mode 100644 index af7980656f67..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JLocalVariable.java +++ /dev/null @@ -1,42 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Representation of a local variable or method argument. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JLocalVariable { - protected final JMethod owner; - protected final JType type; - protected final String name; - protected final int index; - - protected JLocalVariable(FJBGContext context, - JMethod owner, - JType type, - String name, - int index) { - this.owner = owner; - this.type = type; - this.name = name; - this.index = index; - - assert index < 0xFFFF : "index too big for local variable: " + index; - } - - public JMethod getOwner() { return owner; } - public int getIndex() { return index; } - public String getName() { return name; } - public JType getType() { return type; } - - /*@Override*/ public String toString() { - return "0\t"+type.getSize()+"\t"+index+"\t"+name+"\t"+type; - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JLocalVariableTableAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JLocalVariableTableAttribute.java deleted file mode 100644 index b277cc71c02b..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JLocalVariableTableAttribute.java +++ /dev/null @@ -1,167 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedList; - -import ch.epfl.lamp.fjbg.JConstantPool.*; - -/** - * Attribute storing local variables. - * - * @author Stephane Micheloud - * @version 1.0 - */ - -public class JLocalVariableTableAttribute extends JAttribute { - /** Constant pool of the current classfile. */ - private JConstantPool pool; - - protected final LinkedList/**/ entries = new LinkedList(); - protected int localVariableIndex = 0; - - public JLocalVariableTableAttribute(FJBGContext context, - JClass clazz, - JCode code) { - super(context, clazz); - this.pool = clazz.pool; - - assert code.getOwner().getOwner() == clazz; - } - - public JLocalVariableTableAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.pool = clazz.pool; - - int count = stream.readShort(); - for (int i = 0; i < count; ++i) { - int startPc = stream.readShort(); - int length = stream.readShort(); - int nameIndex = stream.readShort(); - int descIndex = stream.readShort(); - int index = stream.readShort(); - addEntry(startPc, length, nameIndex, descIndex, index); - } - - assert name.equals(getName()); - } - - public void addEntry(int startPc, int length, int nameIndex, - int descIndex, int index) { - entries.add(new Entry(startPc, length, nameIndex, descIndex, index)); - } - - public void addEntry(int startPc, int length, String name, - String desc, int index) { - Entry e = new Entry(startPc, length, name, desc, index); - Entry other = getEntry(index); - if (other != null) { - assert other.nameIndex == e.nameIndex && other.descIndex == e.descIndex - : e + " already declared as " + other; - } else - entries.add(e); - } - - public void addEntry(int startPc, int length, String name, String desc) { - entries.add(new Entry(startPc, length, name, desc)); - } - - public String getName() { return "LocalVariableTable"; } - - // Follows javap output format for LocalVariableTable attribute. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" LocalVariableTable: "); - buf.append("\n Start Length Slot Name Signature"); - for (Iterator it = entries.iterator(); it.hasNext(); ) { - buf.append("\n "); - Entry e = (Entry)it.next(); - Utf8Entry name = (Utf8Entry)pool.lookupEntry(e.nameIndex); - Utf8Entry sig = (Utf8Entry)pool.lookupEntry(e.descIndex); - buf.append(e.startPc); - buf.append(" "); - buf.append(e.length); - buf.append(" "); - buf.append(e.index); - buf.append(" "); - buf.append(name.getValue()); - buf.append(" "); - buf.append(sig.getValue()); - } - buf.append("\n"); - return buf.toString(); - } - - public int getMaxLocals() { - return localVariableIndex; - } - - public int getSize() { - return 2 + entries.size() * 10; - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(entries.size()); - for (Iterator it = entries.iterator(); it.hasNext(); ) { - Entry e = (Entry)it.next(); - stream.writeShort(e.startPc); - stream.writeShort(e.length); - stream.writeShort(e.nameIndex); - stream.writeShort(e.descIndex); - stream.writeShort(e.index); - } - } - - private Entry getEntry(int index) { - Entry e = null; - try { e = (Entry)entries.get(index); } catch (Exception ex) {} - return e; - } - - private class Entry { - int startPc; - int length; - int nameIndex; - int descIndex; - int index; - - public Entry(int startPc, int length, int nameIndex, int descIndex, int index) { - this.startPc = startPc; - this.length = length; - this.nameIndex = nameIndex; - this.descIndex = descIndex; - this.index = index; - localVariableIndex += length; - } - - public Entry(int startPc, int length, String name, String desc, int index) { - this(startPc, length, pool.addUtf8(name), pool.addUtf8(desc), index); - } - - public Entry(int startPc, int length, String name, String desc) { - this(startPc, length, pool.addUtf8(name), pool.addUtf8(desc), localVariableIndex); - } - - /** Two entries are equal if they refer to the same index. - */ - public boolean equals(Object other) { - if (other instanceof Entry) { - Entry otherEntry = (Entry) other; - return otherEntry.index == this.index; - } - return false; - } - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JMember.java b/src/fjbg/ch/epfl/lamp/fjbg/JMember.java deleted file mode 100644 index 6356cc874de1..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JMember.java +++ /dev/null @@ -1,109 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -/** - * Abstract superclass for a Java class, field or method. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ - -abstract public class JMember { - - protected boolean frozen = false; - - protected final FJBGContext context; - - protected String name; - - protected int accessFlags; - - protected final List/**/ attributes = new LinkedList(); - - protected JMember(FJBGContext context) { this.context = context; } - - protected JMember(FJBGContext context, int accessFlags, String name) { - this(context); - this.name = name; - this.accessFlags = accessFlags; - } - - /** - * Gets the access flags of the class. - * @return The int representing the access flags of the class. - */ - public int getAccessFlags() { return accessFlags; } - - /** - * Gets the name of the member. - * @return The string representing the name of the member. - */ - public String getName() { return name; } - - /** - * Gets the type of the objects that are instances of the class. - * @return The type of the instances of the class. - */ - public abstract JType getType(); - - /** - * Gets the class corresponding to/owning this member - * @return The class owning this member or the class itself. - */ - public abstract JClass getJClass(); - - /** - * Gets the constant pool of the class. - * @return The constant pool of the class. - */ - public JConstantPool getConstantPool() { return getJClass().getConstantPool(); } - - public FJBGContext getContext() { return context; } - - /** - * Adds an attribute to the class. - * @param attr The attribute to be added. - */ - public void addAttribute(JAttribute attr) { - assert !frozen; - attributes.add(attr); - } - - /** - * Gets the list of all attributes of the class. - * @return The list of the attributes of the class representation. - */ - public List/**/ getAttributes() { - return attributes; - } - - /** - * Get the attribute with the given name, or null if it doesn't - * exist. - */ - public JAttribute getAttribute(String name) { - Iterator attrIt = getAttributes().iterator(); - while (attrIt.hasNext()) { - JAttribute attr = (JAttribute)attrIt.next(); - if (attr.getName().equals(name)) - return attr; - } - return null; - } - - protected static String toExternalName(String name) { - return name.replace('/', '.'); - } - - protected static String toExternalName(JType tpe) { - return tpe.toString().replace(':', '.'); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JMethod.java b/src/fjbg/ch/epfl/lamp/fjbg/JMethod.java deleted file mode 100644 index 01d58a45c7ca..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JMethod.java +++ /dev/null @@ -1,199 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -/** - * Representation of a Java method. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JMethod extends JFieldOrMethod { - public final static String CLASS_CONSTRUCTOR_NAME = ""; - public final static String INSTANCE_CONSTRUCTOR_NAME = ""; - - protected /*final*/ JCode code; - protected final String[] argNames; - - protected final LinkedList/**/ localVariables = - new LinkedList(); - protected int localVariableIndex = 0; - - - protected JMethod(FJBGContext context, - JClass owner, - int accessFlags, - String name, - JType returnType, - JType[] argTypes, - String[] argNames) { - super(context, - owner, - accessFlags, - name, - new JMethodType(returnType, argTypes)); - this.argNames = argNames; - - assert argTypes.length == argNames.length; - - if (isAbstract() || isNative()) { - code = null; - } else { - code = context.JCode(owner, this); - addAttribute(context.JCodeAttribute(owner, this)); - - if (!isStatic()) - addNewLocalVariable(owner.getType(), "this"); - - for (int i = 0; i < argTypes.length; ++i) - addNewLocalVariable(argTypes[i], argNames[i]); - } - } - - protected JMethod(FJBGContext context, - JClass owner, - DataInputStream stream) - throws IOException { - super(context, owner, stream); - - assert isAbstract() || isNative() || code != null; - - int n = 0; - if (code != null) { - for (Iterator it = code.getAttributes().iterator(); it.hasNext(); ) { - JAttribute attr = (JAttribute)it.next(); - if (attr instanceof JLocalVariableTableAttribute) - n = ((JLocalVariableTableAttribute)attr).getMaxLocals(); - } - } - this.localVariableIndex = n; - - - JType[] argTypes = ((JMethodType)getType()).getArgumentTypes(); - argNames = new String[argTypes.length]; // TODO get from attribute - for (int i = 0; i < argNames.length; ++i) - argNames[i] = "v"+i; - } - - public void freeze() throws JCode.OffsetTooBigException { - if (code != null) code.freeze(); - super.freeze(); - } - - public JType getReturnType() { - return ((JMethodType)type).getReturnType(); - } - - public JType[] getArgumentTypes() { - return ((JMethodType)type).getArgumentTypes(); - } - - public int getArgsSize() { - int size = ((JMethodType)type).getArgsSize(); - if (!isStatic()) size += 1; // for this - return size; - } - - public String[] getArgumentNames() { - return argNames; - } - - public JCode getCode() { - assert !isAbstract(); - return code; - } - - // Invoked by the JCode constructor - protected void setCode(JCode code) { - assert null == this.code; - this.code = code; - } - - public JCodeIterator codeIterator() { - return new JCodeIterator(code); - } - - // Local variables - // FIXME : find a better management method for local variables - public JLocalVariable addNewLocalVariable(JType type, String name) { - assert !frozen; - JLocalVariable var = - context.JLocalVariable(this, type, name, localVariableIndex); - localVariableIndex += type.getSize(); - localVariables.add(var); - return var; - } - - public JLocalVariable getLocalVariable(int index) { - for (int i = 0; i < localVariables.size(); i++) { - if (((JLocalVariable)localVariables.get(i)).index == index) - return (JLocalVariable)localVariables.get(i); - } - return null; - } - - public JLocalVariable[] getLocalVariables() { - return (JLocalVariable[])localVariables - .toArray(new JLocalVariable[localVariables.size()]); - } - - - public int getMaxLocals() { - return localVariableIndex; - } - - // Follows javap output format for methods. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(flagsToString()); - String name = getName(); - if (CLASS_CONSTRUCTOR_NAME.equals(name)) - buf.append("{}"); - else { - if (INSTANCE_CONSTRUCTOR_NAME.equals(name)) - name = getOwner().getName(); - else { - buf.append(toExternalName(getReturnType())); - buf.append(" "); - } - buf.append(toExternalName(name)); - buf.append("("); - JType[] ts = getArgumentTypes(); - for (int i = 0; i < ts.length; ++i) { - if (i > 0) buf.append(", "); - buf.append(toExternalName(ts[i])); - } - buf.append(")"); - } - buf.append(";\n"); - Iterator it = attributes.iterator(); - while(it.hasNext()) { - JAttribute attr = (JAttribute)it.next(); - buf.append(attr); - } - return buf.toString(); - } - - private String flagsToString() { - StringBuffer buf = new StringBuffer(); - if (isPublic()) buf.append("public "); - else if (isProtected()) buf.append("protected "); - else if (isPrivate()) buf.append("private "); - if (isBridge()) buf.append(" "); - if (hasVarargs()) buf.append(" "); - if (isStatic()) buf.append("static "); - else if (isNative()) buf.append("native "); - if (isAbstract()) buf.append("abstract "); - else if (isFinal()) buf.append("final "); - return buf.toString(); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JMethodType.java b/src/fjbg/ch/epfl/lamp/fjbg/JMethodType.java deleted file mode 100644 index cd3d71fd9cf1..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JMethodType.java +++ /dev/null @@ -1,87 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Type for Java methods. These types do not really exist in Java, but - * are provided here because they are useful in several places. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JMethodType extends JType { - protected final JType returnType; - protected final JType[] argTypes; - protected String signature = null; - - public final static JMethodType ARGLESS_VOID_FUNCTION = - new JMethodType(JType.VOID, JType.EMPTY_ARRAY); - - public JMethodType(JType returnType, JType[] argTypes) { - this.returnType = returnType; - this.argTypes = argTypes; - } - - public JType getReturnType() { return returnType; } - public JType[] getArgumentTypes() { return argTypes; } - - public int getSize() { - throw new UnsupportedOperationException(); - } - - public String getSignature() { - if (signature == null) { - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < argTypes.length; ++i) - buf.append(argTypes[i].getSignature()); - buf.append(')'); - buf.append(returnType.getSignature()); - signature = buf.toString(); - } - return signature; - } - - public int getTag() { return T_UNKNOWN; } - - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append('('); - for (int i = 0; i < argTypes.length; ++i) - buf.append(argTypes[i].toString()); - buf.append(')'); - buf.append(returnType.toString()); - return buf.toString(); - } - - public int getArgsSize() { - int size = 0; - for (int i = 0; i < argTypes.length; ++i) - size += argTypes[i].getSize(); - return size; - } - - public int getProducedStack() { - return returnType.getSize() - getArgsSize(); - } - - public boolean isCompatibleWith(JType other) { - return false; - } - public boolean equals(Object o) { - if (o instanceof JMethodType) - return ((JMethodType)o).getSignature().equals(this.getSignature()); - else - return false; - } - public int hashCode() { - if (signature == null) - return 0; - else - return signature.hashCode(); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JObjectType.java b/src/fjbg/ch/epfl/lamp/fjbg/JObjectType.java deleted file mode 100644 index 06db5b115a34..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JObjectType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Types for Java objects. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JObjectType extends JReferenceType { - protected final String name; - protected String signature = null; - - public final static JObjectType JAVA_LANG_OBJECT = - new JObjectType("java.lang.Object"); - public final static JObjectType JAVA_LANG_STRING = - new JObjectType("java.lang.String"); - public final static JObjectType CLONEABLE = - new JObjectType("Cloneable"); - public final static JObjectType JAVA_IO_SERIALIZABLE = - new JObjectType("java.io.Serializable"); - - public JObjectType(String name) { - this.name = name; - } - - public int getSize() { return 1; } - - public String getName() { return name; } - - public String getSignature() { - if (signature == null) - signature = "L" + name.replace('.','/') + ";"; - return signature; - } - - public String getDescriptor() { - return name.replace('.','/'); - } - - public int getTag() { return T_OBJECT; } - - public String toString() { return name; } - - public boolean isObjectType() { return true; } - - public boolean isCompatibleWith(JType other) { - return other instanceof JObjectType - || other == JType.REFERENCE; - } - public boolean equals(Object o) { - if (o instanceof JObjectType) - return ((JObjectType)o).getSignature().equals(this.getSignature()); - else - return false; - } - public int hashCode() { - return name.hashCode(); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java b/src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java deleted file mode 100644 index cc68681a9650..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JOpcode.java +++ /dev/null @@ -1,1267 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Definition of opcodes for the JVM. - * - * @author Michel Schinz, Thomas Friedli - * @version 1.0 - */ - -public class JOpcode { - public final String name; - public final int code; - - // The following attributes can be (statically) unknown for some - // instructions, and are therefore not public. To know their value, - // functions have to be used (see JCodeIterator). - protected final int size; - protected final JType[] producedDataTypes; - protected final JType[] consumedDataTypes; - protected final int jumpKind; - protected final int successorCount; - - protected final static int UNKNOWN = Integer.MIN_VALUE; - - protected final static int JMP_NONE = 0; - protected final static int JMP_NEXT = 1; - protected final static int JMP_ALWAYS_S2_OFFSET = 2; - protected final static int JMP_ALWAYS_S4_OFFSET = 3; - protected final static int JMP_MAYBE_S2_OFFSET = 4; - protected final static int JMP_TABLE = 5; - protected final static int JMP_LOOKUP = 6; - - protected final static JType[] NO_DATA = new JType[0]; - - protected final static JType[] INT_TYPE = - new JType[] { JType.INT }; - protected final static JType[] FLOAT_TYPE = - new JType[] { JType.FLOAT }; - protected final static JType[] LONG_TYPE = - new JType[] { JType.LONG }; - protected final static JType[] DOUBLE_TYPE = - new JType[] { JType.DOUBLE }; - protected final static JType[] OBJECT_REF_TYPE = - new JType[] { JObjectType.JAVA_LANG_OBJECT }; - protected final static JType[] ARRAY_REF_TYPE = - new JType[] { new JArrayType(JType.VOID) }; - protected final static JType[] REFERENCE_TYPE = - new JType[] { JType.REFERENCE }; - protected final static JType[] ADDRESS_TYPE = - new JType[] { JType.ADDRESS }; - protected final static JType[] UNKNOWN_TYPE = - new JType[] { JType.UNKNOWN }; - - /// Instruction codes - public final static int cNOP = 0; - public final static int cACONST_NULL = 1; - public final static int cICONST_M1 = 2; - public final static int cICONST_0 = 3; - public final static int cICONST_1 = 4; - public final static int cICONST_2 = 5; - public final static int cICONST_3 = 6; - public final static int cICONST_4 = 7; - public final static int cICONST_5 = 8; - public final static int cLCONST_0 = 9; - public final static int cLCONST_1 = 10; - public final static int cFCONST_0 = 11; - public final static int cFCONST_1 = 12; - public final static int cFCONST_2 = 13; - public final static int cDCONST_0 = 14; - public final static int cDCONST_1 = 15; - public final static int cBIPUSH = 16; - public final static int cSIPUSH = 17; - public final static int cLDC = 18; - public final static int cLDC_W = 19; - public final static int cLDC2_W = 20; - public final static int cILOAD = 21; - public final static int cLLOAD = 22; - public final static int cFLOAD = 23; - public final static int cDLOAD = 24; - public final static int cALOAD = 25; - public final static int cILOAD_0 = 26; - public final static int cILOAD_1 = 27; - public final static int cILOAD_2 = 28; - public final static int cILOAD_3 = 29; - public final static int cLLOAD_0 = 30; - public final static int cLLOAD_1 = 31; - public final static int cLLOAD_2 = 32; - public final static int cLLOAD_3 = 33; - public final static int cFLOAD_0 = 34; - public final static int cFLOAD_1 = 35; - public final static int cFLOAD_2 = 36; - public final static int cFLOAD_3 = 37; - public final static int cDLOAD_0 = 38; - public final static int cDLOAD_1 = 39; - public final static int cDLOAD_2 = 40; - public final static int cDLOAD_3 = 41; - public final static int cALOAD_0 = 42; - public final static int cALOAD_1 = 43; - public final static int cALOAD_2 = 44; - public final static int cALOAD_3 = 45; - public final static int cIALOAD = 46; - public final static int cLALOAD = 47; - public final static int cFALOAD = 48; - public final static int cDALOAD = 49; - public final static int cAALOAD = 50; - public final static int cBALOAD = 51; - public final static int cCALOAD = 52; - public final static int cSALOAD = 53; - public final static int cISTORE = 54; - public final static int cLSTORE = 55; - public final static int cFSTORE = 56; - public final static int cDSTORE = 57; - public final static int cASTORE = 58; - public final static int cISTORE_0 = 59; - public final static int cISTORE_1 = 60; - public final static int cISTORE_2 = 61; - public final static int cISTORE_3 = 62; - public final static int cLSTORE_0 = 63; - public final static int cLSTORE_1 = 64; - public final static int cLSTORE_2 = 65; - public final static int cLSTORE_3 = 66; - public final static int cFSTORE_0 = 67; - public final static int cFSTORE_1 = 68; - public final static int cFSTORE_2 = 69; - public final static int cFSTORE_3 = 70; - public final static int cDSTORE_0 = 71; - public final static int cDSTORE_1 = 72; - public final static int cDSTORE_2 = 73; - public final static int cDSTORE_3 = 74; - public final static int cASTORE_0 = 75; - public final static int cASTORE_1 = 76; - public final static int cASTORE_2 = 77; - public final static int cASTORE_3 = 78; - public final static int cIASTORE = 79; - public final static int cLASTORE = 80; - public final static int cFASTORE = 81; - public final static int cDASTORE = 82; - public final static int cAASTORE = 83; - public final static int cBASTORE = 84; - public final static int cCASTORE = 85; - public final static int cSASTORE = 86; - public final static int cPOP = 87; - public final static int cPOP2 = 88; - public final static int cDUP = 89; - public final static int cDUP_X1 = 90; - public final static int cDUP_X2 = 91; - public final static int cDUP2 = 92; - public final static int cDUP2_X1 = 93; - public final static int cDUP2_X2 = 94; - public final static int cSWAP = 95; - public final static int cIADD = 96; - public final static int cLADD = 97; - public final static int cFADD = 98; - public final static int cDADD = 99; - public final static int cISUB = 100; - public final static int cLSUB = 101; - public final static int cFSUB = 102; - public final static int cDSUB = 103; - public final static int cIMUL = 104; - public final static int cLMUL = 105; - public final static int cFMUL = 106; - public final static int cDMUL = 107; - public final static int cIDIV = 108; - public final static int cLDIV = 109; - public final static int cFDIV = 110; - public final static int cDDIV = 111; - public final static int cIREM = 112; - public final static int cLREM = 113; - public final static int cFREM = 114; - public final static int cDREM = 115; - public final static int cINEG = 116; - public final static int cLNEG = 117; - public final static int cFNEG = 118; - public final static int cDNEG = 119; - public final static int cISHL = 120; - public final static int cLSHL = 121; - public final static int cISHR = 122; - public final static int cLSHR = 123; - public final static int cIUSHR = 124; - public final static int cLUSHR = 125; - public final static int cIAND = 126; - public final static int cLAND = 127; - public final static int cIOR = 128; - public final static int cLOR = 129; - public final static int cIXOR = 130; - public final static int cLXOR = 131; - public final static int cIINC = 132; - public final static int cI2L = 133; - public final static int cI2F = 134; - public final static int cI2D = 135; - public final static int cL2I = 136; - public final static int cL2F = 137; - public final static int cL2D = 138; - public final static int cF2I = 139; - public final static int cF2L = 140; - public final static int cF2D = 141; - public final static int cD2I = 142; - public final static int cD2L = 143; - public final static int cD2F = 144; - public final static int cI2B = 145; - public final static int cI2C = 146; - public final static int cI2S = 147; - public final static int cLCMP = 148; - public final static int cFCMPL = 149; - public final static int cFCMPG = 150; - public final static int cDCMPL = 151; - public final static int cDCMPG = 152; - public final static int cIFEQ = 153; - public final static int cIFNE = 154; - public final static int cIFLT = 155; - public final static int cIFGE = 156; - public final static int cIFGT = 157; - public final static int cIFLE = 158; - public final static int cIF_ICMPEQ = 159; - public final static int cIF_ICMPNE = 160; - public final static int cIF_ICMPLT = 161; - public final static int cIF_ICMPGE = 162; - public final static int cIF_ICMPGT = 163; - public final static int cIF_ICMPLE = 164; - public final static int cIF_ACMPEQ = 165; - public final static int cIF_ACMPNE = 166; - public final static int cGOTO = 167; - public final static int cJSR = 168; - public final static int cRET = 169; - public final static int cTABLESWITCH = 170; - public final static int cLOOKUPSWITCH = 171; - public final static int cIRETURN = 172; - public final static int cLRETURN = 173; - public final static int cFRETURN = 174; - public final static int cDRETURN = 175; - public final static int cARETURN = 176; - public final static int cRETURN = 177; - public final static int cGETSTATIC = 178; - public final static int cPUTSTATIC = 179; - public final static int cGETFIELD = 180; - public final static int cPUTFIELD = 181; - public final static int cINVOKEVIRTUAL = 182; - public final static int cINVOKESPECIAL = 183; - public final static int cINVOKESTATIC = 184; - public final static int cINVOKEINTERFACE = 185; - public final static int cNEW = 187; - public final static int cNEWARRAY = 188; - public final static int cANEWARRAY = 189; - public final static int cARRAYLENGTH = 190; - public final static int cATHROW = 191; - public final static int cCHECKCAST = 192; - public final static int cINSTANCEOF = 193; - public final static int cMONITORENTER = 194; - public final static int cMONITOREXIT = 195; - public final static int cWIDE = 196; - public final static int cMULTIANEWARRAY = 197; - public final static int cIFNULL = 198; - public final static int cIFNONNULL = 199; - public final static int cGOTO_W = 200; - public final static int cJSR_W = 201; - - // Objects representing instructions - public final static JOpcode NOP = - new JOpcode("NOP", cNOP, 1, NO_DATA, NO_DATA, JMP_NEXT); - public final static JOpcode ACONST_NULL = new JOpcode("ACONST_NULL", - cACONST_NULL, - 1, - REFERENCE_TYPE, - NO_DATA, - JMP_NEXT); - public final static JOpcode ICONST_M1 = - new JOpcode("ICONST_M1", cICONST_M1, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ICONST_0 = - new JOpcode("ICONST_0", cICONST_0, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ICONST_1 = - new JOpcode("ICONST_1", cICONST_1, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ICONST_2 = - new JOpcode("ICONST_2", cICONST_2, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ICONST_3 = - new JOpcode("ICONST_3", cICONST_3, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ICONST_4 = - new JOpcode("ICONST_4", cICONST_4, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ICONST_5 = - new JOpcode("ICONST_5", cICONST_5, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LCONST_0 = - new JOpcode("LCONST_0", cLCONST_0, 1, LONG_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LCONST_1 = - new JOpcode("LCONST_1", cLCONST_1, 1, LONG_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FCONST_0 = - new JOpcode("FCONST_0", cFCONST_0, 1, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FCONST_1 = - new JOpcode("FCONST_1", cFCONST_1, 1, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FCONST_2 = - new JOpcode("FCONST_2", cFCONST_2, 1, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode DCONST_0 = - new JOpcode("DCONST_0", cDCONST_0, 1, DOUBLE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode DCONST_1 = - new JOpcode("DCONST_1", cDCONST_1, 1, DOUBLE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode BIPUSH = - new JOpcode("BIPUSH", cBIPUSH, 2, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode SIPUSH = - new JOpcode("SIPUSH", cSIPUSH, 3, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LDC = - new JOpcode("LDC", cLDC, 2, UNKNOWN_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LDC_W = - new JOpcode("LDC_W", cLDC_W, 3, UNKNOWN_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LDC2_W = - new JOpcode("LDC2_W", cLDC2_W, 3, UNKNOWN_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ILOAD = - new JOpcode("ILOAD", cILOAD, 2, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LLOAD = - new JOpcode("LLOAD", cLLOAD, 2, LONG_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FLOAD = - new JOpcode("FLOAD", cFLOAD, 2, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode DLOAD = - new JOpcode("DLOAD", cDLOAD, 2, DOUBLE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ALOAD = - new JOpcode("ALOAD", cALOAD, 2, REFERENCE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ILOAD_0 = - new JOpcode("ILOAD_0", cILOAD_0, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ILOAD_1 = - new JOpcode("ILOAD_1", cILOAD_1, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ILOAD_2 = - new JOpcode("ILOAD_2", cILOAD_2, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ILOAD_3 = - new JOpcode("ILOAD_3", cILOAD_3, 1, INT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LLOAD_0 = - new JOpcode("LLOAD_0", cLLOAD_0, 1, LONG_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LLOAD_1 = - new JOpcode("LLOAD_1", cLLOAD_1, 1, LONG_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LLOAD_2 = - new JOpcode("LLOAD_2", cLLOAD_2, 1, LONG_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode LLOAD_3 = - new JOpcode("LLOAD_3", cLLOAD_3, 1, LONG_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FLOAD_0 = - new JOpcode("FLOAD_0", cFLOAD_0, 1, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FLOAD_1 = - new JOpcode("FLOAD_1", cFLOAD_1, 1, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FLOAD_2 = - new JOpcode("FLOAD_2", cFLOAD_2, 1, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode FLOAD_3 = - new JOpcode("FLOAD_3", cFLOAD_3, 1, FLOAT_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode DLOAD_0 = - new JOpcode("DLOAD_0", cDLOAD_0, 1, DOUBLE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode DLOAD_1 = - new JOpcode("DLOAD_1", cDLOAD_1, 1, DOUBLE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode DLOAD_2 = - new JOpcode("DLOAD_2", cDLOAD_2, 1, DOUBLE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode DLOAD_3 = - new JOpcode("DLOAD_3", cDLOAD_3, 1, DOUBLE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ALOAD_0 = - new JOpcode("ALOAD_0", cALOAD_0, 1, REFERENCE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ALOAD_1 = - new JOpcode("ALOAD_1", cALOAD_1, 1, REFERENCE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ALOAD_2 = - new JOpcode("ALOAD_2", cALOAD_2, 1, REFERENCE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode ALOAD_3 = - new JOpcode("ALOAD_3", cALOAD_3, 1, REFERENCE_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode IALOAD = - new JOpcode("IALOAD", - cIALOAD, - 1, - INT_TYPE, - new JType[] {JType.INT, JArrayType.INT}, - JMP_NEXT); - public final static JOpcode LALOAD = - new JOpcode("LALOAD", - cLALOAD, - 1, - LONG_TYPE, - new JType[] {JType.INT, JArrayType.LONG}, - JMP_NEXT); - public final static JOpcode FALOAD = - new JOpcode("FALOAD", - cFALOAD, - 1, - FLOAT_TYPE, - new JType[] {JType.INT, JArrayType.FLOAT}, - JMP_NEXT); - public final static JOpcode DALOAD = - new JOpcode("DALOAD", - cDALOAD, - 1, - DOUBLE_TYPE, - new JType[] {JType.INT, JArrayType.DOUBLE}, - JMP_NEXT); - public final static JOpcode AALOAD = - new JOpcode("AALOAD", - cAALOAD, - 1, - REFERENCE_TYPE, - new JType[] {JType.INT, JArrayType.REFERENCE}, - JMP_NEXT); - public final static JOpcode BALOAD = - new JOpcode("BALOAD", - cBALOAD, - 1, - INT_TYPE, - new JType[] {JType.INT, new JArrayType(JType.UNKNOWN)}, - JMP_NEXT); - public final static JOpcode CALOAD = - new JOpcode("CALOAD", - cCALOAD, - 1, - INT_TYPE, - new JType[] {JType.INT, JArrayType.CHAR}, - JMP_NEXT); - public final static JOpcode SALOAD = - new JOpcode("SALOAD", - cSALOAD, - 1, - INT_TYPE, - new JType[] {JType.INT, JArrayType.SHORT}, - JMP_NEXT); - public final static JOpcode ISTORE = - new JOpcode("ISTORE", cISTORE, 2, NO_DATA, INT_TYPE, JMP_NEXT); - public final static JOpcode LSTORE = - new JOpcode("LSTORE", cLSTORE, 2, NO_DATA, LONG_TYPE, JMP_NEXT); - public final static JOpcode FSTORE = - new JOpcode("FSTORE", cFSTORE, 2, NO_DATA, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode DSTORE = - new JOpcode("DSTORE", cDSTORE, 2, NO_DATA, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode ASTORE = - new JOpcode("ASTORE", cASTORE, 2, NO_DATA, REFERENCE_TYPE, JMP_NEXT); - public final static JOpcode ISTORE_0 = - new JOpcode("ISTORE_0", cISTORE_0, 1, NO_DATA, INT_TYPE, JMP_NEXT); - public final static JOpcode ISTORE_1 = - new JOpcode("ISTORE_1", cISTORE_1, 1, NO_DATA, INT_TYPE, JMP_NEXT); - public final static JOpcode ISTORE_2 = - new JOpcode("ISTORE_2", cISTORE_2, 1, NO_DATA, INT_TYPE, JMP_NEXT); - public final static JOpcode ISTORE_3 = - new JOpcode("ISTORE_3", cISTORE_3, 1, NO_DATA, INT_TYPE, JMP_NEXT); - public final static JOpcode LSTORE_0 = - new JOpcode("LSTORE_0", cLSTORE_0, 1, NO_DATA, LONG_TYPE, JMP_NEXT); - public final static JOpcode LSTORE_1 = - new JOpcode("LSTORE_1", cLSTORE_1, 1, NO_DATA, LONG_TYPE, JMP_NEXT); - public final static JOpcode LSTORE_2 = - new JOpcode("LSTORE_2", cLSTORE_2, 1, NO_DATA, LONG_TYPE, JMP_NEXT); - public final static JOpcode LSTORE_3 = - new JOpcode("LSTORE_3", cLSTORE_3, 1, NO_DATA, LONG_TYPE, JMP_NEXT); - public final static JOpcode FSTORE_0 = - new JOpcode("FSTORE_0", cFSTORE_0, 1, NO_DATA, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode FSTORE_1 = - new JOpcode("FSTORE_1", cFSTORE_1, 1, NO_DATA, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode FSTORE_2 = - new JOpcode("FSTORE_2", cFSTORE_2, 1, NO_DATA, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode FSTORE_3 = - new JOpcode("FSTORE_3", cFSTORE_3, 1, NO_DATA, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode DSTORE_0 = - new JOpcode("DSTORE_0", cDSTORE_0, 1, NO_DATA, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode DSTORE_1 = - new JOpcode("DSTORE_1", cDSTORE_1, 1, NO_DATA, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode DSTORE_2 = - new JOpcode("DSTORE_2", cDSTORE_2, 1, NO_DATA, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode DSTORE_3 = - new JOpcode("DSTORE_3", cDSTORE_3, 1, NO_DATA, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode ASTORE_0 = new JOpcode("ASTORE_0", - cASTORE_0, - 1, - NO_DATA, - REFERENCE_TYPE, - JMP_NEXT); - public final static JOpcode ASTORE_1 = new JOpcode("ASTORE_1", - cASTORE_1, - 1, - NO_DATA, - REFERENCE_TYPE, - JMP_NEXT); - public final static JOpcode ASTORE_2 = new JOpcode("ASTORE_2", - cASTORE_2, - 1, - NO_DATA, - REFERENCE_TYPE, - JMP_NEXT); - public final static JOpcode ASTORE_3 = new JOpcode("ASTORE_3", - cASTORE_3, - 1, - NO_DATA, - REFERENCE_TYPE, - JMP_NEXT); - public final static JOpcode IASTORE = - new JOpcode("IASTORE", - cIASTORE, - 1, - NO_DATA, - new JType[] { JType.INT, - JType.INT, - JArrayType.INT}, - JMP_NEXT); - public final static JOpcode LASTORE = - new JOpcode("LASTORE", - cLASTORE, - 1, - NO_DATA, - new JType[] { JType.LONG, - JType.INT, - JArrayType.LONG}, - JMP_NEXT); - public final static JOpcode FASTORE = - new JOpcode("FASTORE", - cFASTORE, - 1, - NO_DATA, - new JType[] { JType.FLOAT, - JType.INT, - JArrayType.FLOAT}, - JMP_NEXT); - public final static JOpcode DASTORE = - new JOpcode("DASTORE", - cDASTORE, - 1, - NO_DATA, - new JType[] { JType.DOUBLE, - JType.INT, - JArrayType.DOUBLE}, - JMP_NEXT); - public final static JOpcode AASTORE = - new JOpcode("AASTORE", - cAASTORE, - 1, - NO_DATA, - new JType[] { JType.REFERENCE, - JType.INT, - JArrayType.REFERENCE}, - JMP_NEXT); - public final static JOpcode BASTORE = - new JOpcode("BASTORE", - cBASTORE, - 1, - NO_DATA, - new JType[] { JType.INT, - JType.INT, - new JArrayType(JType.UNKNOWN)}, - JMP_NEXT); - public final static JOpcode CASTORE = - new JOpcode("CASTORE", - cCASTORE, - 1, - NO_DATA, - new JType[] { JType.INT, - JType.INT, - JArrayType.CHAR}, - JMP_NEXT); - public final static JOpcode SASTORE = - new JOpcode("SASTORE", - cSASTORE, - 1, - NO_DATA, - new JType[] { JType.INT, - JType.INT, - JArrayType.SHORT}, - JMP_NEXT); - public final static JOpcode POP = - new JOpcode("POP", cPOP, 1, NO_DATA, UNKNOWN_TYPE, JMP_NEXT); - public final static JOpcode POP2 = - new JOpcode("POP2", cPOP2, 1, NO_DATA, UNKNOWN_TYPE, JMP_NEXT); - public final static JOpcode DUP = - new JOpcode("DUP", cDUP, 1, UNKNOWN_TYPE, UNKNOWN_TYPE, JMP_NEXT); - public final static JOpcode DUP_X1 = new JOpcode("DUP_X1", - cDUP_X1, - 1, - UNKNOWN_TYPE, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode DUP_X2 = new JOpcode("DUP_X2", - cDUP_X2, - 1, - UNKNOWN_TYPE, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode DUP2 = - new JOpcode("DUP2", cDUP2, 1, UNKNOWN_TYPE, UNKNOWN_TYPE, JMP_NEXT); - public final static JOpcode DUP2_X1 = new JOpcode("DUP2_X1", - cDUP2_X1, - 1, - UNKNOWN_TYPE, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode DUP2_X2 = new JOpcode("DUP2_X2", - cDUP2_X2, - 1, - UNKNOWN_TYPE, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode SWAP = - new JOpcode("SWAP", cSWAP, 1, UNKNOWN_TYPE, UNKNOWN_TYPE, JMP_NEXT); - public final static JOpcode IADD = - new JOpcode("IADD", - cIADD, - 1, - INT_TYPE, - new JType[] { JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LADD = - new JOpcode("LADD", - cLADD, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode FADD = - new JOpcode("FADD", - cFADD, - 1, - FLOAT_TYPE, - new JType[] { JType.FLOAT, JType.FLOAT }, - JMP_NEXT); - public final static JOpcode DADD = - new JOpcode("DADD", - cDADD, - 1, - DOUBLE_TYPE, - new JType[] { JType.DOUBLE, JType.DOUBLE }, - JMP_NEXT); - public final static JOpcode ISUB = - new JOpcode("ISUB", - cISUB, - 1, - INT_TYPE, - new JType[] {JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LSUB = - new JOpcode("LSUB", - cLSUB, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode FSUB = - new JOpcode("FSUB", - cFSUB, - 1, - FLOAT_TYPE, - new JType[] { JType.FLOAT, JType.FLOAT }, - JMP_NEXT); - public final static JOpcode DSUB = - new JOpcode("DSUB", - cDSUB, - 1, - DOUBLE_TYPE, - new JType[] { JType.DOUBLE, JType.DOUBLE }, - JMP_NEXT); - public final static JOpcode IMUL = - new JOpcode("IMUL", - cIMUL, - 1, - INT_TYPE, - new JType[] {JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LMUL = - new JOpcode("LMUL", - cLMUL, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode FMUL = - new JOpcode("FMUL", - cFMUL, - 1, - FLOAT_TYPE, - new JType[] { JType.FLOAT, JType.FLOAT }, - JMP_NEXT); - public final static JOpcode DMUL = - new JOpcode("DMUL", - cDMUL, - 1, - DOUBLE_TYPE, - new JType[] { JType.DOUBLE, JType.DOUBLE }, - JMP_NEXT); - public final static JOpcode IDIV = - new JOpcode("IDIV", - cIDIV, - 1, - INT_TYPE, - new JType[] {JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LDIV = - new JOpcode("LDIV", - cLDIV, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode FDIV = - new JOpcode("FDIV", - cFDIV, - 1, - FLOAT_TYPE, - new JType[] { JType.FLOAT, JType.FLOAT }, - JMP_NEXT); - public final static JOpcode DDIV = - new JOpcode("DDIV", - cDDIV, - 1, - DOUBLE_TYPE, - new JType[] { JType.DOUBLE, JType.DOUBLE }, - JMP_NEXT); - public final static JOpcode IREM = - new JOpcode("IREM", - cIREM, - 1, - INT_TYPE, - new JType[] {JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LREM = - new JOpcode("LREM", - cLREM, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode FREM = - new JOpcode("FREM", - cFREM, - 1, - FLOAT_TYPE, - new JType[] { JType.FLOAT, JType.FLOAT }, - JMP_NEXT); - public final static JOpcode DREM = - new JOpcode("DREM", - cDREM, - 1, - DOUBLE_TYPE, - new JType[] { JType.DOUBLE, JType.DOUBLE }, - JMP_NEXT); - public final static JOpcode INEG = - new JOpcode("INEG", cINEG, 1, INT_TYPE, INT_TYPE, JMP_NEXT); - public final static JOpcode LNEG = - new JOpcode("LNEG", cLNEG, 1, LONG_TYPE, LONG_TYPE, JMP_NEXT); - public final static JOpcode FNEG = - new JOpcode("FNEG", cFNEG, 1, FLOAT_TYPE, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode DNEG = - new JOpcode("DNEG", cDNEG, 1, DOUBLE_TYPE, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode ISHL = - new JOpcode("ISHL", cISHL, - 1, - INT_TYPE, - new JType[] { JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LSHL = - new JOpcode("LSHL", - cLSHL, - 1, - LONG_TYPE, - new JType [] { JType.INT, JType.LONG }, - JMP_NEXT); - public final static JOpcode ISHR = - new JOpcode("ISHR", - cISHR, - 1, - INT_TYPE, - new JType[] { JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LSHR = - new JOpcode("LSHR", - cLSHR, - 1, - LONG_TYPE, - new JType[] { JType.INT, JType.LONG }, - JMP_NEXT); - public final static JOpcode IUSHR = - new JOpcode("IUSHR", - cIUSHR, - 1, - INT_TYPE, - new JType[] { JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LUSHR = - new JOpcode("LUSHR", - cLUSHR, - 1, - LONG_TYPE, - new JType[] { JType.INT, JType.LONG }, - JMP_NEXT); - public final static JOpcode IAND = - new JOpcode("IAND", - cIAND, - 1, - INT_TYPE, - new JType[] { JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LAND = - new JOpcode("LAND", - cLAND, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode IOR = - new JOpcode("IOR", - cIOR, - 1, - INT_TYPE, - new JType[] { JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LOR = - new JOpcode("LOR", - cLOR, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode IXOR = - new JOpcode("IXOR", - cIXOR, - 1, - INT_TYPE, - new JType[] { JType.INT, JType.INT }, - JMP_NEXT); - public final static JOpcode LXOR = - new JOpcode("LXOR", - cLXOR, - 1, - LONG_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode IINC = - new JOpcode("IINC", cIINC, 3, NO_DATA, NO_DATA, JMP_NEXT); - public final static JOpcode I2L = - new JOpcode("I2L", cI2L, 1, LONG_TYPE, INT_TYPE, JMP_NEXT); - public final static JOpcode I2F = - new JOpcode("I2F", cI2F, 1, FLOAT_TYPE, INT_TYPE, JMP_NEXT); - public final static JOpcode I2D = - new JOpcode("I2D", cI2D, 1, DOUBLE_TYPE, INT_TYPE, JMP_NEXT); - public final static JOpcode L2I = - new JOpcode("L2I", cL2I, 1, INT_TYPE, LONG_TYPE, JMP_NEXT); - public final static JOpcode L2F = - new JOpcode("L2F", cL2F, 1, FLOAT_TYPE, LONG_TYPE, JMP_NEXT); - public final static JOpcode L2D = - new JOpcode("L2D", cL2D, 1, DOUBLE_TYPE, LONG_TYPE, JMP_NEXT); - public final static JOpcode F2I = - new JOpcode("F2I", cF2I, 1, INT_TYPE, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode F2L = - new JOpcode("F2L", cF2L, 1, LONG_TYPE, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode F2D = - new JOpcode("F2D", cF2D, 1, DOUBLE_TYPE, FLOAT_TYPE, JMP_NEXT); - public final static JOpcode D2I = - new JOpcode("D2I", cD2I, 1, INT_TYPE, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode D2L = - new JOpcode("D2L", cD2L, 1, LONG_TYPE, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode D2F = - new JOpcode("D2F", cD2F, 1, FLOAT_TYPE, DOUBLE_TYPE, JMP_NEXT); - public final static JOpcode I2B = - new JOpcode("I2B", cI2B, 1, INT_TYPE, INT_TYPE, JMP_NEXT); - public final static JOpcode I2C = - new JOpcode("I2C", cI2C, 1, INT_TYPE, INT_TYPE, JMP_NEXT); - public final static JOpcode I2S = - new JOpcode("I2S", cI2S, 1, INT_TYPE, INT_TYPE, JMP_NEXT); - public final static JOpcode LCMP = - new JOpcode("LCMP", - cLCMP, - 1, - INT_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode FCMPL = - new JOpcode("FCMPL", - cFCMPL, - 1, - INT_TYPE, - new JType[] { JType.FLOAT, JType.FLOAT }, - JMP_NEXT); - public final static JOpcode FCMPG = - new JOpcode("FCMPG", - cFCMPG, - 1, - INT_TYPE, - new JType[] { JType.FLOAT, JType.FLOAT }, - JMP_NEXT); - public final static JOpcode DCMPL = - new JOpcode("DCMPL", - cDCMPL, - 1, - INT_TYPE, - new JType[] { JType.LONG, JType.LONG }, - JMP_NEXT); - public final static JOpcode DCMPG = - new JOpcode("DCMPG", - cDCMPG, - 1, - INT_TYPE, - new JType[] { JType.DOUBLE, JType.DOUBLE }, - JMP_NEXT); - public final static JOpcode IFEQ = - new JOpcode("IFEQ", cIFEQ, 3, NO_DATA, INT_TYPE, JMP_MAYBE_S2_OFFSET); - public final static JOpcode IFNE = - new JOpcode("IFNE", cIFNE, 3, NO_DATA, INT_TYPE, JMP_MAYBE_S2_OFFSET); - public final static JOpcode IFLT = - new JOpcode("IFLT", cIFLT, 3, NO_DATA, INT_TYPE, JMP_MAYBE_S2_OFFSET); - public final static JOpcode IFGE = - new JOpcode("IFGE", cIFGE, 3, NO_DATA, INT_TYPE, JMP_MAYBE_S2_OFFSET); - public final static JOpcode IFGT = - new JOpcode("IFGT", cIFGT, 3, NO_DATA, INT_TYPE, JMP_MAYBE_S2_OFFSET); - public final static JOpcode IFLE = - new JOpcode("IFLE", cIFLE, 3, NO_DATA, INT_TYPE, JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ICMPEQ = - new JOpcode("IF_ICMPEQ", - cIF_ICMPEQ, - 3, - NO_DATA, - new JType[] { JType.INT, JType.INT }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ICMPNE = - new JOpcode("IF_ICMPNE", - cIF_ICMPNE, - 3, - NO_DATA, - new JType[] { JType.INT, JType.INT }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ICMPLT = - new JOpcode("IF_ICMPLT", - cIF_ICMPLT, - 3, - NO_DATA, - new JType[] { JType.INT, JType.INT }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ICMPGE = - new JOpcode("IF_ICMPGE", - cIF_ICMPGE, - 3, - NO_DATA, - new JType[] { JType.INT, JType.INT }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ICMPGT = - new JOpcode("IF_ICMPGT", - cIF_ICMPGT, - 3, - NO_DATA, - new JType[] { JType.INT, JType.INT }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ICMPLE = - new JOpcode("IF_ICMPLE", - cIF_ICMPLE, - 3, - NO_DATA, - new JType[] { JType.INT, JType.INT }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ACMPEQ = - new JOpcode("IF_ACMPEQ", - cIF_ACMPEQ, - 3, - NO_DATA, - new JType[] { JType.REFERENCE, JType.REFERENCE }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IF_ACMPNE = - new JOpcode("IF_ACMPNE", - cIF_ACMPNE, - 3, - NO_DATA, - new JType[] { JType.REFERENCE, JType.REFERENCE }, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode GOTO = - new JOpcode("GOTO", cGOTO, 3, NO_DATA, NO_DATA, JMP_ALWAYS_S2_OFFSET); - public final static JOpcode JSR = - new JOpcode("JSR", cJSR, 3, ADDRESS_TYPE, NO_DATA, JMP_ALWAYS_S2_OFFSET); - public final static JOpcode RET = - new JOpcode("RET", cRET, 2, NO_DATA, NO_DATA, JMP_NONE); - public final static JOpcode TABLESWITCH = new JOpcode("TABLESWITCH", - cTABLESWITCH, - UNKNOWN, - NO_DATA, - INT_TYPE, - JMP_TABLE); - public final static JOpcode LOOKUPSWITCH = new JOpcode("LOOKUPSWITCH", - cLOOKUPSWITCH, - UNKNOWN, - NO_DATA, - INT_TYPE, - JMP_LOOKUP); - public final static JOpcode IRETURN = - new JOpcode("IRETURN", cIRETURN, 1, NO_DATA, INT_TYPE, JMP_NONE); - public final static JOpcode LRETURN = - new JOpcode("LRETURN", cLRETURN, 1, NO_DATA, LONG_TYPE, JMP_NONE); - public final static JOpcode FRETURN = - new JOpcode("FRETURN", cFRETURN, 1, NO_DATA, FLOAT_TYPE, JMP_NONE); - public final static JOpcode DRETURN = - new JOpcode("DRETURN", cDRETURN, 1, NO_DATA, DOUBLE_TYPE, JMP_NONE); - public final static JOpcode ARETURN = new JOpcode("ARETURN", - cARETURN, - 1, - NO_DATA, - OBJECT_REF_TYPE, - JMP_NONE); - public final static JOpcode RETURN = - new JOpcode("RETURN", cRETURN, 1, NO_DATA, NO_DATA, JMP_NONE); - public final static JOpcode GETSTATIC = new JOpcode("GETSTATIC", - cGETSTATIC, - 3, - UNKNOWN_TYPE, - NO_DATA, - JMP_NEXT); - public final static JOpcode PUTSTATIC = new JOpcode("PUTSTATIC", - cPUTSTATIC, - 3, - NO_DATA, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode GETFIELD = new JOpcode("GETFIELD", - cGETFIELD, - 3, - UNKNOWN_TYPE, - OBJECT_REF_TYPE, - JMP_NEXT); - public final static JOpcode PUTFIELD = - new JOpcode("PUTFIELD", cPUTFIELD, 3, NO_DATA, UNKNOWN_TYPE, JMP_NEXT); - public final static JOpcode INVOKEVIRTUAL = new JOpcode("INVOKEVIRTUAL", - cINVOKEVIRTUAL, - 3, - NO_DATA, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode INVOKESPECIAL = new JOpcode("INVOKESPECIAL", - cINVOKESPECIAL, - 3, - NO_DATA, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode INVOKESTATIC = new JOpcode("INVOKESTATIC", - cINVOKESTATIC, - 3, - NO_DATA, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode INVOKEINTERFACE = - new JOpcode("INVOKEINTERFACE", - cINVOKEINTERFACE, - 5, - NO_DATA, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode NEW = - new JOpcode("NEW", cNEW, 3, OBJECT_REF_TYPE, NO_DATA, JMP_NEXT); - public final static JOpcode NEWARRAY = - new JOpcode("NEWARRAY", - cNEWARRAY, - 2, - ARRAY_REF_TYPE, - INT_TYPE, - JMP_NEXT); - public final static JOpcode ANEWARRAY = - new JOpcode("ANEWARRAY", - cANEWARRAY, - 3, - ARRAY_REF_TYPE, - INT_TYPE, - JMP_NEXT); - public final static JOpcode ARRAYLENGTH = new JOpcode("ARRAYLENGTH", - cARRAYLENGTH, - 1, - INT_TYPE, - ARRAY_REF_TYPE, - JMP_NEXT); - public final static JOpcode ATHROW = new JOpcode("ATHROW", - cATHROW, - 1, - OBJECT_REF_TYPE, - OBJECT_REF_TYPE, - JMP_NONE); - public final static JOpcode CHECKCAST = new JOpcode("CHECKCAST", - cCHECKCAST, - 3, - OBJECT_REF_TYPE, - OBJECT_REF_TYPE, - JMP_NEXT); - public final static JOpcode INSTANCEOF = new JOpcode("INSTANCEOF", - cINSTANCEOF, - 3, - INT_TYPE, - OBJECT_REF_TYPE, - JMP_NEXT); - public final static JOpcode MONITORENTER = new JOpcode("MONITORENTER", - cMONITORENTER, - 1, - NO_DATA, - OBJECT_REF_TYPE, - JMP_NEXT); - public final static JOpcode MONITOREXIT = new JOpcode("MONITOREXIT", - cMONITOREXIT, - 1, - NO_DATA, - OBJECT_REF_TYPE, - JMP_NEXT); - public final static JOpcode WIDE = new JOpcode("WIDE", - cWIDE, - UNKNOWN, - UNKNOWN_TYPE, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode MULTIANEWARRAY = new JOpcode("MULTIANEWARRAY", - cMULTIANEWARRAY, - 4, - ARRAY_REF_TYPE, - UNKNOWN_TYPE, - JMP_NEXT); - public final static JOpcode IFNULL = new JOpcode("IFNULL", - cIFNULL, - 3, - NO_DATA, - REFERENCE_TYPE, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode IFNONNULL = new JOpcode("IFNONNULL", - cIFNONNULL, - 3, - NO_DATA, - REFERENCE_TYPE, - JMP_MAYBE_S2_OFFSET); - public final static JOpcode GOTO_W = new JOpcode("GOTO_W", - cGOTO_W, - 5, - NO_DATA, - NO_DATA, - JMP_ALWAYS_S4_OFFSET); - public final static JOpcode JSR_W = - new JOpcode("JSR_W", cJSR_W, 5, ADDRESS_TYPE, NO_DATA, JMP_NEXT); - - public final static JOpcode[] OPCODES = { - NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, - ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, - LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, - DCONST_1, BIPUSH, SIPUSH, LDC, LDC_W, - LDC2_W, ILOAD, LLOAD, FLOAD, DLOAD, - ALOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, - LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, FLOAD_0, - FLOAD_1, FLOAD_2, FLOAD_3, DLOAD_0, DLOAD_1, - DLOAD_2, DLOAD_3, ALOAD_0, ALOAD_1, ALOAD_2, - ALOAD_3, IALOAD, LALOAD, FALOAD, DALOAD, - AALOAD, BALOAD, CALOAD, SALOAD, ISTORE, - LSTORE, FSTORE, DSTORE, ASTORE, ISTORE_0, - ISTORE_1, ISTORE_2, ISTORE_3, LSTORE_0, LSTORE_1, - LSTORE_2, LSTORE_3, FSTORE_0, FSTORE_1, FSTORE_2, - FSTORE_3, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, - ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, IASTORE, - LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, - CASTORE, SASTORE, POP, POP2, DUP, - DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, - SWAP, IADD, LADD, FADD, DADD, - ISUB, LSUB, FSUB, DSUB, IMUL, - LMUL, FMUL, DMUL, IDIV, LDIV, - FDIV, DDIV, IREM, LREM, FREM, - DREM, INEG, LNEG, FNEG, DNEG, - ISHL, LSHL, ISHR, LSHR, IUSHR, - LUSHR, IAND, LAND, IOR, LOR, - IXOR, LXOR, IINC, I2L, I2F, - I2D, L2I, L2F, L2D, F2I, - F2L, F2D, D2I, D2L, D2F, - I2B, I2C, I2S, LCMP, FCMPL, - FCMPG, DCMPL, DCMPG, IFEQ, IFNE, - IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, - IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, - IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, RET, - TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, - DRETURN, ARETURN, RETURN, GETSTATIC, PUTSTATIC, - GETFIELD, PUTFIELD, INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, - INVOKEINTERFACE, null, NEW, NEWARRAY, ANEWARRAY, - ARRAYLENGTH, ATHROW, CHECKCAST, INSTANCEOF, MONITORENTER, - MONITOREXIT, WIDE, MULTIANEWARRAY, IFNULL, IFNONNULL, - GOTO_W, JSR_W - }; - - protected JOpcode(String name, - int code, - int size, - JType[] producedDataTypes, - JType[] consumedDataTypes, - int jumpKind) { - this.name = name; - this.code = code; - this.size = size; - this.producedDataTypes = producedDataTypes; - this.consumedDataTypes = consumedDataTypes; - this.jumpKind = jumpKind; - switch (jumpKind) { - case JMP_NONE: successorCount = 0; break; - case JMP_NEXT: successorCount = 1; break; - case JMP_ALWAYS_S2_OFFSET: successorCount = 1; break; - case JMP_ALWAYS_S4_OFFSET: successorCount = 1; break; - case JMP_MAYBE_S2_OFFSET: successorCount = 2; break; - case JMP_TABLE: successorCount = UNKNOWN; break; - case JMP_LOOKUP: successorCount = UNKNOWN; break; - default: successorCount = UNKNOWN; break; - } - } - - public String toString() { return name; } - protected int getSize() { return size; } - protected JType[] getProducedDataTypes() { return producedDataTypes; } - protected JType[] getConsumedDataTypes() { return consumedDataTypes; } - - protected int getProducedDataSize() { - if (producedDataTypes != UNKNOWN_TYPE) - return JType.getTotalSize(producedDataTypes); - else { - switch (code) { - case cLDC: case cLDC_W: case cBALOAD: - return 1; - case cLDC2_W: case cDUP: case cSWAP: - return 2; - case cDUP_X1: - return 3; - case cDUP_X2: case cDUP2: - return 4; - case cDUP2_X1: - return 5; - case cDUP2_X2: - return 6; - default: - throw new Error(this.toString()); - } - } - } - - protected int getConsumedDataSize() { - if (consumedDataTypes != UNKNOWN_TYPE) - return JType.getTotalSize(consumedDataTypes); - else { - switch (code) { - case cPOP: case cDUP: - return 1; - case cPOP2: case cDUP_X1: case cDUP2: case cSWAP: - return 2; - case cDUP_X2: case cDUP2_X1: - return 3; - case cDUP2_X2: - return 4; - default: - throw new Error(this.toString()); - } - } - } - - protected int getProducedDataTypesNumber() { - if (producedDataTypes != UNKNOWN_TYPE) - return producedDataTypes.length; - else { - switch (code) { - case cLDC: case cLDC_W: case cLDC2_W: case cBALOAD: - case cGETSTATIC: case cGETFIELD: - return 1; - case cDUP: case cSWAP: - return 2; - case cDUP_X2: case cDUP2: case cDUP2_X1: case cDUP2_X2: - return 2; - case cDUP_X1: - return 3; - default: - throw new Error(this.toString()); - } - } - } - - protected int getConsumedDataTypesNumber() { - if (consumedDataTypes != UNKNOWN_TYPE) - return consumedDataTypes.length; - else { - switch (code) { - case cPOP: case cDUP: case cPUTSTATIC: - return 1; - case cPUTFIELD: case cDUP_X1: case cDUP_X2: - case cDUP2: case cDUP2_X1: case cPOP2: case cSWAP: - return 2; - default: - throw new Error(this.toString()); - } - } - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JOtherAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JOtherAttribute.java deleted file mode 100644 index 50aa9d36369b..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JOtherAttribute.java +++ /dev/null @@ -1,77 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * Attributes which are unknown to the JVM (or at least to this library). - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JOtherAttribute extends JAttribute { - protected final String name; - protected final byte[] contents; - protected final int length; - - public JOtherAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - byte[] contents, - int length) { - super(context, clazz, name); - this.name = name; - this.contents = contents; - this.length = length; - } - - public JOtherAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.name = name; - this.contents = new byte[size]; - this.length = size; - - stream.read(contents, 0, length); - } - - public String getName() { return name; } - - // Follows javap output format for user-defined attributes. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" "); - buf.append(name); - buf.append(": length = 0x"); - buf.append(Integer.toHexString(length).toUpperCase()); - for (int i = 0; i < length; ++i) { - if (i % 16 == 0) buf.append("\n "); - buf.append(hexString(contents[i])); - buf.append(" "); - } - buf.append("\n"); - return buf.toString(); - } - - protected int getSize() { return length; } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.write(contents, 0, length); - } - - private static final String hexString(int i) { - return ((0 <= i && i < 16) ? "0" : "")+Integer.toHexString(i).toUpperCase(); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JReferenceType.java b/src/fjbg/ch/epfl/lamp/fjbg/JReferenceType.java deleted file mode 100644 index 73d1026c0476..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JReferenceType.java +++ /dev/null @@ -1,19 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -/** - * Types for Java references, i.e. arrays and objects. - * - * @author Michel Schinz - * @version 1.0 - */ - -abstract public class JReferenceType extends JType { - public boolean isReferenceType() { return true; } - - abstract public String getDescriptor(); -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JSourceFileAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JSourceFileAttribute.java deleted file mode 100644 index 3a17cb2c446a..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JSourceFileAttribute.java +++ /dev/null @@ -1,69 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * Sourcefile attribute, which can be attached to class files to - * associate them with their source file. - * - * There can be no more than one SourceFile attribute in the attributes table - * of a given ClassFile structure. See section 4.8.9 of the JVM specification. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class JSourceFileAttribute extends JAttribute { - protected final String sourceFileName; - protected final int sourceFileIndex; - - public JSourceFileAttribute(FJBGContext context, - JClass clazz, - String sourceFileName) { - super(context, clazz); - this.sourceFileName = sourceFileName; - this.sourceFileIndex = clazz.getConstantPool().addUtf8(sourceFileName); - } - - public JSourceFileAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - - this.sourceFileIndex = stream.readShort(); - this.sourceFileName = clazz.getConstantPool().lookupUtf8(sourceFileIndex); - - assert name.equals(getName()); - } - - public String getName() { return "SourceFile"; } - - public String getFileName() { return sourceFileName; } - - // Follows javap output format for SourceFile attribute. - /*@Override*/ public String toString() { - StringBuffer buf = new StringBuffer(" SourceFile: \""); - buf.append(sourceFileName); - buf.append("\"\n"); - return buf.toString(); - } - - protected int getSize() { - return 2; // Short.SIZE - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(sourceFileIndex); - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JStackMapTableAttribute.java b/src/fjbg/ch/epfl/lamp/fjbg/JStackMapTableAttribute.java deleted file mode 100644 index 72a5484d405b..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JStackMapTableAttribute.java +++ /dev/null @@ -1,282 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * - * @author Stephane Micheloud - * @version 1.0 - */ - -public class JStackMapTableAttribute extends JAttribute { - /** Constant pool of the current classfile. */ - private JConstantPool pool; - - /** StackMapTable entries */ - protected final List/**/ entries = new ArrayList(); - protected int entriesSize = 0; - protected boolean usesU2; - - public JStackMapTableAttribute(FJBGContext context, - JClass clazz, - JCode code) { - super(context, clazz); - this.pool = clazz.pool; - - assert code.getOwner().getOwner() == clazz; - } - - public JStackMapTableAttribute(FJBGContext context, - JClass clazz, - Object owner, - String name, - int size, - DataInputStream stream) - throws IOException { - super(context, clazz, name); - this.pool = clazz.pool; - - int count = stream.readShort(); - this.usesU2 = count < 65536; - for (int i = 0; i < count; ++i) - this.entries.add(new Frame(stream)); - this.entriesSize = computeSize(); - - assert name.equals(getName()); - } - - public String getName() { return "StackMapTable"; } - - // Follows javap output format for StackMapTable attribute. - /*@Override*/ public String toString() { - Frame frame = null; - StringBuffer buf = new StringBuffer(" StackMapTable: number_of_entries = "); - buf.append(entries.size()); - Iterator it = entries.iterator(); - while (it.hasNext()) { - frame = (Frame)it.next(); - buf.append("\n frame_type = "); - buf.append(frame.tag); - buf.append(" /* "); - buf.append(getFrameType(frame.tag)); - buf.append(" */"); - if (frame.offsetDelta != -1) - buf.append("\n offset_delta = "+frame.offsetDelta); - if (frame.locals != null) - appendTypeInfoArray(buf, "locals", frame.locals); - if (frame.stackItems != null) - appendTypeInfoArray(buf, "stack", frame.stackItems); - } - buf.append("\n"); - return buf.toString(); - } - - protected int getSize() { - return entriesSize; - } - - protected void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeShort(entriesSize); - Iterator it = entries.iterator(); - while (it.hasNext()) { - Frame frame = (Frame)it.next(); - frame.writeContentsTo(stream); - } - } - - private class TypeInfo { - final int tag; - final int poolIndexOrOffset; // tag == 7 => poolIndex, tag = 8 => offset - private int bytes; - TypeInfo(DataInputStream stream) throws IOException { - int size = 1; - this.tag = stream.readByte(); - if (tag == 7) { // ITEM_Object; // 7 - poolIndexOrOffset = stream.readShort(); - size += 2; - } else if (tag == 8) { // ITEM_Uninitialized // 8 - poolIndexOrOffset = (usesU2) ? stream.readShort() : stream.readInt(); - size += (usesU2) ? 2 : 4; - } else - poolIndexOrOffset = -1; - this.bytes += size; - } - int getSize() { return bytes; } - void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeByte(tag); - if (tag == 7) { // ITEM_Object; // 7 - stream.writeShort(poolIndexOrOffset); - } else if (tag == 8) { // ITEM_Uninitialized // 8 - if (usesU2) stream.writeShort(poolIndexOrOffset); - else stream.writeInt(poolIndexOrOffset); - } - } - /*@Override*/ public String toString() { - switch (tag) { - case 0: // ITEM_Top - return ""; - case 1: // ITEM_Integer - return "int"; - case 2: // ITEM_Float - return "float"; - case 3: // ITEM_Double - return "double"; - case 4: // ITEM_Long - return "long"; - case 5: // ITEM_Null - return "null"; - case 6: // ITEM_UninializedThis - return "this"; - case 7: // ITEM_Object - String name = pool.lookupClass(poolIndexOrOffset); - if (name.startsWith("[")) name = "\""+name+"\""; - return "class "+name; - case 8: // ITEM_Uninitialized - return ""; - default: - return String.valueOf(tag); - } - } - } - - private class Frame { - final int tag; - int offsetDelta = -1; - TypeInfo[] stackItems = null; - TypeInfo[] locals = null; - private int bytes; - Frame(DataInputStream stream) throws IOException { - // The stack_map_frame structure consists of a one-byte tag - // followed by zero or more bytes. - this.tag = stream.readUnsignedByte(); - if (tag < 64) { // SAME; // 0-63 - //done - } else if (tag < 128) { // SAME_LOCALS_1_STACK_ITEM; // 64-127 - this.offsetDelta = tag - 64; - readStackItems(stream, 1); - } else if (tag < 248) { // reserved for future use. - assert false : "Tags in the range [128-247] are reserved for future use."; - } else if (tag < 251) { // CHOP; // 248-250 - int k = 251 - tag; - readOffsetDelta(stream); - } else if (tag == 251) { // SAME_FRAME_EXTENDED - readOffsetDelta(stream); - } else if (tag < 255) { // APPEND; // 252-254 - readOffsetDelta(stream); - readLocals(stream, tag - 251); - } else { // FULL_FRAME; // 255 - readOffsetDelta(stream); - readLocals(stream); - readStackItems(stream); - } - } - int getSize() { return bytes; } - void readOffsetDelta(DataInputStream stream) throws IOException { - this.offsetDelta = (usesU2) ? stream.readShort() : stream.readInt(); - this.bytes += (usesU2) ? 2 : 4; - } - int getOffsetDelta() { return offsetDelta; } - void readStackItems(DataInputStream stream, int k) throws IOException { - this.stackItems = new TypeInfo[k]; - for (int i = 0; i < k; ++i) { - stackItems[i] = new TypeInfo(stream); - this.bytes += stackItems[i].getSize(); - } - } - void readStackItems(DataInputStream stream) throws IOException { - int k = (usesU2) ? stream.readShort() : stream.readInt(); - this.bytes += (usesU2) ? 2 : 4; - readStackItems(stream, k); - } - void readLocals(DataInputStream stream, int k) throws IOException { - this.locals = new TypeInfo[k]; - for (int i = 0; i < k; ++i) { - locals[i] = new TypeInfo(stream); - this.bytes += locals[i].getSize(); - } - } - void readLocals(DataInputStream stream) throws IOException { - int k = (usesU2) ? stream.readShort() : stream.readInt(); - this.bytes += (usesU2) ? 2 : 4; - readLocals(stream, k); - } - void writeContentsTo(DataOutputStream stream) throws IOException { - stream.writeByte(tag); - if (tag < 64) { - //done - } else if (tag < 128) { // SAME; // 0-63 - assert stackItems.length == 1; - stackItems[0].writeContentsTo(stream); - } else if (tag < 248) { - assert false : "Tags in the range [128-247] are reserved for future use."; - } else if (tag < 251) { - if (usesU2) stream.writeShort(offsetDelta); - else stream.writeInt(offsetDelta); - } else if (tag == 251) { - if (usesU2) stream.writeShort(offsetDelta); - else stream.writeInt(offsetDelta); - } else if (tag < 255) { // APPEND; // 252-254 - if (usesU2) stream.writeShort(offsetDelta); - else stream.writeInt(offsetDelta); - for (int i = 0; i < locals.length; ++i) - locals[i].writeContentsTo(stream); - } else { - if (usesU2) stream.writeShort(offsetDelta); - else stream.writeInt(offsetDelta); - for (int i = 0; i < locals.length; ++i) - locals[i].writeContentsTo(stream); - for (int i = 0; i < stackItems.length; ++i) - stackItems[i].writeContentsTo(stream); - } - } - } - - private int computeSize() { - int size = (usesU2) ? 2 : 4; // number of frames - Iterator it = entries.iterator(); - while (it.hasNext()) { - Frame frame = (Frame)it.next(); - size += frame.getSize(); - } - return size; - } - - private static final String getFrameType(int tag) { - if (tag < 64) return "same"; - else if (tag < 128) return "same locals 1 stack item"; - else if (tag < 248) return ""; - else if (tag < 251) return "chop"; - else if (tag == 251) return "same frame extended"; - else if (tag < 255) return "append"; - else return "full frame"; - } - - private static StringBuffer appendTypeInfoArray(StringBuffer buf, - String s, TypeInfo[] a) { - buf.append("\n "); - buf.append(s); - buf.append(" = "); - if (a.length > 0) { - buf.append("[ "); - for (int i = 0; i < a.length; ++i) { - if (i > 0) buf.append(", "); - buf.append(a[i]); - } - buf.append(" ]"); - } - else - buf.append("[]"); - return buf; - } - -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/JType.java b/src/fjbg/ch/epfl/lamp/fjbg/JType.java deleted file mode 100644 index 298a2b056555..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/JType.java +++ /dev/null @@ -1,316 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; - -/** - * Representation of Java types. - * - * @version 1.0 - * @author Michel Schinz - */ - -abstract public class JType { - abstract public int getSize(); - abstract public String getSignature(); - abstract public int getTag(); - abstract public String toString(); - abstract public boolean isCompatibleWith(JType other); - - public boolean isValueType() { return false; } - public boolean isObjectType() { return false; } - public boolean isArrayType() { return false; } - public boolean isReferenceType() { return false; } - - // Tags for types. Taken from BCEL. - public static final int T_BOOLEAN = 4; - public static final int T_CHAR = 5; - public static final int T_FLOAT = 6; - public static final int T_DOUBLE = 7; - public static final int T_BYTE = 8; - public static final int T_SHORT = 9; - public static final int T_INT = 10; - public static final int T_LONG = 11; - public static final int T_VOID = 12; // Non-standard - public static final int T_ARRAY = 13; - public static final int T_OBJECT = 14; - public static final int T_UNKNOWN = 15; - public static final int T_ADDRESS = 16; - - public static final int T_REFERENCE = 17; // type compatible with references - - public static final JType[] EMPTY_ARRAY = new JType[0]; - - protected static JType parseSig(StringReader s) throws IOException { - int nextChar = s.read(); - if (nextChar == -1) throw new IllegalArgumentException(); - - switch ((char)nextChar) { - case 'V' : return VOID; - case 'Z' : return BOOLEAN; - case 'B' : return BYTE; - case 'C' : return CHAR; - case 'S' : return SHORT; - case 'I' : return INT; - case 'F' : return FLOAT; - case 'J' : return LONG; - case 'D' : return DOUBLE; - case 'L': { - StringBuffer className = new StringBuffer(); - for (;;) { - nextChar = s.read(); - if (nextChar == -1 || nextChar == ';') break; - className.append(nextChar == '/' ? ':' : ((char)nextChar)); - } - if (nextChar != ';') throw new IllegalArgumentException(); - return new JObjectType(className.toString()); - } - case '[': { - JType elemType = parseSig(s); - return new JArrayType(elemType); - } - case '(': { - ArrayList argTps = new ArrayList(); - for (;;) { - s.mark(1); - nextChar = s.read(); - if (nextChar == -1 || nextChar == ')') break; - s.reset(); - argTps.add(parseSig(s)); - } - if (nextChar != ')') throw new IllegalArgumentException("a"); - JType[] argTpsA = (JType[])argTps.toArray(new JType[argTps.size()]); - JType returnType = parseSig(s); - return new JMethodType(returnType, argTpsA); - } - default: - throw new IllegalArgumentException(); - } - } - - /** - * A signature is a string representing the generic type of a field or - * method, or generic type information for a class declaration. - * See section 4.4.4 of the JVM specification. - */ - public static JType parseSignature(String signature) { - try { - StringReader sigReader = new StringReader(signature); - JType parsed = parseSig(sigReader); - if (sigReader.read() != -1) - throw new IllegalArgumentException(); - return parsed; - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("invalid signature " + signature); - } catch (IOException e) { - throw new Error(e); - } - } - - public static int getTotalSize(JType[] types) { - int size = 0; - for (int i = 0; i < types.length; ++i) - size += types[i].getSize(); - return size; - } - - protected JType() {} - - public static JType VOID = new JType() { - public int getSize() { return 0; } - public String getSignature() { return "V"; } - public int getTag() { return T_VOID; } - public String toString() { return "void"; } - public boolean isCompatibleWith(JType other) { - throw new UnsupportedOperationException("type VOID is no real " - + "data type therefore " - + "cannot be assigned to " - + other.toString()); - } - }; - - public static JType BOOLEAN = new JType() { - public int getSize() { return 1; } - public String getSignature() { return "Z"; } - public int getTag() { return T_BOOLEAN; } - public String toString() { return "boolean"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == BOOLEAN - || other == INT - || other == BYTE - || other == CHAR - || other == SHORT; - } - }; - - public static JType BYTE = new JType() { - public int getSize() { return 1; } - public String getSignature() { return "B"; } - public int getTag() { return T_BYTE; } - public String toString() { return "byte"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == BOOLEAN - || other == INT - || other == BYTE - || other == CHAR - || other == SHORT; - } - }; - - public static JType CHAR = new JType() { - public int getSize() { return 1; } - public String getSignature() { return "C"; } - public int getTag() { return T_CHAR; } - public String toString() { return "char"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == BOOLEAN - || other == INT - || other == BYTE - || other == CHAR - || other == SHORT; - } - }; - - public static JType SHORT = new JType() { - public int getSize() { return 1; } - public String getSignature() { return "S"; } - public int getTag() { return T_SHORT; } - public String toString() { return "short"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == BOOLEAN - || other == INT - || other == BYTE - || other == CHAR - || other == SHORT; - } - }; - - public static JType INT = new JType() { - public int getSize() { return 1; } - public String getSignature() { return "I"; } - public int getTag() { return T_INT; } - public String toString() { return "int"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == BOOLEAN - || other == INT - || other == BYTE - || other == CHAR - || other == SHORT; - } - }; - - public static JType FLOAT = new JType() { - public int getSize() { return 1; } - public String getSignature() { return "F"; } - public int getTag() { return T_FLOAT; } - public String toString() { return "float"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == FLOAT; - } - }; - - public static JType LONG = new JType() { - public int getSize() { return 2; } - public String getSignature() { return "J"; } - public int getTag() { return T_LONG; } - public String toString() { return "long"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == LONG; - } - }; - - public static JType DOUBLE = new JType() { - public int getSize() { return 2; } - public String getSignature() { return "D"; } - public int getTag() { return T_DOUBLE; } - public String toString() { return "double"; } - public boolean isValueType() { return true; } - public boolean isCompatibleWith(JType other) { - return other == DOUBLE; - } - }; - - public static JType REFERENCE = new JType() { - public int getSize() { return 1; } - public String getSignature() { - throw new UnsupportedOperationException("type REFERENCE is no real " - + "data type and therefore " - + "has no signature"); - } - public int getTag() { return T_REFERENCE; } - public String toString() { return ""; } - public boolean isCompatibleWith(JType other) { - throw new UnsupportedOperationException("type REFERENCE is no real " - + "data type and therefore " - + "cannot be assigned to " - + other.toString()); - } - }; - - public static JType ADDRESS = new JType() { - public int getSize() { return 1; } - public String getSignature() { - throw new UnsupportedOperationException("type ADDRESS is no usable " - + "data type and therefore " - + "has no signature"); - } - public int getTag() { return T_ADDRESS; } - public String toString() { return "
"; } - public boolean isCompatibleWith(JType other) { - return other == ADDRESS; - } - }; - - public static JType UNKNOWN = new JType() { - public int getSize() { - throw new UnsupportedOperationException("type UNKNOWN is no real " - + "data type and therefore " - + "has no size"); - } - public String getSignature() { - throw new UnsupportedOperationException("type UNKNOWN is no real " - + "data type and therefore " - + "has no signature"); - } - public int getTag() { return T_UNKNOWN; } - public String toString() { return ""; } - public boolean isCompatibleWith(JType other) { - throw new UnsupportedOperationException("type UNKNOWN is no real " - + "data type and therefore " - + "cannot be assigned to " - + other.toString()); - } - }; - - protected static String tagToString(int tag) { - switch (tag) { - case T_BOOLEAN : return "boolean"; - case T_CHAR : return "char"; - case T_FLOAT : return "float"; - case T_DOUBLE : return "double"; - case T_BYTE : return "byte"; - case T_SHORT : return "short"; - case T_INT : return "int"; - case T_LONG : return "long"; - case T_VOID : return "void"; // Non-standard - case T_ARRAY : return "[]"; - case T_OBJECT : return "Object"; - case T_UNKNOWN : return ""; - case T_ADDRESS : return "
"; - default: return String.valueOf(tag); - } - } -} diff --git a/src/fjbg/ch/epfl/lamp/fjbg/Main.java b/src/fjbg/ch/epfl/lamp/fjbg/Main.java deleted file mode 100644 index 810ee7c4009f..000000000000 --- a/src/fjbg/ch/epfl/lamp/fjbg/Main.java +++ /dev/null @@ -1,131 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.fjbg; - -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; - -/** - * Main program entry to execute the FJBG reader from the command line. - * - * The reader prints out the decoded data in the same output format as - * javap, the Java bytecode disassembler of the Sun J2SE SDK. - * - * @author Stephane Micheloud - * @version 1.1 - */ - -public class Main { - private static final String PRODUCT_STRING = "Fast Java Bytecode Generator"; - private static final String VERSION_STRING = "version 1.1"; - - private static final int ACTION_USAGE = 0; - private static final int ACTION_DONE = 1; - private static final int ACTION_PROCEED = 2; - - private static String classPath = "."; - private static String[] classNames = null; - - public static void main(String[] args) { - switch (parseArgs(args)) { - case ACTION_USAGE: printUsage(); break; - case ACTION_PROCEED: processClasses(); break; - default: - } - } - - private static void processClasses() { - FJBGContext fjbgContext = new FJBGContext(49, 0); - if (classNames.length > 0) - try { - for (int i = 0; i < classNames.length; ++i) - processClass(fjbgContext, classNames[i]); - } catch (IOException e) { - System.err.println(e.getMessage()); - } - else - System.err.println( - "No classes were specified on the command line. Try -help."); - } - - private static void processClass(FJBGContext fjbgContext, String className) - throws IOException { - InputStream in = getInputStream(className); - JClass jclass = fjbgContext.JClass(new DataInputStream(in)); - System.out.println(jclass); - in.close(); - } - - private static InputStream getInputStream(String className) throws IOException { - String name = null; - String[] paths = classPath.split(File.pathSeparator); - for (int i = 0; i < paths.length; ++i) { - File parent = new File(paths[i]); - if (parent.isDirectory()) { - name = className.replace('.', File.separatorChar)+".class"; - File f = new File(parent, name); - if (f.isFile()) return new FileInputStream(f); - } else if (paths[i].endsWith(".jar")) { - JarFile f = new JarFile(parent); - name = className.replace('.', '/')+".class"; - ZipEntry e = f.getEntry(name); - if (e != null) return f.getInputStream(e); - } - } - throw new IOException("ERROR:Could not find "+className); - } - - private static int parseArgs(String[] args) { - ArrayList/**/ classes = new ArrayList(); - String arg = null; - int action = ACTION_USAGE; - int i = 0, n = args.length; - while (i < n) { - arg = args[i]; - if (arg.equals("-classpath") && (i+1) < n) { - classPath = args[i+1]; i += 2; - } else if (arg.equals("-cp") && (i+1) < n) { - classPath = args[i+1]; i += 2; - } else if (arg.equals("-help")) { - i = n+1; - //} else if (arg.equals("-v")) { - // verbose = true; i += 1; - } else if (arg.equals("-version")) { - System.err.println(PRODUCT_STRING+" "+VERSION_STRING); - action = ACTION_DONE; i = n+1; - } else if (arg.startsWith("-")) { - System.err.println("invalid flag: "+arg); - i = n+1; - } else { - classes.add(arg); i += 1; - } - } - if (i == n && i > 0) { - classNames = (String[])classes.toArray(new String[classes.size()]); - action = ACTION_PROCEED; - } - return action; - } - - private static void printUsage() { - System.out.println("Usage: fjbg "); - System.out.println(); - System.out.println("where possible options include:"); - System.out.println(" -cp Specify where to find user class files"); - System.out.println(" -classpath Specify where to find user class files"); - System.out.println(" -help Print a synopsis of standard options"); - System.out.println(" -version Version information"); - System.out.println(); - System.exit(1); - } -} - diff --git a/src/fjbg/ch/epfl/lamp/util/ByteArray.java b/src/fjbg/ch/epfl/lamp/util/ByteArray.java deleted file mode 100644 index b852e1ac1f30..000000000000 --- a/src/fjbg/ch/epfl/lamp/util/ByteArray.java +++ /dev/null @@ -1,145 +0,0 @@ -/* FJBG -- Fast Java Bytecode Generator - * Copyright 2002-2013 LAMP/EPFL - * @author Michel Schinz - */ - -package ch.epfl.lamp.util; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Array of bytes. - * - * @author Michel Schinz - * @version 1.0 - */ - -public class ByteArray { - protected final static int BYTE_BLOCK_BITS = 8; - protected final static int BYTE_BLOCK_SIZE = 1 << BYTE_BLOCK_BITS; - protected final static int BYTE_BLOCK_MASK = BYTE_BLOCK_SIZE - 1; - - protected byte[][] data = new byte[][] { new byte[BYTE_BLOCK_SIZE] }; - protected int pos = 0; // The next free position. - - protected boolean frozen = false; - - public ByteArray() { } - - public ByteArray(InputStream stream, int size) throws IOException { - pos = size; - for (int i = 0; size > 0; ++i) { - int sizeToRead = Math.min(BYTE_BLOCK_SIZE, size); - stream.read(data[i], 0, sizeToRead); - - size -= sizeToRead; - if (size > 0) addNewBlock(); - } - } - - public void freeze() { frozen = true; } - - public int nextBytePosition() { - return pos; - } - - public int getSize() { - return pos; - } - - protected void addNewBlock() { - int nextBlockPos = pos >>> BYTE_BLOCK_BITS; - if (nextBlockPos == data.length) { - byte[][] newData = new byte[data.length * 2][]; - System.arraycopy(data, 0, newData, 0, data.length); - data = newData; - } - assert data[nextBlockPos] == null : pos + " " + nextBlockPos; - data[nextBlockPos] = new byte[BYTE_BLOCK_SIZE]; - } - - protected void addByte(int b) { - assert !frozen; - - if ((pos & BYTE_BLOCK_MASK) == 0 && pos > 0) - addNewBlock(); - int currPos = pos++; - data[currPos >>> BYTE_BLOCK_BITS][currPos & BYTE_BLOCK_MASK] = (byte)b; - } - - public void addU1(int i) { - assert i <= 0xFF : i; - addByte(i); - } - - public void addU2(int i) { - assert i <= 0xFFFF : i; - - addByte(i >>> 8); - addByte(i & 0xFF); - } - - public void addU4(int i) { - addByte(i >>> 24); - addByte((i >>> 16) & 0xFF); - addByte((i >>> 8) & 0xFF); - addByte(i & 0xFF); - } - - public void putByte(int targetPos, int b) { - assert !frozen; - assert targetPos < pos : targetPos + " >= " + pos; - - data[targetPos >>> BYTE_BLOCK_BITS][targetPos & BYTE_BLOCK_MASK] = (byte)b; - } - - public void putU2(int targetPos, int i) { - assert i < 0xFFFF : i; - putByte(targetPos, i >>> 8); - putByte(targetPos + 1, i & 0xFF); - } - - public void putU4(int targetPos, int i) { - putByte(targetPos, i >>> 24); - putByte(targetPos + 1, (i >>> 16) & 0xFF); - putByte(targetPos + 2, (i >>> 8) & 0xFF); - putByte(targetPos + 3, i & 0xFF); - } - - public int getU1(int sourcePos) { - assert sourcePos < pos : sourcePos + " >= " + pos; - return data[sourcePos >>> BYTE_BLOCK_BITS][sourcePos & BYTE_BLOCK_MASK] & 0xFF; - } - - public int getU2(int sourcePos) { - return (getU1(sourcePos) << 8) | getU1(sourcePos + 1); - } - - public int getU4(int sourcePos) { - return (getU2(sourcePos) << 16) | getU2(sourcePos + 2); - } - - public int getS1(int sourcePos) { - assert sourcePos < pos : sourcePos + " >= " + pos; - return data[sourcePos >>> BYTE_BLOCK_BITS][sourcePos & BYTE_BLOCK_MASK]; - } - - public int getS2(int sourcePos) { - return (getS1(sourcePos) << 8) | getU1(sourcePos + 1); - } - - public int getS4(int sourcePos) { - return (getS2(sourcePos) << 16) | getU2(sourcePos + 2); - } - - public void writeTo(OutputStream stream) throws IOException { - if (!frozen) freeze(); - - for (int i = 0; i < data.length && data[i] != null; ++i) { - int len = Math.min(BYTE_BLOCK_SIZE, pos - (i << BYTE_BLOCK_BITS)); - stream.write(data[i], 0, len); - } - } -} diff --git a/src/intellij/compiler.iml.SAMPLE b/src/intellij/compiler.iml.SAMPLE index 696c347b7b05..f8b1f3132751 100644 --- a/src/intellij/compiler.iml.SAMPLE +++ b/src/intellij/compiler.iml.SAMPLE @@ -20,8 +20,6 @@ - - diff --git a/src/intellij/fjbg.iml.SAMPLE b/src/intellij/fjbg.iml.SAMPLE deleted file mode 100644 index 03eca6924630..000000000000 --- a/src/intellij/fjbg.iml.SAMPLE +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/src/intellij/msil.iml.SAMPLE b/src/intellij/msil.iml.SAMPLE deleted file mode 100644 index 56f794785f8d..000000000000 --- a/src/intellij/msil.iml.SAMPLE +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/intellij/scala-lang.ipr.SAMPLE b/src/intellij/scala-lang.ipr.SAMPLE index 37307c202970..a8cb5eacc1bb 100644 --- a/src/intellij/scala-lang.ipr.SAMPLE +++ b/src/intellij/scala-lang.ipr.SAMPLE @@ -198,11 +198,9 @@ - - @@ -230,7 +228,6 @@ - diff --git a/src/intellij/test.iml.SAMPLE b/src/intellij/test.iml.SAMPLE index 112fec428fd3..3ce369be0515 100644 --- a/src/intellij/test.iml.SAMPLE +++ b/src/intellij/test.iml.SAMPLE @@ -12,9 +12,7 @@ - - diff --git a/src/manual/scala/man1/scalac.scala b/src/manual/scala/man1/scalac.scala index 13b1fd58e0b4..1c0c7c4a9646 100644 --- a/src/manual/scala/man1/scalac.scala +++ b/src/manual/scala/man1/scalac.scala @@ -145,13 +145,6 @@ object scalac extends Command { Definition( CmdOption("sourcepath", Argument("path")), "Specify location(s) of source files."), - Definition( - CmdOptionBound("target:", Argument("target")), - SeqPara( - "Specify which backend to use (" & Mono("jvm-1.5," & - "msil") & ").", - "The default value is " & Mono("\"jvm-1.5\"") & " (was " & - Mono("\"jvm-1.4\"") & " up to Scala version 2.6.1).")), Definition( CmdOption("toolcp", Argument("path")), "Add to the runner classpath."), @@ -181,19 +174,6 @@ object scalac extends Command { Section("Advanced Options", DefinitionList( - Definition( - CmdOption("Xassem-extdirs", Argument("dirs")), - "(Requires " & Mono("-target:msil") & - ") List of directories containing assemblies." & - " default:" & Mono("lib") & "."), - Definition( - CmdOption("Xassem-name", Argument("file")), - "(Requires " & Mono("-target:msil") & - ") Name of the output assembly."), - Definition( - CmdOption("Xassem-path", Argument("path")), - "(Requires " & Mono("-target:msil") & - ") List of assemblies referenced by the program."), Definition( CmdOption("Xcheck-null"), "Warn upon selection of nullable reference"), @@ -289,10 +269,6 @@ object scalac extends Command { Definition( CmdOption("Xsource-reader", Argument("classname")), "Specify a custom method for reading source files."), - Definition( - CmdOption("Xsourcedir", Argument("path")), - "(Requires " & Mono("-target:msil") & - ") Mirror source folder structure in output directory.."), Definition( CmdOption("Xverify"), "Verify generic signatures in generated bytecode."), diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java b/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java deleted file mode 100644 index 59bbeee3a4b7..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.util.Table; -import ch.epfl.lamp.compiler.msil.util.Table.AssemblyDef; -import ch.epfl.lamp.compiler.msil.util.Table.ModuleDef; - -import java.util.HashMap; -import java.util.Iterator; -import java.io.File; -import java.io.FileNotFoundException; - -/** - * Defines an Assembly, which is a reusable, versionable, and self-describing - * building block of a common language runtime application. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class Assembly extends CustomAttributeProvider { - - //########################################################################## - // static members - - // all the assemblies - public static final HashMap assemblies = new HashMap(); - - /** Loads an assembly from the specified path. */ - public static Assembly LoadFrom(String assemblyFileName) { - File afile = new File(assemblyFileName); - return LoadFrom(afile.getParentFile(), afile.getName()); - } - - /** Loads an assembly with the given name from the given directory. */ - public static Assembly LoadFrom(File dir, String name) { - File file = null; - PEFile pefile = null; -// try { -// if (dir == null) -// dir = new File("."); -// dir = dir.getCanonicalFile(); -// } catch (java.io.IOException e) {} - - if (name.toUpperCase().endsWith(".EXE") || name.toUpperCase().endsWith(".DLL")) { - file = new File(dir, name); - pefile = getPEFile(file); - name = name.substring(0, name.length() - 4); - } - - File adir = pefile == null ? new File(dir, name) : null; - - if (pefile == null) { - file = new File(dir, name + ".dll"); - pefile = getPEFile(file); - } - if (pefile == null) { - file = new File(dir, name + ".DLL"); - pefile = getPEFile(file); - } - if (pefile == null && adir.exists()) { - file = new File(adir, name + ".dll"); - pefile = getPEFile(file); - } - if (pefile == null && adir.exists()) { - file = new File(adir, name + ".DLL"); - pefile = getPEFile(file); - } - - if (pefile == null) { - file = new File(dir, name + ".exe"); - pefile = getPEFile(file); - } - if (pefile == null) { - file = new File(dir, name + ".EXE"); - pefile = getPEFile(file); - } - if (pefile == null && adir.exists()) { - file = new File(adir, name + ".exe"); - pefile = getPEFile(file); - } - if (pefile == null && adir.exists()) { - file = new File(adir, name + ".EXE"); - pefile = getPEFile(file); - } - - if (pefile == null) - throw new RuntimeException("Cannot find assembly " + new File(dir, name)); - return getPEAssembly(pefile); - } - - private static Assembly getPEAssembly(PEFile pefile) { - AssemblyDef assem = pefile.AssemblyDef; - if (assem == null) - throw new RuntimeException("File " + pefile - + " does not contain a manifest"); - assem.readRow(1); - String name = pefile.getString(assem.Name); - Assembly a = (Assembly) assemblies.get(name); - if (a != null) { - return a; - } - - AssemblyName an = new AssemblyName(); - an.Name = pefile.getString(assem.Name); - an.Version = new Version(assem.MajorVersion, assem.MinorVersion, - assem.BuildNumber, assem.RevisionNumber); - an.SetPublicKey(pefile.getBlob(assem.PublicKey)); - return new PEAssembly(pefile, an); - } - - protected static PEFile getPEFile(File f) { - PEFile pefile = null; - try { pefile = new PEFile(f.getAbsolutePath()); } - catch (FileNotFoundException e) {} - catch (RuntimeException e) { - java.lang.System.out.println("swallowed RuntimeException at getPEFile"); - } - return pefile; - } - - //########################################################################## - // public fields - - /** The entry point of this assembly. */ - public MethodInfo EntryPoint; - - /** the display name of the assembly. */ - public final String FullName; - - //########################################################################## - // constructor - - protected Assembly(AssemblyName an, boolean external) { - assemblyName = an; - FullName = an.toString(); - if(external) { - assemblies.put(an.Name, this); - } - //System.out.println("assemblies after adding the current one: " + assemblies); - } - - protected Assembly(AssemblyName an) { - this(an, false); - } - - protected static Assembly getAssembly(String name) { - return (Assembly) assemblies.get(name); - } - - //########################################################################## - // instrumental methods - - /** @return the file from which this assembly was loaded. */ - public File getFile() { - throw new RuntimeException("Not supported"); - } - - /** Gets the specified module in this assembly. Works on filenames. */ - public Module GetModule(String name) { - initModules(); - return (Module)modulesMap.get(name); - } - - /** Get all the modules of the assembly. */ - public Module[] GetModules() { - initModules(); - return (Module[])modulesMap.values(). - toArray(new Module[modulesMap.size()]); - } - - /** Get the corresponding type. */ - public Type GetType(String name) { - initModules(); - Iterator modules = modulesMap.values().iterator(); - Type t = null; - while (t == null && modules.hasNext()) { - t = ((Module)modules.next()).GetType(name); - } - return t; - } - - /** @return an array of all types defined in the assembly. */ - public synchronized Type[] GetTypes() { - if (types != null) - return (Type[])types.clone(); - initModules(); - - Iterator modules = modulesMap.values().iterator(); - Type[] newTypes = ((Module)modules.next()).GetTypes(); - while (modules.hasNext()) { - Module module = (Module)modules.next(); - Type[] mtypes = module.GetTypes(); - Type[] oldTypes = newTypes; - newTypes = new Type[oldTypes.length + mtypes.length]; - System.arraycopy(oldTypes, 0, newTypes, 0, oldTypes.length); - System.arraycopy(mtypes, 0, newTypes, oldTypes.length, mtypes.length); - } - types = newTypes; - return (Type[]) types.clone(); - } - - public AssemblyName GetName() { - return assemblyName; - } - - public String toString() { - return FullName; - } - - //########################################################################## - // protected members - - // the assembly name - protected final AssemblyName assemblyName; - - // all the types exported by the assembly - protected Type[] types = null; - - // the module defined in this assembly (only one right now) - private final HashMap/**/ modulesMap = new HashMap(); - - protected void addType(Type type) { - Type.addType(type); - } - - protected void addModule(String name, Module module) { - modulesMap.put(name, module); - } - - private boolean initModules = true; - protected final void initModules() { - if (initModules) { - loadModules(); - initModules = false; - } - } - - /** used for lazy construction of the Assembly. */ - protected abstract void loadModules(); - - void dumpTypes() { - Type[] types = GetTypes(); - for (int i = 0; i < types.length; i++) - System.out.println(types[i]); - } - - //########################################################################## - -} // class Assembly diff --git a/src/msil/ch/epfl/lamp/compiler/msil/AssemblyName.java b/src/msil/ch/epfl/lamp/compiler/msil/AssemblyName.java deleted file mode 100644 index acdcb32e3326..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/AssemblyName.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import javax.crypto.Mac; - -import java.security.MessageDigest; - -import ch.epfl.lamp.compiler.msil.util.Table; - -/** - * Fully describes an assembly's unique identity. - * Right now it's only the name - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class AssemblyName { - - //########################################################################## - // public interface - - /** The simple, unencrypted name of the assembly. */ - public String Name; - - /** - * Gets or sets the major, minor, revision, and build numbers - * of the assembly. - */ - public Version Version; - - /** - * Gets a strong name consisting of a public key, a given name, - * and version parts. - */ - public byte[] GetPublicKeyToken() { - return publicKeyToken == null ? null : (byte[]) publicKeyToken.clone(); - } - - /** - * Sets a strong name consisting of a public key, a given name, - * and version parts. - */ - public void SetPublicKeyToken(byte[] key) { - this.publicKeyToken = key.length == 0 ? null : (byte[]) key.clone(); - } - - /** - * Returns the public key identifying the originator of the assembly. - */ - public byte[] GetPublicKey() { - return publicKey == null ? null : (byte[]) publicKey.clone(); - } - - /** - * Sets the public key identifying the originator of the assembly. - */ - public void SetPublicKey(byte[] key) { - if (key.length > 0) { - this.publicKey = (byte[]) key.clone(); - byte[] hash = sha.digest(key); - byte[] keyToken = new byte[8]; - for (int i = 0; i < keyToken.length; i++) - keyToken[i] = hash[hash.length - 1 - i]; - this.publicKeyToken = keyToken; - //System.out.println("Pubic key and key token of assembly " + this + ":"); - //System.out.println("\tPublic key = " + Table.bytes2hex(key)); - //System.out.println("\tKey token = " + Table.bytes2hex(keyToken)); - } - } - - public String toString() { - return Name + ", Version=" + Version; - } - - //########################################################################## - - private byte[] publicKeyToken; - - private byte[] publicKey; - - private static final MessageDigest sha; - static { - MessageDigest md = null; - try { - md = MessageDigest.getInstance("SHA"); - } catch (java.security.NoSuchAlgorithmException e) {} - sha = md; - } - - //########################################################################## - -} // class AssemblyName diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java b/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java deleted file mode 100644 index 0f2c4e676499..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java +++ /dev/null @@ -1,654 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.util.Signature; - -import java.util.Map; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Iterator; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.io.UnsupportedEncodingException; - -/** - * Describes custom attribute instances. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class Attribute { - - //########################################################################## - - private final ConstructorInfo constr; - - private final byte[] value; - - Attribute(ConstructorInfo constr, byte[] value) { - assert constr != null; - this.constr = constr; - assert value != null : constr.toString(); - this.value = value; - } - - //########################################################################## - // public interface - - /** @return the type (class) of the attribute. */ - public Type GetType() { return constr.DeclaringType; } - - /** @return the constructor of this attribute. */ - public ConstructorInfo getConstructor() { - return constr; - } - - /** @return the Blob with serialized constructor & named arguments. */ - public byte[] getValue() { - byte[] value = new byte[this.value.length]; - System.arraycopy(this.value, 0, value, 0, value.length); - return value; - } - - /**@return an array with the arguments to the attribute's constructor. */ - public Object[] getConstructorArguments() { - parseBlob(); - Object[] cas = new Object[constrArgs.length]; - System.arraycopy(constrArgs, 0, cas, 0, cas.length); - return cas; - } - - /** @return the named argument with the given name. */ - public NamedArgument getNamedArgument(String name) { - return (NamedArgument)namedArgs.get(name); - } - - /** @return an array of all named arguments for this attribute. */ - public NamedArgument[] getNamedArguments() { - NamedArgument[] nargs = - (NamedArgument[])namedArgs.values().toArray(NamedArgument.EMPTY); - return nargs; - } - - /** @return a string representation of this attribute. */ - public String toString() { - parseBlob(); - ParameterInfo[] params = constr.GetParameters(); - assert params.length == constrArgs.length : this.constr; - StringBuffer str = new StringBuffer(); - str.append('['); - str.append(constr.DeclaringType.FullName); - str.append('('); - for (int i = 0; i < constrArgs.length; i++) { - if (i > 0) - str.append(", "); - Type t = params[i].ParameterType; - if (t.IsEnum()) { - str.append('('); - str.append(t.FullName); - str.append(')'); - } - formatValue(str, constrArgs[i]); - } - NamedArgument[] nargs = getNamedArguments(); - for (int i = 0; i < nargs.length; i++) { - str.append(", ").append(nargs[i]); - } - str.append(")]"); - return str.toString(); - } - - //######################################################################### - - private static final Map type2id = new HashMap(); - private static final Map id2type = new HashMap(); - static { - map("Boolean", Signature.ELEMENT_TYPE_BOOLEAN); - map("Char", Signature.ELEMENT_TYPE_CHAR); - map("SByte", Signature.ELEMENT_TYPE_I1); - map("Byte", Signature.ELEMENT_TYPE_U1); - map("Int16", Signature.ELEMENT_TYPE_I2); - map("UInt16", Signature.ELEMENT_TYPE_U2); - map("Int32", Signature.ELEMENT_TYPE_I4); - map("UInt32", Signature.ELEMENT_TYPE_U4); - map("Int64", Signature.ELEMENT_TYPE_I8); - map("UInt64", Signature.ELEMENT_TYPE_U8); - map("Single", Signature.ELEMENT_TYPE_R4); - map("Double", Signature.ELEMENT_TYPE_R8); - map("String", Signature.ELEMENT_TYPE_STRING); - map("Type", Signature.X_ELEMENT_TYPE_TYPE); - map("Object", Signature.ELEMENT_TYPE_OBJECT); - } - private static void map(String type, int id) { - Type t = Type.GetType("System." + type); - assert type != null : type + " -> " + id; - Integer i = new Integer(id); - type2id.put(t, i); - id2type.put(i, t); - } - private static int getTypeId(Type type) { - Integer id = (Integer)type2id.get(type); - assert id != null : type; - return id.intValue(); - } - - private Object[] constrArgs; - private Map namedArgs; - private ByteBuffer buf; - - private void parseBlob() { - try { parseBlob0(); } - catch (RuntimeException e) { - throw new RuntimeException(PEFile.bytes2hex(value), e); - } - } - - private void parseBlob0() { - if (buf != null) - return; - buf = ByteBuffer.wrap(value); // Sec. 23.3 in Partition II of CLR Spec. - buf.order(ByteOrder.LITTLE_ENDIAN); - - short sig = buf.getShort(); // Prolog - assert sig == 1 : PEFile.bytes2hex(value); - ParameterInfo[] params = constr.GetParameters(); - constrArgs = new Object[params.length]; - for (int i = 0; i < params.length; i++) { - constrArgs[i] = parseFixedArg(params[i].ParameterType); // FixedArg - } - - int ncount = buf.getShort(); // NumNamed - namedArgs = new LinkedHashMap(); - for (int i = 0; i < ncount; i++) { - int designator = buf.get(); // designator one of 0x53 (FIELD) or 0x54 (PROPERTY) - assert designator == Signature.X_ELEMENT_KIND_FIELD - || designator == Signature.X_ELEMENT_KIND_PROPERTY - : "0x" + PEFile.byte2hex(designator); - Type type = parseFieldOrPropTypeInNamedArg(); // FieldOrPropType - String name = parseString(); // FieldOrPropName - Object value = parseFixedArg(type); // FixedArg - NamedArgument narg = - new NamedArgument(designator, name, type, value); - namedArgs.put(name, narg); - } - } - - private Object parseFixedArg(Type type) { - if (type.IsArray()) - return parseArray(type.GetElementType()); - else - return parseElem(type); - } - - /* indicates whether the "simple" case (the other is "enum") of the first row - in the Elem production should be taken. */ - private boolean isSimpleElem(Type type) { - if(!type2id.containsKey(type)) return false; - int id = getTypeId(type); - switch(id){ - case Signature.ELEMENT_TYPE_STRING: - case Signature.X_ELEMENT_TYPE_TYPE: - case Signature.ELEMENT_TYPE_OBJECT: - return false; - default: - return true; - } - } - - /* indicates whether the second row in the Elem production - should be taken (and more specifically, "string" case within that row). */ - private boolean isStringElem(Type type) { - if(!type2id.containsKey(type)) return false; - int id = getTypeId(type); - return id == Signature.ELEMENT_TYPE_STRING; - } - - /* indicates whether the second row in the Elem production - should be taken (and more specifically, "type" case within that row). */ - private boolean isTypeElem(Type type) { - if(!type2id.containsKey(type)) return false; - int id = getTypeId(type); - return id == Signature.X_ELEMENT_TYPE_TYPE; - } - - /* indicates whether the third row in the Elem production - should be taken (and more specifically, "boxed" case within that row). */ - private boolean isSystemObject(Type type) { - if(!type2id.containsKey(type)) return false; - int id = getTypeId(type); - return id == Signature.ELEMENT_TYPE_OBJECT; - } - - private Object parseElem(Type type) { - // simple or enum - if (isSimpleElem(type)) return parseVal(getTypeId(type)); - if (type.IsEnum()) return parseVal(getTypeId(type.getUnderlyingType())); - // string or type - if (isStringElem(type)) return parseString(); - if (isTypeElem(type)) return getTypeFromSerString(); - // boxed valuetype, please notice that a "simple" boxed valuetype is preceded by 0x51 - if (isSystemObject(type)) { - Type boxedT = parse0x51(); - if(boxedT.IsEnum()) { - return new BoxedArgument(boxedT, parseVal(getTypeId(boxedT.getUnderlyingType()))); - } else { - return new BoxedArgument(boxedT, parseVal(getTypeId(boxedT))); // TODO dead code? - } - } else { - Type boxedT = parseType(); - return parseVal(getTypeId(boxedT)); - } - } - - /* this does not parse an Elem, but a made-up production (Element). Don't read too much into this method name! */ - private Object parseVal(int id) { - switch (id) { - case Signature.ELEMENT_TYPE_BOOLEAN: - return new Boolean(buf.get() == 0 ? false : true); - case Signature.ELEMENT_TYPE_CHAR: - return new Character(buf.getChar()); - case Signature.ELEMENT_TYPE_I1: - case Signature.ELEMENT_TYPE_U1: - return new Byte(buf.get()); // TODO U1 not the same as I1 - case Signature.ELEMENT_TYPE_I2: - case Signature.ELEMENT_TYPE_U2: - return new Short(buf.getShort()); // TODO U2 not the same as I2 - case Signature.ELEMENT_TYPE_I4: - case Signature.ELEMENT_TYPE_U4: - return new Integer(buf.getInt()); // TODO U4 not the same as I4 - case Signature.ELEMENT_TYPE_I8: - case Signature.ELEMENT_TYPE_U8: - return new Long(buf.getLong()); // TODO U8 not the same as I8 - case Signature.ELEMENT_TYPE_R4: - return new Float(buf.getFloat()); - case Signature.ELEMENT_TYPE_R8: - return new Double(buf.getDouble()); - case Signature.X_ELEMENT_TYPE_TYPE: - return getTypeFromSerString(); - case Signature.ELEMENT_TYPE_STRING: - return parseString(); - default: - throw new RuntimeException("Shouldn't have called parseVal with: " + id); - } - } - - private Object parseArray(Type type) { - if (type.IsEnum()) - return parseArray(type.getUnderlyingType()); - return parseArray(getTypeId(type)); - } - - private Object parseArray(int id) { - switch (id) { - case Signature.ELEMENT_TYPE_BOOLEAN: - return parseBooleanArray(); - case Signature.ELEMENT_TYPE_CHAR: - return parseCharArray(); - case Signature.ELEMENT_TYPE_I1: - case Signature.ELEMENT_TYPE_U1: // TODO U1 not the same as I1 - return parseByteArray(); - case Signature.ELEMENT_TYPE_I2: - case Signature.ELEMENT_TYPE_U2: - return parseShortArray(); - case Signature.ELEMENT_TYPE_I4: - case Signature.ELEMENT_TYPE_U4: - return parseIntArray(); - case Signature.ELEMENT_TYPE_I8: - case Signature.ELEMENT_TYPE_U8: - return parseLongArray(); - case Signature.ELEMENT_TYPE_R4: - return parseFloatArray(); - case Signature.ELEMENT_TYPE_R8: - return parseDoubleArray(); - case Signature.ELEMENT_TYPE_STRING: - return parseStringArray(); - case Signature.X_ELEMENT_TYPE_ENUM: - return parseArray(getTypeFromSerString()); - default: - throw new RuntimeException("Unknown type id: " + id); - } - } - - private Type parseType() { // FieldOrPropType, Sec. 23.3 in Partition II of CLR Spec. - int id = buf.get(); - switch (id) { - case Signature.ELEMENT_TYPE_SZARRAY: - Type arrT = Type.mkArray(parseType(), 1); - return arrT; - case Signature.X_ELEMENT_TYPE_ENUM: - String enumName = parseString(); - Type enumT = Type.getType(enumName); - return enumT; - default: - Type t = (Type)id2type.get(new Integer(id)); - assert t != null : PEFile.byte2hex(id); - return t; - } - } - - private Type parse0x51() { - int id = buf.get(); - switch (id) { - case 0x51: - return parse0x51(); - case Signature.ELEMENT_TYPE_SZARRAY: - Type arrT = Type.mkArray(parseType(), 1); - return arrT; - case Signature.X_ELEMENT_TYPE_ENUM: - String enumName = parseString(); - Type enumT = Type.getType(enumName); - return enumT; - default: - Type t = (Type)id2type.get(new Integer(id)); - assert t != null : PEFile.byte2hex(id); - return t; - } - } - - - private Type parseFieldOrPropTypeInNamedArg() { // FieldOrPropType, Sec. 23.3 in Partition II of CLR Spec. - int id = buf.get(); - switch (id) { - case 0x51: - return (Type)(id2type.get(new Integer(Signature.ELEMENT_TYPE_OBJECT))); - // TODO remove case Signature.ELEMENT_TYPE_SZARRAY: - // Type arrT = Type.mkArray(parseType(), 1); - // return arrT; - case Signature.X_ELEMENT_TYPE_ENUM: - String enumName = parseString(); - Type enumT = Type.getType(enumName); // TODO this "lookup" only covers already-loaded assemblies. - return enumT; // TODO null as return value (due to the above) spells trouble later. - default: - Type t = (Type)id2type.get(new Integer(id)); - assert t != null : PEFile.byte2hex(id); - return t; - } - } - - private Type getTypeFromSerString() { - String typename = parseString(); - int i = typename.indexOf(','); - /* fully qualified assembly name follows. Just strip it on the assumption that - the assembly is referenced in the externs and the type will be found. */ - String name = (i < 0) ? typename : typename.substring(0, i); - Type t = Type.GetType(name); - if (t == null && i > 0) { - int j = typename.indexOf(',', i + 1); - if (j > 0) { - String assemName = typename.substring(i + 1, j); - try { - Assembly.LoadFrom(assemName); - } catch (Throwable e) { - throw new RuntimeException(typename, e); - } - t = Type.GetType(name); - } - } - assert t != null : typename; - return t; - } - - private boolean[] parseBooleanArray() { - boolean[] arr = new boolean[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.get() == 0 ? false : true; - return arr; - } - - private char[] parseCharArray() { - char[] arr = new char[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.getChar(); - return arr; - } - - private byte[] parseByteArray() { - byte[] arr = new byte[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.get(); - return arr; - } - - private short[] parseShortArray() { - short[] arr = new short[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.getShort(); - return arr; - } - - private int[] parseIntArray() { - int[] arr = new int[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.getInt(); - return arr; - } - - private long[] parseLongArray() { - long[] arr = new long[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.getLong(); - return arr; - } - - private float[] parseFloatArray() { - float[] arr = new float[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.getFloat(); - return arr; - } - - private double[] parseDoubleArray() { - double[] arr = new double[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = buf.getDouble(); - return arr; - } - - private String[] parseStringArray() { - String[] arr = new String[buf.getInt()]; - for (int i = 0; i < arr.length; i++) - arr[i] = parseString(); - return arr; - } - - private String parseString() { // SerString convention - String str = null; - int length = parseLength(); - if (length < 0) - return null; - try { str = new String(value, buf.position(), length, "UTF-8" ); } - catch (UnsupportedEncodingException e) { throw new Error(e); } - buf.position(buf.position() + length); - return str; - } - - private int getByte() { - return (buf.get() + 0x0100) & 0xff; - } - - public int parseLength() { - int length = getByte(); - // check for invalid length format: the first, second or third - // most significant bits should be 0; if all are 1 the length is invalid. - if ((length & 0xe0) == 0xe0) - return -1; - if ((length & 0x80) != 0) { - length = ((length & 0x7f) << 8) | getByte(); - if ((length & 0x4000) != 0) - length = ((length & 0x3fff) << 16) | (getByte()<<8) | getByte(); - } - return length; - } - - //########################################################################## - private static void formatValue(StringBuffer str, Object o) { - Class c = (o == null) ? null : o.getClass(); - if (c == null) { - str.append(""); - } else if (c == String.class) { - str.append('"'); - str.append(o); - str.append('"'); - } else if (c == Character.class) { - str.append('\''); - str.append(o); - str.append('\''); - } else if (c == boolean[].class) { - str.append("new boolean[] {"); - boolean[] arr = (boolean[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == char[].class) { - str.append("new short[] {"); - short[] arr = (short[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == byte[].class) { - str.append("new byte[] {"); - byte[] arr = (byte[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == short[].class) { - str.append("new short[] {"); - short[] arr = (short[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == int[].class) { - str.append("new int[] {"); - int[] arr = (int[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == long[].class) { - str.append("new long[] {"); - long[] arr = (long[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == float[].class) { - str.append("new float[] {"); - float[] arr = (float[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == double[].class) { - str.append("new double[] {"); - double[] arr = (double[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - str.append(arr[i]); - } - str.append('}'); - } else if (c == String[].class) { - str.append("new String[] {"); - String[] arr = (String[])o; - for (int i = 0; i < arr.length; i++) { - if (i > 0) str.append(", "); - formatValue(str, arr[i]); - } - str.append('}'); - } else if (o instanceof Type) { - str.append("typeof("); - str.append(o); - str.append(")"); - } else - str.append(o); - } - - //########################################################################## - - /** Represents named arguments (assigned outside of the constructor) - * of a custom attribute - */ - public static class NamedArgument { - - /** Designates if the named argument corresponds to a field or property. - * Possible values: - * Signature.X_ELEMENT_KIND_FIELD = 0x53 - * Signature.X_ELEMENT_KIND_PROPERTY = 0x54 - */ - public final int designator; - - /** The name of the field/property. */ - public final String name; - - /** Type of the field/property. */ - public final Type type; - - /** The value for the field/property. */ - public final Object value; - - /** An empty array NamedArgument. */ - public static final NamedArgument[] EMPTY = new NamedArgument[0]; - - public NamedArgument(int designator, String name,Type type,Object value) - { - this.designator = designator; - this.name = name; - this.type = type; - this.value = value; - } - - /** @return true if the named argument specifies a field; - * false otherwise. - */ - public boolean isField() { - return designator == Signature.X_ELEMENT_KIND_FIELD; - } - - /** @return true if the named argument specifies a property; - * false otherwise. - */ - public boolean isProperty() { - return designator == Signature.X_ELEMENT_KIND_PROPERTY; - } - - /** @return a string representation of the named argument. */ - public String toString() { - StringBuffer str = new StringBuffer(name); - str.append(" = "); - if (type.IsEnum()) - str.append('(').append(type.FullName).append(')'); - formatValue(str, value); - return str.toString(); - } - } - - //########################################################################## - - public static class BoxedArgument { - public final Type type; - public final Object value; - public BoxedArgument(Type type, Object value) { - this.type = type; this.value = value; - } - public String toString() { - return "(" + type.FullName + ")" + value; - } - } - - //########################################################################## - -} // class Attribute diff --git a/src/msil/ch/epfl/lamp/compiler/msil/BindingFlags.java b/src/msil/ch/epfl/lamp/compiler/msil/BindingFlags.java deleted file mode 100644 index cac2319b50b2..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/BindingFlags.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Specifies flags that control binding and the way in which - * the search for members and types is conducted by reflection. - * - * Note: You must specify Instance or Static along with Public or NonPublic - * or no members will be returned. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class BindingFlags { - - //########################################################################## - - // disallows extending the class; - private BindingFlags() {} - - /** - * Specifies no binding flag. - */ - public static final int Default = 0x0000; - - /** - * Specifies that the case of the member name should not be considered - * when binding. - */ - public static final int IgnoreCase = 0x0001; - - /** - * Specifies that only members declared at the level of the supplied type's - * hierarchy should be considered. Inherited members are not considered. - */ - public static final int DeclaredOnly = 0x0002; - - /** - * Specifies that instance members are to be included in the search. - */ - public static final int Instance = 0x0004; - - /** - * Specifies that static members are to be included in the search. - */ - public static final int Static = 0x0008; - - /** - * Specifies that public members are to be included in the search. - */ - public static final int Public = 0x0010; - - /** - * Specifies that non-public members are to be included in the search. - */ - public static final int NonPublic = 0x0020; - - /** - * Specifies that static members up the hierarchy should be returned. - * Static members include fields, methods, events, and properties. - * Nested types are not returned. - */ - public static final int FlattenHierarchy = 0x0040; - - /** - * Specifies that a method is to be invoked. This may not be a constructor - * or a type initializer. - */ - public static final int InvokeMethod = 0x0100; - - /** - * Specifies that Reflection should create an instance of - * the specified type. Calls the constructor that matches - * the given arguments. The supplied member name is ignored. - * If the type of lookup is not specified, (Instance | Public) - * will apply. It is not possible to call a type initializer. - */ - public static final int CreateInstance = 0x0200; - - /** - * Specifies that the value of the specified field should be returned. - */ - public static final int GetField = 0x0400; - - /** - * Specifies that the value of the specified field should be set. - */ - public static final int SetField = 0x0800; - - /** - * Specifies that the value of the specified property should be returned. - */ - public static final int GetProperty = 0x1000; - - /** - * Specifies that the value of the specified property should be set. - * For COM properties, specifying this binding flag is equivalent to - * specifying PutDispProperty and PutRefDispProperty. - */ - public static final int SetProperty = 0x2000; - - /** - * Specifies that the PROPPUT member on a COM object should be invoked. - * PROPPUT specifies a property-setting function that uses a value. - * Use PutDispProperty if a property has both PROPPUT and PROPPUTREF - * and you need to distinguish which one is called. - */ - public static final int PutDispProperty = 0x4000; - - - /** - * Specifies that the PROPPUTREF member on a COM object should be invoked. - * PROPPUTREF specifies a property-setting function that uses a reference - * instead of a value. Use PutRefDispProperty if a property has both - * PROPPUT and PROPPUTREF and you need to distinguish which one is called. - */ - public static final int PutRefDispProperty = 0x8000; - - /** - * Specifies that types of the supplied arguments must exactly match - * the types of the corresponding formal parameters. Reflection - * throws an exception if the caller supplies a non-null Binder object, - * since that implies that the caller is supplying BindToXXX - * implementations that will pick the appropriate method. - * Reflection models the accessibility rules of the common type system. - * For example, if the caller is in the same assembly, the caller - * does not need special permissions for internal members. Otherwise, - * the caller needs ReflectionPermission. This is consistent with - * lookup of members that are protected, private, and so on. - * The general principle is that ChangeType should perform only - * widening coercions, which never lose data. An example of a - * widening coercion is coercing a value that is a 32-bit signed integer - * to a value that is a 64-bit signed integer. This is distinguished - * from a narrowing coercion, which may lose data. An example of - * a narrowing coercion is coercing a 64-bit signed integer to - * a 32-bit signed integer. - * The default binder ignores this flag, while custom binders can - * implement the semantics of this flag. - */ - public static final int ExactBinding = 0x10000; - - /** - * Used in COM interop to specify that the return value of the member - * can be ignored. - */ - public static final int IgnoreReturn = 0x100000 ; - - /** - * Returns the set of members whose parameter count matches the number - * of supplied arguments. This binding flag is used for methods with - * parameters that have default values and methods with variable arguments - * (varargs). This flag should only be used with Type.InvokeMember. - * Parameters with default values are used only in calls where trailing - * arguments are omitted. They must be the last arguments. - */ - public static final int OptionalParamBinding = 0x40000; - - /** - * Not implemented. - */ - public static final int SuppressChangeType = 0x20000; - - //########################################################################## - -} // class BindingFlags diff --git a/src/msil/ch/epfl/lamp/compiler/msil/CallingConventions.java b/src/msil/ch/epfl/lamp/compiler/msil/CallingConventions.java deleted file mode 100644 index 50bf9fb5d52e..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/CallingConventions.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - - -/** - * Calling conventions - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class CallingConventions { - - //######################################################################## - - /** - * Specifies the default calling convention as determined by the - * common language runtime. - */ - public static final short Standard = (short) 0x0001; - - /** - * Specifies the calling convention for methods with variable arguments. - */ - public static final short VarArgs = (short) 0x0002; - - /** - * Specifies that either the Standard or the VarArgs calling - * convention may be used. - */ - public static final short Any = Standard | VarArgs; - - /** - * Specifies an instance or virtual method (not a static method). - * At run-time, the called method is passed a pointer to the target - * object as its first argument (the this pointer). The signature - * stored in metadata does not include the type of this first argument, - * because the method is known and its owner class can be discovered - * from metadata. - */ - public static final short HasThis = (short) 0x0020; - - /** - * Specifies that the signature is a function-pointer signature, - * representing a call to an instance or virtual method (not a static - * method). If ExplicitThis is set, HasThis must also be set. The first - * argument passed to the called method is still a this pointer, but the - * type of the first argument is now unknown. Therefore, a token that - * describes the type (or class) of the this pointer is explicitly stored - * into its metadata signature. - */ - public static final short ExplicitThis = (short) 0x0040; - - //######################################################################## - - private CallingConventions() {} - - public static String toString(int callConv) { - StringBuffer s = new StringBuffer(); - - if ((callConv & HasThis) != 0) { - s.append("instance"); - if ((callConv & ExplicitThis) != 0) - s.append(" explicit"); - } - - return s.toString(); - } - - //########################################################################## - -} // class CallingConventions diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java b/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java deleted file mode 100644 index 8c82cb487640..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java +++ /dev/null @@ -1,48 +0,0 @@ -package ch.epfl.lamp.compiler.msil; - -import java.util.Arrays; - -/* The only reason for ConstructedType to extend Type is complying with existing code - (e.g., caseFieldBuilder in ILPrinterVisitor) expecting a Type. - */ -public class ConstructedType extends Type { - - public final Type instantiatedType; - public final Type[] typeArgs; - - public ConstructedType(Type instantiatedType, Type[] typeArgs) { - super(instantiatedType.Module, instantiatedType.Attributes, "", null, null, null, instantiatedType.auxAttr /*AuxAttr.None*/ , null); - this.instantiatedType = instantiatedType; - this.typeArgs = typeArgs; - } - - public String toString() { - String res = instantiatedType.toString() + "["; - for (int i = 0; i < typeArgs.length; i++) { - res = res + typeArgs[i].toString(); - if(i + 1 < typeArgs.length) { - res = res + ", "; - } - } - return res + "]"; - } - - - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ConstructedType that = (ConstructedType) o; - - if (!instantiatedType.equals(that.instantiatedType)) return false; - if (!Arrays.equals(typeArgs, that.typeArgs)) return false; - - return true; - } - - public int hashCode() { - int result = instantiatedType.hashCode(); - result = 31 * result + Arrays.hashCode(typeArgs); - return result; - } -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java deleted file mode 100644 index 69f5d6d32a58..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Discovers the attributes of a class constructor and provides - * access to constructor metadata. - * ConstructorInfo is used to discover the attributes of a constructor - * as well as to invoke a constructor. Objects are created by invoking - * either the GetConstructors or GetConstructor method of a Type object. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class ConstructorInfo extends MethodBase { - //########################################################################## - - public final int MemberType() { return MemberTypes.Constructor; } - - public final boolean IsConstructor() { return true; } - - protected static final String CTOR = ".ctor"; - protected static final String CCTOR = ".cctor"; - protected static final ConstructorInfo[] EMPTY_ARRAY = new ConstructorInfo[0]; - - protected static String getName(int attrs) { - return (attrs & MethodAttributes.Static) == 0 ? CTOR : CCTOR; - } - - /** Public constructors */ - - public ConstructorInfo(Type declType, int attrs, Type[] paramTypes) { - super(getName(attrs), declType, attrs, paramTypes); - assert declType != null : "Owner can't be 'null' for a constructor!"; - } - - public ConstructorInfo(Type declType, int attrs, ParameterInfo[] params) - { - super(getName(attrs), declType, attrs, params); - assert declType != null : "Owner can't be 'null' for a constructor!"; - } - - - public String toString() { - return MethodAttributes.toString(Attributes) + " " + Type.VOID() + - " " + DeclaringType.FullName + "::" + Name + params2String(); - } - - //########################################################################## - -} // class ConstructorInfo diff --git a/src/msil/ch/epfl/lamp/compiler/msil/CustomAttributeProvider.java b/src/msil/ch/epfl/lamp/compiler/msil/CustomAttributeProvider.java deleted file mode 100644 index 0e58c181147c..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/CustomAttributeProvider.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import java.util.List; -import java.util.LinkedList; -import java.util.Iterator; - -/** - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class CustomAttributeProvider implements ICustomAttributeProvider { - - //########################################################################## - - protected List/**/ custAttrs; - private static final Object[] EMPTY = new Object[0]; - - //TODO: take inherit into account - public Object[] GetCustomAttributes(boolean inherit) { - initAttributes(null); - return custAttrs.size() == 0 ? EMPTY - : custAttrs.toArray(new Attribute[custAttrs.size()]); - } - - //TODO: take inherit into account - public Object[] GetCustomAttributes(Type attributeType, boolean inherit) { - initAttributes(attributeType); - List tAttrs = null; - if (constrType == attributeType) - tAttrs = custAttrs; - else { - tAttrs = new LinkedList(); - for (Iterator attrs = custAttrs.iterator(); attrs.hasNext(); ) { - Attribute a = (Attribute) attrs.next(); - if (a.GetType() == attributeType) tAttrs.add(a); - } - } - return tAttrs.size() == 0 ? EMPTY - : tAttrs.toArray(new Attribute[tAttrs.size()]); - } - - //TODO: take inherit into account - public boolean IsDefined(Type attributeType, boolean inherit) { - initAttributes(attributeType); - if (constrType == attributeType) - return custAttrs.size() > 0; - Iterator attrs = custAttrs.iterator(); - while (attrs.hasNext()) { - if (((Attribute)attrs.next()).GetType() == attributeType) - return true; - } - return false; -// return inherit && (DeclaringClass.BaseType != null) -// && DeclaringClass.BaseType.IsDefined(inherit); - } - - protected void addCustomAttribute(ConstructorInfo constr, byte[] value) { - Attribute attr = new Attribute(constr, value); - assert constrType == null || constrType == attr.GetType(); - if (custAttrs == null) - custAttrs = new LinkedList(); - custAttrs.add(attr); - } - - private void initAttributes(Type atype) { - if (custAttrs != null - && (constrType == null || constrType == atype)) - return; - custAttrs = new LinkedList(); - constrType = atype; - loadCustomAttributes(atype); - } - - protected void loadCustomAttributes(Type atype) {} - - private Type constrType; -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java b/src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java deleted file mode 100644 index cf30008c60d5..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/CustomModifier.java +++ /dev/null @@ -1,45 +0,0 @@ -package ch.epfl.lamp.compiler.msil; - -/** - * Quoting from the CIL spec, Partition II, Sec. 7.1.1: - * - * Custom modifiers, defined using `modreq` (required modifier) and `modopt` (optional modifier), are - * similar to custom attributes (Sec. 21) except that modifiers are part of a signature rather than being attached to a - * declaration. Each modifer associates a type reference with an item in the signature. - * - */ -public class CustomModifier { - - public boolean isReqd; - public Type marker; - - public CustomModifier(boolean isReqd, Type marker) { - this.isReqd = isReqd; - this.marker = marker; - } - - public String toString() { - String res = (isReqd ? "modreq( " : "modopt( ") + marker.toString() + " )"; - return res; - } - - public static Type[] helperCustomMods(boolean isReqd, CustomModifier[] cmods) { - if(cmods == null) return null; - int count = 0; - for (int idx = 0; idx < cmods.length; idx++) { - if(cmods[idx].isReqd == isReqd) count++; - } - Type[] res = new Type[count]; - int residx = 0; - for (int idx = 0; idx < cmods.length; idx++) { - res[residx] = cmods[idx].marker; - residx++; - } - return res; - } - - public static Type VolatileMarker() { - return Type.GetType("System.Runtime.CompilerServices.IsVolatile"); - } - -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/EventAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/EventAttributes.java deleted file mode 100644 index a183993cb960..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/EventAttributes.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Specifies flags that describe the attributes of a an event. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class EventAttributes { - - //########################################################################## - - /** Specifies that the event has no attributes. */ - public static final short None = 0x000; - - /** Specifies a reserved flag for CLR use only. */ - public static final short ReservedMask = 0x0400; - - /** Specifies that the event is special in a way described by the name. */ - public static final short SpecialName = 0x0200; - - /** Specifies the the CLR should check name encoding. */ - public static final short RTSpecialName = 0x0400; - - //########################################################################## - -} // class EventAttributes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/EventInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/EventInfo.java deleted file mode 100644 index 3ccba7900b33..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/EventInfo.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - - -/** - * Discovers the attributes of an event - * and provides access to event metadata. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class EventInfo extends MemberInfo { - - //########################################################################## - - public final int MemberType() { return MemberTypes.Event; } - - /** Attributes associated with the event. */ - public final short Attributes; - - /** The Type object for the underlying event-handler delegate - * associated with this event. - */ - public final Type EventHandlerType; - - public MethodInfo GetAddMethod() { return addMethod; } - - public MethodInfo GetRemoveMethod() { return removeMethod; } - - public String toString() { - return "" + EventHandlerType + " " + Name; - } - - //########################################################################## - - protected static final EventInfo[] EMPTY_ARRAY = new EventInfo[0]; - - protected MethodInfo addMethod; - - protected MethodInfo removeMethod; - - protected EventInfo(String name, Type declType, short attr, - Type handlerType, MethodInfo add, MethodInfo remove) - { - super(name, declType); - Attributes = attr; - EventHandlerType = handlerType; - this.addMethod = add; - this.removeMethod = remove; - } - - //########################################################################## - -} // class EventInfo diff --git a/src/msil/ch/epfl/lamp/compiler/msil/FieldAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/FieldAttributes.java deleted file mode 100644 index d7d1bb3d54f0..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/FieldAttributes.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Specifies flags that describe the attributes of a field. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class FieldAttributes { - - //########################################################################## - - /** Specifies the access level of a given field. */ - public static final short FieldAccessMask = 0x0007; - - /** Member not refereneceable. */ - public static final short CompilerControlled = 0x0000; - - /** Field is accessible only by the parent type. */ - public static final short Private = 0x0001; - - /** Field is accessible only by subtypes in this assembly. */ - public static final short FamANDAssem = 0x0002; - - /** Field is accessible throughout the assembly. */ - public static final short Assembly = 0x0003; - - /** Field is accessible only by type and subtypes. */ - public static final short Family = 0x0004; - - /** Field is accessible by subtypes anywhere, - * as well as throughout this assembly. */ - public static final short FamORAssem = 0x0005; - - /** Specifies that the field is accessible by any member - * for whom this scope is visible. */ - public static final short Public = 0x0006; - - //########################################################################## - // - - /** Field represents the defined type, or else it is per-instance. */ - public static final short Static = 0x0010; - - /** Field is initialized only and cannot be written after initialization. */ - public static final short InitOnly = 0x0020; - - /** Value is compile-time constant. */ - public static final short Literal = 0x0040; - - /** Field does not have to be serialized when the type is remoted. */ - public static final short NotSerialized = 0x0080; - - /** Field is special. */ - public static final short SpecialName = 0x0200; - - //########################################################################## - // Interop attributes - - /** Implementation is forwarded through PInvoke */ - public static final short PinvokeImpl = 0x2000; - - - //########################################################################## - // Additional flags - - /** CLI provides 'special' behavior depending upon the name of the field */ - public static final short RTSpecialName = 0x0400; - - /** Field has marshalling information. */ - public static final short HasFieldMarshal = 0x1000; - - /** Field has a default value. */ - public static final short HasDefault = (short)0x8000; - - /** Field has a Relative Virtual Address (RVA). The RVA is the location - * of the method body in the current image, as an address relative - * to the start of the image file in which it is located. */ - public static final short HasFieldRVA = 0x0100; - - //########################################################################## - // - - public static String toString(short attrs) { - StringBuffer str = new StringBuffer(); - switch (attrs & FieldAccessMask) { - case CompilerControlled: str.append("compilercontrolled"); break; - case Private: str.append("private"); break; - case FamANDAssem: str.append("famandassem"); break; - case Assembly: str.append("assembly"); break; - case Family: str.append("family"); break; - case FamORAssem: str.append("famorassem"); break; - case Public: str.append("public"); break; - } - if ((attrs & Static) != 0) str.append(" static"); - if ((attrs & InitOnly) != 0) str.append(" initonly"); - if ((attrs & Literal) != 0) str.append(" literal"); - if ((attrs & NotSerialized) != 0) str.append(" notserialized"); - if ((attrs & SpecialName) != 0) str.append(" specialname"); - if ((attrs & PinvokeImpl) != 0) str.append(""); - if ((attrs & RTSpecialName) != 0) str.append(" rtspecialname"); - if ((attrs & HasFieldMarshal) != 0) str.append(" marshal()"); - //if ((attrs & HasDefault) != 0) str.append(" default(???)"); - return str.toString(); - } - - //########################################################################## - - // makes the class uninstantiable - private FieldAttributes() {} - - //########################################################################## - -} // class FieldAttributes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java deleted file mode 100644 index 536a67e9a83d..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.util.PECustomMod; - -/** - * Discovers the attributes of a field and provides access to field metadata. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class FieldInfo extends MemberInfo implements HasCustomModifiers { - - //########################################################################## - // public interface - - public final int MemberType() { return MemberTypes.Field; } - - /** Attributes associated with this field. */ - public final short Attributes; - - /** Type of the field represented by this FieldInfo object. */ - public final Type FieldType; - - /** can be null */ - public final CustomModifier[] cmods; - - protected final Object value; - - public final boolean IsStatic() { - return (Attributes & FieldAttributes.Static) != 0; - } - - public final boolean IsInitOnly() { - return (Attributes & FieldAttributes.InitOnly) != 0; - } - - public final boolean IsLiteral() { - return (Attributes & FieldAttributes.Literal) != 0; - - } - - public final boolean IsPublic() { - return (Attributes & FieldAttributes.FieldAccessMask) - == FieldAttributes.Public; - } - - public final boolean IsPrivate() { - return (Attributes & FieldAttributes.FieldAccessMask) - == FieldAttributes.Private; - } - - public final boolean IsFamily() { - return (Attributes & FieldAttributes.FieldAccessMask) - == FieldAttributes.Family; - } - - public final boolean IsAssembly() { - return (Attributes & FieldAttributes.FieldAccessMask) - == FieldAttributes.Assembly; - } - - public final boolean IsFamilyOrAssembly() { - return (Attributes & FieldAttributes.FieldAccessMask) - == FieldAttributes.FamORAssem; - } - - public final boolean IsFamilyAndAssembly() { - return (Attributes & FieldAttributes.FieldAccessMask) - == FieldAttributes.FamANDAssem; - } - public final boolean IsSpecialName() { - return (Attributes & FieldAttributes.SpecialName) != 0; - } - - public final boolean IsPinvokeImpl() { - return (Attributes & FieldAttributes.PinvokeImpl) != 0; - } - - public final boolean IsNotSerialized() { - return (Attributes & FieldAttributes.NotSerialized) != 0; - } - - private boolean knownVolatile = false; - private boolean cachedVolatile = false; - public final boolean IsVolatile() { - if(knownVolatile) return cachedVolatile; - knownVolatile = true; - if(cmods == null) { - cachedVolatile = false; - return cachedVolatile; - } - for (int idx = 0; idx < cmods.length; idx++) { - if(cmods[idx].marker == CustomModifier.VolatileMarker()) { - cachedVolatile = true; - return cachedVolatile; - } - } - cachedVolatile = false; - return cachedVolatile; - } - - public final Type[] GetOptionalCustomModifiers () { - return CustomModifier.helperCustomMods(false, cmods); - } - - public final Type[] GetRequiredCustomModifiers() { - return CustomModifier.helperCustomMods(true, cmods); - } - - public String toString() { - return FieldAttributes.toString(Attributes) + " " + - FieldType + " " + DeclaringType.FullName + "::" + Name; - } - - //########################################################################## - - protected static final FieldInfo[] EMPTY_ARRAY = new FieldInfo[0]; - - /** Initializes a new instance of the FieldInfo class. */ - protected FieldInfo(String name, Type declType, - int attrs, PECustomMod fieldTypeWithMods, Object value) - { - super(name, declType); - FieldType = fieldTypeWithMods.marked; - cmods = fieldTypeWithMods.cmods; - Attributes = (short) attrs; - this.value = value; - } - - /** - */ - public Object getValue() { return value; } - - //########################################################################## - -} // class FieldInfo diff --git a/src/msil/ch/epfl/lamp/compiler/msil/GenericParamAndConstraints.java b/src/msil/ch/epfl/lamp/compiler/msil/GenericParamAndConstraints.java deleted file mode 100644 index 6237fbafee59..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/GenericParamAndConstraints.java +++ /dev/null @@ -1,40 +0,0 @@ -package ch.epfl.lamp.compiler.msil; - -/** - * @author Miguel Garcia - */ -public class GenericParamAndConstraints { - - public GenericParamAndConstraints(int Number, String Name, Type[] Constraints, - boolean isInvariant, boolean isCovariant, boolean isContravariant, - boolean isReferenceType, boolean isValueType, boolean hasDefaultConstructor) { - this.Number = Number; - this.Name = Name; - this.Constraints = Constraints; // TODO representation for the class and new() constraints missing - this.isInvariant = isInvariant; - this.isCovariant = isCovariant; - this.isContravariant = isContravariant; - this.isReferenceType = isReferenceType; - this.isValueType = isValueType; - this.hasDefaultConstructor = hasDefaultConstructor; - - } - - public final int Number; - public final String Name; // can be null - public final Type[] Constraints; // can be empty array - public final boolean isInvariant; // only relevant for TVars, not for an MVar - public final boolean isCovariant; // only relevant for TVars, not for an MVar - public final boolean isContravariant; // only relevant for TVars, not for an MVar - public final boolean isReferenceType; - public final boolean isValueType; - public final boolean hasDefaultConstructor; - - public String toString() { - String res = Name == null ? "" : (Name.equals("") ? "" : Name); - res = res + " <: " + Constraints; - return res; - } - -} - diff --git a/src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java b/src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java deleted file mode 100644 index 5ead0873505e..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/HasCustomModifiers.java +++ /dev/null @@ -1,9 +0,0 @@ -package ch.epfl.lamp.compiler.msil; - -public interface HasCustomModifiers { - - public Type[] GetOptionalCustomModifiers(); - - public Type[] GetRequiredCustomModifiers(); - -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ICustomAttributeProvider.java b/src/msil/ch/epfl/lamp/compiler/msil/ICustomAttributeProvider.java deleted file mode 100644 index 927185962c0e..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/ICustomAttributeProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Provides custom attributes for reflection objects that support them. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public interface ICustomAttributeProvider { - - //########################################################################## - // interface method definitions - - /** Returns an array of all of the custom attributes - * defined on this member, excluding named attributes, - * or an empty array if there are no custom attributes. - * - * @param inherit - When true, look up the hierarchy chain - * for the inherited custom attribute. - * @return - An array of Objects representing custom attributes, - * or an empty array. - */ - public Object[] GetCustomAttributes(boolean inherit); - - - /** Returns an array of custom attributes defined on this member, - * identified by type, or an empty array - * if there are no custom attributes of that type. - * - * @param attributeType - The type of the custom attributes. - * @param inherit - When true, look up the hierarchy chain - * for the inherited custom attribute. - * @return - An array of Objects representing custom attributes, - * or an empty array. - */ - public Object[] GetCustomAttributes(Type attributeType, boolean inherit); - - - /** Indicates whether one or more instance of attributeType - * is defined on this member - * - * @param attributeType - The type of the custom attributes - * @param inherit - When true, look up the hierarchy chain - * for the inherited custom attribute. - * @return - true if the attributeType is defined on this member; - * false otherwise. - */ - public boolean IsDefined(Type attributeType, boolean inherit); - - //########################################################################## - -} // interface ICustomAttributeProvider diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MemberInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/MemberInfo.java deleted file mode 100644 index 65ff1b290ba3..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/MemberInfo.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * The root class of the Reflection hierarchy. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class MemberInfo extends CustomAttributeProvider { - - //########################################################################## - - /** The name of this member. */ - public final String Name; - - /** - * The class that declares this member. - * Note: if the MemberInfo object is a global member, - * (that is, it was obtained from Module.GetMethods, - * which returns global methods on a module), then DeclaringType - * will be a null reference. - */ - public final Type DeclaringType; - - /** An enumerated value from the MemberTypes class, - * specifying a constructor, event, field, method, - * property, type information, all, or custom. */ - public abstract int MemberType(); - - //########################################################################## - // protected members - - protected static final MemberInfo[] EMPTY_ARRAY = new MemberInfo[0]; - - protected MemberInfo(String name, Type declType) { - Name = name; - DeclaringType = declType; - } - - //######################################################################## - -} // class MemberInfo diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MemberTypes.java b/src/msil/ch/epfl/lamp/compiler/msil/MemberTypes.java deleted file mode 100644 index 5f49ad33231d..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/MemberTypes.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Marks each type of member that is defined as a derived class of MemberInfo. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class MemberTypes { - - //########################################################################## - - /** Specifies that the member is a constructor, - * representing a ConstructorInfo member. */ - public static final int Constructor = 0x01; - - - /** Specifies that the member is an event, - * representing an EventInfo member. */ - public static final int Event = 0x02; - - - /** Specifies that the member is a field, - * representing a FieldInfo member. */ - public static final int Field = 0x04; - - - /** Specifies that the member is a method, - * representing a MethodInfo member. */ - public static final int Method = 0x08; - - - /** Specifies that the member is a property, - * representing a PropertyInfo member. - */ - public static final int Property = 0x10; - - /** Specifies that the member is a type, - * representing a TypeInfo member. */ - public static final int TypeInfo = 0x20; - - - /** Specifies that the member is a custom member type. */ - public static final int Custom = 0x40; - - - /** Specifies that the member is a nested type, - * extending MemberInfo. */ - public static final int NestedType = 0x80; - - - /** Specifies all member types. */ - public static final int All = - Constructor | Event | Field | Method | Property | TypeInfo | NestedType; - - - public static String toString(int memberType) { - if ((memberType & Constructor) != 0) return "Constructor"; - if ((memberType & Event) != 0) return "Event"; - if ((memberType & Field) != 0) return "Field"; - if ((memberType & Method) != 0) return "Method"; - if ((memberType & Property) != 0) return "Property"; - if ((memberType & TypeInfo) != 0) return "TypeInfo"; - if ((memberType & Custom) != 0) return "Custom"; - if ((memberType & NestedType) != 0) return "NestedType"; - return "Unknown MemberType: " + memberType; - } - - //########################################################################## - - // makes the class uninstantiable - private MemberTypes() {} - - //########################################################################## - -} // class MemberTypes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodAttributes.java deleted file mode 100644 index a703c38fb841..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/MethodAttributes.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** Specifies flags for method attributes. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class MethodAttributes { - - //########################################################################## - // Method access attributes - - /** Bitmask used to retrieve accessibility information. */ - public static final short MemberAccessMask = 0x0007; - - ///** Member not referenceable*/ - //public static final short CompilerConstrolled = 0x0000; - - /** Indicates that the member cannot be referenced. */ - public static final short PrivateScope = 0x0000; - - /** Method is accessible only by the current class. */ - public static final short Private = 0x0001; - - /** Method is accessible to members of this type - * and its derived types that are in this assembly only. */ - public static final short FamANDAssem = 0x0002; - - /** Method is accessible to any class of this assembly. */ - public static final short Assembly = 0x0003; - - /** Method is accessible only to members of this class - * and its derived classes. */ - public static final short Family = 0x0004; - - /** Method is accessible to derived classes anywhere, - * as well as to any class in the assembly. */ - public static final short FamORAssem = 0x0005; - - /** Method is accessible to any object for which this object is in scope. */ - public static final short Public = 0x0006; - - - //########################################################################## - // Flags - - /** Method is defined on the type; otherwise, it is defined per instance. */ - public static final short Static = 0x0010; - - /** Method cannot be overridden. */ - public static final short Final = 0x0020; - - /** Method is virtual. */ - public static final short Virtual = 0x0040; - - /** Method hides by name and signature; otherwise, by name only. */ - public static final short HideBySig = 0x0080; - - - //########################################################################## - // vtable attributes - - /** Bitmask used to retrieve vtable attributes. */ - public static final short VtableLayoutMask = 0x0100; - - /** Method reuses existing slot in the vtable. */ - public static final short ReuseSlot = 0x0000; - - - /** Method always gets a new slot in the vtable. */ - public static final short NewSlot = 0x0100; - - - //########################################################################## - // Flags - - /** Method does not provide implementation. */ - public static final short Abstract = 0x0400; - - /** Method is special. */ - public static final short SpecialName = 0x0800; - - - //########################################################################## - // Interop attributes - - /** Method implementation is forwarded through PInvoke. */ - public static final short PInvokeImpl = 0x2000; - - /** Reserved: shall be zero for conforming implementations. - * Managed method is exported by thunk to unmanaged code. */ - public static final short UnmanagedExport = 0x0008; - - - //########################################################################## - // Additional flags - - /** CLI provides special behavior, depending on the name of the method. */ - public static final short RTSpecialName = 0x1000; - - /** Method has security associated with it. - * Reserved flag for runtime use only. - */ - public static final short HasSecurity = 0x00000040; - - /** - * Indicates that the method calls another method containing security code. - * Reserved flag for runtime use only. - */ - public static final short RequireSecObject = 0x00004000; - - /** Indicates a reserved flag for runtime use only. */ - public static final short ReservedMask = 0x0000; - - - //########################################################################## - - public static String toString(short attrs) { - StringBuffer str = new StringBuffer(accessFlagsToString(attrs)); - if ((attrs & Static) != 0) str.append(" static"); - if ((attrs & Final) != 0) str.append(" final"); - if ((attrs & Virtual) != 0) str.append(" virtual"); - if ((attrs & Abstract) != 0) str.append(" abstract"); - if ((attrs & HideBySig) != 0) str.append(" hidebysig"); - if ((attrs & NewSlot) != 0) str.append(" newslot"); - if ((attrs & SpecialName) != 0) str.append(" specialname"); - if ((attrs & PInvokeImpl) != 0) str.append(" pinvokeimpl(?!?)"); - if ((attrs & RTSpecialName) != 0) str.append(" rtspecialname"); - return str.toString(); - - } - - public static String accessFlagsToString(short attrs) { - switch (attrs & MemberAccessMask) { - case PrivateScope: return "compilercontrolled"; - case Private: return "private"; - case FamANDAssem: return "famandassem"; - case Assembly: return "assembly"; - case Family: return "family"; - case FamORAssem: return "famorassem"; - case Public: return "public"; - default: return "xxx"; - } - } - - //########################################################################## - - // makes the class uninstantiable - private MethodAttributes() {} - - //########################################################################## - -} // class Method Attributes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java deleted file mode 100644 index fe6404346ecb..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import java.util.Iterator; - -/** - * The common superclass of MemberInfo and ConstructorInfo - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class MethodBase extends MemberInfo { - - //########################################################################## - // public interface - - private java.util.List /* GenericParamAndConstraints */ mVars = new java.util.LinkedList(); - private GenericParamAndConstraints[] sortedMVars = null; - - public void addMVar(GenericParamAndConstraints tvarAndConstraints) { - sortedMVars = null; - mVars.add(tvarAndConstraints); - } - - public GenericParamAndConstraints[] getSortedMVars() { - if(sortedMVars == null) { - sortedMVars = new GenericParamAndConstraints[mVars.size()]; - for (int i = 0; i < sortedMVars.length; i ++){ - Iterator iter = mVars.iterator(); - while(iter.hasNext()) { - GenericParamAndConstraints tvC = (GenericParamAndConstraints)iter.next(); - if(tvC.Number == i) { - sortedMVars[i] = tvC; - } - } - } - } - return sortedMVars; - } - - public final boolean IsGeneric() { - return mVars.size() > 0; - } - - /** The attributes associated with this method/constructor. */ - public final short Attributes; - - /***/ - public final short CallingConvention; - - public abstract boolean IsConstructor(); - - public final boolean IsAbstract() { - return (Attributes & MethodAttributes.Abstract) != 0; - } - - public final boolean IsFinal() { - return (Attributes& MethodAttributes.Final) != 0; - } - - public final boolean IsVirtual() { - return (Attributes& MethodAttributes.Virtual) != 0; - } - - public final boolean IsInstance() { - return !IsStatic() && !IsVirtual(); - } - - public final boolean IsStatic() { - return (Attributes & MethodAttributes.Static) != 0; - } - - public final boolean IsHideBySig() { - return (Attributes & MethodAttributes.HideBySig) != 0; - } - - public final boolean IsSpecialName() { - return (Attributes & MethodAttributes.SpecialName) != 0; - } - - - public final boolean IsPublic() { - return (Attributes & MethodAttributes.MemberAccessMask) - == MethodAttributes.Public; - } - - public final boolean IsPrivate() { - return (Attributes & MethodAttributes.MemberAccessMask) - == MethodAttributes.Private; - } - - public final boolean IsFamily() { - return (Attributes & MethodAttributes.MemberAccessMask) - == MethodAttributes.Family; - } - - public final boolean IsAssembly() { - return (Attributes & MethodAttributes.MemberAccessMask) - == MethodAttributes.Assembly; - } - - public final boolean IsFamilyOrAssembly() { - return (Attributes & MethodAttributes.MemberAccessMask) - == MethodAttributes.FamORAssem; - } - - public final boolean IsFamilyAndAssembly() { - return (Attributes & MethodAttributes.MemberAccessMask) - == MethodAttributes.FamANDAssem; - } - - public boolean HasPtrParamOrRetType() { - // the override in MethodInfo checks the return type - ParameterInfo[] ps = GetParameters(); - for (int i = 0; i < ps.length; i++) { - Type pT = ps[i].ParameterType; - if(pT.IsPointer()) { - // Type.mkPtr creates a msil.Type for a pointer type - return true; - } - if(pT.IsByRef() && !pT.GetElementType().CanBeTakenAddressOf()) { - /* TODO Cases where GenMSIL (so far) con't emit good bytecode: - the type being taken address of IsArray(), IsGeneric(), or IsTMVarUsage. - For example, System.Enum declares - public static bool TryParse(string value, out TEnum result) where TEnum : struct, new(); - */ - return true; - } - } - return false; - } - - /** Returns the parameters of the method/constructor. */ - public ParameterInfo[] GetParameters() { - return (ParameterInfo[]) params.clone(); - } - - public int GetMethodImplementationFlags() { return implAttributes; } - - //########################################################################## - - /** Method parameters. */ - protected ParameterInfo[] params; - - protected short implAttributes; - - protected MethodBase(String name, Type declType, int attrs, Type[] paramTypes) - { - this(name, declType, attrs); - assert paramTypes != null; - params = new ParameterInfo[paramTypes.length]; - for (int i = 0; i < params.length; i++) - params[i] = new ParameterInfo(null, paramTypes[i], 0, i); - } - - protected MethodBase(String name, Type declType, int attrs, - ParameterInfo[] params) - { - this(name, declType, attrs); - this.params = params; - } - - /** - */ - private MethodBase(String name, Type declType, int attrs) { - super(name, declType); - - Attributes = (short) attrs; - - if (IsConstructor()) { - attrs |= MethodAttributes.SpecialName; - attrs |= MethodAttributes.RTSpecialName; - } - - CallingConvention = (short) (CallingConventions.Standard - | (IsStatic() ? (short)0 : CallingConventions.HasThis)); - } - - //########################################################################## - // internal methods - - protected String params2String() { - StringBuffer s = new StringBuffer("("); - for (int i = 0; i < params.length; i++) { - if (i > 0) s.append(", "); - s.append(params[i].ParameterType); - } - s.append(")"); - return s.toString(); - } - - //########################################################################## - -} // class MethodBase diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodImplAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodImplAttributes.java deleted file mode 100644 index 8e8d8795938a..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/MethodImplAttributes.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Method implementation attributes - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class MethodImplAttributes { - - //########################################################################## - - /** - * Specifies flags about code type. 3 - */ - public static final short CodeTypeMask = (short) 0x0003; - - /** - * Specifies that the method implementation is in MSIL. 0 - */ - public static final short IL = (short) 0x0000; - - /** - * Specifies that the method implementation is native. 1 - */ - public static final short Native = (short) 0x0001; - - /** - * This member supports the .NET Framework infrastructure and - * is not intended to be used directly from your code. 2 - */ - public static final short OPTIL = (short) 0x0002; - - /** - * Specifies that the method implementation is provided by the runtime. 3 - */ - public static final short Runtime = (short) 0x0003; - - - - /** - * Specifies whether the code is managed or unmanaged. 4 - */ - public static final short ManagedMask = (short) 0x0004; - - /** - * Specifies that the method implementation is managed, otherwise unmanaged. - */ - public static final short Managed = (short) 0x0000; - - /** - * Specifies that the method implementation is unmanaged, otherwise managed. - */ - public static final short Unmanaged = (short) 0x0004; - - - - /** - * Specifies that the method cannot be inlined. 8 - */ - public static final short NoInlining = (short) 0x0008; - - /** - * Specifies that the method is not defined. 16 - */ - public static final short ForwardRef = (short) 0x0010; - - /** - * Specifies that the method is single-threaded through the body. - * You can also use the C# lock statement or the Visual Basic - * Lock function for this purpose. 32 - */ - public static final short Synchronized = (short) 0x0020; - - /** - * Specifies that the method signature is exported exactly as declared. 128 - */ - public static final short PreserveSig = (short) 0x0080; - - /** - * Specifies an internal call. 4096 - */ - public static final short InternalCall = (short) 0x1000; - - /** - * Specifies a range check value. 65535 - */ - public static final short MaxMethodImplVal = (short) 0xffff; - - //########################################################################## - - public static String toString(int implAttr) { - StringBuffer s = new StringBuffer(); - switch (implAttr & CodeTypeMask) { - case IL: s.append("cil"); break; - case Native: s.append("native"); break; - case Runtime: s.append("runtime"); break; - } - switch (implAttr & ManagedMask) { - case Managed: s.append(" managed"); break; - case Unmanaged: s.append(" unmanaged"); break; - } - if ((implAttr & NoInlining) != 0) s.append(" noinlining"); - if ((implAttr & ForwardRef) != 0) s.append(" forwardref"); - if ((implAttr & Synchronized) != 0) s.append(" synchronized"); - if ((implAttr & InternalCall) != 0) s.append(" internalcall"); - return s.toString(); - } - - //########################################################################## - -} // class MethodImplAttributes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java deleted file mode 100644 index a415e7551f7f..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import java.util.Iterator; - -/** - * Discovers the attributes of a method and provides access to method metadata. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class MethodInfo extends MethodBase { - - public boolean HasPtrParamOrRetType() { - if(ReturnType.IsByRef() && !(ReturnType.GetElementType().IsValueType())) { - /* A method returning ByRef won't pass peverify, so I guess this is dead code. */ - return true; - } - if(ReturnType.IsPointer()) { - return true; - } - return super.HasPtrParamOrRetType(); - } - - //########################################################################## - // public members - - public final int MemberType() { return MemberTypes.Method; } - - public final boolean IsConstructor() { return false; } - - /** The return type of this method. - */ - public final Type ReturnType; - - //########################################################################## - // protected members - - protected static final MethodInfo[] EMPTY_ARRAY = new MethodInfo[0]; - - /** - * Constructor Initializes a new instance of the MethodInfo class. - */ - protected MethodInfo(String name, Type declType, - int attrs, Type returnType, Type[] paramTypes ) - { - super(name, declType, attrs, paramTypes); - ReturnType = returnType; - } - - protected MethodInfo(String name, Type declType, - int attrs, Type returnType, ParameterInfo[] params ) - { - super(name, declType, attrs, params); - ReturnType = returnType; - } - - public String toString() { - return MethodAttributes.toString(Attributes) + " " + ReturnType + - " " + DeclaringType + "::" + Name + params2String(); - } - - //########################################################################## - -} // class MethodInfo diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Module.java b/src/msil/ch/epfl/lamp/compiler/msil/Module.java deleted file mode 100644 index 8dd5e7119f21..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/Module.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import java.util.Map; -import java.util.HashMap; - -/** - * Defines and represents a module. Get an instance of ModuleBuilder - * by calling DefineDynamicModule - * A module is a portable executable file of type .dll or .exe consisting - * of one or more classes and interfaces. There may be multiple namespaces - * contained in a single module, and a namespace may span multiple modules. - * One or more modules deployed as a unit compose an assembly. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class Module extends CustomAttributeProvider { - - //########################################################################## - // public fields - - /** String representing the name of the module with the path removed. */ - public final String Name; - - /** String representing the fully qualified name and path to this module. */ - public final String FullyQualifiedName; - - /** String representing the name of the module. */ - public String ScopeName; - - /** The Assembly the Module belongs to. */ - public final Assembly Assembly; - - //########################################################################## - // constructor - - protected Module(String name, String filename, - String scopeName, Assembly assembly) - { - this.Name = name; - this.FullyQualifiedName = filename; - this.ScopeName = scopeName; - this.Assembly = assembly; - } - - //########################################################################## - // public methods - - /** Returns the specified class, performing a case-sensitive search. */ - public Type GetType(String name) { - initTypes(); - return (Type) typesMap.get(name); - } - - /** - * @return all the classes defined within this module. - */ - public Type[] GetTypes() { - initTypes(); - return (Type[]) types.clone(); - } - - /** - * @return the global field with the specified name. - */ - public FieldInfo GetField(String name) { - for (int i = 0; i < fields.length; i++) - if (fields[i].Name.equals(name)) - return fields[i]; - return null; - } - - /** - * @return an array of the global fields of the module - */ - public FieldInfo[] GetFields() { - return (FieldInfo[]) fields.clone(); - } - - /** - * @return - the global method with the specified name - */ - public MethodInfo GetMethod(String name) { - for (int i = 0; i < methods.length; i++) - if (methods[i].Name.equals(name)) - return methods[i]; - return null; - } - - /** - * @return - an array of all the global methods defined in this modules. - */ - public MethodInfo[] GetMethods() { - return (MethodInfo[]) methods.clone(); - } - - /** - */ - public String toString() { return Name; } - - //######################################################################## - // protected members - - // all the types defined in this module - protected final Map typesMap = new HashMap(); - - // all the types defined in this module - protected Type[] types; - - // the global fields of the module - protected FieldInfo[] fields = FieldInfo.EMPTY_ARRAY; - - // the global methods of the module - protected MethodInfo[] methods = MethodInfo.EMPTY_ARRAY; - - protected Type addType(Type type) { - addType(type.FullName, type); - Assembly.addType(type); - return type; - } - - protected Type addType(String name, Type type) { - assert type!= null; - typesMap.put(name, type); - return type; - } - - private boolean initTypes = true; - protected final void initTypes() { - if (initTypes) { - loadTypes(); - initTypes = false; - } - } - - protected void loadTypes() {} - - private boolean initGlobals = true; - protected final void initGlobals() { - if (initGlobals) { - loadGlobals(); - initGlobals = false; - } - } - - protected void loadGlobals() {} - - //########################################################################## - -} // class Module diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEAssembly.java b/src/msil/ch/epfl/lamp/compiler/msil/PEAssembly.java deleted file mode 100644 index a31db16c92c4..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/PEAssembly.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.util.Table; -import ch.epfl.lamp.compiler.msil.util.Table.*; - -import java.io.File; - -import java.util.Map; -import java.util.HashMap; - -/** Represents an assembly that resides in a real .NET assembly - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -final class PEAssembly extends Assembly { - - private final PEFile pefile; - - private PEModule mainModule; - - public PEAssembly(PEFile pefile, AssemblyName an) { - super(an, true); - this.pefile = pefile; - String name = pefile.ModuleDef(1).getName(); - mainModule = new PEModule(pefile, 1, name, this); - addModule(name, mainModule); - //initModules(); - } - - protected void loadModules() { - File parentDir = pefile.getParentFile(); - FileDef fd = pefile.FileDef; - for (int row = 1; row <= fd.rows; row++) { - fd.readRow(row); - String filename = fd.getName(); - File f = new File(parentDir, filename); - PEFile pe = Assembly.getPEFile(f); - if (pe == null) { - f = new File(filename); - pe = Assembly.getPEFile(f); - if (pe == null) - continue; -// throw new RuntimeException("Cannot find file " + filename + -// " referenced by assembly " + this); - } - String name = pe.ModuleDef(1).getName(); - PEModule module = new PEModule(pe, 1, name, this); - addModule(name, module); - } - } - - public File getFile() { - return pefile.getUnderlyingFile(); - } - - protected void loadCustomAttributes(Type attributeType) { - initModules(); - mainModule.initAttributes(this, 1, Table.AssemblyDef.ID, attributeType); - } - - //########################################################################## - -} // class PEAssembly diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java deleted file mode 100644 index 3eb22b998523..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java +++ /dev/null @@ -1,941 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.util.*; -import ch.epfl.lamp.compiler.msil.util.Table.*; - -import ch.epfl.lamp.compiler.msil.Type; -import ch.epfl.lamp.compiler.msil.Module; - -import java.io.File; -import java.io.RandomAccessFile; -import java.io.PrintStream; -import java.io.IOException; -import java.io.FileNotFoundException; - -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.MappedByteBuffer; - -import java.util.Date; - -/** - * A class that represents a .NET PE/COFF image. - * - * @author Nikolay Mihaylov - * @version 1.0 - * @see Standard ECMA-335: Common Language Infrastructure (CLI), 4th edition (June 2006) - */ -public class PEFile { - - //########################################################################## - - public static final int INT_SIZE = 4; - - protected final int PE_SIGNATURE_OFFSET; - protected final int COFF_HEADER_OFFSET; - protected final int PE_HEADER_OFFSET; - - protected final int numOfSections; - protected final int CLI_RVA; - protected final int CLI_Length; - public final int rvaMetadata; - public final int posMetadata; - protected final int numOfStreams; - protected final int optHeaderSize; - - protected final File underlyingFile; - protected final RandomAccessFile file; - protected final MappedByteBuffer buf; - - protected final PESection [] sections; - - public PEStream Meta, Strings, US, Blob, GUID; - - private final Table [] tables = new Table[Table.MAX_NUMBER]; - - public final boolean isDLL; - - protected final int heapSizes; - public final boolean StringIsShort, BlobIsShort, GUIDIsShort; - - protected PEModule pemodule = null; - - //########################################################################## - // PEFile constructor - - private static void fileFormatCheck(boolean cond, String s) { - if (cond) - throw new RuntimeException(s); - } - - /** - */ - public PEFile(String filename) throws FileNotFoundException { - this.underlyingFile = new File(filename); - this.file = new RandomAccessFile(underlyingFile, "r"); - FileChannel fc = file.getChannel(); - MappedByteBuffer bb = null; - try { - bb = fc.map(FileChannel.MapMode.READ_ONLY, 0L, fc.size()); - } catch (IOException e) { throw new RuntimeException(e); } - - /** Ecma 335, 25 File format extensions to PE: - * - * "Unless stated otherwise, all binary values are stored in little-endian format." - */ - - bb.order(java.nio.ByteOrder.LITTLE_ENDIAN); - this.buf = bb; - - /** Ecma 335, 25.2.1 MS-DOS header: - * - * "The PE format starts with an MS-DOS stub of exactly the following 128 bytes to - * be placed at the front of the module." - * - * We are only checking for MZ (Mark Zbikowski) - */ - - seek(0); - fileFormatCheck(readByte() != 0x4d, "Invalid PE file format: " + filename); // 'M' - fileFormatCheck(readByte() != 0x5a, "Invalid PE file format: " + filename); // 'Z' - - /** Ecma 335, 25.2.1 MS-DOS header: - * - * "At offset 0x3c in the DOS header is a 4-byte unsigned integer offset, lfanew, - * to the PE signature (shall be "PE\0\0"), immediately followed by the PE file header." - */ - - seek(0x3c); - PE_SIGNATURE_OFFSET = readInt(); - seek(PE_SIGNATURE_OFFSET); - // start of PE signature (a signature that is just 4 bytes long) - fileFormatCheck(readByte() != 0x50, "Invalid PE file format: " + filename); // 'P' - fileFormatCheck(readByte() != 0x45, "Invalid PE file format: " + filename); // 'E' - fileFormatCheck(readByte() != 0x00, "Invalid PE file format: " + filename); // 0 - fileFormatCheck(readByte() != 0x00, "Invalid PE file format: " + filename); // 0 - - //trace("PE signature offset = 0x" + Table.int2hex(PE_SIGNATURE_OFFSET)); - - COFF_HEADER_OFFSET = PE_SIGNATURE_OFFSET + 4; - PE_HEADER_OFFSET = COFF_HEADER_OFFSET + 20; - - seek(COFF_HEADER_OFFSET); - - /* start of PE file header, Sec. 25.2.2 in Partition II */ - skip(2); // Machine (always 0x14c) - numOfSections = readShort(); // Number of sections; indicates size of the Section Table - Date timeStamp = new Date(readInt() * 1000L); - skip(2 * INT_SIZE); // skip Pointer to Symbol Table (always 0) and Number of Symbols (always 0) - optHeaderSize = readShort(); - int characteristics = readShort(); - isDLL = (characteristics & 0x2000) != 0; - - seek(PE_HEADER_OFFSET + 208); // p.157, Partition II - - CLI_RVA = readInt(); // called "Data Directory Table" in Ch. 4 of Expert IL book - CLI_Length = readInt(); - //trace("CLI_RVA = 0x" + Table.int2hex(CLI_RVA)); - //trace("CLI_Length = 0x" + Table.int2hex(CLI_Length)); - - sections = new PESection[numOfSections]; - - seek(PE_HEADER_OFFSET + optHeaderSize); // go to the sections descriptors - - for (int i = 0; i < numOfSections; i++) { - seek(PE_HEADER_OFFSET + optHeaderSize + i * 40); - sections[i] = new PESection(this); - //sections[i].dump(System.out); - } - - seek(fromRVA(CLI_RVA)); - skip(8); - rvaMetadata = readInt(); - posMetadata = fromRVA(rvaMetadata); - //trace("rvaMetadata = 0x" + Table.int2hex(rvaMetadata)); - //trace("posMetadata = 0x" + Table.int2hex(posMetadata)); - - seek(posMetadata); - int magic = readInt(); - //trace("Magic metadata signature = 0x" + Table.int2hex(magic)); - fileFormatCheck(magic != 0x424a5342, "Invalid metadata signature!"); - skip(8); - - int strlength = readInt(); - //trace("version name string length = " + strlength); - skip(strlength); - align(INT_SIZE, posMetadata); - //trace("position of flags = 0x" + Table.int2hex((int)pos())); - skip(2); // ignore the flags - numOfStreams = readShort(); - //trace("Number of metadata streams = " + numOfStreams); - - for (int i = 0; i < numOfStreams; i++) { - PEStream strm = new PEStream(this); - //strm.dump(System.out); - if (strm.name.equals("#~") - || strm.name.equals("#-")) Meta = strm; - if (strm.name.equals("#Strings")) Strings = strm; - if (strm.name.equals("#US")) US = strm; - if (strm.name.equals("#Blob")) Blob = strm; - if (strm.name.equals("#GUID")) GUID = strm; - } - - seek(Meta.offset); - skip(6); - heapSizes = readByte(); - StringIsShort = (heapSizes & 0x01) == 0; - GUIDIsShort = (heapSizes & 0x02) == 0; - BlobIsShort = (heapSizes & 0x04) == 0; - - skip(1); - long tablesMask = readLong(); - long nonStandardTables = tablesMask & ~Table.VALID_TABLES_MASK; - skip(8); //go to the list of number of rows - for (int i = 0; i < tables.length; i++) { - tables[i] = Table.newTable - (this, i, ((tablesMask >> i) & 0x01) != 0 ? readInt() : 0); - } - - initIndexSize(); - initTableRefs(); - // populate the tables from the CLI image file - long start = pos(); - for (int i = 0; i < tables.length; i++) - start = tables[i].init(start); - - } // PEFile() - - - public final int[] indexSize = new int[Table.TABLE_SET_LENGTH]; - - private void initIndexSize() { - for (int i = 0; i < Table.TABLE_SET_LENGTH; i++) { - indexSize[i] = 2; - int[] tableSet = Table.TableSet[i]; - int treshold = (65536 >> Table.NoBits[i]); - for (int j = 0; j < tableSet.length; j++) { - if (tableSet[j] >= 0) { - Table t = tables[tableSet[j]]; - if (t.rows >= treshold) { - indexSize[i] = 4; - break; - } - } - } - } - } - - protected void initModule(PEModule module) { - if (pemodule != null) - throw new RuntimeException("File " + this - + " has already been assigned module " - + pemodule + "; new module is " + module); - this.pemodule = module; - } - - //########################################################################## - - public ModuleDef ModuleDef; - public ModuleDef ModuleDef(int i) { - ModuleDef.readRow(i); - return ModuleDef; - } - - public TypeRef TypeRef; - - public TypeDef TypeDef; - public TypeDef TypeDef(int i) { - TypeDef.readRow(i); - return TypeDef; - } - - public FieldTrans FieldTrans; - public FieldTrans FieldTrans(int i) { - FieldTrans.readRow(i); - return FieldTrans; - } - - public FieldDef FieldDef; - public FieldDef FieldDef(int i) { - FieldDef.readRow(i); - return FieldDef; - } - - public MethodTrans MethodTrans; - public MethodTrans MethodTrans(int i) { - MethodTrans.readRow(i); - return MethodTrans; - } - - public MethodDef MethodDef; - public MethodDef MethodDef(int i) { MethodDef.readRow(i); return MethodDef; } - - - public ParamDef ParamDef; - public ParamDef ParamDef(int i) { ParamDef.readRow(i); return ParamDef; } - - public GenericParam GenericParam; - - public GenericParam GenericParam(int i) { - GenericParam.readRow(i); - return GenericParam; - } - - public MethodSpec MethodSpec; - - public MethodSpec MethodSpec(int i) { - MethodSpec.readRow(i); - return MethodSpec; - } - - public GenericParamConstraint GenericParamConstraint; - - public GenericParamConstraint GenericParamConstraint(int i) { - GenericParamConstraint.readRow(i); - return GenericParamConstraint; - } - - public InterfaceImpl InterfaceImpl; - public MemberRef MemberRef; - public Constant Constant; - public CustomAttribute CustomAttribute; - public FieldMarshal FieldMarshal; - public DeclSecurity DeclSecurity; - public ClassLayout ClassLayout; - public FieldLayout FieldLayout; - public StandAloneSig StandAloneSig; - public EventMap EventMap; - public EventDef EventDef; - public PropertyMap PropertyMap; - public PropertyDef PropertyDef; - public MethodSemantics MethodSemantics; - public MethodImpl MethodImpl; - public ModuleRef ModuleRef; - public TypeSpec TypeSpec; - public ImplMap ImplMap; - public FieldRVA FieldRVA; - public AssemblyDef AssemblyDef; - public AssemblyRef AssemblyRef; - public FileDef FileDef; - public ExportedType ExportedType; - public ManifestResource ManifestResource; - public NestedClass NestedClass; - - - private void initTableRefs() { - ModuleDef = (ModuleDef) getTable(Table.ModuleDef.ID); - TypeRef = (TypeRef) getTable(Table.TypeRef.ID); - TypeDef = (TypeDef) getTable(Table.TypeDef.ID); - FieldTrans = (FieldTrans) getTable(Table.FieldTrans.ID); - FieldDef = (FieldDef) getTable(Table.FieldDef.ID); - MethodTrans = (MethodTrans) getTable(Table.MethodTrans.ID); - MethodDef = (MethodDef) getTable(Table.MethodDef.ID); - ParamDef = (ParamDef) getTable(Table.ParamDef.ID); - InterfaceImpl = (InterfaceImpl) getTable(Table.InterfaceImpl.ID); - MemberRef = (MemberRef) getTable(Table.MemberRef.ID); - Constant = (Constant) getTable(Table.Constant.ID); - CustomAttribute = (CustomAttribute) getTable(Table.CustomAttribute.ID); - FieldMarshal = (FieldMarshal) getTable(Table.FieldMarshal.ID); - DeclSecurity = (DeclSecurity) getTable(Table.DeclSecurity.ID); - ClassLayout = (ClassLayout) getTable(Table.ClassLayout.ID); - FieldLayout = (FieldLayout) getTable(Table.FieldLayout.ID); - StandAloneSig = (StandAloneSig) getTable(Table.StandAloneSig.ID); - EventMap = (EventMap) getTable(Table.EventMap.ID); - EventDef = (EventDef) getTable(Table.EventDef.ID); - PropertyMap = (PropertyMap) getTable(Table.PropertyMap.ID); - PropertyDef = (PropertyDef) getTable(Table.PropertyDef.ID); - MethodSemantics = (MethodSemantics) getTable(Table.MethodSemantics.ID); - MethodImpl = (MethodImpl) getTable(Table.MethodImpl.ID); - ModuleRef = (ModuleRef) getTable(Table.ModuleRef.ID); - TypeSpec = (TypeSpec) getTable(Table.TypeSpec.ID); - ImplMap = (ImplMap) getTable(Table.ImplMap.ID); - FieldRVA = (FieldRVA) getTable(Table.FieldRVA.ID); - AssemblyDef = (AssemblyDef) getTable(Table.AssemblyDef.ID); - AssemblyRef = (AssemblyRef) getTable(Table.AssemblyRef.ID); - FileDef = (FileDef) getTable(Table.FileDef.ID); - ExportedType = (ExportedType) getTable(Table.ExportedType.ID); - NestedClass = (NestedClass) getTable(Table.NestedClass.ID); - ManifestResource = - (ManifestResource) getTable(Table.ManifestResource.ID); - GenericParam = (GenericParam) getTable(Table.GenericParam.ID); - MethodSpec = (MethodSpec) getTable(Table.MethodSpec.ID); - GenericParamConstraint = (GenericParamConstraint) getTable(Table.GenericParamConstraint.ID); - } - - public static String long2hex(long a) { - StringBuffer str = new StringBuffer("0000000000000000"); - str.append(Long.toHexString(a)); - int l = str.length(); - return str.substring(l - 16, l); - } - - public static String int2hex(int a) { - StringBuffer str = new StringBuffer("00000000"); - str.append(Integer.toHexString(a)); - int l = str.length(); - return str.substring(l - 8, l); - } - - public static String short2hex(int a) { - StringBuffer str = new StringBuffer("0000"); - str.append(Integer.toHexString(a)); - int l = str.length(); - return str.substring(l - 4, l); - } - - public static String byte2hex(int a) { - StringBuffer str = new StringBuffer("00"); - str.append(Integer.toHexString(a)); - int l = str.length(); - return str.substring(l - 2, l); - } - - public static String bytes2hex(byte[] buf) { - StringBuffer str = new StringBuffer(); - for (int i = 0; i < buf.length; i++) { - str.append(byte2hex(buf[i])); - if (i < buf.length - 1) - str.append(" "); - } - return str.toString(); - } - - //########################################################################## - // filename - - public File getUnderlyingFile() { - return underlyingFile; - } - - /** - * @return the absolute path of the file - */ - public String getAbsolutePath() { - return underlyingFile.getAbsolutePath(); - } - - /** - * @return the name of this file - */ - public String getName() { - return underlyingFile.getName(); - } - - /** - * @return - */ - public String getParent() { - return underlyingFile.getParent(); - } - - /** - * @return the file representing the directory the file belongs to - */ - public File getParentFile() { - return underlyingFile.getParentFile(); - } - - public String toString() { - return getAbsolutePath(); - } - - //########################################################################## - // file pointer manipulation methods - - /** Returns the current position in the file. */ - public int pos() { - return buf.position(); - } - - /** Go to the specified position in the file. */ - public void seek(int pos) { - buf.position(pos); - } - - - /** Align the current position in the file. */ - public void align(int base) { align(base, 0); } - - /** Align the current position in a section starting at offset. */ - public void align(int base, int offset) { - int p = pos() - offset; - seek( offset + ((p % base) == 0 ? p : (p/base + 1) * base)); - } - - /** Computes the position in the file that corresponds to the given RVA. */ - public int fromRVA(int rva) { - int i; - for(i = 0; i < numOfSections; i++) - if(sections[i].virtAddr <= rva && - rva <= (sections[i].virtAddr + sections[i].virtSize)) - return rva - sections[i].virtAddr + sections[i].realAddr; - throw new RuntimeException("RVA 0x" + Integer.toHexString(rva) + - " is not within this file's sections!"); - } - - /** Go to the specified RVA (Relative Virtual Address). */ - public void gotoRVA(int rva) { - seek(fromRVA(rva)); - } - - /** Move the forward in the file by the specified number of bytes. */ - public void skip(int n) { - buf.position(buf.position() + n); - } - - /** - * Returns a memory mapped little-endian buffer - * for the specified region of the file. - */ - public MappedByteBuffer mapBuffer(long offset, int size) { - try { - MappedByteBuffer b = file.getChannel() - .map(FileChannel.MapMode.READ_ONLY, offset, size); - b.order(java.nio.ByteOrder.LITTLE_ENDIAN); - return b; - } catch (IOException e) { throw new RuntimeException(e); } - } - - /** Returns a buffer from the given offset to the end of the file. */ - public ByteBuffer getBuffer(long offset, int size) { - buf.mark(); - buf.position((int)offset); - ByteBuffer bb = buf.slice(); - buf.reset(); - bb.limit(size); - bb.order(java.nio.ByteOrder.LITTLE_ENDIAN); - return bb; - } - - //########################################################################## - // file read methods - - /** - * Read bs.length number of bytes - */ - public void read(byte[] bs) { - buf.get(bs); - } - - /** - * Read 1-byte integer from the current position in the file. - */ - public int readByte() { - return buf.get(); - } - - /** - * Read 2-byte integer from the current position in the file. - */ - public int readShort() { - return buf.getShort(); - } - - /** - * Read 4-byte integer from the current position in the file. - */ - public int readInt() { - return buf.getInt(); - } - - /** - * Read 8-byte integer from the current position in the file. - */ - public long readLong() { - return buf.getLong(); - } - - /** - * @return the size of string indeces for this file. - */ - public int getStringIndexSize() { - return StringIsShort ? 2 : 4; - } - - /** - * @return the size of GUID indeces for this file. - */ - public int getGUIDIndexSize() { - return GUIDIsShort ? 2 : 4; - } - - /** - * @return the size of Blob indeces for this file. - */ - public int getBlobIndexSize() { - return BlobIsShort ? 2 : 4; - } - - /** - * @return the size of the index to tableID for this file; - * @param tableID the ID of the table - */ - public int getTableIndexSize(int tableID) { - return tables[tableID].isShort ? 2 : 4; - } - - /** - * @return the size of the index to a set of tables with the given @param TableSetID - * @param tableSetID the ID of the table set - */ - public int getTableSetIndexSize(int tableSetID) { - return indexSize[tableSetID]; - } - - /** - * Read a String index from the current position in the file. - * @return an index into the String stream - */ - public int readStringIndex() { - return StringIsShort ? readShort() : readInt(); - } - - /** - * Read a GUID index from the current position in the file. - * @return an index in to the GUID stream - */ - public int readGUIDIndex() { - return GUIDIsShort ? readShort() : readInt(); - } - - /** - * Read a Blob index from the current position in the file. - * @return an index into the Blob stream - */ - public int readBlobIndex() { - return BlobIsShort ? readShort() : readInt(); - } - - /** Read an entry interpreted as index into table @param tableID. */ - public int readTableIndex(int tableId) { - return tables[tableId].isShort ? readShort() : readInt(); - } - - /***/ - public int readTableSetIndex(int tableSetId) { - return indexSize[tableSetId] == 2 ? readShort() : readInt(); - } - - /** - * Read a string from the String stream - * @return the string at the given position - * @param pos the position of the string in the String stream - */ - public String getString(int pos) { - String s = Strings.getString(pos); - return s;//.length() == 0 ? null : s; - } - - /** - * Read a string from the US (User Strings) stream - * @return the string at the given position - * @param pos the position of the string in the US stream - */ - public String getUString(int pos) { - return US.getString(pos); - } - - /** - * Read a blob from the Blob Stream - * @return the blob at the given position - * @param pos the position of the blob in the Blob stream - */ - public byte[] getBlob(int pos) { - return Blob.getBlob(pos); - } - - /***/ - public Sig getSignature(int pos) { - //return new Sig(getBlob(pos)); - return Blob.getSignature(pos); - } - - /***/ - public byte[] getGUID(int pos) { - return GUID.getGUID(pos); - } - - /** - * @return the table with the corresponding ID. - */ - public final Table getTable(int tableID) { - return tables[tableID]; - } - - //########################################################################## - - /***/ - void trace(String msg) { - System.out.println("[trace] " + msg); - } - - //########################################################################## - - public Sig newSignature(ByteBuffer buf) { - return new Sig(buf); - } - - /** - */ - public class Sig implements Signature { - - //###################################################################### - // instance members - - protected final ByteBuffer buf; - protected final int pos; - protected final int length; - - public Sig(ByteBuffer buf) { - this.buf = buf; - //int tmpPos = buf.position(); - length = decodeInt(); - this.pos = buf.position(); - } - - public String toString() { - StringBuffer b = new StringBuffer("("); - int savedPos = buf.position(); - reset(); - for (int i = 0; i < length; i++) { - b.append(byte2hex(readByte())); - if (i < length - 1) - b.append(" "); - } - buf.position(savedPos); - return b.append(")").toString(); - } - - public Sig reset() { buf.position(pos); return this; } - - public int pos() { return buf.position() - pos; } - - /** @return the byte at the current position in the signature Blob. - * Stay at the same position - */ - public int getByte() { - return (buf.get(buf.position()) + 0x100) & 0xff; - } - - /** @return the byte at the current position in the signature Blob. - * Move to the next byte. - */ - public int readByte() { return (buf.get() + 0x100) & 0xff; } - - /** Skip the current byte if equal to the given value. */ - public void skipByte(int b) { if (b == getByte()) buf.get(); } - - /** Decodes an integer from the signature Blob. - * @return the decoded integer - */ - public int decodeInt() { - int res = readByte(); - if ((res & 0x80) != 0) { - res = ((res & 0x7f) << 8) | readByte(); - if ((res & 0x4000) != 0) - res = ((res & 0x3fff)<<16) | (readByte()<<8) | readByte(); - } - return res; - } - - /** @return - the type encoded at the current position in the signature - * according to 23.2.12 - */ - public Type decodeType() { - try { return decodeType0(); } - catch (RuntimeException e) { - System.out.println("" + pos() + "@" + this); - throw e; - } - } - - public Type decodeType0() { - Type type = null; - int desc = readByte(); - switch (desc) { - case ELEMENT_TYPE_BOOLEAN:type = Type.GetType("System.Boolean"); break; - case ELEMENT_TYPE_CHAR: type = Type.GetType("System.Char"); break; - case ELEMENT_TYPE_I1: type = Type.GetType("System.SByte"); break; - case ELEMENT_TYPE_U1: type = Type.GetType("System.Byte"); break; - case ELEMENT_TYPE_I2: type = Type.GetType("System.Int16"); break; - case ELEMENT_TYPE_U2: type = Type.GetType("System.UInt16"); break; - case ELEMENT_TYPE_I4: type = Type.GetType("System.Int32"); break; - case ELEMENT_TYPE_U4: type = Type.GetType("System.UInt32"); break; - case ELEMENT_TYPE_I8: type = Type.GetType("System.Int64"); break; - case ELEMENT_TYPE_U8: type = Type.GetType("System.UInt64"); break; - case ELEMENT_TYPE_R4: type = Type.GetType("System.Single"); break; - case ELEMENT_TYPE_R8: type = Type.GetType("System.Double"); break; - case ELEMENT_TYPE_OBJECT: type = Type.GetType("System.Object"); break; - case ELEMENT_TYPE_STRING: type = Type.GetType("System.String"); break; - case ELEMENT_TYPE_I: type = Type.GetType("System.IntPtr"); break; - case ELEMENT_TYPE_U: type = Type.GetType("System.UIntPtr"); break; - case ELEMENT_TYPE_PTR: // Followed by token. - if (getByte() == ELEMENT_TYPE_VOID) { - readByte(); - type = Type.mkPtr(Type.GetType("System.Void")); - } else type = Type.mkPtr(decodeType()); - break; - case ELEMENT_TYPE_BYREF: /* although BYREF is not listed in 23.2.12. as possible alternative, this method is also called when parsing the signatures of a method param and a method return, which do allow for BYREF */ - type = Type.mkByRef(decodeType()); - break; - case ELEMENT_TYPE_VALUETYPE: // Followed by TypeDefOrRefEncoded - assert true; - case ELEMENT_TYPE_CLASS: - // Followed by token - type = pemodule.getTypeDefOrRef(decodeInt()); - if (type == null) throw new RuntimeException(); - break; - - case ELEMENT_TYPE_SZARRAY: // Single-dim array with 0 lower bound. - skipCustomMods(); - type = Type.mkArray(decodeType(), 1); - break; - case ELEMENT_TYPE_ARRAY: - // ... ... - // ArrayShape defined in 23.2.13 ArrayShape - Type elem = decodeType(); - int rank = decodeInt(); - int numSizes = decodeInt(); - for (int i = 0; i < numSizes; i++) - decodeInt(); // TODO don't ignore - int numLoBounds = decodeInt(); - for (int i = 0; i < numLoBounds; i++) - decodeInt(); // TODO don't ignore - type = Type.mkArray(elem, rank); - break; - - // a grammar production from 23.2.12 Type - // GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type* - case ELEMENT_TYPE_GENERICINST: - int b = readByte(); - /*- TODO don't ignore b as done above. Should .NET valuetypes be represented as Scala case classes? */ - Type instantiatedType = pemodule.getTypeDefOrRef(decodeInt()); - int numberOfTypeArgs = decodeInt(); - Type[] typeArgs = new Type[numberOfTypeArgs]; - for (int iarg = 0; iarg < numberOfTypeArgs; iarg++) { - typeArgs[iarg] = decodeType(); - } - type = new ConstructedType(instantiatedType, typeArgs); - break; - - // another grammar production from 23.2.12 Type - // ELEMENT_TYPE_VAR number The number non-terminal following MVAR - // or VAR is an unsigned integer value (compressed). - /* See also duplicate code in PEModule.java */ - case ELEMENT_TYPE_VAR: - int typeArgAsZeroBased = decodeInt(); - type = new Type.TMVarUsage(typeArgAsZeroBased, true); - break; - - // another grammar production from 23.2.12 Type - // ELEMENT_TYPE_MVAR number The number non-terminal following MVAR - // or VAR is an unsigned integer value (compressed). - /* See also duplicate code in PEModule.java */ - case ELEMENT_TYPE_MVAR: - typeArgAsZeroBased = decodeInt(); - type = new Type.TMVarUsage(typeArgAsZeroBased, false); - break; - - case ELEMENT_TYPE_FNPTR: - // Followed MethodDefSig or by MethodRefSig. - case ELEMENT_TYPE_END: - // Marks end of a list - case ELEMENT_TYPE_CMOD_REQD: - // Required modifier : followed by a TypeDef or TypeRef token. - case ELEMENT_TYPE_CMOD_OPT: - // Optional modifier : followed by a TypeDef or TypeRef token. - case ELEMENT_TYPE_INTERNAL: - // Implemented within the CLI. - case ELEMENT_TYPE_MODIFIER: - // Or'd with following element types. - case ELEMENT_TYPE_SENTINEL: - // Sentinel for varargs method signature. - case ELEMENT_TYPE_PINNED: - // Denotes a local variable that points at a pinned object. - default: - throw new RuntimeException(byte2hex(desc) + - "@" + pos() + " in " + this); - - } - if (type == null) throw new RuntimeException(); - return type; - } // decodeType0() - - public PECustomMod decodeFieldType() { - skipByte(FIELD); // 0x06 - CustomModifier[] cmods = getCustomMods(); - Type fieldType = decodeType(); - return new PECustomMod(fieldType, cmods); - } - - /** decodes the return type of a method signature (22.2.11). */ - public Type decodeRetType() { - skipCustomMods(); - switch (getByte()) { - case ELEMENT_TYPE_VOID: - readByte(); - return Type.GetType("System.Void"); - case ELEMENT_TYPE_TYPEDBYREF: - return Type.GetType("System.TypedReference"); - case ELEMENT_TYPE_BYREF: - return decodeType(); - default: - return decodeType(); - } - } - - public Type decodeParamType() { - skipCustomMods(); - switch (getByte()) { - case ELEMENT_TYPE_BYREF: - return decodeType(); - case ELEMENT_TYPE_TYPEDBYREF: - return Type.GetType("System.TypedReference"); - default: - return decodeType(); - } - } - - public void skipCustomMods() { - while (getByte() == ELEMENT_TYPE_CMOD_OPT /* 0x20 */ - || getByte() == ELEMENT_TYPE_CMOD_REQD /* 0x1f */ ) - { - boolean isREQD = (getByte() == ELEMENT_TYPE_CMOD_REQD); // 0x1f - // skip the tag 23.2.7 - readByte(); - // skip the TypeDefOrRefEncoded (23.2.8) - Type ignored = pemodule.getTypeDefOrRef(decodeInt()); - if(isREQD) { - // System.err.println("ELEMENT_TYPE_CMOD_REQD: " + ignored); - // throw new RuntimeException("Reqired CMOD: " + ignored); - } - } - } - - /** - * @see CustomModifier - */ - public CustomModifier[] getCustomMods() { - java.util.List/**/ cmods = new java.util.LinkedList(); - while (getByte() == ELEMENT_TYPE_CMOD_OPT || getByte() == ELEMENT_TYPE_CMOD_REQD) { - boolean isReqd = (getByte() == ELEMENT_TYPE_CMOD_REQD); - readByte(); // tag 23.2.7 - Type t = pemodule.getTypeDefOrRef(decodeInt()); // TypeDefOrRefEncoded (23.2.8) - cmods.add(new CustomModifier(isReqd, t)); - } - CustomModifier[] res = (CustomModifier[])cmods.toArray(new CustomModifier[0]); - return res; - } - - //###################################################################### - - } // class Sig - - //########################################################################## - -} // class PEFile diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java b/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java deleted file mode 100644 index cb8cd8f09805..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.PEFile; -import ch.epfl.lamp.compiler.msil.PEFile.Sig; -import ch.epfl.lamp.compiler.msil.util.Signature; -import ch.epfl.lamp.compiler.msil.util.Table; -import ch.epfl.lamp.compiler.msil.util.Table.*; - -import java.nio.ByteBuffer; - -/** Represents a module corresponding to a PE/COFF file - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -final class PEModule extends Module { - - //########################################################################## - - protected final PEFile pefile; - - private final int definingRow; - - private Type[] typeRefs = null; - - protected PEModule(PEFile pefile, int definingRow, String scopeName, - Assembly assem) - { - super(pefile.getName(), pefile.getAbsolutePath(), scopeName, assem); - this.pefile = pefile; - this.definingRow = definingRow; - pefile.initModule(this); - pefile.TypeDef.load(); // load into memory - //loadTypes(); - //pefile.FieldDef.load(); - //pefile.MethodDef.load(); - loadGlobals(); - } - - //########################################################################## - - public Type GetType(String typeName) { - initTypes(); - Object o = typesMap.get(typeName); - if (o == null) { - //System.out.println("PEModule.GetType(): Unable to find type " - // + typeName + " int module " + this); - return null; - } - return o instanceof Type ? (Type)o - : getTypeDef(((Integer)o).intValue()); - } - - - /** Load information about the types defined in this module. - */ - protected void loadTypes() { - typeRefs = new Type[pefile.TypeRef.rows]; - final int nbTypes = pefile.TypeDef.rows; - for (int row = 2; row <= nbTypes; row++) { - String name = pefile.TypeDef(row).getFullName(); - typesMap.put(name, new Integer(row)); - } - this.types = new Type[nbTypes - 1]; - for (int row = 2; row <= nbTypes; row++) { - getTypeDef(row); - } - } - - /** Return the type defined at the given row in the TypeDef table. - */ - Type getTypeDef(int row) { - if (this.types[row - 2] != null) - return this.types[row - 2]; - - TypeDef type = pefile.TypeDef(row); - int attrs = type.Flags; - String name = type.getFullName(); - - Type declType = null; - if (TypeAttributes.isNested(attrs)) { - for (int i = 1; i <= pefile.NestedClass.rows; i++) { - pefile.NestedClass.readRow(i); - if (pefile.NestedClass.NestedClass == row) - declType = getTypeDef - (pefile.NestedClass.EnclosingClass); - } - } - Type t = new PEType - (this, attrs, name, declType, Type.AuxAttr.None, pefile, row); - types[row - 2] = t; - addType(t); - int[] tvarIdxes = pefile.GenericParam.getTVarIdxes(row); - // if(tvarIdxes.length > 0) { System.out.println("Type: " + t); } - for(int i = 0; i < tvarIdxes.length; i++) { - GenericParamAndConstraints tvarAndConstraints = getTypeConstraints(tvarIdxes[i]); - // add tvarAndConstraints as i-th TVar in t - t.addTVar(tvarAndConstraints); - } - return t; - } - - public GenericParamAndConstraints getTypeConstraints(int genParamIdx) { - int tvarNumber = pefile.GenericParam(genParamIdx).Number; - // tvarName can be null - String tvarName = pefile.GenericParam.getName(); - boolean isInvariant = pefile.GenericParam.isInvariant(); - boolean isCovariant = pefile.GenericParam.isCovariant(); - boolean isContravariant = pefile.GenericParam.isContravariant(); - boolean isReferenceType = pefile.GenericParam.isReferenceType(); - boolean isValueType = pefile.GenericParam.isValueType(); - boolean hasDefaultConstructor = pefile.GenericParam.hasDefaultConstructor(); - // grab constraints - int[] TypeDefOrRefIdxes = pefile.GenericParamConstraint.getTypeDefOrRefIdxes(genParamIdx); - Type[] tCtrs = new Type[TypeDefOrRefIdxes.length]; - for(int i = 0; i < TypeDefOrRefIdxes.length; i++) { - Type tConstraint = getTypeDefOrRef(TypeDefOrRefIdxes[i]); - tCtrs[i] = tConstraint; - // System.out.println("\t\tConstraint: " + tConstraint); - } - GenericParamAndConstraints res = new GenericParamAndConstraints(tvarNumber, tvarName, tCtrs, - isInvariant, isCovariant, isContravariant, - isReferenceType, isValueType, hasDefaultConstructor); - return res; - } - - /** - * Load the desription of the module-global fields and methods - */ - protected void loadGlobals() { - //TODO: - } - - protected void loadCustomAttributes(Type attributeType) { - initAttributes(this, 1, Table.ModuleDef.ID, attributeType); - } - - /** Return the type referenced by the given row in the TypeRef table. - */ - Type getTypeRef(int row) { - return getTypeRef(row, null); - } - - /** Return the type referenced by the given row in the TypeRef table - * only if it resides in the given assembly. - * Used by initCustomAttributes to avoid unnecessary loading - * of referenced assemblies. - */ - Type getTypeRef(int row, Assembly inAssembly) { - Type type = typeRefs[row - 1]; - if (type != null) - return type; - - Table.TypeRef tr = pefile.TypeRef; - tr.readRow(row); - int tableId = Table.getTableId(Table._ResolutionScope, - tr.ResolutionScope); - int refRow = tr.ResolutionScope >> Table.NoBits[Table._ResolutionScope]; - final String typeName = tr.getFullName(); - pefile.getTable(tableId).readRow(refRow); - switch (tableId) { - case AssemblyRef.ID: - String name = pefile.AssemblyRef.getName(); - if (inAssembly != null && !inAssembly.GetName().Name.equals(name)) - return null; - Assembly assem = getAssembly(name); - type = assem.GetType(typeName); - if (type == null) { - // HACK: the IKVM.OpenJDK.Core assembly is compiled against mscorlib.dll v2.0 - // The MSIL library cannot parse the v2.0 mscorlib because of generics, so we - // use the v1.0 - // However, the java.io.FileDescriptor.FlushFileBuffers method uses a type - // Microsoft.Win32.SafeHandles.SafeFileHandle, which only exists in mscorlib - // v2.0 - // For now, jsut return Object (fine as long as we don't use that method). - Assembly asmb = getAssembly("mscorlib"); - type = asmb.GetType("System.Object"); - //throw new RuntimeException("Failed to locate type " + - //typeName + " in assembly " + assem); - } - break; - case ModuleDef.ID: - assert refRow == 1; - type = this.GetType(typeName); - //assert type != null; - break; - case TypeRef.ID: - Type nestingType = getTypeRef(refRow); - String nestedName = typeName; - type = nestingType.GetNestedType(nestedName); - break; - case ModuleRef.ID: - type = getAssembly(pefile.ModuleRef.getName()).GetType(typeName); - default: - throw new RuntimeException(refRow + "@" + pefile.getTable(tableId).getTableName()/* PEFile.byte2hex(tableId)*/); - } - if (typeRefs[row - 1] != null) - System.out.println("TypeRef[" + PEFile.short2hex(row) + "] " + - "changing type " + typeRefs[row - 1] + - " for type " + type); - typeRefs[row - 1] = type; - assert type != null : "Couldn't find type " + typeName; - return type; - } - - private Assembly getAssembly(String name) { - Assembly assem = Assembly.getAssembly(name); - if (assem != null) - return assem; - java.io.File dir = pefile.getParentFile(); - assem = Assembly.LoadFrom(dir, name); - if (assem != null) - return assem; - try { - dir = pefile.getUnderlyingFile().getCanonicalFile().getParentFile(); - } catch (java.io.IOException e) { - throw new RuntimeException(e); - } - assem = Assembly.LoadFrom(dir, name); - if (assem != null) - return assem; - throw new RuntimeException("Cannot find assembly: " + name); - - } - - /** Return the type corresponding to TypeDefOrRef coded index. - * @param index - TypeDefOrRef coded index according to 23.2.6. - */ - public Type getTypeDefOrRef(int index) { - int tableId = Table.getTableId(Table._TypeDefOrRef, index); - int row = index >> Table.NoBits[Table._TypeDefOrRef]; - Type type = null; - switch (tableId) { - case Table.TypeDef.ID: - type = getTypeDef(row); - break; - case Table.TypeRef.ID: - return getTypeRef(row); - case Table.TypeSpec.ID: - Table.TypeSpec ts = pefile.TypeSpec; - ts.readRow(row); - int posInBlobStream = ts.Signature; - byte[] blobArrWithLengthStripped = pefile.Blob.getBlob(posInBlobStream); - byte[] compressedUInt = compressUInt(blobArrWithLengthStripped.length); - byte[] byteArr = new byte[blobArrWithLengthStripped.length + compressedUInt.length]; - System.arraycopy(compressedUInt, 0, byteArr, 0, compressedUInt.length); - System.arraycopy(blobArrWithLengthStripped, 0, byteArr, compressedUInt.length, blobArrWithLengthStripped.length); - ByteBuffer buf = ByteBuffer.wrap(byteArr); - Sig sig = pefile.new Sig(buf); - int desc = sig.readByte(); - - switch (desc) { - - // GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncodred GenArgCount Type* - case Signature.ELEMENT_TYPE_GENERICINST: // i.e. 0x15 - int b = sig.readByte(); // i.e. (0x12 | 0x11) - /* TODO don't ignore b as done above */ - Type instantiatedType = getTypeDefOrRef(sig.decodeInt()); // TypeDefOrRefEncoded - int numberOfTypeArgs = sig.decodeInt(); // GenArgCount - Type[] typeArgs = new Type[numberOfTypeArgs]; - for (int iarg = 0; iarg < numberOfTypeArgs; iarg++) { - typeArgs[iarg] = sig.decodeType(); // Type* - } - type = new ConstructedType(instantiatedType, typeArgs); - break; - - /* Miguel says: Actually the following grammar rule production is not among those for a TypeSpecBlob - but I've found it in assemblies compiled from C# 3.0. - See also duplicate code in PEFile.java */ - case Signature.ELEMENT_TYPE_VAR: - int typeArgAsZeroBased = sig.decodeInt(); - type = new Type.TMVarUsage(typeArgAsZeroBased, true); - break; - - /* Miguel says: Actually the following grammar rule production is not among those for a TypeSpecBlob - but I've found it in assemblies compiled from C# 3.0. - See also duplicate code in PEFile.java */ - case Signature.ELEMENT_TYPE_MVAR: - typeArgAsZeroBased = sig.decodeInt(); - type = new Type.TMVarUsage(typeArgAsZeroBased, false); - break; - - case Signature.ELEMENT_TYPE_SZARRAY: // Single-dim array with 0 lower bound. - sig.skipCustomMods(); - type = Type.mkArray(sig.decodeType(), 1); - break; - - case Signature.ELEMENT_TYPE_ARRAY: - // ... ... - // ArrayShape defined in 23.2.13 ArrayShape - Type elem = sig.decodeType(); - int rank = sig.decodeInt(); - int numSizes = sig.decodeInt(); - for (int i = 0; i < numSizes; i++) - sig.decodeInt(); // TODO don't ignore - int numLoBounds = sig.decodeInt(); - for (int i = 0; i < numLoBounds; i++) - sig.decodeInt(); // TODO don't ignore - type = Type.mkArray(elem, rank); - break; - - default: - // TODO remaining grammar productions in 23.2.14 are for PTR and FNPTR only - throw new RuntimeException("PEModule.getTypeDefOrRef(): TypeSpec"); - } - break; - default: - throw new RuntimeException("PEModule.getTypeDefOrRef(): oops!"); - } - return type; - } - - private byte[] compressUInt(int u) { - // 23.2 in Partition II - // TODO add tests based on the examples in 23.2 in Partition II - // the CCI implementation is WriteCompressedUInt - - /* informal discussion at http://www.cnblogs.com/AndersLiu/archive/2010/02/09/en-compressed-integer-in-metadata.html */ - if (u <= 127 && 0 <= u) { - return new byte[]{(byte) u}; - } else if (u > 127 && u <= (2 ^ 14 - 1)) { - byte loByte = (byte)(u & 0xff); - byte hiByte = (byte)((u >> 8) | 0x80); - byte[] res = new byte[] { hiByte, loByte }; - return res; - } else { - byte b0 = (byte)(u & 0xff); - byte b1 = (byte)((u & 0xff00)>>8); - byte b2 = (byte)((u & 0xff0000)>>16); - byte b3 = (byte)((u >> 24)|0xc0); - byte[] res = new byte[] { b3, b2, b1, b0 }; - return res; - } - } - - /** - * Returns the method defined at the given row of the MethodDef table - * by looking up the type that defines the method. - */ - MethodBase getMethod(int row) { - for (int i = 0; i < types.length; i++) { - PEType type = (PEType)types[i]; - if ((type.methodListBeg <= row) && (row < type.methodListEnd)) { - type.initMethods(); - return type.methoddefs[row - type.methodListBeg]; - } - } - throw new RuntimeException("In module " + this - + ": cannot find type defining method 0x" - + PEFile.int2hex(row)); - } - - /** Returns the member referenced by the given row of the MemberRef table. - */ - protected MemberInfo getMemberRef(int row) { - return getMemberRef(row, null); - } - - /** Returns the member referenced by the given row of the MemberRef table - * if defined in the given assembly. - * Used by initCustomAttributes to avoid unnecessary loading of - * referenced assemblies - */ - protected MemberInfo getMemberRef(int row, Assembly inAssembly) { - MemberInfo member = null; - MemberRef mref = pefile.MemberRef; - mref.readRow(row); - int mtbl = Table.getTableId(Table._MemberRefParent, mref.Class); - int mind = Table.getTableIndex(Table._MemberRefParent, mref.Class); - switch (mtbl) { - case TypeRef.ID: - Type type = getTypeRef(mind, inAssembly); - if (type == null) - return null; - Sig sig = mref.getSignature(); - int callconv = sig.readByte(); // should be 0x20 - int paramCount = sig.decodeInt(); - //sig.skipByte(Signature.ELEMENT_TYPE_BYREF); //from MethodDef - Type retType = sig.decodeRetType(); - Type[] paramType = new Type[paramCount]; - for (int i = 0; i < paramCount; i++) - paramType[i] = sig.decodeParamType(); - - String memberName = mref.getName(); - if (memberName.equals(ConstructorInfo.CTOR) || - memberName.equals(ConstructorInfo.CCTOR)) - { - member = type.GetConstructor(paramType); - } else { - member = type.GetMethod(memberName, paramType); - } - assert member != null : type + "::" + memberName; - break; - case ModuleRef.ID: - case MethodDef.ID: - case TypeSpec.ID: - throw new RuntimeException("initCustomAttributes: " - + pefile.getTable(mtbl).getTableName()); - } - return member; - } - - protected void initCustomAttributes(Type attributeType) { - initAttributes(this, definingRow, Table.ModuleDef.ID, attributeType); - } - - // explicitly only package-visible - void initAttributes(CustomAttributeProvider cap, int definingRow, - int sourceTableId, Type attributeType) - { - int parentIndex = Table.encodeIndex(definingRow, - Table._HasCustomAttribute, - sourceTableId); - Table.CustomAttribute attrs = pefile.CustomAttribute; - for (int row = 1; row <= attrs.rows; row++) { - ConstructorInfo attrConstr = null; - attrs.readRow(row); - if (attrs.Parent == parentIndex) { - int tableId = Table.getTableId(Table._CustomAttributeType, - attrs.Type); - int ind = Table.getTableIndex(Table._CustomAttributeType, - attrs.Type); - switch (tableId) { - case MethodDef.ID: - attrConstr = (ConstructorInfo)this.getMethod(ind); - break; - case MemberRef.ID: - //System.out.println(PEFile.short2hex(ind) + "@MemberRef"); - Assembly attrAssem = - attributeType == null ? null : attributeType.Assembly(); - MemberInfo mi = this.getMemberRef(ind, attrAssem); - if (mi != null) { - assert mi instanceof ConstructorInfo - : "Expected ConstructorInfo; found " + mi; - attrConstr = (ConstructorInfo)mi; - } - break; - default: - throw new RuntimeException(); - } - if (attrConstr != null - && (attrConstr.DeclaringType == attributeType - || attributeType == null)) - cap.addCustomAttribute(attrConstr, attrs.getValue()); - } - } - } - - //########################################################################## - -} // class PEModule diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEType.java b/src/msil/ch/epfl/lamp/compiler/msil/PEType.java deleted file mode 100644 index 418c6603b330..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/PEType.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.PEFile.Sig; - -import ch.epfl.lamp.compiler.msil.util.Table; -import ch.epfl.lamp.compiler.msil.util.Table.*; -import ch.epfl.lamp.compiler.msil.util.Signature; -import ch.epfl.lamp.compiler.msil.util.PECustomMod; - -import java.util.ArrayList; - -/** - * Represents a type from a .NET assembly - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -final class PEType extends Type implements Signature { - - //########################################################################## - - /** The PEFile that holds the description of the type. */ - final PEFile file; - - /** The number of the row in the TypeDef table defining the type. */ - final int definingRow; - - /** The row of the first method in the MethodDef table. */ - final int methodListBeg; - - /** The row of the last method in the MethodDef table + 1. */ - final int methodListEnd; - - /** @param definingRow - the index in the TypeDef table where - * the type description is. - */ - PEType(PEModule module, - int attributes, - String fullName, - Type declType, - int auxAttr, - PEFile file, - int definingRow) - { - super(module, attributes, fullName, null, null, declType, auxAttr); - this.file = file; - this.definingRow = definingRow; - methodListBeg = file.TypeDef(definingRow).MethodList; - methodListEnd = definingRow < file.TypeDef.rows - ? file.TypeDef(definingRow + 1).MethodList - : file.MethodDef.rows + 1; - } - - //########################################################################## - // lazy type construction methods - - protected void loadBaseType() { - TypeDef type = file.TypeDef(definingRow); - baseType = type.Extends == 0 ? null - : ((PEModule)Module).getTypeDefOrRef(type.Extends); - } - - protected void loadFields() { - // the list of the declared fields starts from the - // FieldList index in the TypeDef table up to the smaller of the: - // - the last row of the FieldDef table - // - the start of the next list of fields determined by the - // FieldList index of the next row in the TypeDef table - final ArrayList fields = new ArrayList(); - int fieldListBeg = file.TypeDef(definingRow).FieldList; - int fieldListEnd = file.FieldDef.rows + 1; - if (definingRow < file.TypeDef.rows) - fieldListEnd = file.TypeDef(definingRow + 1).FieldList; - - for (int row = fieldListBeg; row < fieldListEnd; row++) { - int frow = file.FieldTrans.rows == 0 - ? row : file.FieldTrans(row).Field; - int attrs = file.FieldDef(frow).Flags; - String name = file.FieldDef.getName(); - //System.out.println("\t-->Loading field: " + name); - Sig sig = file.FieldDef.getSignature(); - PECustomMod pecmod = sig.decodeFieldType(); - Object val = null; - Table.Constant consts = file.Constant; - for (int i = 1; i <= consts.rows; i++) { - consts.readRow(i); - int tableId = Table.getTableId(Table._HasConstant,consts.Parent); - int refRow = consts.Parent >> Table.NoBits[Table._HasConstant]; - if (tableId == Table.FieldDef.ID && refRow == frow) - val = consts.getValue(); - } - FieldInfo field = new PEFieldInfo(row, name, attrs, pecmod, val); - if (field.Name.equals("value__") && field.IsSpecialName()) { - assert underlyingType == null : underlyingType.toString(); - underlyingType = field.FieldType; - } - fields.add(field); - } - this.fields = (FieldInfo[]) - fields.toArray(FieldInfo.EMPTY_ARRAY); - fields.clear(); - } - - protected MethodBase[] methoddefs; - - protected MethodInfo getMethod(int n) { - return (MethodInfo)methoddefs[n - methodListBeg]; - } - - protected void loadMethods() { - methoddefs = new MethodBase[methodListEnd - methodListBeg]; - - final ArrayList methods = new ArrayList(); - final ArrayList constrs = new ArrayList(); - PEModule pemodule = (PEModule) Module; - for (int row = methodListBeg; row < methodListEnd; row++) { - int mrow = file.MethodTrans.rows == 0 - ? row : file.MethodTrans(row).Method; - int attrs = file.MethodDef(mrow).Flags; - String name = file.MethodDef.getName(); - Sig sig = file.MethodDef.getSignature(); - /* we're about to parse a MethodDefSig, defined in Sec. 23.2.1 of Partition II () */ - - int callConv = sig.readByte(); - // TODO decode HASTHIS from high byte of calling convention - // TODO decode EXPLICITTHIS from high byte of calling convention - // TODO handle VARARG calling convention (not CLS but may show up ) - if((callConv & 0x1F) == Signature.GENERIC) { - int genParamCount = sig.decodeInt(); - /* genParamCount is ignored because the method's type params will be obtained below - (see: file.GenericParam.getMVarIdxes(row) ) */ - } - int paramCount = sig.decodeInt(); - Type retType = sig.decodeRetType(); - Type[] paramType = new Type[paramCount]; - for (int i = 0; i < paramCount; i++) - paramType[i] = sig.decodeParamType(); - - ParameterInfo[] params = new ParameterInfo[paramCount]; - int paramListBeg = file.MethodDef.ParamList; - int paramListEnd = paramListBeg + paramCount; - if (paramListEnd > file.ParamDef.rows) { - /* don't try to read param names past ParamDef's row count - Some assembly-writers don't bother to give names for all params. */ - paramListEnd = file.ParamDef.rows + 1; - } - for (int i = paramListBeg; i < paramListEnd; i++) { - int pattr = file.ParamDef(i).Flags; - String paramName = file.ParamDef.getName(); - int seq = file.ParamDef.Sequence; - if (seq == 0) { - //System.out.println("Retval attributes 0x" + - // PEFile.short2hex(pattr)); - } else { - params[seq - 1] = new ParameterInfo(paramName, paramType[seq - 1], pattr, seq - 1); - } - } - for (int i = 0; i < params.length; i++) { - if (params[i] == null) - params[i] = new ParameterInfo(null, paramType[i], 0, 0); - } - MethodBase method = null; - if ((attrs & MethodAttributes.SpecialName) != 0 - && (attrs & MethodAttributes.RTSpecialName) != 0 - && (name.equals(ConstructorInfo.CTOR) - || name.equals(ConstructorInfo.CCTOR))) - { - method = new PEConstructorInfo(row, attrs, params); - } - else { - method = new PEMethodInfo(row, name, attrs, retType, params); - int[] mvarIdxes = file.GenericParam.getMVarIdxes(row); - // if(mvarIdxes.length > 0) { System.out.println("Method: " + method); } - for(int i = 0; i < mvarIdxes.length; i++) { - GenericParamAndConstraints mvarAndConstraints = pemodule.getTypeConstraints(mvarIdxes[i]); - // add mvarAndConstraints as i-th MVar in method - ((PEMethodInfo)method).addMVar(mvarAndConstraints); - } - } - (method.IsConstructor() ? constrs : methods).add(method); - methoddefs[row - methodListBeg] = method; - } - - this.constructors = (ConstructorInfo[]) - constrs.toArray(ConstructorInfo.EMPTY_ARRAY); - this.methods = (MethodInfo[]) - methods.toArray(MethodInfo.EMPTY_ARRAY); - constrs.clear(); methods.clear(); - } - - protected void loadProperties() { - final PropertyMap pmap = file.PropertyMap; - if (pmap == null) { - properties = PropertyInfo.EMPTY_ARRAY; - return; - } - - final PropertyDef pdef = file.PropertyDef; - int propListBeg = -1; - int propListEnd = pdef.rows + 1; - for (int i = 1; i <= pmap.rows; i++) { - pmap.readRow(i); - if (pmap.Parent == this.definingRow) { - propListBeg = pmap.PropertyList; - if (i < pmap.rows) { - pmap.readRow(i + 1); - propListEnd = pmap.PropertyList; - } - break; - } - } - if (propListBeg < 0) { - properties = PropertyInfo.EMPTY_ARRAY; - return; - } - - final ArrayList properties = new ArrayList(); - for (int i = propListBeg; i < propListEnd; i++) { - pdef.readRow(i); - Sig sig = pdef.getSignature(); - int b = sig.readByte(); - b &= ~HASTHIS; - int paramCount = sig.readByte(); - assert b == PROPERTY; - Type propType = sig.decodeType(); - int index = Table.encodeIndex(i, Table._HasSemantics, - Table.PropertyDef.ID); - MethodSemantics msem = file.MethodSemantics; - MethodInfo getter = null, setter = null; - for (int j = 1; j <= msem.rows; j++) { - msem.readRow(j); - if (msem.Association != index) - continue; - if (msem.isGetter()) - getter = getMethod(msem.Method); - else if (msem.isSetter()) - setter = getMethod(msem.Method); - else - System.err.println("PEType.loadProperties(): !?!"); - } - properties.add - (new PEPropertyInfo(i, pdef.getName(), (short)pdef.Flags, - propType, getter, setter)); - } - this.properties = (PropertyInfo[]) properties - .toArray(PropertyInfo.EMPTY_ARRAY); - } - - protected void loadEvents() { - EventMap emap = file.EventMap; - if (emap == null) { - this.events = EventInfo.EMPTY_ARRAY; - return; - } - - final EventDef edef = file.EventDef; - int eventListBeg = -1; - int eventListEnd = edef.rows + 1; - for (int i = 1; i <= emap.rows; i++) { - emap.readRow(i); - if (emap.Parent == this.definingRow) { - eventListBeg = emap.EventList; - if (i < emap.rows) { - emap.readRow(i + 1); - eventListEnd = emap.EventList; - } - break; - } - } - if (eventListBeg < 0) { - this.events = EventInfo.EMPTY_ARRAY; - return; - } - - final ArrayList events = new ArrayList(); - final MethodSemantics msem = file.MethodSemantics; - for (int i = eventListBeg; i < eventListEnd; i++) { - edef.readRow(i); - final Type handler = - ((PEModule)Module).getTypeDefOrRef(edef.EventType); - int index = - Table.encodeIndex(i, Table._HasSemantics, Table.EventDef.ID); - MethodInfo add = null, remove = null; - for (int j = 1; j <= msem.rows; j++) { - msem.readRow(j); - if (msem.Association != index) - continue; - if (msem.isAddOn()) - add = getMethod(msem.Method); - else if (msem.isRemoveOn()) - remove = getMethod(msem.Method); - else { - } - } - events.add(new PEEventInfo(i, edef.getName(), - (short)edef.EventFlags, - handler, add, remove)); - } - this.events = (EventInfo[]) events - .toArray(EventInfo.EMPTY_ARRAY); - } - - protected void loadNestedTypes() { - final ArrayList nested = new ArrayList(); - for (int i = 1; i <= file.NestedClass.rows; i++) { - file.NestedClass.readRow(i); - if (file.NestedClass.EnclosingClass == this.definingRow) - nested.add(((PEModule)Module) - .getTypeDef(file.NestedClass.NestedClass)); - } - this.nestedTypes = (Type[]) nested.toArray(Type.EmptyTypes); - } - - protected void loadInterfaces() { - // get the interfaces implemented by this class - interfaces = Type.EmptyTypes; - int index = file.InterfaceImpl.findType(definingRow); - if (index > 0) { - ArrayList ifaces = new ArrayList(); - for (int i = index; i <= file.InterfaceImpl.rows; i++) { - file.InterfaceImpl.readRow(i); - if (file.InterfaceImpl.Class != definingRow) - break; - ifaces.add(((PEModule)Module) - .getTypeDefOrRef(file.InterfaceImpl.Interface)); - } - interfaces = (Type[]) ifaces.toArray(new Type[ifaces.size()]); - } - } - - protected void loadCustomAttributes(Type attributeType) { - initAttributes(this, definingRow, Table.TypeDef.ID, attributeType); - } - - private void initAttributes(CustomAttributeProvider cap, int definingRow, - int sourceTableId, Type attributeType) - { - ((PEModule)this.Module).initAttributes - (cap, definingRow, sourceTableId, attributeType); - } - - //########################################################################## - - private class PEFieldInfo extends FieldInfo { - private final int definingRow; - public PEFieldInfo(int definingRow, String name, - int attrs, PECustomMod pecmod, Object value) - { - super(name, PEType.this, attrs, pecmod, value); - this.definingRow = definingRow; - } - protected void loadCustomAttributes(Type attributeType) { - PEType.this.initAttributes - (this, definingRow, Table.FieldDef.ID, attributeType); - } - } - - private class PEMethodInfo extends MethodInfo { - private final int definingRow; - public PEMethodInfo(int row, String name, - int attrs, Type retType, ParameterInfo[] params) - { - super(name, PEType.this, attrs, retType, params); - this.definingRow = row; - } - protected void loadCustomAttributes(Type attributeType) { - PEType.this.initAttributes - (this, definingRow, Table.MethodDef.ID, attributeType); - } - } - - private class PEConstructorInfo extends ConstructorInfo { - private final int definingRow; - public PEConstructorInfo(int row, int attrs, ParameterInfo[] params) { - super(PEType.this, attrs, params); - this.definingRow = row; - } - protected void loadCustomAttributes(Type attributeType) { - PEType.this.initAttributes - (this, definingRow, Table.MethodDef.ID, attributeType); - } - } - - private class PEPropertyInfo extends PropertyInfo { - private final int definingRow; - public PEPropertyInfo(int row, String name, short attrs, Type propType, - MethodInfo getter, MethodInfo setter) - { - super(name, PEType.this, attrs, propType, getter, setter); - this.definingRow = row; - } - protected void loadCustomAttributes(Type attributeType) { - PEType.this.initAttributes - (this, definingRow, Table.PropertyDef.ID, attributeType); - } - } - - private class PEEventInfo extends EventInfo { - private final int definingRow; - public PEEventInfo(int row, String name, short attrs, Type handler, - MethodInfo add, MethodInfo remove) - { - super(name, PEType.this, attrs, handler, add, remove); - this.definingRow = row; - } - protected void loadCustomAttributes(Type attributeType) { - PEType.this.initAttributes - (this, definingRow, Table.EventDef.ID, attributeType); - } - } - - //########################################################################## - -} // class PEType diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ParameterAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/ParameterAttributes.java deleted file mode 100644 index d4360363fcb2..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/ParameterAttributes.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Defines the attributes that may be associated with a parameter. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class ParameterAttributes { - - // just to make the class uninstantiable - private ParameterAttributes() {} - - //########################################################################## - - /** Specifies that there is no parameter attribute. */ - public static final short None = 0x0000; - - /** Specifies that the parameter is an input parameter. */ - public static final short In = 0x0001; - - /** Specifies that the parameter is an output parameter. */ - public static final short Out = 0x0002; - - /** Specifies that the parameter is a locale identifier. */ - public static final short Lcid = 0x0004; - - /** Specifies that the parameter is a return value. */ - public static final short Retval = 0x0008; - - /** Specifies that the parameter is optional. - * Attention: In the specification the value is 0x0004 but - * in mscorlib.dll that it Lcid and Optional is 0x0010 - */ - public static final short Optional = 0x0010; - - /** Specifies that the parameter has a default value. */ - public static final short HasDefault = 0x1000; - - /** Specifies that the parameter has field marshaling information. */ - public static final short HasFieldMarshal = 0x2000; - - /** Reserved. */ - public static final short Reserved3 = 0x4000; - - /** Reserved. */ - public static final short Reserved4 = (short)0x8000; - - /** Specifies that the parameter is reserved. */ - public static final short ReservedMask = (short)0xf000; - - /** Reserved: shall be zero in all conforming implementations. */ - public static final short Unused = (short) 0xcfe0; - - public static final String toString(int attrs) { - StringBuffer s = new StringBuffer(); - if ((attrs & In) != 0) s.append("in "); - if ((attrs & Out) != 0) s.append("out "); - if ((attrs & Optional) != 0) s.append("opt "); - if ((attrs & HasDefault) != 0) s.append("default(???) "); - if ((attrs & HasFieldMarshal) != 0) s.append("marshal(???) "); - return s.toString(); - } - - //########################################################################## - -} // class ParameterAttributes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ParameterInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/ParameterInfo.java deleted file mode 100644 index 877d7aa8a5bc..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/ParameterInfo.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Discovers the attributes of a parameter and provides access to - * parameter metadata. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class ParameterInfo extends CustomAttributeProvider { - - //########################################################################## - - /** Attributes of the parameter. */ - public final short Attributes; - - /** Name of the parameter. */ - public final String Name; - - /** Type of the parameter. */ - public final Type ParameterType; - - /** Position of the parameter in the parameter list. */ - public final int Position; - - //########################################################################## - - /** Is this an input parameter? */ - public final boolean IsIn() { - return (Attributes & ParameterAttributes.In) != 0; - } - - /** Is this an output parameter? */ - public final boolean IsOut() { - return (Attributes & ParameterAttributes.Out) != 0; - } - - /** Is this an Lcid? */ - public final boolean IsLcid() { - return (Attributes & ParameterAttributes.Lcid) != 0; - } - - /** Is this a return value? */ - public final boolean IsRetval() { - return (Attributes & ParameterAttributes.Retval) != 0; - } - - /** Is this an optional parameter? */ - public final boolean IsOptional() { - return (Attributes & ParameterAttributes.Optional) != 0; - } - - //########################################################################## - // members not part of the public Reflection.ParameterInfo interface - - /** Initializes a new instance of the ParameterInfo class. */ - protected ParameterInfo(String name, Type type, int attr, int pos) { - Name = name; - ParameterType = type; - Attributes = (short)attr; - Position = pos; - } - - public String toString() { - return ParameterAttributes.toString(Attributes) + ParameterType + " " - + Name; - } - - //########################################################################## - -} // class ParameterInfo diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java b/src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java deleted file mode 100644 index b19fe2986995..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/PrimitiveType.java +++ /dev/null @@ -1,62 +0,0 @@ -package ch.epfl.lamp.compiler.msil; - -import ch.epfl.lamp.compiler.msil.util.PECustomMod; - -public final class PrimitiveType extends Type { - public PrimitiveType(Module module, - int attributes, - String fullName, - Type baseType, - Type[] interfaces, - Type declType, - int auxAttr, - Type elemType) { - super(module, attributes, fullName, - baseType, interfaces, declType, auxAttr, elemType); - clearMembers(); - } - - public void clearMembers() { - fields = FieldInfo.EMPTY_ARRAY; - methods = MethodInfo.EMPTY_ARRAY; - constructors = ConstructorInfo.EMPTY_ARRAY; - events = EventInfo.EMPTY_ARRAY; - - initBaseType(); - initInterfaces(); - - initFields(); - initMethods(); - initEvents(); - initProperties(); - initNestedTypes(); - } - - public FieldInfo addField(String name, int attrs, Type fieldType) { - PECustomMod fieldTypeWithMods = new PECustomMod(fieldType, null); - FieldInfo res = new FieldInfo(name, this, attrs, fieldTypeWithMods, null); - FieldInfo[] ms = new FieldInfo[fields.length + 1]; - System.arraycopy(fields, 0, ms, 0, fields.length); - ms[ms.length - 1] = res; - fields = ms; - return res; - } - - public MethodInfo addMethod(String name, int attrs, Type returnType, Type[] paramTypes) { - MethodInfo res = new MethodInfo(name, this, attrs, returnType, paramTypes); - MethodInfo[] ms = new MethodInfo[methods.length + 1]; - System.arraycopy(methods, 0, ms, 0, methods.length); - ms[ms.length - 1] = res; - return res; - } - - public ConstructorInfo addConstructor(int attrs, Type[] paramTypes) { - ConstructorInfo res = new ConstructorInfo(this, attrs, paramTypes); - ConstructorInfo[] ms = new ConstructorInfo[constructors.length + 1]; - System.arraycopy(constructors, 0, ms, 0, constructors.length); - ms[ms.length - 1] = res; - return res; - } - -} - diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PropertyAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/PropertyAttributes.java deleted file mode 100644 index b1bec64afffa..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/PropertyAttributes.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Attributes applcicable to properties - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class PropertyAttributes { - - // makes the class uninstantiable - private PropertyAttributes() {} - - //########################################################################## - - /** Specifies that the property is special, with the name describing - * how the property is special. - */ - public static final short SpecialName = 0x0200; - - /** Specifies that the metadata internal APIs check the name encoding. - */ - public static final short RTSpecialName = 0x0400; - - /** Specifies that the property has a default value. - */ - public static final short HasDefault = 0x1000; - - //########################################################################## - - public static String toString(short attrs) { - StringBuffer str = new StringBuffer(); - if ((attrs & SpecialName) != 0) str.append("specialname "); - if ((attrs & RTSpecialName) != 0) str.append("rtspecialname "); - return str.toString(); - } - - //########################################################################## - -} // class PropertyAttributes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PropertyInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/PropertyInfo.java deleted file mode 100644 index 4b7cef8bc100..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/PropertyInfo.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Discovers the attributes of a property - * and provides access to property metadata. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public class PropertyInfo extends MemberInfo { - - //########################################################################## - - public final int MemberType() { return MemberTypes.Property; } - - public final short Attributes; - - public final boolean CanRead; - - public final boolean CanWrite; - - public final Type PropertyType; - - /** Returns an array of the public get and set accessors for this property. - */ - public MethodInfo[] GetAccessors() { - return GetAccessors(false); - } - - /** Returns an array of the public or non-public get - * and set accessors for this property. - */ - public MethodInfo[] GetAccessors(boolean nonPublic) { - MethodInfo getter = GetGetMethod(nonPublic); - MethodInfo setter = GetSetMethod(nonPublic); - if (getter == null) - if (setter == null) return MethodInfo.EMPTY_ARRAY; - else return new MethodInfo[]{setter}; - else if (setter == null) return new MethodInfo[] {getter}; - else return new MethodInfo[] {getter, setter}; - } - - /** Returns the public get accessor for this property. - */ - public MethodInfo GetGetMethod() { - return GetGetMethod(false); - } - - /** Returns the public or non-public get accessor for this property. - */ - public MethodInfo GetGetMethod(boolean nonPublic) { - return nonPublic ? getter - : getter == null || getter.IsPublic() ? getter : null; - } - - /** Returns the public set accessor for this property. - */ - public MethodInfo GetSetMethod() { - return GetSetMethod(false); - } - - /** Returns the public or non-public set accessor for this property. - */ - public MethodInfo GetSetMethod(boolean nonPublic) { - return nonPublic ? setter - : setter == null || setter.IsPublic() ? setter : null; - } - - public String toString() { - MethodInfo m = getter != null ? getter : setter; - return MethodAttributes.accessFlagsToString - ((getter != null ? getter : setter).Attributes) - + " " + PropertyAttributes.toString(Attributes) - + DeclaringType + "::" + Name; - } - - //########################################################################## - // protected members - - protected static final PropertyInfo[] EMPTY_ARRAY = new PropertyInfo[0]; - - protected MethodInfo getter; - protected MethodInfo setter; - - protected PropertyInfo(String name, Type declType, short attr, - Type propType, MethodInfo getter, MethodInfo setter) - { - super(name, declType); - Attributes = attr; - PropertyType = propType; - this.getter = getter; - this.setter = setter; - CanRead = getter != null; - CanWrite = setter != null; - } - - //########################################################################## - -} // class PropertyInfo diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Type.java b/src/msil/ch/epfl/lamp/compiler/msil/Type.java deleted file mode 100644 index 830632ce455d..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/Type.java +++ /dev/null @@ -1,1142 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Arrays; - -/** - * Represents type declarations: class types, interface types, array types, - * value types, and enumeration types. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class Type extends MemberInfo { - - private java.util.List /* GenericParamAndConstraints */ tVars = new java.util.LinkedList(); - private GenericParamAndConstraints[] sortedTVars = null; - - public void addTVar(GenericParamAndConstraints tvarAndConstraints) { - sortedTVars = null; - tVars.add(tvarAndConstraints); - } - - public GenericParamAndConstraints[] getSortedTVars() { - if(sortedTVars == null) { - sortedTVars = new GenericParamAndConstraints[tVars.size()]; - for (int i = 0; i < sortedTVars.length; i ++){ - Iterator iter = tVars.iterator(); - while(iter.hasNext()) { - GenericParamAndConstraints tvC = (GenericParamAndConstraints)iter.next(); - if(tvC.Number == i) { - sortedTVars[i] = tvC; - } - } - } - } - return sortedTVars; - } - - - //########################################################################## - // public static members - - /** Empty array of type Type. */ - public static final Type[] EmptyTypes = new Type[0]; - - /** Separates names in the namespace of the Type. */ - public static final char Delimiter = '.'; - - //########################################################################## - // public properties - - /** The fully qualified name of the Type. */ - public final String FullName; - - /** The namespace of the Type. */ - public final String Namespace; - - /** The type from which the current Type directly inherits. */ - public final Type BaseType() { - initBaseType(); - return baseType; - } - protected Type baseType; - - /** The attributes associated with the Type. */ - public final int Attributes; - - /** The sssembly that the type is declared in. */ - public final Assembly Assembly() { return Module.Assembly; } - - /** The module (the EXE/DLL) in which the current Type is defined. */ - public final Module Module; - - public final int MemberType() { - return DeclaringType == null - ? MemberTypes.TypeInfo : MemberTypes.NestedType; - } - - //########################################################################## - // internal members - - // Fields declared by this class - protected FieldInfo[] fields; - - // Methods declared by this class - protected MethodInfo[] methods; - - // Constructors of this class - protected ConstructorInfo[] constructors; - - // Properties of the class - protected PropertyInfo[] properties; - - // Events of the class - protected EventInfo[] events; - - // Interfaces implemented by this class - protected Type[] interfaces; - - // Nested types declared by this class - protected Type[] nestedTypes; - - // holds the element type of array, pointer and byref types - private final Type elemType; - - // the underlying type of an enumeration. null if the type is not enum. - protected Type underlyingType; - - protected int auxAttr; - - //########################################################################## - // Map with all the types known so far and operations on it - - private static final Map types = new HashMap(); - - protected static Type getType(String name) { - return (Type) types.get(name); - } - - protected static Type addType(Type t) { - assert(!(t instanceof TMVarUsage)); - assert(!(t instanceof ConstructedType)); - Type oldType = (Type) types.put(t.FullName, t); -// if (oldType != null) -// throw new RuntimeException("The type: [" + t.Assembly + "]" + t -// + " replaces the type: [" + -// oldType.Assembly + "]" + oldType); - return t; - } - - //########################################################################## - - /** The main constructor. */ - protected Type(Module module, - int attr, - String fullName, - Type baseType, - Type[] interfaces, - Type declType, - int auxAttr, - Type elemType) - { - super(fullName.lastIndexOf(Delimiter) < 0 ? fullName : - fullName.substring(fullName.lastIndexOf(Delimiter) + 1, - fullName.length()), - declType); - - Module = module; // null only for TMVarUsage and for PrimitiveType - Attributes = attr; - this.baseType = baseType; - if (DeclaringType == null) { - FullName = fullName; - int i = FullName.lastIndexOf(Delimiter); - Namespace = (i < 0) ? "" : FullName.substring(0,i); - } else { - FullName = declType.FullName + "+" + fullName; - Namespace = DeclaringType.Namespace; - } - - this.interfaces = interfaces; - this.elemType = elemType; - this.auxAttr = auxAttr; - } - - public final boolean IsAbstract() { - return (Attributes & TypeAttributes.Abstract) != 0; - - } - public final boolean IsPublic() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.Public; - } - - public final boolean IsNotPublic() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.NotPublic; - } - - public final boolean IsNestedPublic() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.NestedPublic; - } - - public final boolean IsNestedPrivate() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.NestedPrivate; - } - - public final boolean IsNestedFamily() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.NestedFamily; - } - - public final boolean IsNestedAssembly() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.NestedAssembly; - } - - public final boolean IsNestedFamORAssem() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.NestedFamORAssem; - } - - public final boolean IsNestedFamANDAssem() { - return (Attributes & TypeAttributes.VisibilityMask) - == TypeAttributes.NestedFamANDAssem; - } - - public final boolean IsSealed() { - return (Attributes & TypeAttributes.Sealed) != 0; - } - - public final boolean IsSpecialName() { - return (Attributes & TypeAttributes.SpecialName) != 0; - } - - public final boolean IsClass() { - return (Attributes & TypeAttributes.ClassSemanticsMask) - == TypeAttributes.Class; - } - - public final boolean IsInterface(){ - return (Attributes & TypeAttributes.ClassSemanticsMask) - == TypeAttributes.Interface; - } - - public final boolean IsAutoLayout() { - return (Attributes & TypeAttributes.LayoutMask) - == TypeAttributes.AutoLayout; - } - public final boolean IsExplictitLayout() { - return (Attributes & TypeAttributes.LayoutMask) - == TypeAttributes.ExplicitLayout; - } - public final boolean IsLayoutSequential() { - return (Attributes & TypeAttributes.LayoutMask) - == TypeAttributes.SequentialLayout; - } - - public final boolean IsImport() { - return (Attributes & TypeAttributes.Import) != 0; - } - public final boolean IsSerializable() { - return (Attributes & TypeAttributes.Serializable) != 0; - } - - public final boolean IsAnsiClass() { - return (Attributes & TypeAttributes.StringFormatMask) - == TypeAttributes.AnsiClass; - } - - public final boolean IsUnicodeClass() { - return (Attributes & TypeAttributes.StringFormatMask) - == TypeAttributes.UnicodeClass; - } - public final boolean IsAutoClass() { - return (Attributes & TypeAttributes.StringFormatMask) - == TypeAttributes.AutoClass; - } - - public final boolean IsArray() { - return (auxAttr & AuxAttr.Array) != 0; - } - public final boolean IsByRef() { - return (auxAttr & AuxAttr.ByRef) != 0; - } - public final boolean IsPointer() { - return (auxAttr & AuxAttr.Pointer) != 0; - } - public final boolean IsPrimitive() { - return (auxAttr & AuxAttr.Primitive) != 0; - } - public final boolean IsValueType() { - return BaseType() == VALUE_TYPE() || IsEnum(); - } - public final boolean IsEnum() { - return BaseType() == ENUM(); - } - public boolean CanBeTakenAddressOf() { - /* TODO should be overridden in TMVarUsage, - but there's currently no way to bind a TMVarUsage to its GenericParamAndConstraints definition. Why? - Because of the way the msil library is organized (e.g., mkArray() returns the same !0[] representation - for all !0[] usages, irrespective of the scope of the !0 type-param) - This in turn is so because without generics there's no harm in using a type-def instance - where a type-ref should go (e.g., the ParameterType of a ParameterInfo nowadays may point to a PEType). - The net effect is that this method (CanBeTakenAddressOf) is conservative, it will answer "no" - for example for !0 where !0 refers to a type-param with the isValuetype constraint set. - The whole thing is ok at this point in time, where generics are not supported at the backend. */ - return IsValueType() && (this != ENUM()); - /* ENUM() is a singleton, i.e. System.Enum is not generic */ - } - - /** IsGeneric, true for a PEType or TypeBuilder (i.e., a type definition) - * containing one or more type params. Not to be called on a reference - * to a constructed type. */ - public final boolean IsGeneric() { - return tVars.size() > 0; - } - - public final boolean HasElementType() { - return IsArray() || IsPointer() || IsByRef(); - } - - public boolean IsTMVarUsage() { - // overridden in TMVarUsage - return false; - } - - public boolean IsNestedType() { - return DeclaringType != null; - } - - public boolean IsDefinitelyInternal() { - if(IsNestedType()) { - return IsNestedPrivate(); - } else { - return IsNotPublic(); - } - } - - //public final boolean IsCOMObject; - //public final boolean IsContextful; - //public final boolean IsMarshalByRef; - - protected Type(Module module, - int attr, - String fullName, - Type baseType, - Type[] interfaces, - Type declType, - int auxAttr) - { - this(module, attr, fullName, baseType, interfaces, - declType, auxAttr, null); - } - - //########################################################################## - - public static final class TMVarUsage extends Type { - - public final int Number; - public final boolean isTVar; - - /** Non-defining reference to either a TVar or an MVar. - * An instance of GenericParamAndConstraints represents a TVar or an MVar definition. */ - public TMVarUsage(int Number, boolean isTVar) { - super(null, 0, ((isTVar ? "!" : "!!") + Number), null, null, null, AuxAttr.None, null); - this.Number = Number; - this.isTVar = isTVar; - } - - public String toString() { - return (isTVar ? "!" : "!!") + Number; - } - - public final boolean IsTMVarUsage() { - return true; - } - - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TMVarUsage that = (TMVarUsage) o; - - if (Number != that.Number) return false; - if (isTVar != that.isTVar) return false; - - return true; - } - - public int hashCode() { - int result = Number; - result = 31 * result + (isTVar ? 1 : 0); - return result; - } - } - - protected static final class AuxAttr { - public static final int None = 0x0000; - public static final int Array = 0x0001; - public static final int ByRef = 0x0002; - public static final int Pointer = 0x0008; - public static final int Primitive = 0x0010; - } - - /***/ - public static Type mkArray(Type elemType, int rank) { - StringBuffer arrSig = new StringBuffer("["); - for (int i = 0; i < rank; i++) { - if (i > 0) arrSig.append(','); - } - arrSig.append(']'); - Type array = getType(elemType.FullName + arrSig); - if (array != null) - return array; - array = new PrimitiveType(elemType.Module, - elemType.Attributes - | TypeAttributes.Sealed - | TypeAttributes.Serializable, - elemType.FullName + arrSig, - ARRAY(), EmptyTypes, null, - AuxAttr.Array, elemType); - return addType(array); - } - - /***/ - public static Type mkPtr(Type elemType) { - String name = elemType.FullName + "*"; - Type type = getType(name); - if (type != null) return type; - type = new PrimitiveType(elemType.Module, - elemType.Attributes, - name, null, EmptyTypes, null, - AuxAttr.Pointer, elemType); - return addType(type); - } - - /***/ - public static Type mkByRef(Type elemType) { - String name = elemType.FullName + "&"; - Type type = getType(name); - if (type != null) return type; - type = new PrimitiveType(elemType.Module, - elemType.Attributes, - name, null, EmptyTypes, null, - AuxAttr.ByRef, elemType); - return addType(type); - } - - //########################################################################## - // public methods - - /** - * Return the type with the specified signature parameters. - * For example, the fully qualified name for a class might look like this: - * TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly - */ - public static Type GetType(String fullName) { - Type type = getType(fullName); - if (type != null) return type; - - // check if it's an array type; TODO: make array type handling more robust - int i = fullName.lastIndexOf('['); - int j = fullName.lastIndexOf(']'); - if (i >= 0) - if (j > i && j == (fullName.length() - 1)) { - String elementTypeName = fullName.substring(0, i); - Type elementType = GetType(elementTypeName); - if (elementType == null) - throw new RuntimeException - ("Unknown element type '" + elementTypeName + - "' for the array type: " + fullName); - int rank = j - i; - for (int k = i + 1; k < j; k++) { - if (fullName.charAt(k) != ',') - throw new RuntimeException - ("Malformed type name: " + fullName); - } - return mkArray(elementType, rank); - } else - throw new RuntimeException("Malformed type name: " + fullName); - - // check if it's a pointer type - if (fullName.charAt(fullName.length() - 1) == '*') - return addType - (mkPtr(GetType(fullName.substring(0, fullName.length()-1)))); - - // check if it's a nested class - i = fullName.lastIndexOf('+'); - if (i > 0) { - if (i == 0 || i == (fullName.length() - 1)) - throw new RuntimeException("malformedTypeName"); - Type enclosing = GetType(fullName.substring(0, i)); - return enclosing == null ? null - : enclosing.GetNestedType(fullName.substring(i + 1)); - } - - //System.out.println("Looking for type: " + fullName + " (" + fullName.length() + ")"); - // try in the assemblies - Iterator assems = ch.epfl.lamp.compiler.msil.Assembly. - assemblies.values().iterator(); - while (type == null && assems.hasNext()) { - Assembly assem = ((Assembly) assems.next()); - type = assem.GetType(fullName); - //System.out.println("\tin assemby " + assem + " -> " + type); - } - - Type type2 = getType(fullName); - if (type == type2) return type; - return type == null ? null : addType(type); - } - - /** - * @return the type of the object encompassed or referenced to - * by the current array, pointer or reference type. - */ - public Type GetElementType() { - return elemType; - } - - /** - * @return the type underlying an enumeration type. - */ - public Type getUnderlyingType() { - if (!IsEnum()) return null; - // this would force the loading of the underlying type from the - // the type of the value__ field of the enumeration - initFields(); - return underlyingType; - } - - //########################################################################## - // GetField/s/ - - /** Searches for the field with the specified name. */ - public FieldInfo GetField(String name) { - initFields(); - for (int i = 0; i < fields.length; i++) - if (fields[i].Name.equals(name) && !fields[i].IsPrivate()) - return fields[i]; - return null; - } - - /** - */ - public FieldInfo GetField(String name, int bindingFlags) { - FieldInfo[] fields = this.GetFields(bindingFlags); - for (int i = 0; i < fields.length; i++) - if (name.equals(fields[i].Name)) - return fields[i]; - return null; - } - - /** Gets the fields of the current Type. */ - public FieldInfo[] GetFields() { - return GetFields(BindingFlags.Instance | BindingFlags.Public); - } - - /** - */ - public FieldInfo[] GetFields(int bindingFlags) { - initFields(); - final FieldInfo[] fields = - getAllFields((bindingFlags & BindingFlags.DeclaredOnly) != 0); - final boolean getInstance = (bindingFlags & BindingFlags.Instance) != 0; - final boolean getStatic = (bindingFlags & BindingFlags.Static) != 0; - final boolean getPublic = (bindingFlags & BindingFlags.Public) != 0; - final boolean getNonPublic = - (bindingFlags & BindingFlags.NonPublic) != 0; - - int cnt = 0; - for (int i = 0; i < fields.length; i++) { - FieldInfo field = fields[i]; - boolean accessible = (getPublic && field.IsPublic()) - || (getNonPublic && !field.IsPublic()); - if (accessible - // strip off the private fields up the hierarchy - && ((field.DeclaringType == this) - || ((field.DeclaringType != this) && !field.IsPrivate())) - && ((getInstance && !field.IsStatic()) - || ((getStatic && field.IsStatic()) && - (field.DeclaringType == this - || (bindingFlags & BindingFlags.FlattenHierarchy) != 0)) - ) - ) - fields[cnt++] = field; - } - FieldInfo [] resFields = new FieldInfo[cnt]; - System.arraycopy(fields, 0, resFields, 0, cnt); - return resFields; - } - - protected FieldInfo[] getAllFields(boolean declaredOnly) { - initFields(); - FieldInfo [] inherited = BaseType() == null || declaredOnly - ? FieldInfo.EMPTY_ARRAY - : BaseType().getAllFields(declaredOnly); - FieldInfo[] allFields = - new FieldInfo[inherited.length + this.fields.length]; - System.arraycopy(inherited, 0, allFields, 0, inherited.length); - System.arraycopy(this.fields, 0, - allFields, inherited.length, this.fields.length); - return allFields; - } - - //########################################################################## - // GetConstructor/s/ - - /** Searches for a public instance constructor whose parameters - * match the types in the specified array. */ - public ConstructorInfo GetConstructor(Type[] paramTypes) { - initMethods(); - for (int i = 0; i < constructors.length; i++) { - if (equalParameters(constructors[i].GetParameters(), paramTypes)) - return constructors[i]; - } - return null; - } - - /** Returns all public instance constructors defined for the current Type.*/ - public ConstructorInfo[] GetConstructors() { - return GetConstructors(BindingFlags.Instance | BindingFlags.Public); - } - - /***/ - public ConstructorInfo[] GetConstructors(int bindingFlags) { - initMethods(); - final boolean getInstance = (bindingFlags & BindingFlags.Instance) != 0; - final boolean getStatic = (bindingFlags & BindingFlags.Static) != 0; - final boolean getPublic = (bindingFlags & BindingFlags.Public) != 0; - final boolean getNonPublic = - (bindingFlags & BindingFlags.NonPublic) != 0; - - ConstructorInfo[] constrs = - new ConstructorInfo[this.constructors.length]; - int cnt = 0; - for (int i = 0; i < this.constructors.length; i++) { - ConstructorInfo constr = this.constructors[i]; - boolean accessible = (getPublic && constr.IsPublic()) - || (getNonPublic && !constr.IsPublic()); - if (accessible - && ((getInstance && !constr.IsStatic()) - || (getStatic && constr.IsStatic()))) - constrs[cnt++] = constr; - } - ConstructorInfo [] resConstrs = new ConstructorInfo[cnt]; - System.arraycopy(constrs, 0, resConstrs, 0, cnt); - return resConstrs; - } - - //########################################################################## - // GetMethod/s/ - - /** Searches for the specified public method whose parameters - * match the specified argument types. */ - public MethodInfo GetMethod(String name, Type[] paramTypes) { - return GetMethod(name, paramTypes, null); - } - - public MethodInfo GetMethod(String name, Type[] paramTypes, Type retType) { - initMethods(); - MethodInfo method = findMethod(methods, name, paramTypes, retType); - if (method != null) - return method; - if (BaseType() != null) { - method = BaseType().GetMethod(name, paramTypes, retType); - if (method != null) - return method; - } -// StringBuffer str = new StringBuffer(name); -// str.append('('); -// for (int i = 0; i < paramTypes.length; i++) { -// if (i > 0) str.append(", "); -// str.append(paramTypes[i]); -// } -// str.append(')'); -// System.out.println("Cannot find method " + str + ":"); -// System.out.println("Methods of class " + this); -// for (int i = 0; i < methods.length; i++) -// System.out.println("\t" + methods[i]); - return null; - } - - /** - */ - protected static MethodInfo findMethod(MethodInfo[] methods, - String name, - Type[] paramTypes, - Type retType) - { - for (int i = 0; i < methods.length; i++) - if (name.equals(methods[i].Name) - && equalParameters(methods[i].GetParameters(), paramTypes) - && (retType == null || methods[i].ReturnType == retType)) - return methods[i]; - return null; - } - - /** - */ - protected static boolean equalParameters(ParameterInfo[] params, - Type[] paramTypes) - { - if (params.length != paramTypes.length) - return false; - for (int i = 0; i < params.length; i++) { -// System.out.println(params[i].ParameterType + " == " + paramTypes[i] -// + " = " + (params[i].ParameterType == paramTypes[i])); - if (params[i].ParameterType != paramTypes[i]) - return false; - } - return true; - } - - /** - */ - public MethodInfo GetMethod(String name, Type[] paramTypes, int bindingFlags) { - MethodInfo[] methods = GetMethods(bindingFlags); - MethodInfo method = findMethod(methods, name, paramTypes, null); - if (method == null) { - StringBuffer str = new StringBuffer(name); - str.append('('); - for (int i = 0; i < paramTypes.length; i++) { - if (i > 0) str.append(", "); - str.append(paramTypes[i]); - } - str.append(')'); - System.out.println("Cannot find method " + str + ":"); - System.out.println("Methods of class " + this); - for (int i = 0; i < methods.length; i++) - System.out.println("\t" + methods[i]); - } - return method; - } - - /** Returns all public methods of the current Type. */ - public MethodInfo[] GetMethods() { - return GetMethods(BindingFlags.Instance | BindingFlags.Public); - } - - /** - */ - public MethodInfo[] GetMethods(int bindingFlags) { - initMethods(); - final MethodInfo[] methods = - getAllMethods((bindingFlags & BindingFlags.DeclaredOnly) != 0); - //System.out.println("" + this + ".GetMethods(int) -> " + methods.length); - final boolean getInstance = (bindingFlags & BindingFlags.Instance) != 0; - final boolean getStatic = (bindingFlags & BindingFlags.Static) != 0; - final boolean getPublic = (bindingFlags & BindingFlags.Public) != 0; - final boolean getNonPublic = - (bindingFlags & BindingFlags.NonPublic) != 0; - - int cnt = 0; - for (int i = 0; i < methods.length; i++) { - MethodInfo method = methods[i]; - boolean accessible = (getPublic && method.IsPublic()) - || (getNonPublic && !method.IsPublic()); - if (accessible - // strip off the private methods up the hierarchy - && ((method.DeclaringType == this) - || ((method.DeclaringType != this) && !method.IsPrivate())) - && ((getInstance && !method.IsStatic()) - || ((getStatic && method.IsStatic()) && - (method.DeclaringType == this - || (bindingFlags & BindingFlags.FlattenHierarchy) != 0)) - ) - ) - methods[cnt++] = method; - } - MethodInfo [] resMethods = new MethodInfo[cnt]; - System.arraycopy(methods, 0, resMethods, 0, cnt); - return resMethods; - } - - protected MethodInfo[] getAllMethods(boolean declaredOnly) { - initMethods(); - MethodInfo[] inherited = BaseType() == null || declaredOnly - ? MethodInfo.EMPTY_ARRAY - : BaseType().getAllMethods(declaredOnly); - MethodInfo[] allMethods = - new MethodInfo[inherited.length + this.methods.length]; - System.arraycopy(inherited, 0, allMethods, 0, inherited.length); - System.arraycopy(this.methods, 0, - allMethods, inherited.length, this.methods.length); - return allMethods; - } - - //########################################################################## - // GetProperty/ies/ - - /** Returns all public properties of the current Type. - */ - public PropertyInfo[] GetProperties() { - initProperties(); - return (PropertyInfo[]) properties.clone(); - } - - /** Returns the properties of the current class - * that satisfy the binding constrints. - */ - public PropertyInfo[] GetProperties(int bindingFlags) { - initProperties(); - return (PropertyInfo[]) properties.clone(); - } - - /** Returns the public property with the given name. - */ - public PropertyInfo GetProperty(String name) { - initProperties(); - for (int i = 0; i < properties.length; i++) - if (name.equals(properties[i].Name)) - return properties[i]; - return null; - } - - /** Returns the property with the given name - * that satisfies the binding constraints. - */ - public PropertyInfo GetProperty(String name, int bindingFlags) { - throw new RuntimeException("Method not implemented yet"); - } - - //########################################################################## - // GetEvent(s) - - public EventInfo[] GetEvents() { - initEvents(); - return (EventInfo[]) events.clone(); - } - - //########################################################################## - // GetNestedType/s/ - - /** Searches for nested type with the specified name. */ - public Type GetNestedType(String name) { - initNestedTypes(); - for (int i = 0; i < nestedTypes.length; i++) - if (nestedTypes[i].Name.equals(name)) - return nestedTypes[i]; - return null; - } - - /** Returns all types nested within the current Type. */ - public Type[] GetNestedTypes() { - initNestedTypes(); - return (Type[]) nestedTypes.clone(); - } - - //########################################################################## - // GetInterface/s/ - - /** Searches for an Interface with the given name implemented by this type - */ - public Type GetInterface(String name) { - return GetInterface(name, false); - } - - /** Searches for the specified interface, - * specifying whether to do a case-sensitive search. - * @param name - the name of the interface to get - * @param ignoreCase true to perform a case-insensitive search for name - * false to perform a case-sensitive search for name - * @return A Type object representing the interface with the specified name, - * implemented or inherited by the current Type, if found; - * otherwise, a null reference - */ - public Type GetInterface(String name, boolean ignoreCase) { - initInterfaces(); - for (int i = 0; i < interfaces.length; i++) { - Type iface = interfaces[i]; - if (ignoreCase) { - if (name.equalsIgnoreCase(iface.Name)) return iface; - if (name.equalsIgnoreCase(iface.FullName)) return iface; - } else { - if (name.equals(iface.Name)) return iface; - if (name.equals(iface.FullName)) return iface; - } - } - return BaseType() == null ? null - : BaseType().GetInterface(name, ignoreCase); - } - - /** Returns the interfaces implemented or inherited by the current Type. */ - public Type[] GetInterfaces() { - initInterfaces(); - if (BaseType() == null) return interfaces; - - Type[] ifaces = interfaces; - int count = 0; - for (int i = 0; i < interfaces.length; i++) { - if (BaseType().GetInterface(interfaces[i].FullName) == null) - ifaces[count++] = ifaces[i]; - } - Type[] baseTypeIfaces = BaseType().GetInterfaces(); - - Type[] res = new Type[baseTypeIfaces.length + count]; - System.arraycopy(baseTypeIfaces, 0, res, 0, baseTypeIfaces.length); - System.arraycopy(ifaces, 0, res, baseTypeIfaces.length, count); - - return res; - } - - - public boolean isSubtypeOf(Type that) { - if (this == that || BaseType() == that || that == OBJECT()) return true; - initInterfaces(); - for (int i = 0; i < interfaces.length; i++) - if (interfaces[i].isSubtypeOf(that)) - return true; - boolean res = BaseType() == null ? false : BaseType().isSubtypeOf(that); -// if (!res) { -// System.out.println(dumpType(this) + " not a subtype of " + -// dumpType(that)); -// } - return res; - } - - private static String formatType(Type t) { - if (t == null) return ""; - String cname = t.getClass().getName(); - int k = cname.lastIndexOf("."); - if (k >= 0) - cname = cname.substring(k + 1); - return "[" + t.Assembly().GetName() + "]" + t + - "(" + cname + "#" + Integer.toHexString(t.hashCode()) + ")"; - } - private static String dumpType(Type t) { - StringBuffer str = new StringBuffer(); - str.append(formatType(t) + " : "); - str.append(formatType(t.BaseType())); - Type[] ifaces = t.GetInterfaces(); - for (int i = 0; i < ifaces.length; i++) - str.append(", " + formatType(ifaces[i])); - return str.toString(); - } - - //########################################################################## - // GetMember/s/ - - protected MemberInfo[] members; - - public MemberInfo[] GetMember(String name) { - aggregateMembers(); - List l = new ArrayList(); - for (int i = 0; i < members.length; i++) { - if (name.equals(members[i].Name)) - l.add(members[i]); - } - return (MemberInfo[])l.toArray(MemberInfo.EMPTY_ARRAY); - } - - protected void aggregateMembers() { - if (members != null) - return; - initFields(); - initMethods(); - initProperties(); - initNestedTypes(); - // the List returned by Arrays.asList doesn't support the addAll method - // so we have to wrap it in ArrayList - List l = new ArrayList(Arrays.asList(fields)); - l.addAll(Arrays.asList(constructors)); - l.addAll(Arrays.asList(methods)); - l.addAll(Arrays.asList(properties)); - l.addAll(Arrays.asList(nestedTypes)); - members = (MemberInfo[]) l.toArray(MemberInfo.EMPTY_ARRAY); - } - - //########################################################################## - // non-standard methods that return only members declared in this type - - /** - * Return only the fields declared in this type. - */ - public FieldInfo[] getFields() { - initFields(); - FieldInfo[] fields = new FieldInfo[this.fields.length]; - System.arraycopy(this.fields, 0, fields, 0, fields.length); - return fields; - } - - /** - * Return only the conrtuctors declared in this type. - */ - public ConstructorInfo[] getConstructors() { - initMethods(); - ConstructorInfo[] ctors = new ConstructorInfo[constructors.length]; - System.arraycopy(constructors, 0, ctors, 0, ctors.length); - return ctors; - } - - /** - * Return only the methods declared in this type. - */ - public MethodInfo[] getMethods() { - initMethods(); - MethodInfo[] methods = new MethodInfo[this.methods.length]; - System.arraycopy(this.methods, 0, methods, 0, methods.length); - return methods; - } - - /** - * Return only the properties declared in this type. - */ - public PropertyInfo[] getProperties() { - initProperties(); - PropertyInfo[] props = new PropertyInfo[properties.length]; - System.arraycopy(properties, 0, props, 0, props.length); - return props; - } - - /** - * Return only the interfaces directly implemented by this type. - */ - public Type[] getInterfaces() { - initInterfaces(); - Type[] ifaces = new Type[interfaces.length]; - System.arraycopy(interfaces, 0, ifaces, 0, ifaces.length); - return ifaces; - } - - /** - * Return the types declared in this type. - */ - public Type[] getNestedTypes() { - initNestedTypes(); - Type[] nested = new Type[nestedTypes.length]; - System.arraycopy(nestedTypes, 0, nested, 0, nested.length); - return nested; - } - - //########################################################################## - - public String toString() { - return FullName; - } - - //########################################################################## - // lazy type construction members - - private boolean initBaseType = true; - protected final void initBaseType() { - if (initBaseType) { - loadBaseType(); - initBaseType = false; - } - } - protected void loadBaseType() {} - - private boolean initInterfaces = true; - protected void initInterfaces() { - if (initInterfaces) { - loadInterfaces(); - initInterfaces = false; - } - assert interfaces != null : "In type " + this; - } - protected void loadInterfaces() {} - - private boolean initNestedTypes = true; - protected void initNestedTypes() { - if (initNestedTypes) { - loadNestedTypes(); - initNestedTypes = false; - } - assert nestedTypes != null : "In type " + this; - } - protected void loadNestedTypes() {} - - private boolean initFields = true; - protected void initFields() { - if (initFields) { - loadFields(); - initFields = false; - } - assert fields != null : "In type " + this; - } - protected void loadFields() {} - - private boolean initMethods = true; - protected void initMethods() { - if (initMethods) { - loadMethods(); - initMethods = false; - } - assert constructors != null : "In type " + this; - assert methods != null : "In type " + this; - } - protected void loadMethods() {} - - private boolean initProperties = true; - protected void initProperties() { - if (initProperties) { - initMethods(); - loadProperties(); - initProperties = false; - } - assert properties != null : "In type " + this; - } - protected void loadProperties() {} - - private boolean initEvents = true; - protected void initEvents() { - if (initEvents) { - initMethods(); - loadEvents(); - initEvents = false; - } - assert events != null : "In type " + this; - } - protected void loadEvents() {} - - //########################################################################## - - //########################################################################## - // static members - - private static Assembly MSCORLIB; - private static Module MSCORLIB_DLL; - - public static Type OBJECT() { return __OBJECT; } - public static Type STRING() { return __STRING; } - public static Type ARRAY() { return __ARRAY; } - public static Type VOID() { return __VOID; } - public static Type ENUM() { return __ENUM; } - public static Type VALUE_TYPE() { return __VALUE_TYPE; } - - private static Type __OBJECT; - private static Type __STRING; - private static Type __ARRAY; - private static Type __VOID; - private static Type __ENUM; - private static Type __VALUE_TYPE; - - public static void initMSCORLIB(Assembly mscorlib) { - if (MSCORLIB != null) - throw new RuntimeException("mscorlib already initialized"); - MSCORLIB = mscorlib; - MSCORLIB_DLL = MSCORLIB.GetModules()[0]; - - __OBJECT = mscorlib.GetType("System.Object"); - __STRING = mscorlib.GetType("System.String"); - __ARRAY = mscorlib.GetType("System.Array"); - __VOID = mscorlib.GetType("System.Void"); - __ENUM = mscorlib.GetType("System.Enum"); - __VALUE_TYPE = mscorlib.GetType("System.ValueType"); - } - - //########################################################################## - -} // class Type diff --git a/src/msil/ch/epfl/lamp/compiler/msil/TypeAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/TypeAttributes.java deleted file mode 100644 index 8f489fa46f28..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/TypeAttributes.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - -/** - * Specifies type attributes. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class TypeAttributes { - - //########################################################################## - // Visibilty attributes - - /** Bitmask used to retrieve visibility information. */ - public static final int VisibilityMask = 0x00000007; - - /** Class has no public scope. */ - public static final int NotPublic = 0x00000000; - - /** Class has public scope. */ - public static final int Public = 0x00000001; - - /** Class is nested with public visibility. */ - public static final int NestedPublic = 0x00000002; - - /** Class is nested with private visibility. */ - public static final int NestedPrivate = 0x00000003; - - /** Class is nested with family visibility, and is thus accessible - * only by methods within its own type and any subtypes. */ - public static final int NestedFamily = 0x00000004; - - /** Class is nested with assembly visibility, and is thus accessible - * only by methods within its assembly. */ - public static final int NestedAssembly = 0x00000005; - - /** Class is nested with assembly and family visibility, and is thus accessible - * only by methods lying in the intersection of its family and assembly. */ - public static final int NestedFamANDAssem = 0x00000006; - - /** Class is nested with family or assembly visibility, and is thus accessible - * only by methods lying in the union of its family and assembly. */ - public static final int NestedFamORAssem = 0x00000007; - - //########################################################################## - // Class layout attributes - - /** Bitmask used to retrieve class layout information. */ - public static final int LayoutMask = 0x00000018; - - /** Class fields are automatically laid out by the CLR. */ - public static final int AutoLayout = 0x00000000; - - /** Class fields are laid out sequentially, in the order that the fields - * were emitted to the metadata. */ - public static final int SequentialLayout = 0x00000008; - - /** Class fields are laid out at the specified offsets. */ - public static final int ExplicitLayout = 0x00000010; - - //########################################################################## - // Class semantics attributes - - /** Bitmask used to retrieve class semantics information. */ - public static final int ClassSemanticsMask = 0x00000020; - - /** Type is a class. */ - public static final int Class = 0x00000000; - - /** Type is an interface. */ - public static final int Interface = 0x00000020; - - //########################################################################## - // Special semantics in addition to class semantics - - /** Class is abstract. */ - public static final int Abstract = 0x00000080; - - /** Class is cannot be extended. */ - public static final int Sealed = 0x00000100; - - /** Class is special in a way denoted by the name. */ - public static final int SpecialName = 0x00000400; - - //########################################################################## - // Implementation attributes - - /** Class/interface is imported from another module. */ - public static final int Import = 0x00001000; - - /** Class can be serialized. */ - public static final int Serializable = 0x00002000; - - //########################################################################## - // String formatting attributes - - /** Bitmask used to retrieve string information for native interop. */ - public static final int StringFormatMask = 0x00030000; - - /** LPTSTR is interpreted as ANSI. */ - public static final int AnsiClass = 0x00000000; - - /** LPTSTR is interpreted as UNICODE. */ - public static final int UnicodeClass = 0x00010000; - - /** LPTSTR is interpreted automatically. */ - public static final int AutoClass = 0x00020000; - - //########################################################################## - // Class initialization attributes - - /** Initialize the class before first static field access. */ - public static final int BeforeFieldInit = 0x00100000; - - //########################################################################## - // Additional flags - - /** CLI provides 'special' behavior, depending upon the name of the type. */ - public static final int RTSpecialName = 0x00000800; - - /** Type has security associate with it. */ - public static final int HasSecurity = 0x00040000; - - //########################################################################## - - public static String accessModsToString(int attrs) { - switch (attrs & VisibilityMask) { - case NotPublic: return "private"; - case Public: return "public"; - case NestedPublic: return "nested public"; - case NestedPrivate: return "nested private"; - case NestedFamily: return "nested family"; - case NestedAssembly: return "nested assembly"; - case NestedFamANDAssem: return "nested famandassem"; - case NestedFamORAssem: return "nested famorassem"; - default: - throw new RuntimeException(); - } - } - - /** Returns a string representation of the given attributes. */ - public static String toString(int attrs) { - StringBuffer str = new StringBuffer(accessModsToString(attrs)); - switch (attrs & LayoutMask) { - case AutoLayout: str.append(" auto"); break; - case SequentialLayout: str.append(" sequential"); break; - case ExplicitLayout: str.append(" explicit"); break; - } - switch (attrs & StringFormatMask) { - case AnsiClass: str.append(" ansi"); break; - case UnicodeClass: str.append(" unicode"); break; - case AutoClass: str.append(" autochar"); break; - } - if ((attrs & Interface) != 0) str.append(" interface"); - if ((attrs & Abstract) != 0) str.append(" abstract"); - if ((attrs & Sealed) != 0) str.append(" sealed"); - if ((attrs & BeforeFieldInit) != 0) str.append(" beforefieldinit"); - if ((attrs & Serializable) != 0) str.append(" serializable"); - if ((attrs & SpecialName) != 0) str.append(" specialname"); - if ((attrs & RTSpecialName) != 0) str.append(" rtspecialname"); - return str.toString(); - } - - /***/ - public static final boolean isNested(int attrs) { - switch (attrs & VisibilityMask) { - case NestedPublic: - case NestedPrivate: - case NestedFamily: - case NestedAssembly: - case NestedFamANDAssem: - case NestedFamORAssem: - return true; - default: return false; - } - } - - //########################################################################## - - // makes the class uninstantiable - private TypeAttributes() {} - - //########################################################################## - -} // class TypeAttributes diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Version.java b/src/msil/ch/epfl/lamp/compiler/msil/Version.java deleted file mode 100644 index ad4b09b16319..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/Version.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * System.Reflection-like API for access to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil; - - -/** - * Represents the version number for a common language runtime assembly - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class Version { - - //########################################################################## - // public interface - - /** - * Gets the value of the major component of the version - * number for this instance. - */ - public final int Major; - - /** - * Gets the value of the minor component of the version - * number for this instance. - */ - public final int Minor; - - /** - * Gets the value of the build component of the version - * number for this instance. - */ - public final int Build; - - /** - * Gets the value of the revision component of the version - * number for this instance. - */ - public final int Revision; - - /** - * Initializes a new instance of the Version class. - */ - public Version() { - this(0,0,0,0); - } - - /** - * Initializes a new instance of the Version class with - * the specified major, minor, build, and revision numbers. - */ - public Version(int major, int minor, int build, int revision) { - this.Major = major; - this.Minor = minor; - this.Build = build; - this.Revision = revision; - } - - /** - * Converts the value of this instance to its equivalent String representation - */ - public String toString() { - return "" + Major + "." + Minor + "." + Build + "." + Revision; - } - - //########################################################################## - -} // class Version diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala deleted file mode 100644 index 6bf4c7d1daee..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala +++ /dev/null @@ -1,122 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil._ -import java.io.IOException - -/** - * Defines and represents a dynamic assembly. - * A dynamic assembly is an assembly that is created using the compiler.msil - * emit APIs. The dynamic modules in the assembly are saved when the dynamic - * assembly is saved using the Save method. To generate an executable, the - * SetEntryPoint method must be called to identify the method that is the - * entry point to the assembly. Assemblies are saved as DLL by default, - * unless SetEntryPoint requests the generation of a console application - * or a Windows-based application. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class AssemblyBuilder(name: AssemblyName) - extends Assembly(name) - with ICustomAttributeSetter - with Visitable -{ - //########################################################################## - // public methods - - /** - * Defines a dynamic module with the given name that will be saved - * to the specified file. No symbol information is emitted. - */ - def DefineDynamicModule(name: String, fileName: String): ModuleBuilder = { - val module = new ModuleBuilder(name, fileName, "" + null, this) - addModule(name, module) - return module - } - - /** Returns the dynamic module with the specified name. */ - def GetDynamicModule(name: String): ModuleBuilder = { - return GetModule(name).asInstanceOf[ModuleBuilder] - } - - /** Saves this dynamic assembly to disk. */ - @throws(classOf[IOException]) - def Save(fileName: String) { - generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String] - ILPrinterVisitor.printAssembly(this, fileName) - } - - @throws(classOf[IOException]) - def Save(destPath: String, sourceFilesPath: String) { - generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String] - ILPrinterVisitor.printAssembly(this, destPath, sourceFilesPath) - } - - /** Returns the list of generated files from calling Save(). */ - def GetGeneratedFiles(): Array[String] = { - return generatedFiles.toArray // (new Array[String](generatedFiles.size())).asInstanceOf[Array[String]] - } - - /** Sets the entry point for this dynamic assembly. */ - def SetEntryPoint(entryMethod: MethodInfo) { - EntryPoint = entryMethod - } - - /** Sets a custom attribute. */ - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) { - addCustomAttribute(constr, value) - } - - //########################################################################## - // protected members - - // all extern assemblies used in this assembly builder - protected var externAssemblies = scala.collection.mutable.Set.empty[Assembly] - - // register an extern assembly - protected def registerExternAssembly(assembly: Assembly) { - externAssemblies += assembly - } - - // get all extern Assemblies used in this Assembly Builder - def getExternAssemblies(): Array[Assembly] = { - externAssemblies = scala.collection.mutable.Set[Assembly]() - val iter = Assembly.assemblies.values().iterator - while (iter.hasNext) { - externAssemblies += iter.next.asInstanceOf[Assembly] - } - externAssemblies -= this - return externAssemblies.toArray - } - - def loadModules() {} - - // contains list of generated .msil files after calling Save() - var generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String] - - //########################################################################## - //########################################################################## - - /** the apply method for a visitor */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseAssemblyBuilder(this) - } - - //########################################################################## -} - -object AssemblyBuilderFactory { - /** - * Defines a dynamic assembly with the specified name. - */ - def DefineDynamicAssembly(name: AssemblyName): AssemblyBuilder = { - //Assembly.reset() - return new AssemblyBuilder(name) - } -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ConstructorBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ConstructorBuilder.scala deleted file mode 100644 index ddd4708ecd8f..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ConstructorBuilder.scala +++ /dev/null @@ -1,64 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil.ConstructorInfo -import ch.epfl.lamp.compiler.msil.Type -import java.io.IOException - -/** - * Defines and represents a constructor of a dynamic class. - * ConstructorBuilder is used to fully describe a constructor in - * Microsoft intermediate language (MSIL), including the name, attributes, - * signature, and constructor body. It is used in conjunction with the - * TypeBuilder class to create classes at run time. Call DefineConstructor - * to get an instance of ConstructorBuilder. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class ConstructorBuilder(declType: Type, attrs: Int, paramTypes: Array[Type]) - extends ConstructorInfo(declType, attrs, paramTypes) - with ICustomAttributeSetter - with Visitable -{ - - //########################################################################## - // public interface - - /** Defines a parameter of this constructor. */ - def DefineParameter(pos: Int, attr: Int, name: String): ParameterBuilder = { - val param = new ParameterBuilder(name, params(pos).ParameterType, attr, pos) - params(pos) = param - return param - } - - /** Returns an ILGenerator for this constructor. */ - def GetILGenerator(): ILGenerator = { - return ilGenerator - } - - /** Sets a custom attribute. */ - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) { - addCustomAttribute(constr, value) - } - - //########################################################################## - - /** The apply method for a visitor. */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseConstructorBuilder(this) - } - - //########################################################################## - - // the Intermediate Language Generator - // it contains the method's body - protected var ilGenerator: ILGenerator = new ILGenerator(this) - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala deleted file mode 100644 index 7ef9dc7a5b76..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil.FieldInfo -import ch.epfl.lamp.compiler.msil.Type -import ch.epfl.lamp.compiler.msil.FieldAttributes -import ch.epfl.lamp.compiler.msil.ConstructorInfo - -import ch.epfl.lamp.compiler.msil.util.PECustomMod - -import java.io.IOException - -/** - * Discovers the attributes of a field and provides access to field metadata. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class FieldBuilder(name: String, declType: Type, attrs: Int, fieldTypeWithMods: PECustomMod) - extends FieldInfo(name, declType, attrs, fieldTypeWithMods, null) - with ICustomAttributeSetter - with Visitable -{ - - //########################################################################## - // public interface - - /** Sets a custom attribute. */ - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) { - addCustomAttribute(constr, value) - } - - //########################################################################## - - /** the apply method for a visitor */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseFieldBuilder(this) - } - - //########################################################################## - - protected var defaultValue: Object = _ - - /** Sets the default value of this field. */ - def SetConstant(defaultValue: Object) { - this.defaultValue = defaultValue - } - - /** Specifies the field layout. */ - def SetOffset(iOffset: Int) { - //this.fieldOffset = FieldAttributes.Offset.Value(iOffset) - } - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ICustomAttributeSetter.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ICustomAttributeSetter.scala deleted file mode 100644 index 5d74d3aa954c..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ICustomAttributeSetter.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil.ConstructorInfo - -/** - * Declares the possibility to set a custom attribute for a member - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -trait ICustomAttributeSetter { - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala deleted file mode 100644 index 63ecbfd353a6..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala +++ /dev/null @@ -1,539 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil._ -import ch.epfl.lamp.compiler.msil.util.Table -import java.util.Stack -import java.io.IOException -import ILGenerator._ - -/** - * Generates Microsoft intermediate language (MSIL) instructions. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ - final class ILGenerator(_owner: MethodBase) extends Visitable { - - //########################################################################## - // public interface - - /** - * Puts the specified instruction onto the stream of instructions. - */ - def Emit(opcode: OpCode) { - // switch opcode - if (opcode == OpCode.Ret) { - emit(opcode, null, 0) - } else { - emit(opcode, null) - } - } - - /** - * Puts the specified instruction and character argument onto - * the Microsoft intermediate language (MSIL) stream of instructions. - */ - def Emit(opcode: OpCode, arg: Char) { - emit(opcode,new Character(arg)) - } - - /** - * Puts the specified instruction and metadata token for the - * specified constructor onto the Microsoft intermediate language - * (MSIL) stream of instructions. - */ - def Emit(opcode: OpCode, arg: ConstructorInfo) { - assert(arg != null) - // newobj - // pop size is the number of parameters - emit(opcode,arg, OpCode.PUSH_size(opcode.CEE_push) - - arg.GetParameters().length) - } - - /** - * Puts the specified instruction onto the Microsoft intermediate language (MSIL) - * stream followed by the index of the given local variable. - */ - def Emit(opcode: OpCode, arg: LocalBuilder) { - assert(arg != null) - // ldarg | ldarg.s | ldarga - // ldarga.s | ldloc | ldloc.s | ldloca - // ldloca.s | starg | starg.s | stloc - // stloc.s - - // - emit(opcode, arg) - } - - - /** - * Puts the specified instruction and numerical argument onto - * the Microsoft intermediate language (MSIL) stream of instructions. - */ - def Emit(opcode: OpCode, arg: Double) { - // ldc.r4 | ldc.r8 - emit(opcode, new java.lang.Double(arg)) - } - - /** - * Puts the specified instruction and metadata token for the - * specified field onto the Microsoft intermediate language (MSIL) - * stream of instructions. - */ - def Emit(opcode: OpCode,arg: FieldInfo) { - assert(arg != null) - // ldfld | ldflda | ldsfld | ldsflda | stfld | stsfld - emit(opcode,arg) - } - - /** - * Puts the specified instruction and numerical argument onto - * the Microsoft intermediate language (MSIL) stream of instructions. - */ - def Emit(opcode: OpCode, arg: Short ) { - emit(opcode, new java.lang.Short(arg)) - } - - /** - * Puts the specified instruction and numerical argument onto - * the Microsoft intermediate language (MSIL) stream of instructions. - */ - def Emit(opcode: OpCode, arg: Int) { - // ldc.i4 | ldc.i4.s | unaligned - emit(opcode, new java.lang.Integer(arg)) - } - - /** - * Puts the specified instruction and numerical argument onto - * the Microsoft intermediate language (MSIL) stream of instructions. - */ - def Emit(opcode: OpCode, arg: Long) { - // ldc.i8 - emit(opcode, new java.lang.Long(arg)) - } - - /** - * Puts the specified instruction onto the Microsoft intermediate - * language (MSIL) stream and leaves space to include a label when - * fixes are done. - */ - def Emit(opcode: OpCode,label: Label) { - assert(label != null) - // beq | beq.s | bge | bge.s | - // bge.un | bge.un.s | bgt | bgt.s | bgt.un | bgt.un.s | - // ble | ble.s | ble.un | ble.un.s | blt | blt.s | - // blt.un | blt.un.s | bne.un | bne.un.s | br | br.s | - // brfalse | brfalse.s | brtrue | brtrue.s | leave | leave.s - - emit(opcode, label) - // is the label initialized ? if true backward jump else forward jump - if (label.isInitialized()) { -// if (arg.stacksize != lastLabel.stacksize) { -// System.err.println("ILGenerator.Emit: Stack depth differs depending on path:"); -// System.err.println("\tmethod = " + owner); -// System.err.println("\tPC = 0x" + Table.short2hex(lastLabel.address)); -// } - //assert arg.stacksize == lastLabel.stacksize; - } - else { - label.setStacksize(lastLabel.getStacksize()) - } - } - - /** - * Puts the specified instruction onto the Microsoft intermediate - * language (MSIL) stream and leaves space to include a label when - * fixes are done. - */ - def Emit(opcode: OpCode, arg: Array[Label] ) { - assert(arg != null) - // switch - - // ::= ( ) - // Examples: - // switch (0x3, -14, Label1) - // switch (5, Label2) - emit(opcode, arg, arg.length) - } - - /** - * Puts the specified instruction onto the Microsoft intermediate - * language (MSIL) stream followed by the metadata token for the - * given method. - */ - def Emit(opcode: OpCode,arg: MethodInfo) { - assert(arg != null) - // call | callvirt | jmp | ldftn | ldvirtftn - // pop size is the number of parameters - // pop 1 more if method is not static ! - // push size is either 0 (void Method) either 1 - assert(arg.ReturnType != null, "No ReturnType: " + arg.DeclaringType + "::" + arg.Name) - - val popush: Int = if (opcode == OpCode.Ldftn || - opcode == OpCode.Ldvirtftn || - opcode == OpCode.Jmp) - { - OpCode.PUSH_size(opcode.CEE_push) - OpCode.POP_size(opcode.CEE_pop) - } else if (opcode == OpCode.Calli || opcode == OpCode.Callvirt) { - (if(arg.ReturnType == VOID) 0 else 1) - arg.GetParameters().length - 1 - } else { - (if(arg.ReturnType == VOID) 0 else 1) - arg.GetParameters().length - } - emit(opcode, arg, popush) - } - - /** - * Puts the specified instruction and numerical argument onto - * the Microsoft intermediate language (MSIL) stream of instructions. - */ - def Emit(opcode: OpCode, arg: Float ) { - emit(opcode, new java.lang.Float(arg)) - } - - /** - * Puts the specified instruction onto the Microsoft intermediate - * language (MSIL) stream followed by the metadata token for the - * given string. - */ - def Emit(opcode: OpCode, arg: String ) { - assert(arg != null) - // ldstr - emit(opcode, arg) - } - - /** - * Puts the specified instruction onto the Microsoft intermediate - * language (MSIL) stream followed by the metadata token for the - * given type. - */ - def Emit(opcode: OpCode, arg: Type) { - assert(arg != null) - // box | castclass | cpobj | initobj | isinst | - // ldelema | ldobj | mkrefany | newarr | refanyval | - // sizeof | stobj | unbox - - emit(opcode, arg) - } - - /** - * Puts a call or callvirt instruction onto the Microsoft intermediate - * language (MSIL) stream. - */ - def EmitCall(opcode: OpCode, arg: MethodInfo, - optionalParameterTypes: Array[Type]) { - assert(arg != null) - // pop size is the number of parameters - // push size is either 0 (void Method) either 1 - //System.out.println(arg.ReturnType.Size + " " + arg.GetParameters().length); - emit(opcode, arg, (if(arg.ReturnType == VOID) 0 else 1) - - arg.GetParameters().length) - } - - /** - * Emits the Microsoft intermediate language (MSIL) necessary to - * call WriteLine with the given field. - */ - def EmitWriteLine(arg: FieldInfo) { - // first load field info - // if static use OpCode.Ldsfld - if (arg.IsStatic()) - Emit(OpCodes.Ldsfld, arg) - else - Emit(OpCodes.Ldfld, arg) - // then call System.Console.WriteLine(arg.Type) - val t: Type = Type.GetType("System.Console") - val argsType: Array[Type] = new Array[Type](1) - argsType(0) = arg.FieldType - val m: MethodInfo = t.GetMethod("WriteLine", argsType) - EmitCall(OpCode.Call, m, null) - } - - /** - * Emits the Microsoft intermediate language (MSIL) necessary - * to call WriteLine with the given local variable. - */ - def EmitWriteLine(arg: LocalBuilder) { - // first load local variable - Emit(OpCodes.Ldloc, arg) - // then call System.Console.WriteLine(arg.Type) - val t: Type = Type.GetType("System.Console") - val argsType: Array[Type] = new Array[Type](1) - argsType(0) = arg.LocalType - val m: MethodInfo = t.GetMethod("WriteLine", argsType) - EmitCall(OpCode.Call, m, null) - } - - /** - * Emits the Microsoft intermediate language (MSIL) to call - * WriteLine with a string. - */ - def EmitWriteLine(arg: String) { - // first load string - Emit(OpCode.Ldstr, arg) - // then call System.Console.WriteLine(string) - val t: Type = Type.GetType("System.Console") - val argsType: Array[Type] = new Array[Type](1) - argsType(0) = Type.GetType("System.String") - val m: MethodInfo = t.GetMethod("WriteLine", argsType) - EmitCall(OpCode.Call, m, null) - } - - /** - * Declares a local variable. - */ - def DeclareLocal(localType: Type): LocalBuilder = { - val l: LocalBuilder = new LocalBuilder(locals, localType) - locals = locals + 1 - localList += l - return l - } - - /** - * Returns a new label that can be used as a token for branching. - * In order to set the position of the label within the stream, you - * must call MarkLabel. This is just a token and does not yet represent - * any particular location within the stream. - */ - def DefineLabel():Label = { - new Label.NormalLabel() - } - - /** - * Marks the Microsoft intermediate language (MSIL) stream's - * current position with the given label. - */ - def MarkLabel(label: Label) { - label.mergeWith(lastLabel) - /* - label.address = lastLabel.address; - //label.stacksize = lastLabel.stacksize; - if (label.stacksize >= 0) - lastLabel.stacksize = label.stacksize; - */ - } - - /** Begins a lexical scope. */ - def BeginScope() { - emitSpecialLabel(Label.NewScope) - } - - /** Ends a lexical scope. */ - def EndScope() { - emitSpecialLabel(Label.EndScope) - } - - /** - * Begins an exception block for a non-filtered exception. - * The label for the end of the block. This will leave you in the correct - * place to execute finally blocks or to finish the try. - */ - def BeginExceptionBlock() { - emitSpecialLabel(Label.Try) - val endExc: Label = new Label.NormalLabel() // new Label(lastLabel) ??? - excStack.push(Label.Try, endExc) - } - - /** Begins a catch block. */ - def BeginCatchBlock(exceptionType: Type) { - val kind = excStack.peekKind() - if (kind == Label.Kind.Try || - kind == Label.Kind.Catch) { - /* ok */ - } else { - throw new RuntimeException("Catch should follow either a try or catch") - } - val endExc: Label = excStack.popLabel() - Emit(OpCodes.Leave, endExc) - // the CLI automatically provide the exception object on the evaluation stack - // we adjust the stacksize - lastLabel.incStacksize() - excStack.push(Label.Catch, endExc) - emitSpecialLabel(Label.Catch, exceptionType) - } - - /** Ends an exception block. */ - def EndExceptionBlock() { - val kind = excStack.peekKind() - if (kind == Label.Kind.Try) { - throw new RuntimeException("Try block with neither catch nor finally") - } else if (kind == Label.Kind.Catch) { - Emit(OpCodes.Leave, excStack.peekLabel()) - } else if (kind == Label.Kind.Finally) { - Emit(OpCodes.Endfinally) - } - MarkLabel(excStack.popLabel()) - emitSpecialLabel(Label.EndTry) - } - - /** - * Begins a finally block in the Microsoft intermediate language - * (MSIL) instruction stream. - */ - def BeginFinallyBlock() { - val endExc: Label = excStack.popLabel() - Emit(OpCodes.Leave, endExc) - excStack.push(Label.Finally, endExc) - emitSpecialLabel(Label.Finally) - } - - /** - * Emits an instruction to throw an exception. - */ - def ThrowException(exceptionType: Type) { - assert(exceptionType != null) - if (!exceptionType.isSubtypeOf(Type.GetType("System.Exception"))) - throw new RuntimeException - (exceptionType + " doesn't extend System.Exception" ) - val ctor: ConstructorInfo = exceptionType.GetConstructor(Type.EmptyTypes) - if (ctor == null) - throw new RuntimeException("Type " + exceptionType - + "doesn't have a default constructor") - Emit(OpCodes.Newobj, ctor) - Emit(OpCodes.Throw) - } - - /** - * sets the line of the source file corresponding to the next instruction - */ - def setPosition(line: Int) { - if (line != 0) lineNums.put(lastLabel, Integer.toString(line)) - } - - def setPosition(line: Int, filename: String) { - if (line != 0) lineNums.put(lastLabel, line + " '" + filename + "'") - } - - def setPosition(startLine: Int, endLine: Int, startCol: Int, endCol: Int, filename: String) { - val lineRange = startLine + "," + endLine - val colRange = startCol + "," + endCol - lineNums.put(lastLabel, lineRange + ":" + colRange + " '" + filename + "'") - } - - def getLocals(): Array[LocalBuilder] = localList.toArray - - def getLabelIterator() = labelList.iterator - - def getOpcodeIterator() = opcodeList.iterator - - def getArgumentIterator() = argumentList.iterator - - //########################################################################## - // private implementation details - - - - // the local variable list - private final val localList = scala.collection.mutable.ArrayBuffer.empty[LocalBuilder] - - // the label list, the opcode list and the opcode argument list - // labelList is an array of Label - // opcodeList is an array of OpCode - // argumentList is an array of Object (null if no argument) - private final val labelList = scala.collection.mutable.ArrayBuffer.empty[Label] - private final val opcodeList = scala.collection.mutable.ArrayBuffer.empty[OpCode] - private final val argumentList = scala.collection.mutable.ArrayBuffer.empty[Object] - - // the program counter (pc) - // also called the stream's current position - private var pc: Int = 0 - - // last label - private var lastLabel: Label = new Label.NormalLabel(pc,0) - - // the maximum size of stack - private var maxstack: Int = 0 - - // the number of the locals - private var locals: Int = 0 - - // stack of label for exception mechanism - private val excStack: ExceptionStack = new ExceptionStack() - - // the method info owner of this ILGenerator - var owner: MethodBase = _owner - - val lineNums = scala.collection.mutable.Map.empty[Label, String] - - - def getMaxStacksize(): Int = { this.maxstack } - - // private emit with Object Argument - private def emit(opcode: OpCode, arg: Object) { - emit(opcode, arg, opcode.CEE_popush) - } - - // private emit with Object Argument and override POPUSH - private def emit(opcode: OpCode, arg: Object, overridePOPUSH: Int) { - // add label, opcode and argument - labelList += lastLabel - opcodeList += opcode - argumentList += arg - // compute new lastLabel (next label) - val stackSize: Int = lastLabel.getStacksize() + overridePOPUSH - if (stackSize < 0) { - val msg = "ILGenerator.emit(): Stack underflow in method: " + owner - scala.Console.println(msg) - // throw new RuntimeException(msg) - } - if (stackSize > maxstack) - maxstack = stackSize - var address: Int = lastLabel.getAddress() + opcode.CEE_length - if (opcode.CEE_opcode == OpCode.CEE_SWITCH) { - address = address + 4*arg.asInstanceOf[Array[Label]].length - } - lastLabel = new Label.NormalLabel(address, stackSize) - pc = pc + 1 - } - - def Ldarg0WasJustEmitted() : Boolean = { - if(opcodeList.isEmpty) - return false - val lastEmitted = opcodeList(opcodeList.size - 1) - lastEmitted eq OpCode.Ldarg_0 - } - - private def emitSpecialLabel(l: Label) { - emitSpecialLabel(l, null) - } - private def emitSpecialLabel(l: Label, catchType: Type) { - labelList += l - opcodeList += null - argumentList += catchType - } - - //########################################################################## - // - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseILGenerator(this) - } - - //########################################################################## -} // class ILGenerator - - -object ILGenerator { - - val VOID: Type = Type.GetType("System.Void") - val NO_LABEL: String = "" - - private final class ExceptionStack { - private val labels = new scala.collection.mutable.Stack[Label]() - private val kinds = new scala.collection.mutable.Stack[Label]() - def ExceptionStack() {} - def pop() { labels.pop; kinds.pop } - def push(kind: Label, label: Label) { - kinds.push(kind); labels.push(label) - } - def peekKind(): Label.Kind = kinds.top.getKind - def peekLabel(): Label = labels.top - def popLabel(): Label = { kinds.pop(); labels.pop() } - } - -} - diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala deleted file mode 100644 index 413b08ddd882..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala +++ /dev/null @@ -1,860 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies in MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import java.io.File -import java.io.FileWriter -import java.io.BufferedWriter -import java.io.PrintWriter -import java.io.IOException -import java.util.Comparator - -import ch.epfl.lamp.compiler.msil._ -import ch.epfl.lamp.compiler.msil.util.Table - -/** - * The MSIL printer Visitor. It prints a complete - * assembly in a single or multiple files. Then this file can be compiled by ilasm. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -abstract class ILPrinterVisitor extends Visitor { - - import ILPrinterVisitor._ - import OpCode._ - - //########################################################################## - - protected final val assemblyNameComparator = - new scala.math.Ordering[Assembly]() { - override def compare(o1: Assembly, o2: Assembly): Int = { - val a1 = o1.asInstanceOf[Assembly] - val a2 = o2.asInstanceOf[Assembly] - return a1.GetName().Name.compareTo(a2.GetName().Name) - } - } - - // the output file writer - protected var out: PrintWriter = null - - // the left margin - private var lmargin = 0 - - // indicate a newline - private var newline = true - - // print types without or with members? - protected var nomembers: Boolean = false - - // external assemblies - protected var as: Array[Assembly] = null - - private def align() { - if (newline) - padding = lmargin - printPadding() - newline = false - } - private def indent() { - lmargin += TAB - } - private def undent() { - lmargin -= TAB - assert(lmargin >= 0) - } - - private var padding = 0 - private def pad(n: Int) { - assert(n >= 0, "negative padding: " + n) - padding += n - } - private def printPadding() { - if (padding <= 0) - return - while (padding > SPACES_LEN) { - out.print(SPACES) - padding -= SPACES_LEN - } - out.print(SPACES.substring(0, padding)) - padding = 0 - } - - // methods to print code - protected def print(s: String) { align(); out.print(s)} - protected def print(o: Object) { align(); out.print(o) } - protected def print(c: Char) { align(); out.print(c) } - protected def print(`val`: Int) { align(); out.print(`val`)} - protected def print(`val`: Long){ align(); out.print(`val`)} - protected def println() { out.println(); newline = true; padding = 0 } - protected def println(c: Char) { print(c); println() } - protected def println(i: Int) { print(i); println() } - protected def println(l: Long) { print(l); println() } - protected def println(s: String){ print(s); println() } - protected def println(o: Object){ print(o); println() } - protected def printName(name: String) { - val ch = name.charAt(0) - //if (Character.isLetter(ch) && Character.isLowerCase(ch)) { - if ((ch != '.') && (ch != '!')) { - print('\''); print(name); print('\'') - } else - print(name) - } - - protected def printAssemblyBoilerplate() { - // print all the external assemblies - for (j <- 0 until as.length) { - printAssemblySignature(as(j), true) - } - // print assembly declaration - printAssemblySignature(currAssembly, false) - } - - // the entrypoint method - protected var entryPoint: MethodInfo = null - - // current opcode argument - protected var argument: Object = null - - /***/ - @throws(classOf[IOException]) - protected def print(vAble: Visitable) { - if (vAble != null) - vAble.apply(this) - } - - /** - * Visit an AssemblyBuilder - */ - @throws(classOf[IOException]) - def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) - - protected var currentModule: Module = null - /** - * Visit a ModuleBuilder - */ - @throws(classOf[IOException]) - def caseModuleBuilder(module: ModuleBuilder) - - protected var currentType: Type = null - - def printTypeParams(sortedTVars : Array[GenericParamAndConstraints]) { - - def constraintFlags(tVar : GenericParamAndConstraints) = { - val varianceDirective = (if (tVar.isCovariant) "+ " else (if (tVar.isContravariant) "- " else "")) - val typeKindDirective = (if (tVar.isReferenceType) "class " else (if (tVar.isValueType) "valuetype " else "")) - val dfltConstrDirective = (if (tVar.hasDefaultConstructor) ".ctor " else "") - varianceDirective + typeKindDirective + dfltConstrDirective - } - - def tparamName(tVar : GenericParamAndConstraints) = { - /* TODO Type-params in referenced assemblies may lack a name (those in a TypeBuilder or MethodBuilder shouldn't). - Given that we need not list (in ilasm syntax) the original type-params' names when - providing type arguments to it, the only type-param-names we'll serialize into a .msil file - are those for type-params in a TypeBuilder or MethodBuilder. Still, more details on this - appear in Sec. 4.5 "Faulty metadata in XMLReaderFactory" of - http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/Libs4Lib.pdf - - To avoid name clashes when choosing a param name, - first collect all existing tparam-names from a type (and its nested types). - Not that those names are needed (ordinal positions can be used instead) - but will look better when disassembling with ildasm. */ - assert(tVar.Name != null) - tVar.Name - } - - if(sortedTVars.length == 0) { return } - print('<') - val lastIdx = sortedTVars.length - 1 - for (it <- 0 until sortedTVars.length) { - val tVar = sortedTVars(it) - print(constraintFlags(tVar)) - if(tVar.Constraints.length > 0) { - print('(') - for (ic <- 0 until tVar.Constraints.length) { - val cnstrt = tVar.Constraints(ic) - printReference(cnstrt) - if (ic < lastIdx) { print(", ") } - } - print(')') - } - print(" " + tparamName(tVar)) - if (it < lastIdx) { print(", ") } - } - print('>') - } - - /** - * Visit a TypeBuilder - */ - @throws(classOf[IOException]) - def caseTypeBuilder(`type`: TypeBuilder) { - currentType = `type` - if (!`type`.Namespace.equals("") && `type`.DeclaringType == null) { - print(".namespace \'" ); print(`type`.Namespace); println("\'") - println("{"); indent() - } - print(".class ") - // ::= - // * - // [extends ] - // [implements [, ]*] - print(TypeAttributes.toString(`type`.Attributes)) - print(" \'"); print(`type`.Name); print("\'") - printTypeParams(`type`.getSortedTVars()) - if (`type`.BaseType() != null) { - println() - print(" extends ") - printReference(`type`.BaseType()) - } - val ifaces: Array[Type] = `type`.getInterfaces() - if (ifaces.length > 0) { - println() - print(" implements ") - for (i <- 0 until ifaces.length) { - if (i > 0) { - println(",") - print(" ") - } - printReference(ifaces(i)) - } - } - println() - println("{") - indent() - if (!nomembers && `type`.sourceFilename != null) - println(".line " + `type`.sourceLine - + " '" + `type`.sourceFilename + "'") - if (!nomembers) { - printAttributes(`type`) - } - // print nested classes - val nested = `type`.nestedTypeBuilders.iterator - while(nested.hasNext) - print(nested.next().asInstanceOf[TypeBuilder]) - - // print each field - val fields = `type`.fieldBuilders.iterator - while(fields.hasNext) - print(fields.next().asInstanceOf[FieldBuilder]) - - // print each constructor - val constrs = `type`.constructorBuilders.iterator - while (constrs.hasNext) - print(constrs.next().asInstanceOf[ConstructorBuilder]) - - // print each method - val methods = `type`.methodBuilders.iterator - while (methods.hasNext) { - val method = methods.next().asInstanceOf[MethodBuilder] - assert(method.DeclaringType == `type`) - print(method) - } - - undent(); println("}") - if (!`type`.Namespace.equals("") && `type`.DeclaringType == null) { - undent(); println("}") - } - currentType = null - } - - /** - * Visit a FieldBuilder - */ - @throws(classOf[IOException]) - def caseFieldBuilder(field: FieldBuilder) { - if (nomembers) return - // [[int32]] * [= | at ] - print(".field ") - print(FieldAttributes.toString(field.Attributes)) - print(" "); printSignature(field.FieldType, field.cmods) - print(" \'"); print(field.Name); print("\'") - if (field.IsLiteral()) { - print(" = ") - val value = field.getValue() - if (value == null) { - print("nullref") - } else if (value.isInstanceOf[String]) { - print(msilString(value.asInstanceOf[String])) - } else if (value.isInstanceOf[Boolean]) { - print("bool (") - print(if((value.asInstanceOf[Boolean]).booleanValue()) { "true" } else { "false" }) - print(")") - } else if (value.isInstanceOf[Byte]) { - print("int8 (") - print(value) - print(")") - } else if (value.isInstanceOf[java.lang.Short]) { - print("int16 (") - print(value) - print(")") - } else if (value.isInstanceOf[Character]) { - print("char (") - print((value.asInstanceOf[Character]).charValue()) - print(")") - } else if (value.isInstanceOf[Integer]) { - print("int32 (") - print((value.asInstanceOf[Integer]).intValue()) - print(")") - } else if (value.isInstanceOf[Long]) { - print("int64 (") - print((value.asInstanceOf[Long]).longValue()) - print(")") - } else if (value.isInstanceOf[Float]) { - print(msilSyntaxFloat(value.asInstanceOf[Float])) - } else if (value.isInstanceOf[Double]) { - print(msilSyntaxDouble(value.asInstanceOf[Double])) - } else { - throw new Error("ILPrinterVisitor: Illegal default value: " - + value.getClass()) - } - } - println() - printAttributes(field) - } - - def msilSyntaxFloat(valFlo: java.lang.Float) : String = { - // !!! check if encoding is correct - val bits = java.lang.Float.floatToRawIntBits(valFlo.floatValue()) - /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */ - /* Note: no value is equal to Nan, including NaN. Thus, x == Float.NaN always evaluates to false. */ - val res = if (valFlo.isNaN) "0xFFC00000 /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */ - else if (java.lang.Float.NEGATIVE_INFINITY == valFlo.floatValue) "0xFF800000 /* NEGATIVE_INFINITY */ " - else if (java.lang.Float.POSITIVE_INFINITY == valFlo.floatValue) "0x7F800000 /* POSITIVE_INFINITY */ " - else bits - "float32 (" + res + ")" - } - - def msilSyntaxDouble(valDou: java.lang.Double) : String = { - // !!! check if encoding is correct - val bits = java.lang.Double.doubleToRawLongBits(valDou.doubleValue()) - /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */ - /* Note: no value is equal to Nan, including NaN. Thus, x == Double.NaN always evaluates to false. */ - val res = if (valDou.isNaN) "0xffffffffffffffff /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */ - else if (java.lang.Double.NEGATIVE_INFINITY == valDou.doubleValue) "0xfff0000000000000 /* NEGATIVE_INFINITY */ " - else if (java.lang.Double.POSITIVE_INFINITY == valDou.doubleValue) "0x7ff0000000000000 /* POSITIVE_INFINITY */ " - else bits - // float64(float64(...)) != float64(...) - "float64 (" + res + ")" - } - - /** - * Visit a ConstructorBuilder - */ - @throws(classOf[IOException]) - def caseConstructorBuilder(constr: ConstructorBuilder) { - if (nomembers) return - print(".method "); printHeader(constr, VOID) - println(); println("{"); indent() - printAttributes(constr) - try { - print(constr.GetILGenerator()) - } catch { - case e : RuntimeException => { - System.err.println("In method " + constr) - e.printStackTrace() - } - } - undent(); println("}") - } - - /** - * Visit a MethodBuilder - */ - @throws(classOf[IOException]) - def caseMethodBuilder(method: MethodBuilder) { - if (nomembers) return - print(".method "); printHeader(method, method.ReturnType) - if (method.IsAbstract() - || (method.DeclaringType != null - && method.DeclaringType.IsInterface() - && !method.IsStatic())) - { - println(" {"); indent() - printAttributes(method) - undent(); println("}") - } else { - println(); println("{"); indent() - printAttributes(method) - if (method == entryPoint) - println(".entrypoint") - try { - print(method.GetILGenerator()) - } catch { - case e: RuntimeException => - System.err.println("In method " + method) - e.printStackTrace() - } - undent(); println("}") - } - } - - /** - * Visit a ParameterBuilder - */ - @throws(classOf[IOException]) - def caseParameterBuilder(param: ParameterBuilder) { - print(ParameterAttributes.toString(param.Attributes)) - printSignature(param.ParameterType) - //print(' ') print(marshal) - print(' '); printName(param.Name) - } - - var locals: Array[LocalBuilder] = null - /** - * Visit an ILGenerator - */ - @throws(classOf[IOException]) - def caseILGenerator(code: ILGenerator) { - // print maxstack - println(".maxstack " + code.getMaxStacksize()) - // get the local variables - locals = code.getLocals() - if (locals.length > 0) { - println(".locals init (") - indent() - for (i <- 0 until locals.length) { - if (i > 0) println(",") - print(locals(i)) - } // end while - undent() - println(")") - } - // get 3 iterators for the 3 lists - val itL = code.getLabelIterator() - val itO = code.getOpcodeIterator() - val itA = code.getArgumentIterator() - // iterate over each opcode - while (itO.hasNext) { - // first print label - val label = itL.next - val oOpt = code.lineNums.get(label) - if (oOpt.isDefined) { - println(".line " + oOpt.get) - } - argument = itA.next.asInstanceOf[Object] - printLabel(label) - val o2 = itO.next - if (o2 != null) { - print(" ") - print(o2.asInstanceOf[OpCode]) - } - println() - } // end while - } - - /** - * visit an OpCode - */ - @throws(classOf[IOException]) - def caseOpCode(opCode: OpCode) { - val opString = opCode.toString() - print(opString) - pad(14 - opString.length()) - - // switch opcode - if (opCode == OpCode.Ldstr) { - print(msilString(argument.toString())) - } else if(opCode == OpCode.Switch) { - // switch ( ) - print("(") - val targets = argument.asInstanceOf[Array[Label]] - val m = targets.length - for (i <- 0 until m) { - if (i != 0) print(", ") - print(targets(i)) - } // end for - print(")") - } else if(opCode == OpCode.Call || opCode == OpCode.Callvirt || opCode == OpCode.Jmp || opCode == OpCode.Ldftn || opCode == OpCode.Ldvirtftn) { - // call | callvirt | jmp | ldftn | ldvirtftn - // [ :: ] - printSignature(argument.asInstanceOf[MethodBase]) - } else if (opCode == OpCode.Newobj) { - printSignature(argument.asInstanceOf[ConstructorInfo]) - // ldfld | ldflda | ldsfld | ldsflda | stfld | stsfld - } else if (opCode == OpCode.Ldfld || opCode == OpCode.Ldflda || opCode == OpCode.Ldsfld || opCode == OpCode.Ldsflda || opCode == OpCode.Stfld || opCode == OpCode.Stsfld) { - printSignature(argument.asInstanceOf[FieldInfo]) - } else if (opCode == OpCode.Castclass || opCode == OpCode.Isinst || opCode == OpCode.Ldobj || opCode == OpCode.Newarr) { - printSignature(argument.asInstanceOf[Type]) - } else if (opCode == OpCode.Box || opCode == OpCode.Unbox || opCode == OpCode.Ldtoken || opCode == OpCode.Initobj) { - printReference(argument.asInstanceOf[Type]) - } else if (opCode == OpCode.Ldloc || opCode == OpCode.Ldloc_S || opCode == OpCode.Ldloca || opCode == OpCode.Ldloca_S || opCode == OpCode.Stloc || opCode == OpCode.Stloc_S) { - val loc = argument.asInstanceOf[LocalBuilder] - print(loc.slot); print("\t// "); printSignature(loc.LocalType) - print(" \'"); print(loc.name); print("\'") - //print("'") print(((LocalBuilder)argument).name) print("'") - } else if (opCode == OpCode.Ldloc_0 || opCode == OpCode.Ldloc_1 || opCode == OpCode.Ldloc_2 || opCode == OpCode.Ldloc_3 ) { - val loc = locals(opCode.CEE_opcode - OpCode.CEE_LDLOC_0) - print("\t// "); printSignature(loc.LocalType) - print(" \'"); print(loc.name); print("\'") - } else if (opCode == OpCode.Stloc_0 || opCode == OpCode.Stloc_1 || opCode == OpCode.Stloc_2 || opCode == OpCode.Stloc_3 ) { - val loc = locals(opCode.CEE_opcode - OpCode.CEE_STLOC_0) - print("\t// "); printSignature(loc.LocalType) - print(" \'"); print(loc.name); print("\'") - } else if (opCode == OpCode.Readonly) { - // nothing to do - } else if (opCode == OpCode.Constrained) { - printReference(argument.asInstanceOf[Type]) - } else if (opCode == OpCode.Ldelema) { - printReference(argument.asInstanceOf[Type]) - } else { - // by default print toString argument if any - if (argument != null) { - val strArgument = java.lang.String.valueOf(argument) - if ( argument.isInstanceOf[java.lang.Float] - && ( strArgument.equals("NaN") - || strArgument.equals("-Infinity") - || strArgument.equals("Infinity"))) - print(msilSyntaxFloat(argument.asInstanceOf[java.lang.Float])) - else if ( argument.isInstanceOf[java.lang.Double] - && ( strArgument.equals("NaN") - || strArgument.equals("-Infinity") - || strArgument.equals("Infinity"))) - print(msilSyntaxDouble(argument.asInstanceOf[java.lang.Double])) - else print(strArgument) - } - - } // end switch - } - - /** - * Visit a Label - */ - def printLabel(label: Label) { - val kind = label.getKind() - if (kind == Label.Kind.Normal) { - print(label+ ": ") - } else if (kind == Label.Kind.NewScope) { - print("{"); indent() - } else if (kind == Label.Kind.EndScope) { - undent(); print("}") - } else if (kind == Label.Kind.Try) { - print(".try {"); indent() - } else if (kind == Label.Kind.Catch) { - undent() - println("}") - print("catch ") - printReference(argument.asInstanceOf[Type]) - print(" {") - indent() - } else if (kind == Label.Kind.Filter) { - undent() - println("}") - print("filter {") - indent() - } else if (kind == Label.Kind.EndFilter) { - print("endfilter") - undent() - println("}") - } else if (kind == Label.Kind.Finally) { - undent() - println("}") - print("finally {") - indent() - } else if (kind == Label.Kind.EndTry) { - undent() - print("}") - } - } - - /** - * Visit a LocalBuilder - */ - @throws(classOf[IOException]) - def caseLocalBuilder(localBuilder: LocalBuilder) { - // print type - printSignature(localBuilder.LocalType) - // space - print(" \'") - // print name - print(localBuilder.name) - print("\'") - } - - - //########################################################################## - - def printAssemblySignature(assem: Assembly, extern: Boolean) { - print(".assembly ") - if (extern) - print("extern ") - val an = assem.GetName() - printName(an.Name); println() - println("{") - if (!extern) - printAttributes(assem) - val v = an.Version - if (v != null) { - print(" .ver "); print(v.Major); print(':'); print(v.Minor) - print(':'); print(v.Build); print(':') - print(v.Revision); println() - } - var key = an.GetPublicKeyToken() - if (key != null) { - print(" .publickeytoken = ("); print(PEFile.bytes2hex(key)) - println(")") - } else { - key = an.GetPublicKey() - if (key != null) { - print(" .publickey = ("); print(PEFile.bytes2hex(key)) - println(")") - } - } - println("}") - } - - - def printSignature(field: FieldInfo) { - printSignature(field.FieldType, field.cmods) - //print(' ') print(owner) - print(' ') - //if (field.IsStatic && field.DeclaringType != currentType) { - printReference(field.DeclaringType) - print("::") - //} - printName(field.Name) - } - - // print method head - @throws(classOf[IOException]) - def printHeader(method: MethodBase, returnType: Type) { - print(MethodAttributes.toString(method.Attributes)) - print(' '); print(CallingConventions.toString(method.CallingConvention)) - print(' '); printSignature(returnType) - //print(' ') print(marshal) - print(' '); printName(method.Name) - if(method.isInstanceOf[MethodInfo]) { - val mthdInfo = method.asInstanceOf[MethodInfo] - printTypeParams(mthdInfo.getSortedMVars()) - } - val params = method.GetParameters() - print('(') - for (i <- 0 until params.length) { - if (i > 0) print(", ") - print(params(i).asInstanceOf[ParameterBuilder]) - } - print(") ") - - print(MethodImplAttributes - .toString(method.GetMethodImplementationFlags())) - } - - - def printSignature(method: MethodBase) { - var returnType: Type = null - if (method.isInstanceOf[MethodInfo]) - returnType = (method.asInstanceOf[MethodInfo]).ReturnType - else if (method.isInstanceOf[ConstructorInfo]) - returnType = VOID - else - throw new RuntimeException() - - val s = CallingConventions.toString(method.CallingConvention) - print(s) - if (s.length() > 0) print(' ') - printSignature(returnType) - //print(' ') print(owner) - print(' '); printReference(method.DeclaringType) - print("::"); printName(method.Name) - - val params = method.GetParameters() - print("(") - for (i <- 0 until params.length) { - if (i > 0) print(", ") - printSignature(params(i).ParameterType) - } - print(")") - } - - def printSignature(marked: Type, cmods: Array[CustomModifier]) { - printSignature(marked) - if( (cmods != null) && !cmods.isEmpty ) { - print(" ") - for(cm <- cmods) { - print(if (cm.isReqd) "modreq( " else "modopt( ") - printReference(cm.marker) - print(" ) ") - } - } - } - - def printSignature(`type`: Type) { - val sigOpt = primitive.get(`type`) - if (sigOpt.isDefined) { - print(sigOpt.get) - return - } - if (`type`.HasElementType()) { - printSignature(`type`.GetElementType()) - if (`type`.IsArray()) - print("[]") - else if (`type`.IsPointer()) - print('*') - else if (`type`.IsByRef()) - print('&') - } else { - val preref = if (`type`.isInstanceOf[Type.TMVarUsage]) "" - else if(`type`.IsValueType()) "valuetype " - else "class " - print(preref) - printReference(`type`) - } - } - - def printReference(`type`: Type) { - if (`type`.Module != null) { // i.e. not PrimitiveType and not TMVarUsage - if (`type`.Assembly() != currentModule.Assembly) { - print('['); print(`type`.Assembly().GetName().Name); print("]") - } else if (`type`.Module != currentModule) { - print("[.module "); print(`type`.Module.Name); print("]") - } - } - printTypeName(`type`) - } - - def printTypeName(`type`: Type) { - if (`type`.isInstanceOf[ConstructedType]) { - val ct = `type`.asInstanceOf[ConstructedType] - printTypeName(ct.instantiatedType) - print("<") - var i = 0 - while (i < ct.typeArgs.length) { - val ta = ct.typeArgs(i) - val sigOpt = primitive.get(ta) - if (sigOpt.isDefined) print(sigOpt.get) - else printTypeName(ta); /* should be printSignature, but don't want `class` or `valuetype` - appearing before a type param usage. */ - i = i + 1; - if (i < ct.typeArgs.length) { - print(", ") - } - } - print(">") - } else if (`type`.DeclaringType != null) { - printTypeName(`type`.DeclaringType) - print('/') - printName(`type`.Name) - } else { - printName(`type`.FullName) - } - } - - def printAttributes(icap: ICustomAttributeProvider) { - val attrs = icap.GetCustomAttributes(false) - for (i <- 0 until attrs.length) { - print(".custom ") - printSignature((attrs(i).asInstanceOf[Attribute]).getConstructor()) - print(" = (") - print(PEFile.bytes2hex((attrs(i).asInstanceOf[Attribute]).getValue())) - println(")") - } - } - - //########################################################################## - -} // class ILPrinterVisitor - -object ILPrinterVisitor { - final val VOID: Type = Type.GetType("System.Void") - protected final val TAB = 4 - - protected final val SPACES = " " - protected final val SPACES_LEN = SPACES.length() - - def hasControlChars(str: String): Boolean = { - for(i <- 0 until str.length()) { - val ch = str.charAt(i) - ch match { - case '\b' => - case '\t' => - case '\n' => - case '\f' => - case '\r' => - case _ => if(Character.isISOControl(ch)) return true - } - } - return false - } - - final val EMPTY: String = "" - def msilString(s: String): String = { - if (hasControlChars(s)) { - try { - return "bytearray (" + PEFile.bytes2hex(s.getBytes("UTF-16LE")) + ")" - } catch { - case e : java.io.UnsupportedEncodingException => throw new RuntimeException(e) - } - } - val str = new StringBuffer(s) - var ss = EMPTY - var i = 0 - while(i < str.length()) { - ss = EMPTY - val c = str.charAt(i) - c match { - case '\b' => ss = "\\b" - case '\t' => ss = "\\t" - case '\n' => ss = "\\n" - case '\f' => ss = "\\f" - case '\r' => ss = "\\r" - case '\"' => ss = "\\\"" - case '\'' => ss = "\\\'" - case '\\' => ss = "\\\\" - case _ => if (Character.isISOControl(c)) - ss = "\\u" + PEFile.int2hex(Character.getNumericValue(c)) - } - if (ss != EMPTY) { - str.replace(i, i + 1, ss) - i = i + ss.length() - 1 - } - i = i + 1 - } - return "\"" + str.toString() + "\"" - } - - /** - * the main printer method - */ - @throws(classOf[IOException]) - def printAssembly(assemblyBuilder: AssemblyBuilder, fileName: String) { - assemblyBuilder.apply(new SingleFileILPrinterVisitor(fileName)) - } - - @throws(classOf[IOException]) - def printAssembly(assemblyBuilder: AssemblyBuilder, destPath: String, sourceFilesPath: String) { - assemblyBuilder.apply(new MultipleFilesILPrinterVisitor(destPath, sourceFilesPath)) - } - - /** The current assembly */ - var currAssembly: Assembly = _ - - final var primitive = scala.collection.mutable.Map.empty[Type, String] - def addPrimitive(name: String, sig: String) { - val `type` = - Type.GetType(name) - assert(`type` != null, "Cannot lookup primitive type " + `type`) - primitive.put(`type`, sig) - } - - addPrimitive("System.Object", "object") - addPrimitive("System.String", "string") - addPrimitive("System.Void", "void") - addPrimitive("System.Boolean", "bool") - addPrimitive("System.Char", "char") - addPrimitive("System.SByte", "int8") - addPrimitive("System.Byte", "unsigned int8") - addPrimitive("System.Int16", "int16") - addPrimitive("System.UInt16", "unsigned int16") - addPrimitive("System.Int32", "int32") - addPrimitive("System.UInt32", "unsigned int32") - addPrimitive("System.Int64", "int64") - addPrimitive("System.UInt64", "unsigned int64") - addPrimitive("System.IntPtr", "native int") - addPrimitive("System.UIntPtr", "unsigned native int") - addPrimitive("System.Single", "float32") - addPrimitive("System.Double", "float64") - addPrimitive("System.TypedReference", "typedref") -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala deleted file mode 100644 index a80ea7232306..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala +++ /dev/null @@ -1,147 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil.Type - -/** - * Represents a label in the instruction stream. Label is used in conjunction - * with the ILGenerator class. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -abstract class Label protected { - import Label._ - def isInitialized(): Boolean - def getKind(): Kind - def getAddress(): Int - def getStacksize(): Int - def setStacksize(stacksize: Int): Unit - def incStacksize(): Unit - def mergeWith(that: Label): Unit -} - -object Label { - final val DUMMY: Int = -((1<<31)-1) - - //########################################################################## - - final class NormalLabel(_address: Int, _stacksize: Int) extends Label { - - //########################################################################## - // protected constructors - - //the position of the label - private var address: Int = _address - - //the stacksize at the label - private var stacksize: Int = _stacksize - - def this() { - this(-1, DUMMY) - } - - def this(that: NormalLabel) { - this(that.getAddress(), that.getStacksize()) - } - - //########################################################################## - // instrumental methods only used by ILGenerator - - def isInitialized() = (getAddress() != -1) || (stacksize != DUMMY) - - def getAddress() = address - - def getStacksize() = stacksize - - def setStacksize(stacksize: Int) { - assert(stacksize >= 0) - this.stacksize = stacksize - } - - def incStacksize() { - stacksize = stacksize + 1 - } - - def getKind(): Kind = Kind.Normal - - def mergeWith(that: Label) { - //assert address < 0 : "this.address = " + address + " that.address = " + that.address - address = that.getAddress() - - // assert stacksize == that.stacksize - // : "this.stacksize = " + stacksize + " that.stacksize = " - // + that.stacksize - // stacksize = that.stacksize - val ss: Int = math.max(stacksize, that.getStacksize()) - stacksize = ss - that.setStacksize(ss) - } - - //########################################################################## - // - - /** - * the toString Method return the label name - * it's "IL" + address - */ - override def toString(): String = { - var pad: String = "" - if (address < 16) pad = "000" - else if (address < 256) pad = "00" - else if (address < 4096) pad = "0" - return "IL_" + pad + Integer.toHexString(address) - } - - def getString(): String = { - val name = super.toString() - val i: Int = name.lastIndexOf('.') - return name.substring(i+1, name.length()) - } - } - - //######################################################################## - // Special Labels - - final class SpecialLabel(kind: Label.Kind) extends Label { - def isInitialized() = true - def getAddress(): Int = { throw new RuntimeException("" + kind) } - def getStacksize(): Int = { throw new RuntimeException("" + kind) } - def setStacksize(stacksize: Int) { throw new RuntimeException("" + kind) } - def incStacksize() { throw new RuntimeException("" + kind) } - def getKind(): Kind = kind - def mergeWith(that: Label) { throw new RuntimeException("" + kind) } - override def toString() = s"Label($kind)" - } - - final val NewScope: Label = new SpecialLabel(Kind.NewScope) - final val EndScope: Label = new SpecialLabel(Kind.EndScope) - final val Try: Label = new SpecialLabel(Kind.Try) - final val Catch: Label = new SpecialLabel(Kind.Catch) - final val Filter: Label = new SpecialLabel(Kind.Filter) - final val EndFilter: Label = new SpecialLabel(Kind.EndFilter) - final val Finally: Label = new SpecialLabel(Kind.Finally) - final val EndTry: Label = new SpecialLabel(Kind.EndTry) - - final class Kind() {} - - final object Kind { - final val Normal: Kind = new Kind() - - final val NewScope: Kind = new Kind() - final val EndScope: Kind = new Kind() - - final val Try: Kind = new Kind() - final val Catch: Kind = new Kind() - final val Filter: Kind = new Kind() - final val EndFilter: Kind = new Kind() - final val Finally: Kind = new Kind() - final val EndTry: Kind = new Kind() - } - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/LocalBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/LocalBuilder.scala deleted file mode 100644 index 73bca4639fa9..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/LocalBuilder.scala +++ /dev/null @@ -1,44 +0,0 @@ -/** - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil.Type - -/** - * Represents a local variable within a method or constructor. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class LocalBuilder(_slot : Int, localType : Type) extends Visitable { - - /** - * the type of the local variable. - */ - var LocalType : Type = localType - - // the name of the local variable - var name : String = "L_" + slot - - // the slot occupied by this local in the corresponding ILGenerator - var slot : Int = _slot - - /** - * Sets the name of this local variable. - */ - def SetLocalSymInfo(name : String) { - this.name = name - } - - override def toString() : String = name - - /** - * the apply method for a visitor - */ - def apply(v : Visitor) { - v.caseLocalBuilder(this) - } -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/MethodBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/MethodBuilder.scala deleted file mode 100644 index 237d8fd7284e..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/MethodBuilder.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil.MethodInfo -import ch.epfl.lamp.compiler.msil.ParameterInfo -import ch.epfl.lamp.compiler.msil.Type -import ch.epfl.lamp.compiler.msil.ConstructorInfo -import java.io.IOException - -/** - * Defines and represents a method of a dynamic class. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class MethodBuilder(name: String, declType: Type, attrs: Int, returnType: Type, paramTypes: Array[Type]) - extends MethodInfo(name, declType, attrs, returnType, paramTypes) - with ICustomAttributeSetter - with Visitable -{ - - //########################################################################## - // public interface - - /** Defines a parameter of this method. TODO: Parameters are indexed staring - * from number 1 for the first parameter - */ - def DefineParameter(pos: Int, attr: Int, name: String): ParameterBuilder = { - val param = new ParameterBuilder(name, params(pos).ParameterType, attr, pos) - params(pos) = param - return param - } - - /** Returns an ILGenerator for this method. */ - def GetILGenerator(): ILGenerator = { - if (ilGenerator == null) - throw new RuntimeException - ("No code generator available for this method: " + this) - return ilGenerator - } - - /** Sets a custom attribute. */ - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) { - addCustomAttribute(constr, value) - } - - //########################################################################## - - /** The apply method for a visitor. */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseMethodBuilder(this) - } - - //########################################################################## - - // the Intermediate Language Generator - // it contains the method's body - protected final val ilGenerator : ILGenerator = - if (DeclaringType == null // global method - || !DeclaringType.IsInterface()) - new ILGenerator(this) - else null - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala deleted file mode 100644 index 2319d5ca2701..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala +++ /dev/null @@ -1,136 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil._ -import java.io.IOException - -/** - * Defines and represents a module. Get an instance of ModuleBuilder - * by calling DefineDynamicModule - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly: Assembly) - extends Module(name, fullname, scopeName, assembly) - with ICustomAttributeSetter - with Visitable -{ - - //########################################################################## - // public interface - - /** - * Complete the global function definitions for this dynamic module. - * This method should be called when the user is done with defining - * all of the global functions within this dynamic module. After calling - * this function, no more new global functions or new global data are - * allowed. - */ - def CreateGlobalFunctions() { - if (globalsCreated) - throw new RuntimeException("Global functions are already created") - this.fields = fieldBuilders.toArray // (fields).asInstanceOf[Array[FieldInfo]] - this.methods = methodBuilders.toArray // (methods).asInstanceOf[Array[MethodInfo]] - globalsCreated = true - } - - /** - * Constructs a TypeBuilder for a type with the specified name - */ - def DefineType(typeName: String): TypeBuilder = { - return DefineType(typeName, 0, null, Type.EmptyTypes) - } - - /** - * Constructs a TypeBuilder for a type with the specified name - * and specified attributes - */ - def DefineType(typeName: String, attributes: Int): TypeBuilder = { - return DefineType(typeName, attributes, null, Type.EmptyTypes) - } - - /** - * Constructs a TypeBuilder given type name, its attributes, - * and the type that the defined type extends. - */ - def DefineType(typeName: String, attributes: Int, - baseType: Type): TypeBuilder = { - return DefineType(typeName, attributes, baseType, Type.EmptyTypes) - } - - /** - * Constructs a TypeBuilder given the Full specification of a type, - * Given the type name, attributes, the type that the defined type - * extends, and the interfaces that the defined type implements. - */ - def DefineType(typeName: String, - attributes: Int, - baseType: Type, - interfaces: Array[Type]): TypeBuilder = - { - val t: Type = GetType(typeName) // Module.GetType(String) - if (t != null) - throw new RuntimeException - ("Type [" + Assembly + "]" + typeName + "' already exists!") - val `type` = - new TypeBuilder(this, attributes, typeName, baseType, interfaces, null) - addType(`type`) - return `type` - } - - /** - * Defines a global method given its name, attributes, return type, and - * parameter types. - */ - def DefineGlobalMethod(name: String, attributes: Int, - returnType: Type, paramTypes: Array[Type]): MethodBuilder = - { - val method = - new MethodBuilder(name, null, attributes, returnType, paramTypes) - methodBuilders += method - return method - } - - - override def GetTypes(): Array[Type] = { - val res = scala.collection.mutable.ArrayBuffer.empty[Type] - val iter = typesMap.values().iterator - while (iter.hasNext) { - res += iter.next.asInstanceOf[Type] - } - return res.toArray - } - - /** Sets a custom attribute. */ - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) { - addCustomAttribute(constr, value) - } - - //########################################################################## - // internal members - - var globalsCreated = false - protected var fieldBuilders = scala.collection.mutable.ArrayBuffer.empty[FieldInfo] - protected var methodBuilders = scala.collection.mutable.ArrayBuffer.empty[MethodInfo] - - override def addType(t: Type): Type = { - return super.addType(t) - } - - //########################################################################## - - /** - * the apply method for a visitor - */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseModuleBuilder(this) - } - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala deleted file mode 100644 index bbbbf40508c6..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala +++ /dev/null @@ -1,137 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies in MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import java.io.File -import java.io.FileWriter -import java.io.BufferedWriter -import java.io.PrintWriter -import java.io.IOException -import java.util.Iterator -import java.util.Arrays - -import ch.epfl.lamp.compiler.msil._ -import ch.epfl.lamp.compiler.msil.emit -import ch.epfl.lamp.compiler.msil.util.Table - -/** - * The MSIL printer Visitor. It prints a complete - * assembly into separate files. Then these files can be compiled by ilasm. - * - * @author Nikolay Mihaylov - * @author Daniel Lorch - * @version 1.0 - */ -final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: String) extends ILPrinterVisitor { - /** - * Visit an AssemblyBuilder - */ - @throws(classOf[IOException]) - def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) { - ILPrinterVisitor.currAssembly = assemblyBuilder - - // first get the entryPoint - this.entryPoint = assemblyBuilder.EntryPoint - - // all external assemblies - as = assemblyBuilder.getExternAssemblies() - scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator) - - // print each module - val m: Array[Module] = assemblyBuilder.GetModules() - nomembers = true - for(i <- 0 until m.length) { - print(m(i).asInstanceOf[ModuleBuilder]) - } - - nomembers = false - for(i <- 0 until m.length) { - print(m(i).asInstanceOf[ModuleBuilder]) - } - ILPrinterVisitor.currAssembly = null - } - - /** - * Visit a ModuleBuilder - */ - @throws(classOf[IOException]) - def caseModuleBuilder(module: ModuleBuilder) { - val assemblyBuilder = ILPrinterVisitor.currAssembly.asInstanceOf[AssemblyBuilder] - - // print module declaration - currentModule = module - - // global methods typically contain the main method - if (!module.globalsCreated) - module.CreateGlobalFunctions() - - val m: Array[MethodInfo] = module.GetMethods() - - // "Types" contain all the classes - val t: Array[Type] = module.GetTypes() - for(i <- 0 until t.length) { - val tBuilder = t(i).asInstanceOf[TypeBuilder] - val sourceFilename = tBuilder.sourceFilename - val sourceFilepath = new File(tBuilder.sourceFilepath).getCanonicalPath - val sourcePath = new File(sourceFilesPath).getCanonicalPath - var append = false - - if(!sourceFilepath.startsWith(sourcePath)) { - throw new IOException("Source file " + sourceFilename + " must lie inside sourcepath " + sourcePath) - } - - assert(sourceFilepath.endsWith(".scala"), "Source file doesn't end with .scala") - val relativeFilename = sourceFilepath.substring(sourcePath.length, sourceFilepath.length() - 6) + ".msil" - val fileName = new File(destPath, relativeFilename) - if(assemblyBuilder.generatedFiles.contains(fileName.getPath)) { - append = true - } else { - fileName.getParentFile().mkdirs() - assemblyBuilder.generatedFiles += (fileName.getPath) - } - - out = new PrintWriter(new BufferedWriter(new FileWriter(fileName, append))) - // only write assembly boilerplate and class prototypes - if (!append && nomembers) { - printAssemblyBoilerplate() - - print(".module \'"); print(module.Name); println("\'") - printAttributes(module) - } - - print(t(i).asInstanceOf[TypeBuilder]) - out.close() - } - - // now write the global methods (typically contains the "main" method) - if(!nomembers) { - val globalMethods: File = new File(destPath, ILPrinterVisitor.currAssembly.GetName().Name + ".msil") - val append = assemblyBuilder.generatedFiles.contains(globalMethods.getPath) - - out = new PrintWriter(new BufferedWriter(new FileWriter(globalMethods, append))) - - // make sure we're the first in the list (ilasm uses the first file name to guess the output file name) - assemblyBuilder.generatedFiles.insert(0, globalMethods.getPath) - - // if this file hasn't been created by one of the classes, write boilerplate - if(!append) { - printAssemblyBoilerplate() - - print(".module \'"); print(module.Name); println("\'") - printAttributes(module) - } - - for(i <- 0 until m.length) { - print(m(i).asInstanceOf[MethodBuilder]) - } - - out.close() - } - - currentModule = null - } - -} // class MultipleFilesILPrinterVisitor diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala deleted file mode 100644 index b0c26884af57..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala +++ /dev/null @@ -1,1948 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import java.io.IOException - -/** Describes a Microsoft intermediate language (MSIL) instruction. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class OpCode extends Visitable { - import OpCode._ - - /** The Operation Code of Microsoft intermediate language (MSIL) instruction. */ - var CEE_opcode : Int = _ - - /** The name of the Microsoft intermediate language (MSIL) instruction. */ - var CEE_string: String = _ - - /** The type of Microsoft intermediate language (MSIL) instruction. */ - var CEE_code: Short = _ - - /** How the Microsoft intermediate language (MSIL) instruction pops the stack. */ - var CEE_pop: Byte = _ - - /** How the Microsoft intermediate language (MSIL) instruction pushes operand onto the stack. */ - var CEE_push: Byte = _ - - /** Describes the type of flow control. */ - var CEE_flow: Byte = _ - - /** ????? */ - var CEE_inline: Byte = _ - - var CEE_length: Byte = _ - - var CEE_popush: Byte = _ - - /** - * the apply method for a visitor - */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseOpCode(this) - } - - protected def length(): Byte = { - val code = OpCode.length(CEE_code) - val inline = OpCode.INLINE_length(CEE_inline) - return if(inline < 0) { -1 } else { (code + inline).toByte } - } - - protected def popush(): Byte = { - val pop = OpCode.POP_size(CEE_pop) - val push = OpCode.PUSH_size(CEE_push) - return if(pop < 0 || push < 0) { OpCode.POPUSH_SPECIAL } else { (push - pop).toByte } - } - - override def toString(): String = { - return CEE_string - } -} - -object OpCode { - - //######################################################################## - // Common Execution Environment opcodes - - final val CEE_NOP : Int = 0x0000 - final val CEE_BREAK : Int = 0x0001 - final val CEE_LDARG_0 : Int = 0x0002 - final val CEE_LDARG_1 : Int = 0x0003 - final val CEE_LDARG_2 : Int = 0x0004 - final val CEE_LDARG_3 : Int = 0x0005 - final val CEE_LDLOC_0 : Int = 0x0006 - final val CEE_LDLOC_1 : Int = 0x0007 - final val CEE_LDLOC_2 : Int = 0x0008 - final val CEE_LDLOC_3 : Int = 0x0009 - final val CEE_STLOC_0 : Int = 0x000A - final val CEE_STLOC_1 : Int = 0x000B - final val CEE_STLOC_2 : Int = 0x000C - final val CEE_STLOC_3 : Int = 0x000D - final val CEE_LDARG_S : Int = 0x000E - final val CEE_LDARGA_S : Int = 0x000F - final val CEE_STARG_S : Int = 0x0010 - final val CEE_LDLOC_S : Int = 0x0011 - final val CEE_LDLOCA_S : Int = 0x0012 - final val CEE_STLOC_S : Int = 0x0013 - final val CEE_LDNULL : Int = 0x0014 - final val CEE_LDC_I4_M1 : Int = 0x0015 - final val CEE_LDC_I4_0 : Int = 0x0016 - final val CEE_LDC_I4_1 : Int = 0x0017 - final val CEE_LDC_I4_2 : Int = 0x0018 - final val CEE_LDC_I4_3 : Int = 0x0019 - final val CEE_LDC_I4_4 : Int = 0x001A - final val CEE_LDC_I4_5 : Int = 0x001B - final val CEE_LDC_I4_6 : Int = 0x001C - final val CEE_LDC_I4_7 : Int = 0x001D - final val CEE_LDC_I4_8 : Int = 0x001E - final val CEE_LDC_I4_S : Int = 0x001F - final val CEE_LDC_I4 : Int = 0x0020 - final val CEE_LDC_I8 : Int = 0x0021 - final val CEE_LDC_R4 : Int = 0x0022 - final val CEE_LDC_R8 : Int = 0x0023 - final val CEE_UNUSED49 : Int = 0x0024 - final val CEE_DUP : Int = 0x0025 - final val CEE_POP : Int = 0x0026 - final val CEE_JMP : Int = 0x0027 - final val CEE_CALL : Int = 0x0028 - final val CEE_CALLI : Int = 0x0029 - final val CEE_RET : Int = 0x002A - final val CEE_BR_S : Int = 0x002B - final val CEE_BRFALSE_S : Int = 0x002C - final val CEE_BRTRUE_S : Int = 0x002D - final val CEE_BEQ_S : Int = 0x002E - final val CEE_BGE_S : Int = 0x002F - final val CEE_BGT_S : Int = 0x0030 - final val CEE_BLE_S : Int = 0x0031 - final val CEE_BLT_S : Int = 0x0032 - final val CEE_BNE_UN_S : Int = 0x0033 - final val CEE_BGE_UN_S : Int = 0x0034 - final val CEE_BGT_UN_S : Int = 0x0035 - final val CEE_BLE_UN_S : Int = 0x0036 - final val CEE_BLT_UN_S : Int = 0x0037 - final val CEE_BR : Int = 0x0038 - final val CEE_BRFALSE : Int = 0x0039 - final val CEE_BRTRUE : Int = 0x003A - final val CEE_BEQ : Int = 0x003B - final val CEE_BGE : Int = 0x003C - final val CEE_BGT : Int = 0x003D - final val CEE_BLE : Int = 0x003E - final val CEE_BLT : Int = 0x003F - final val CEE_BNE_UN : Int = 0x0040 - final val CEE_BGE_UN : Int = 0x0041 - final val CEE_BGT_UN : Int = 0x0042 - final val CEE_BLE_UN : Int = 0x0043 - final val CEE_BLT_UN : Int = 0x0044 - final val CEE_SWITCH : Int = 0x0045 - final val CEE_LDIND_I1 : Int = 0x0046 - final val CEE_LDIND_U1 : Int = 0x0047 - final val CEE_LDIND_I2 : Int = 0x0048 - final val CEE_LDIND_U2 : Int = 0x0049 - final val CEE_LDIND_I4 : Int = 0x004A - final val CEE_LDIND_U4 : Int = 0x004B - final val CEE_LDIND_I8 : Int = 0x004C - final val CEE_LDIND_I : Int = 0x004D - final val CEE_LDIND_R4 : Int = 0x004E - final val CEE_LDIND_R8 : Int = 0x004F - final val CEE_LDIND_REF : Int = 0x0050 - final val CEE_STIND_REF : Int = 0x0051 - final val CEE_STIND_I1 : Int = 0x0052 - final val CEE_STIND_I2 : Int = 0x0053 - final val CEE_STIND_I4 : Int = 0x0054 - final val CEE_STIND_I8 : Int = 0x0055 - final val CEE_STIND_R4 : Int = 0x0056 - final val CEE_STIND_R8 : Int = 0x0057 - final val CEE_ADD : Int = 0x0058 - final val CEE_SUB : Int = 0x0059 - final val CEE_MUL : Int = 0x005A - final val CEE_DIV : Int = 0x005B - final val CEE_DIV_UN : Int = 0x005C - final val CEE_REM : Int = 0x005D - final val CEE_REM_UN : Int = 0x005E - final val CEE_AND : Int = 0x005F - final val CEE_OR : Int = 0x0060 - final val CEE_XOR : Int = 0x0061 - final val CEE_SHL : Int = 0x0062 - final val CEE_SHR : Int = 0x0063 - final val CEE_SHR_UN : Int = 0x0064 - final val CEE_NEG : Int = 0x0065 - final val CEE_NOT : Int = 0x0066 - final val CEE_CONV_I1 : Int = 0x0067 - final val CEE_CONV_I2 : Int = 0x0068 - final val CEE_CONV_I4 : Int = 0x0069 - final val CEE_CONV_I8 : Int = 0x006A - final val CEE_CONV_R4 : Int = 0x006B - final val CEE_CONV_R8 : Int = 0x006C - final val CEE_CONV_U4 : Int = 0x006D - final val CEE_CONV_U8 : Int = 0x006E - final val CEE_CALLVIRT : Int = 0x006F - final val CEE_CPOBJ : Int = 0x0070 - final val CEE_LDOBJ : Int = 0x0071 - final val CEE_LDSTR : Int = 0x0072 - final val CEE_NEWOBJ : Int = 0x0073 - final val CEE_CASTCLASS : Int = 0x0074 - final val CEE_ISINST : Int = 0x0075 - final val CEE_CONV_R_UN : Int = 0x0076 - final val CEE_UNUSED58 : Int = 0x0077 - final val CEE_UNUSED1 : Int = 0x0078 - final val CEE_UNBOX : Int = 0x0079 - final val CEE_THROW : Int = 0x007A - final val CEE_LDFLD : Int = 0x007B - final val CEE_LDFLDA : Int = 0x007C - final val CEE_STFLD : Int = 0x007D - final val CEE_LDSFLD : Int = 0x007E - final val CEE_LDSFLDA : Int = 0x007F - final val CEE_STSFLD : Int = 0x0080 - final val CEE_STOBJ : Int = 0x0081 - final val CEE_CONV_OVF_I1_UN : Int = 0x0082 - final val CEE_CONV_OVF_I2_UN : Int = 0x0083 - final val CEE_CONV_OVF_I4_UN : Int = 0x0084 - final val CEE_CONV_OVF_I8_UN : Int = 0x0085 - final val CEE_CONV_OVF_U1_UN : Int = 0x0086 - final val CEE_CONV_OVF_U2_UN : Int = 0x0087 - final val CEE_CONV_OVF_U4_UN : Int = 0x0088 - final val CEE_CONV_OVF_U8_UN : Int = 0x0089 - final val CEE_CONV_OVF_I_UN : Int = 0x008A - final val CEE_CONV_OVF_U_UN : Int = 0x008B - final val CEE_BOX : Int = 0x008C - final val CEE_NEWARR : Int = 0x008D - final val CEE_LDLEN : Int = 0x008E - final val CEE_LDELEMA : Int = 0x008F - final val CEE_LDELEM_I1 : Int = 0x0090 - final val CEE_LDELEM_U1 : Int = 0x0091 - final val CEE_LDELEM_I2 : Int = 0x0092 - final val CEE_LDELEM_U2 : Int = 0x0093 - final val CEE_LDELEM_I4 : Int = 0x0094 - final val CEE_LDELEM_U4 : Int = 0x0095 - final val CEE_LDELEM_I8 : Int = 0x0096 - final val CEE_LDELEM_I : Int = 0x0097 - final val CEE_LDELEM_R4 : Int = 0x0098 - final val CEE_LDELEM_R8 : Int = 0x0099 - final val CEE_LDELEM_REF : Int = 0x009A - final val CEE_STELEM_I : Int = 0x009B - final val CEE_STELEM_I1 : Int = 0x009C - final val CEE_STELEM_I2 : Int = 0x009D - final val CEE_STELEM_I4 : Int = 0x009E - final val CEE_STELEM_I8 : Int = 0x009F - final val CEE_STELEM_R4 : Int = 0x00A0 - final val CEE_STELEM_R8 : Int = 0x00A1 - final val CEE_STELEM_REF : Int = 0x00A2 - final val CEE_UNUSED2 : Int = 0x00A3 - final val CEE_UNUSED3 : Int = 0x00A4 - final val CEE_UNUSED4 : Int = 0x00A5 - final val CEE_UNUSED5 : Int = 0x00A6 - final val CEE_UNUSED6 : Int = 0x00A7 - final val CEE_UNUSED7 : Int = 0x00A8 - final val CEE_UNUSED8 : Int = 0x00A9 - final val CEE_UNUSED9 : Int = 0x00AA - final val CEE_UNUSED10 : Int = 0x00AB - final val CEE_UNUSED11 : Int = 0x00AC - final val CEE_UNUSED12 : Int = 0x00AD - final val CEE_UNUSED13 : Int = 0x00AE - final val CEE_UNUSED14 : Int = 0x00AF - final val CEE_UNUSED15 : Int = 0x00B0 - final val CEE_UNUSED16 : Int = 0x00B1 - final val CEE_UNUSED17 : Int = 0x00B2 - final val CEE_CONV_OVF_I1 : Int = 0x00B3 - final val CEE_CONV_OVF_U1 : Int = 0x00B4 - final val CEE_CONV_OVF_I2 : Int = 0x00B5 - final val CEE_CONV_OVF_U2 : Int = 0x00B6 - final val CEE_CONV_OVF_I4 : Int = 0x00B7 - final val CEE_CONV_OVF_U4 : Int = 0x00B8 - final val CEE_CONV_OVF_I8 : Int = 0x00B9 - final val CEE_CONV_OVF_U8 : Int = 0x00BA - final val CEE_UNUSED50 : Int = 0x00BB - final val CEE_UNUSED18 : Int = 0x00BC - final val CEE_UNUSED19 : Int = 0x00BD - final val CEE_UNUSED20 : Int = 0x00BE - final val CEE_UNUSED21 : Int = 0x00BF - final val CEE_UNUSED22 : Int = 0x00C0 - final val CEE_UNUSED23 : Int = 0x00C1 - final val CEE_REFANYVAL : Int = 0x00C2 - final val CEE_CKFINITE : Int = 0x00C3 - final val CEE_UNUSED24 : Int = 0x00C4 - final val CEE_UNUSED25 : Int = 0x00C5 - final val CEE_MKREFANY : Int = 0x00C6 - final val CEE_UNUSED59 : Int = 0x00C7 - final val CEE_UNUSED60 : Int = 0x00C8 - final val CEE_UNUSED61 : Int = 0x00C9 - final val CEE_UNUSED62 : Int = 0x00CA - final val CEE_UNUSED63 : Int = 0x00CB - final val CEE_UNUSED64 : Int = 0x00CC - final val CEE_UNUSED65 : Int = 0x00CD - final val CEE_UNUSED66 : Int = 0x00CE - final val CEE_UNUSED67 : Int = 0x00CF - final val CEE_LDTOKEN : Int = 0x00D0 - final val CEE_CONV_U2 : Int = 0x00D1 - final val CEE_CONV_U1 : Int = 0x00D2 - final val CEE_CONV_I : Int = 0x00D3 - final val CEE_CONV_OVF_I : Int = 0x00D4 - final val CEE_CONV_OVF_U : Int = 0x00D5 - final val CEE_ADD_OVF : Int = 0x00D6 - final val CEE_ADD_OVF_UN : Int = 0x00D7 - final val CEE_MUL_OVF : Int = 0x00D8 - final val CEE_MUL_OVF_UN : Int = 0x00D9 - final val CEE_SUB_OVF : Int = 0x00DA - final val CEE_SUB_OVF_UN : Int = 0x00DB - final val CEE_ENDFINALLY : Int = 0x00DC - final val CEE_LEAVE : Int = 0x00DD - final val CEE_LEAVE_S : Int = 0x00DE - final val CEE_STIND_I : Int = 0x00DF - final val CEE_CONV_U : Int = 0x00E0 - final val CEE_UNUSED26 : Int = 0x00E1 - final val CEE_UNUSED27 : Int = 0x00E2 - final val CEE_UNUSED28 : Int = 0x00E3 - final val CEE_UNUSED29 : Int = 0x00E4 - final val CEE_UNUSED30 : Int = 0x00E5 - final val CEE_UNUSED31 : Int = 0x00E6 - final val CEE_UNUSED32 : Int = 0x00E7 - final val CEE_UNUSED33 : Int = 0x00E8 - final val CEE_UNUSED34 : Int = 0x00E9 - final val CEE_UNUSED35 : Int = 0x00EA - final val CEE_UNUSED36 : Int = 0x00EB - final val CEE_UNUSED37 : Int = 0x00EC - final val CEE_UNUSED38 : Int = 0x00ED - final val CEE_UNUSED39 : Int = 0x00EE - final val CEE_UNUSED40 : Int = 0x00EF - final val CEE_UNUSED41 : Int = 0x00F0 - final val CEE_UNUSED42 : Int = 0x00F1 - final val CEE_UNUSED43 : Int = 0x00F2 - final val CEE_UNUSED44 : Int = 0x00F3 - final val CEE_UNUSED45 : Int = 0x00F4 - final val CEE_UNUSED46 : Int = 0x00F5 - final val CEE_UNUSED47 : Int = 0x00F6 - final val CEE_UNUSED48 : Int = 0x00F7 - final val CEE_PREFIX7 : Int = 0x00F8 - final val CEE_PREFIX6 : Int = 0x00F9 - final val CEE_PREFIX5 : Int = 0x00FA - final val CEE_PREFIX4 : Int = 0x00FB - final val CEE_PREFIX3 : Int = 0x00FC - final val CEE_PREFIX2 : Int = 0x00FD - final val CEE_PREFIX1 : Int = 0x00FE - final val CEE_PREFIXREF : Int = 0x00FF - - final val CEE_ARGLIST : Int = 0x0100 - final val CEE_CEQ : Int = 0x0101 - final val CEE_CGT : Int = 0x0102 - final val CEE_CGT_UN : Int = 0x0103 - final val CEE_CLT : Int = 0x0104 - final val CEE_CLT_UN : Int = 0x0105 - final val CEE_LDFTN : Int = 0x0106 - final val CEE_LDVIRTFTN : Int = 0x0107 - final val CEE_UNUSED56 : Int = 0x0108 - final val CEE_LDARG : Int = 0x0109 - final val CEE_LDARGA : Int = 0x010A - final val CEE_STARG : Int = 0x010B - final val CEE_LDLOC : Int = 0x010C - final val CEE_LDLOCA : Int = 0x010D - final val CEE_STLOC : Int = 0x010E - final val CEE_LOCALLOC : Int = 0x010F - final val CEE_UNUSED57 : Int = 0x0110 - final val CEE_ENDFILTER : Int = 0x0111 - final val CEE_UNALIGNED : Int = 0x0112 - final val CEE_VOLATILE : Int = 0x0113 - final val CEE_TAILCALL : Int = 0x0114 - final val CEE_INITOBJ : Int = 0x0115 - final val CEE_CONSTRAINED : Int = 0xFE16 - final val CEE_READONLY : Int = 0xFE1E - final val CEE_UNUSED68 : Int = 0x0116 - final val CEE_CPBLK : Int = 0x0117 - final val CEE_INITBLK : Int = 0x0118 - final val CEE_UNUSED69 : Int = 0x0119 - final val CEE_RETHROW : Int = 0x011A - final val CEE_UNUSED51 : Int = 0x011B - final val CEE_SIZEOF : Int = 0x011C - final val CEE_REFANYTYPE : Int = 0x011D - final val CEE_UNUSED52 : Int = 0x011E - final val CEE_UNUSED53 : Int = 0x011F - final val CEE_UNUSED54 : Int = 0x0120 - final val CEE_UNUSED55 : Int = 0x0121 - final val CEE_UNUSED70 : Int = 0x0122 - - final val CEE_ILLEGAL : Int = 0x0140 - final val CEE_MACRO_END : Int = 0x0141 - - final val CEE_BRNULL : Int = 0x0180 // CEE_BRFALSE - final val CEE_BRNULL_S : Int = 0x0181 // CEE_BRFALSE_S - final val CEE_BRZERO : Int = 0x0182 // CEE_BRFALSE - final val CEE_BRZERO_S : Int = 0x0183 // CEE_BRFALSE_S - final val CEE_BRINST : Int = 0x0184 // CEE_BRTRUE - final val CEE_BRINST_S : Int = 0x0185 // CEE_BRTRUE_S - final val CEE_LDIND_U8 : Int = 0x0186 // CEE_LDIND_I8 - final val CEE_LDELEM_U8 : Int = 0x0187 // CEE_LDELEM_I8 - final val CEE_LDC_I4_M1x : Int = 0x0188 // CEE_LDC_I4_M1 - final val CEE_ENDFAULT : Int = 0x0189 // CEE_ENDFINALLY - - final val CEE_BRNONZERO : Int = 0x01C0 // CEE_BRTRUE - final val CEE_BRNONZERO_S : Int = 0x01C1 // CEE_BRTRUE_S - - final val CEE_BRNOT : Int = 0x01C2 - final val CEE_BRNOT_S : Int = 0x01C3 - final val CEE_NOCODE : Int = 0x01C4 - - final val CEE_count : Int = 0x0200 - - - //######################################################################## - // Opcode's amount and type of poped data - - final val POP_NONE : Byte = 0x00 - final val POP_1 : Byte = 0x01 - final val POP_1_1 : Byte = 0x02 - final val POP_I : Byte = 0x03 - final val POP_I_1 : Byte = 0x04 - final val POP_I_I : Byte = 0x05 - final val POP_I_I8 : Byte = 0x06 - final val POP_I_R4 : Byte = 0x07 - final val POP_I_R8 : Byte = 0x08 - final val POP_I_I_I : Byte = 0x09 - final val POP_REF : Byte = 0x0A - final val POP_REF_1 : Byte = 0x0B - final val POP_REF_I : Byte = 0x0C - final val POP_REF_I_I : Byte = 0x0D - final val POP_REF_I_I8 : Byte = 0x0E - final val POP_REF_I_R4 : Byte = 0x0F - final val POP_REF_I_R8 : Byte = 0x10 - final val POP_REF_I_REF : Byte = 0x11 - final val POP_SPECIAL : Byte = 0x12 - final val POP_count : Int = 0x13 - final val POP_size : Array[Byte] = new Array[Byte](POP_count) - - POP_size(POP_NONE) = 0 - POP_size(POP_1) = 1 - POP_size(POP_1_1) = 2 - POP_size(POP_I) = 1 - POP_size(POP_I_1) = 2 - POP_size(POP_I_I) = 2 - POP_size(POP_I_I8) = 2 - POP_size(POP_I_R4) = 2 - POP_size(POP_I_R8) = 2 - POP_size(POP_I_I_I) = 3 - POP_size(POP_REF) = 1 - POP_size(POP_REF_1) = 2 - POP_size(POP_REF_I) = 2 - POP_size(POP_REF_I_I) = 3 - POP_size(POP_REF_I_I8) = 3 - POP_size(POP_REF_I_R4) = 3 - POP_size(POP_REF_I_R8) = 3 - POP_size(POP_REF_I_REF) = 3 - POP_size(POP_SPECIAL) = -1 - - //######################################################################## - // Opcode's amount and type of pushed data - - final val PUSH_NONE : Byte = 0x00 - final val PUSH_1 : Byte = 0x01 - final val PUSH_1_1 : Byte = 0x02 - final val PUSH_I : Byte = 0x03 - final val PUSH_I8 : Byte = 0x04 - final val PUSH_R4 : Byte = 0x05 - final val PUSH_R8 : Byte = 0x06 - final val PUSH_REF : Byte = 0x07 - final val PUSH_SPECIAL : Byte = 0x08 - final val PUSH_count : Int = 0x09 - final val PUSH_size : Array[Byte] = new Array[Byte](PUSH_count) - - PUSH_size(PUSH_NONE) = 0 - PUSH_size(PUSH_1) = 1 - PUSH_size(PUSH_1_1) = 2 - PUSH_size(PUSH_I) = 1 - PUSH_size(PUSH_I8) = 1 - PUSH_size(PUSH_R4) = 1 - PUSH_size(PUSH_R8) = 1 - PUSH_size(PUSH_REF) = 1 - PUSH_size(PUSH_SPECIAL) = -1 - - //######################################################################## - // Opcode's amount of moved data - - final val POPUSH_SPECIAL : Byte = -128 - - //######################################################################## - // Opcode's inline argument types - - final val INLINE_NONE : Byte = 0x00 - final val INLINE_VARIABLE_S : Byte = 0x01 - final val INLINE_TARGET_S : Byte = 0x02 - final val INLINE_I_S : Byte = 0x03 - final val INLINE_VARIABLE : Byte = 0x04 - final val INLINE_TARGET : Byte = 0x05 - final val INLINE_I : Byte = 0x06 - final val INLINE_I8 : Byte = 0x07 - final val INLINE_R : Byte = 0x08 - final val INLINE_R8 : Byte = 0x09 - final val INLINE_STRING : Byte = 0x0A - final val INLINE_TYPE : Byte = 0x0B - final val INLINE_FIELD : Byte = 0x0C - final val INLINE_METHOD : Byte = 0x0D - final val INLINE_SIGNATURE : Byte = 0x0E - final val INLINE_TOKEN : Byte = 0x0F - final val INLINE_SWITCH : Byte = 0x10 - final val INLINE_count : Int = 0x11 - final val INLINE_length : Array[Byte] = new Array[Byte](INLINE_count) - - INLINE_length(INLINE_NONE) = 0 - INLINE_length(INLINE_VARIABLE_S) = 1 - INLINE_length(INLINE_TARGET_S) = 1 - INLINE_length(INLINE_I_S) = 1 - INLINE_length(INLINE_VARIABLE) = 2 - INLINE_length(INLINE_TARGET) = 4 - INLINE_length(INLINE_I) = 4 - INLINE_length(INLINE_I8) = 8 - INLINE_length(INLINE_R) = 4 - INLINE_length(INLINE_R8) = 8 - INLINE_length(INLINE_STRING) = 4 - INLINE_length(INLINE_TYPE) = 4 - INLINE_length(INLINE_FIELD) = 4 - INLINE_length(INLINE_METHOD) = 4 - INLINE_length(INLINE_SIGNATURE) = 4 - INLINE_length(INLINE_SWITCH) = 4 - INLINE_length(INLINE_TOKEN) = 4 - - //######################################################################## - // Opcode's control flow implications - - final val FLOW_META : Byte = 0x00 - final val FLOW_NEXT : Byte = 0x01 - final val FLOW_BRANCH : Byte = 0x02 - final val FLOW_COND_BRANCH : Byte = 0x03 - final val FLOW_BREAK : Byte = 0x04 - final val FLOW_CALL : Byte = 0x05 - final val FLOW_RETURN : Byte = 0x06 - final val FLOW_THROW : Byte = 0x07 - final val FLOW_count : Int = 0x08 - - //######################################################################## - // Init methods for Opcode - - def opcode(that: OpCode, opcode: Int, string: String, code: Int, - pop: Byte, push: Byte, inline: Byte, flow: Byte) { - that.CEE_opcode = opcode - that.CEE_string = string - that.CEE_code = code.toShort - that.CEE_pop = pop - that.CEE_push = push - that.CEE_inline = inline - that.CEE_flow = flow - that.CEE_length = that.length() - that.CEE_popush = that.popush() - } - - def length(code: Int): Byte = { - if ((code & 0xFFFFFF00) == 0xFFFFFF00) return 1 - if ((code & 0xFFFFFF00) == 0xFFFFFE00) return 2 - return 0 - } - - //######################################################################## - // case OpCode - - /** - * Adds two values and pushes the result onto the evaluation stack. - */ - final val Add = new OpCode() - opcode(Add, CEE_ADD, "add", 0xFFFFFF58, POP_1_1, PUSH_1, INLINE_NONE, FLOW_NEXT) - - /** - * Fills space if bytecodes are patched. No meaningful operation is performed - * although a processing cycle can be consumed. - */ - final val Nop = new OpCode() - opcode(Nop, CEE_NOP, "nop", 0xFFFFFF00, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * Signals the Common Language Infrastructure (CLI) to inform the debugger that - * a break point has been tripped. - */ - final val Break = new OpCode() - opcode(Break, CEE_BREAK, "break" , 0xFFFFFF01, POP_NONE, PUSH_NONE , INLINE_NONE , FLOW_BREAK) - - /** - * Loads the argument at index 0 onto the evaluation stack. - */ - final val Ldarg_0 = new OpCode() - opcode(Ldarg_0, CEE_LDARG_0 , "ldarg.0" , 0xFFFFFF02, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Loads the argument at index 1 onto the evaluation stack. - */ - final val Ldarg_1 = new OpCode() - opcode(Ldarg_1, CEE_LDARG_1 , "ldarg.1" , 0xFFFFFF03, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Loads the argument at index 2 onto the evaluation stack. - */ - final val Ldarg_2 = new OpCode() - opcode(Ldarg_2, CEE_LDARG_2 , "ldarg.2" , 0xFFFFFF04, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Loads the argument at index 3 onto the evaluation stack. - */ - final val Ldarg_3 = new OpCode() - opcode(Ldarg_3, CEE_LDARG_3 , "ldarg.3" , 0xFFFFFF05, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Loads the local variable at index 0 onto the evaluation stack. - */ - final val Ldloc_0 = new OpCode() - opcode(Ldloc_0, CEE_LDLOC_0 , "ldloc.0" , 0xFFFFFF06, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Loads the local variable at index 1 onto the evaluation stack. - */ - final val Ldloc_1 = new OpCode() - opcode(Ldloc_1, CEE_LDLOC_1 , "ldloc.1" , 0xFFFFFF07, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Loads the local variable at index 2 onto the evaluation stack. - */ - final val Ldloc_2 = new OpCode() - opcode(Ldloc_2, CEE_LDLOC_2 , "ldloc.2" , 0xFFFFFF08, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Loads the local variable at index 3 onto the evaluation stack. - */ - final val Ldloc_3 = new OpCode() - opcode(Ldloc_3, CEE_LDLOC_3 , "ldloc.3" , 0xFFFFFF09, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 0. - */ - final val Stloc_0 = new OpCode() - opcode(Stloc_0, CEE_STLOC_0 , "stloc.0" , 0xFFFFFF0A, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 1. - */ - final val Stloc_1 = new OpCode() - opcode(Stloc_1, CEE_STLOC_1 , "stloc.1" , 0xFFFFFF0B, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 2. - */ - final val Stloc_2 = new OpCode() - opcode(Stloc_2, CEE_STLOC_2 , "stloc.2" , 0xFFFFFF0C, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 3. - */ - final val Stloc_3 = new OpCode() - opcode(Stloc_3, CEE_STLOC_3 , "stloc.3" , 0xFFFFFF0D, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the argument (referenced by a specified short form index) - * onto the evaluation stack. - */ - final val Ldarg_S = new OpCode() - opcode(Ldarg_S, CEE_LDARG_S , "ldarg.s" , 0xFFFFFF0E, POP_NONE, PUSH_1 , INLINE_VARIABLE_S, FLOW_NEXT) - - /** - * Load an argument address, in short form, onto the evaluation stack. - */ - final val Ldarga_S = new OpCode() - opcode(Ldarga_S, CEE_LDARGA_S , "ldarga.s" , 0xFFFFFF0F, POP_NONE, PUSH_I , INLINE_VARIABLE_S, FLOW_NEXT) - - /** - * Loads the local variable at a specific index onto the evaluation stack, - * short form. - */ - final val Ldloc_S = new OpCode() - opcode(Ldloc_S, CEE_LDLOC_S , "ldloc.s" , 0xFFFFFF11, POP_NONE, PUSH_1 , INLINE_VARIABLE_S, FLOW_NEXT) - - /** - * Loads the address of the local variable at a specific index onto - * the evaluation stack, short form. - */ - final val Ldloca_S = new OpCode() - opcode(Ldloca_S, CEE_LDLOCA_S , "ldloca.s" , 0xFFFFFF12, POP_NONE, PUSH_I , INLINE_VARIABLE_S, FLOW_NEXT) - - /** - * Stores the value on top of the evaluation stack in the argument slot - * at a specified index, short form. - */ - final val Starg_S = new OpCode() - opcode(Starg_S, CEE_STARG_S , "starg.s" , 0xFFFFFF10, POP_1 , PUSH_NONE , INLINE_VARIABLE_S, FLOW_NEXT) - - /** - * Pops the current value from the top of the evaluation stack and stores it - * in a the local variable list at index (short form). - */ - final val Stloc_S = new OpCode() - opcode(Stloc_S, CEE_STLOC_S , "stloc.s" , 0xFFFFFF13, POP_1 , PUSH_NONE, INLINE_VARIABLE_S, FLOW_NEXT) - - /** - * Pushes a null reference (type O) onto the evaluation stack. - */ - final val Ldnull = new OpCode() - opcode(Ldnull, CEE_LDNULL , "ldnull" , 0xFFFFFF14, POP_NONE, PUSH_REF , INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of -1 onto the evaluation stack as an int32. - */ - final val Ldc_I4_M1 = new OpCode() - opcode(Ldc_I4_M1, CEE_LDC_I4_M1, "ldc.i4.m1", 0xFFFFFF15, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 0 onto the evaluation stack as an int32. - */ - final val Ldc_I4_0 = new OpCode() - opcode(Ldc_I4_0, CEE_LDC_I4_0 , "ldc.i4.0" , 0xFFFFFF16, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 1 onto the evaluation stack as an int32. - */ - final val Ldc_I4_1 = new OpCode() - opcode(Ldc_I4_1, CEE_LDC_I4_1 , "ldc.i4.1" , 0xFFFFFF17, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 2 onto the evaluation stack as an int32. - */ - final val Ldc_I4_2 = new OpCode() - opcode(Ldc_I4_2, CEE_LDC_I4_2 , "ldc.i4.2" , 0xFFFFFF18, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 3 onto the evaluation stack as an int32. - */ - final val Ldc_I4_3 = new OpCode() - opcode(Ldc_I4_3, CEE_LDC_I4_3 , "ldc.i4.3" , 0xFFFFFF19, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 4 onto the evaluation stack as an int32. - */ - final val Ldc_I4_4 = new OpCode() - opcode(Ldc_I4_4, CEE_LDC_I4_4 , "ldc.i4.4" , 0xFFFFFF1A, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 5 onto the evaluation stack as an int32. - */ - final val Ldc_I4_5 = new OpCode() - opcode(Ldc_I4_5, CEE_LDC_I4_5 , "ldc.i4.5" , 0xFFFFFF1B, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 6 onto the evaluation stack as an int32. - */ - final val Ldc_I4_6 = new OpCode() - opcode(Ldc_I4_6, CEE_LDC_I4_6 , "ldc.i4.6", 0xFFFFFF1C, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 7 onto the evaluation stack as an int32. - */ - final val Ldc_I4_7 = new OpCode() - opcode(Ldc_I4_7, CEE_LDC_I4_7 , "ldc.i4.7", 0xFFFFFF1D, POP_NONE , PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the integer value of 8 onto the evaluation stack as an int32. - */ - final val Ldc_I4_8 = new OpCode() - opcode(Ldc_I4_8, CEE_LDC_I4_8 , "ldc.i4.8", 0xFFFFFF1E, POP_NONE , PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Pushes the supplied int8 value onto the evaluation stack as an int32, short form. - */ - final val Ldc_I4_S = new OpCode() - opcode(Ldc_I4_S, CEE_LDC_I4_S , "ldc.i4.s", 0xFFFFFF1F, POP_NONE , PUSH_I, INLINE_I_S, FLOW_NEXT) - - /** - * Pushes a supplied value of type int32 onto the evaluation stack as an int32. - */ - final val Ldc_I4 = new OpCode() - opcode(Ldc_I4, CEE_LDC_I4, "ldc.i4" , 0xFFFFFF20, POP_NONE , PUSH_I, INLINE_I , FLOW_NEXT) - - /** - * Pushes a supplied value of type int64 onto the evaluation stack as an int64. - */ - final val Ldc_I8 = new OpCode() - opcode(Ldc_I8, CEE_LDC_I8, "ldc.i8" , 0xFFFFFF21, POP_NONE , PUSH_I8, INLINE_I8 , FLOW_NEXT) - - /** - * Pushes a supplied value of type float32 onto the evaluation stack as type F (float). - */ - final val Ldc_R4 = new OpCode() - opcode(Ldc_R4, CEE_LDC_R4, "ldc.r4" , 0xFFFFFF22, POP_NONE , PUSH_R4, INLINE_R , FLOW_NEXT) - - /** - * Pushes a supplied value of type float64 onto the evaluation stack as type F (float). - */ - final val Ldc_R8 = new OpCode() - opcode(Ldc_R8, CEE_LDC_R8, "ldc.r8" , 0xFFFFFF23, POP_NONE , PUSH_R8, INLINE_R8 , FLOW_NEXT) - - /** - * Copies the current topmost value on the evaluation stack, and then pushes the copy - * onto the evaluation stack. - */ - final val Dup = new OpCode() - opcode(Dup, CEE_DUP , "dup" , 0xFFFFFF25, POP_1 , PUSH_1_1 , INLINE_NONE , FLOW_NEXT) - - /** - * Removes the value currently on top of the evaluation stack. - */ - final val Pop = new OpCode() - opcode(Pop, CEE_POP , "pop" , 0xFFFFFF26, POP_1 , PUSH_NONE , INLINE_NONE , FLOW_NEXT) - - /** - * Exits current method and jumps to specified method. - */ - final val Jmp = new OpCode() - opcode(Jmp, CEE_JMP , "jmp" , 0xFFFFFF27, POP_NONE , PUSH_NONE , INLINE_METHOD, FLOW_CALL) - - /** - * Calls the method indicated by the passed method descriptor. - */ - final val Call = new OpCode() - opcode(Call, CEE_CALL , "call" , 0xFFFFFF28, POP_SPECIAL, PUSH_SPECIAL, INLINE_METHOD , FLOW_CALL) - - /** - * constrained prefix - */ - final val Constrained = new OpCode() -opcode(Constrained, CEE_CONSTRAINED , "constrained." , 0xFFFFFE16, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * readonly prefix - */ - final val Readonly = new OpCode() -opcode(Readonly, CEE_READONLY , "readonly." , 0xFFFFFE1E, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * Calls the method indicated on the evaluation stack (as a pointer to an entry point) - * with arguments described by a calling convention. - */ - final val Calli = new OpCode() - opcode(Calli, CEE_CALLI, "calli" , 0xFFFFFF29, POP_SPECIAL, PUSH_SPECIAL, INLINE_SIGNATURE , FLOW_CALL) - - /** - * Returns from the current method, pushing a return value (if present) from the caller's - * evaluation stack onto the callee's evaluation stack. - */ - final val Ret = new OpCode() - opcode(Ret, CEE_RET , "ret" , 0xFFFFFF2A, POP_SPECIAL, PUSH_NONE, INLINE_NONE , FLOW_RETURN) - - /** - * Unconditionally transfers control to a target instruction (short form). - */ - final val Br_S = new OpCode() - opcode(Br_S, CEE_BR_S , "br.s" , 0xFFFFFF2B, POP_NONE, PUSH_NONE, INLINE_TARGET_S , FLOW_BRANCH) - - /** - * Transfers control to a target instruction if value is false, a null reference, or zero. - */ - final val Brfalse_S = new OpCode() - opcode(Brfalse_S, CEE_BRFALSE_S,"brfalse.s", 0xFFFFFF2C, POP_I, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if value is true, not null, or non-zero. - */ - final val Brtrue_S = new OpCode() - opcode(Brtrue_S, CEE_BRTRUE_S , "brtrue.s", 0xFFFFFF2D, POP_I, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if two values are equal. - */ - final val Beq_S = new OpCode() - opcode(Beq_S, CEE_BEQ_S, "beq.s", 0xFFFFFF2E, POP_1_1 , PUSH_NONE, INLINE_TARGET_S , FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is greater than - * or equal to the second value. - */ - final val Bge_S = new OpCode() - opcode(Bge_S, CEE_BGE_S, "bge.s", 0xFFFFFF2F, POP_1_1 , PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is greater than - * the second value. - */ - final val Bgt_S = new OpCode() - opcode(Bgt_S, CEE_BGT_S, "bgt.s" , 0xFFFFFF30, POP_1_1 , PUSH_NONE, INLINE_TARGET_S , FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * or equal to the second value. - */ - final val Ble_S = new OpCode() - opcode(Ble_S, CEE_BLE_S, "ble.s" , 0xFFFFFF31, POP_1_1 , PUSH_NONE, INLINE_TARGET_S , FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * the second value. - */ - final val Blt_S = new OpCode() - opcode(Blt_S, CEE_BLT_S, "blt.s", 0xFFFFFF32, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) when two unsigned integer values - * or unordered float values are not equal. - */ - final val Bne_Un_S = new OpCode() - opcode(Bne_Un_S, CEE_BNE_UN_S, "bne.un.s", 0xFFFFFF33, POP_1_1 , PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is greather - * than the second value, when comparing unsigned integer values or unordered float values. - */ - final val Bge_Un_S = new OpCode() - opcode(Bge_Un_S, CEE_BGE_UN_S, "bge.un.s", 0xFFFFFF34, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is greater than - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Bgt_Un_S = new OpCode() - opcode(Bgt_Un_S, CEE_BGT_UN_S, "bgt.un.s", 0xFFFFFF35, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * or equal to the second value, when comparing unsigned integer values or unordered float values. - */ - final val Ble_Un_S = new OpCode() - opcode(Ble_Un_S, CEE_BLE_UN_S , "ble.un.s", 0xFFFFFF36, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Blt_Un_S = new OpCode() - opcode(Blt_Un_S, CEE_BLT_UN_S, "blt.un.s", 0xFFFFFF37, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH) - - /** - * Unconditionally transfers control to a target instruction. - */ - final val Br = new OpCode() - opcode(Br, CEE_BR , "br" , 0xFFFFFF38, POP_NONE, PUSH_NONE, INLINE_TARGET, FLOW_BRANCH) - - /** - * Transfers control to a target instruction if value is false, a null reference - * (Nothing in Visual Basic), or zero. - */ - final val Brfalse = new OpCode() - opcode(Brfalse, CEE_BRFALSE, "brfalse", 0xFFFFFF39, POP_I, PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if value is true, not null, or non-zero. - */ - final val Brtrue = new OpCode() - opcode(Brtrue, CEE_BRTRUE , "brtrue", 0xFFFFFF3A, POP_I , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if two values are equal. - */ - final val Beq = new OpCode() - opcode(Beq, CEE_BEQ, "beq", 0xFFFFFF3B, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is greater than or - * equal to the second value. - */ - final val Bge = new OpCode() - opcode(Bge, CEE_BGE, "bge", 0xFFFFFF3C, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is greater than the second value. - */ - final val Bgt = new OpCode() - opcode(Bgt, CEE_BGT, "bgt", 0xFFFFFF3D, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is less than or equal - * to the second value. - */ - final val Ble = new OpCode() - opcode(Ble, CEE_BLE, "ble", 0xFFFFFF3E, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is less than the second value. - */ - final val Blt = new OpCode() - opcode(Blt, CEE_BLT, "blt", 0xFFFFFF3F, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction when two unsigned integer values or - * unordered float values are not equal. - */ - final val Bne_Un = new OpCode() - opcode(Bne_Un, CEE_BNE_UN , "bne.un", 0xFFFFFF40, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is greather than - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Bge_Un = new OpCode() - opcode(Bge_Un, CEE_BGE_UN , "bge.un", 0xFFFFFF41, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is greater than the - * second value, when comparing unsigned integer values or unordered float values. - */ - final val Bgt_Un = new OpCode() - opcode(Bgt_Un, CEE_BGT_UN , "bgt.un", 0xFFFFFF42, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is less than or equal to - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Ble_Un = new OpCode() - opcode(Ble_Un, CEE_BLE_UN , "ble.un" , 0xFFFFFF43, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Transfers control to a target instruction if the first value is less than the second value, - * when comparing unsigned integer values or unordered float values. - */ - final val Blt_Un = new OpCode() - opcode(Blt_Un, CEE_BLT_UN , "blt.un", 0xFFFFFF44, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH) - - /** - * Implements a jump table. - */ - final val Switch = new OpCode() - opcode(Switch, CEE_SWITCH , "switch", 0xFFFFFF45, POP_I , PUSH_NONE, INLINE_SWITCH, FLOW_COND_BRANCH) - - /** - * Loads a value of type int8 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_I1 = new OpCode() - opcode(Ldind_I1, CEE_LDIND_I1 , "ldind.i1" , 0xFFFFFF46, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type int16 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_I2 = new OpCode() - opcode(Ldind_I2, CEE_LDIND_I2 , "ldind.i2" , 0xFFFFFF48, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type int32 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_I4 = new OpCode() - opcode(Ldind_I4, CEE_LDIND_I4 , "ldind.i4" , 0xFFFFFF4A, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type int64 as an int64 onto the evaluation stack indirectly. - */ - final val Ldind_I8 = new OpCode() - opcode(Ldind_I8, CEE_LDIND_I8 , "ldind.i8" , 0xFFFFFF4C, POP_I , PUSH_I8 , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type natural int as a natural int onto the evaluation stack indirectly. - */ - final val Ldind_I = new OpCode() - opcode(Ldind_I, CEE_LDIND_I , "ldind.i" , 0xFFFFFF4D, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type float32 as a type F (float) onto the evaluation stack indirectly. - */ - final val Ldind_R4 = new OpCode() - opcode(Ldind_R4, CEE_LDIND_R4 , "ldind.r4" , 0xFFFFFF4E, POP_I , PUSH_R4 , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type float64 as a type F (float) onto the evaluation stack indirectly. - */ - final val Ldind_R8 = new OpCode() - opcode(Ldind_R8, CEE_LDIND_R8 , "ldind.r8" , 0xFFFFFF4F, POP_I , PUSH_R8 , INLINE_NONE, FLOW_NEXT) - - /** - * Loads an object reference as a type O (object reference) onto the evaluation stack indirectly. - */ - final val Ldind_Ref = new OpCode() - opcode(Ldind_Ref, CEE_LDIND_REF, "ldind.ref", 0xFFFFFF50, POP_I , PUSH_REF, INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type unsigned int8 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_U1 = new OpCode() - opcode(Ldind_U1, CEE_LDIND_U1 , "ldind.u1" , 0xFFFFFF47, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type unsigned int16 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_U2 = new OpCode() - opcode(Ldind_U2, CEE_LDIND_U2 , "ldind.u2" , 0xFFFFFF49, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Loads a value of type unsigned int32 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_U4 = new OpCode() - opcode(Ldind_U4, CEE_LDIND_U4 , "ldind.u4" , 0xFFFFFF4B, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Stores a object reference value at a supplied address. - */ - final val Stind_Ref = new OpCode() - opcode(Stind_Ref, CEE_STIND_REF, "stind.ref", 0xFFFFFF51, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Stores a value of type int8 at a supplied address. - */ - final val Stind_I1 = new OpCode() - opcode(Stind_I1, CEE_STIND_I1 , "stind.i1", 0xFFFFFF52, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Stores a value of type int16 at a supplied address. - */ - final val Stind_I2 = new OpCode() - opcode(Stind_I2, CEE_STIND_I2 , "stind.i2", 0xFFFFFF53, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Stores a value of type int32 at a supplied address. - */ - final val Stind_I4 = new OpCode() - opcode(Stind_I4, CEE_STIND_I4 , "stind.i4", 0xFFFFFF54, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Stores a value of type int64 at a supplied address. - */ - final val Stind_I8 = new OpCode() - opcode(Stind_I8, CEE_STIND_I8 , "stind.i8", 0xFFFFFF55, POP_I_I8, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Stores a value of type float32 at a supplied address. - */ - final val Stind_R4 = new OpCode() - opcode(Stind_R4, CEE_STIND_R4 , "stind.r4", 0xFFFFFF56, POP_I_R4, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Stores a value of type float64 at a supplied address. - */ - final val Stind_R8 = new OpCode() - opcode(Stind_R8, CEE_STIND_R8 , "stind.r8", 0xFFFFFF57, POP_I_R8, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Subtracts one value from another and pushes the result onto the evaluation stack. - */ - final val Sub = new OpCode() - opcode(Sub, CEE_SUB, "sub" , 0xFFFFFF59, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Multiplies two values and pushes the result on the evaluation stack. - */ - final val Mul = new OpCode() - opcode(Mul, CEE_MUL, "mul" , 0xFFFFFF5A, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Divides two values and pushes the result as a floating-point (type F) or - * quotient (type int32) onto the evaluation stack. - */ - final val Div = new OpCode() - opcode(Div, CEE_DIV, "div" , 0xFFFFFF5B, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Divides two unsigned integer values and pushes the result (int32) onto the evaluation stack. - */ - final val Div_Un = new OpCode() - opcode(Div_Un, CEE_DIV_UN, "div.un" , 0xFFFFFF5C, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Divides two values and pushes the remainder onto the evaluation stack. - */ - final val Rem = new OpCode() - opcode(Rem, CEE_REM , "rem" , 0xFFFFFF5D, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Divides two unsigned values and pushes the remainder onto the evaluation stack. - */ - final val Rem_Un = new OpCode() - opcode(Rem_Un, CEE_REM_UN, "rem.un" , 0xFFFFFF5E, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Computes the bitwise AND of two values and pushes the result onto the evaluation stack. - */ - final val And = new OpCode() - opcode(And, CEE_AND, "and" , 0xFFFFFF5F, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Compute the bitwise complement of the two integer values on top of the stack and - * pushes the result onto the evaluation stack. - */ - final val Or = new OpCode() - opcode(Or, CEE_OR , "or" , 0xFFFFFF60, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Computes the bitwise XOR of the top two values on the evaluation stack, - * pushing the result onto the evaluation stack. - */ - final val Xor = new OpCode() - opcode(Xor, CEE_XOR, "xor" , 0xFFFFFF61, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Shifts an integer value to the left (in zeroes) by a specified number of bits, - * pushing the result onto the evaluation stack. - */ - final val Shl = new OpCode() - opcode(Shl, CEE_SHL, "shl" , 0xFFFFFF62, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Shifts an integer value (in sign) to the right by a specified number of bits, - * pushing the result onto the evaluation stack. - */ - final val Shr = new OpCode() - opcode(Shr, CEE_SHR, "shr" , 0xFFFFFF63, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Shifts an unsigned integer value (in zeroes) to the right by a specified number of bits, - * pushing the result onto the evaluation stack. - */ - final val Shr_Un = new OpCode() - opcode(Shr_Un, CEE_SHR_UN, "shr.un" , 0xFFFFFF64, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Negates a value and pushes the result onto the evaluation stack. - */ - final val Neg = new OpCode() - opcode(Neg, CEE_NEG , "neg" , 0xFFFFFF65, POP_1 , PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Computes the bitwise complement of the integer value on top of the stack and pushes - * the result onto the evaluation stack as the same type. - */ - final val Not = new OpCode() - opcode(Not, CEE_NOT , "not" , 0xFFFFFF66, POP_1 , PUSH_1 , INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to int8, then extends (pads) it to int32. - */ - final val Conv_I1 = new OpCode() - opcode(Conv_I1, CEE_CONV_I1, "conv.i1", 0xFFFFFF67, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to int16, then extends (pads) it to int32. - */ - final val Conv_I2 = new OpCode() - opcode(Conv_I2, CEE_CONV_I2, "conv.i2", 0xFFFFFF68, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to int32. - */ - final val Conv_I4 = new OpCode() - opcode(Conv_I4, CEE_CONV_I4, "conv.i4", 0xFFFFFF69, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to int64. - */ - final val Conv_I8 = new OpCode() - opcode(Conv_I8, CEE_CONV_I8, "conv.i8", 0xFFFFFF6A, POP_1 , PUSH_I8, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to float32. - */ - final val Conv_R4 = new OpCode() - opcode(Conv_R4, CEE_CONV_R4, "conv.r4", 0xFFFFFF6B, POP_1 , PUSH_R4, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to float64. - */ - final val Conv_R8 = new OpCode() - opcode(Conv_R8, CEE_CONV_R8, "conv.r8", 0xFFFFFF6C, POP_1 , PUSH_R8, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to unsigned int32, and extends it to int32. - */ - final val Conv_U4 = new OpCode() - opcode(Conv_U4, CEE_CONV_U4, "conv.u4", 0xFFFFFF6D, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to unsigned int64, and extends it to int64. - */ - final val Conv_U8 = new OpCode() - opcode(Conv_U8, CEE_CONV_U8, "conv.u8", 0xFFFFFF6E, POP_1 , PUSH_I8, INLINE_NONE, FLOW_NEXT) - - /** - * Calls a late-bound method on an object, pushing the return value onto the evaluation stack. - */ - final val Callvirt = new OpCode() - opcode(Callvirt, CEE_CALLVIRT, "callvirt", 0xFFFFFF6F,POP_SPECIAL,PUSH_SPECIAL,INLINE_METHOD,FLOW_CALL) - - /** - * Copies the value type located at the address of an object (type &, * or natural int) - * to the address of the destination object (type &, * or natural int). - */ - final val Cpobj = new OpCode() - opcode(Cpobj, CEE_CPOBJ , "cpobj" , 0xFFFFFF70, POP_I_I , PUSH_NONE, INLINE_TYPE , FLOW_NEXT) - - /** - * Copies the value type object pointed to by an address to the top of the evaluation stack. - */ - final val Ldobj = new OpCode() - opcode(Ldobj, CEE_LDOBJ , "ldobj" , 0xFFFFFF71, POP_I , PUSH_1 , INLINE_TYPE , FLOW_NEXT) - - /** - * Pushes a new object reference to a string literal stored in the metadata. - */ - final val Ldstr = new OpCode() - opcode(Ldstr, CEE_LDSTR , "ldstr" , 0xFFFFFF72, POP_NONE , PUSH_REF , INLINE_STRING, FLOW_NEXT) - - /** - * Creates a new object or a new instance of a value type, pushing an object reference - * (type O) onto the evaluation stack. - */ - final val Newobj = new OpCode() - opcode(Newobj, CEE_NEWOBJ, "newobj", 0xFFFFFF73, POP_SPECIAL , PUSH_REF , INLINE_METHOD, FLOW_CALL) - - /** - * Attempts to cast an object passed by reference to the specified class. - */ - final val Castclass = new OpCode() - opcode(Castclass, CEE_CASTCLASS, "castclass", 0xFFFFFF74, POP_REF , PUSH_REF , INLINE_TYPE , FLOW_NEXT) - - /** - * Tests whether an object reference (type O) is an instance of a particular class. - */ - final val Isinst = new OpCode() - opcode(Isinst, CEE_ISINST , "isinst" , 0xFFFFFF75, POP_REF , PUSH_I , INLINE_TYPE , FLOW_NEXT) - - /** - * Converts the unsigned integer value on top of the evaluation stack to float32. - */ - final val Conv_R_Un = new OpCode() - opcode(Conv_R_Un, CEE_CONV_R_UN, "conv.r.un", 0xFFFFFF76, POP_1 , PUSH_R8 , INLINE_NONE , FLOW_NEXT) - - /** - * Converts the boxed representation of a value type to its unboxed form. - */ - final val Unbox = new OpCode() - opcode(Unbox, CEE_UNBOX , "unbox" , 0xFFFFFF79, POP_REF , PUSH_I , INLINE_TYPE , FLOW_NEXT) - - /** - * Throws the exception object currently on the evaluation stack. - */ - final val Throw = new OpCode() - opcode(Throw, CEE_THROW , "throw" , 0xFFFFFF7A, POP_REF , PUSH_NONE, INLINE_NONE , FLOW_THROW) - - /** - * Finds the value of a field in the object whose reference is currently - * on the evaluation stack. - */ - final val Ldfld = new OpCode() - opcode(Ldfld, CEE_LDFLD , "ldfld" , 0xFFFFFF7B, POP_REF , PUSH_1 , INLINE_FIELD , FLOW_NEXT) - - /** - * Finds the address of a field in the object whose reference is currently - * on the evaluation stack. - */ - final val Ldflda = new OpCode() - opcode(Ldflda, CEE_LDFLDA , "ldflda" , 0xFFFFFF7C, POP_REF , PUSH_I , INLINE_FIELD , FLOW_NEXT) - - /** - * Pushes the value of a static field onto the evaluation stack. - */ - final val Ldsfld = new OpCode() - opcode(Ldsfld, CEE_LDSFLD , "ldsfld" , 0xFFFFFF7E, POP_NONE , PUSH_1 , INLINE_FIELD , FLOW_NEXT) - - /** - * Pushes the address of a static field onto the evaluation stack. - */ - final val Ldsflda = new OpCode() - opcode(Ldsflda, CEE_LDSFLDA, "ldsflda", 0xFFFFFF7F, POP_NONE , PUSH_I , INLINE_FIELD , FLOW_NEXT) - - /** - * Replaces the value stored in the field of an object reference or pointer with a new value. - */ - final val Stfld = new OpCode() - opcode(Stfld, CEE_STFLD , "stfld" , 0xFFFFFF7D, POP_REF_1, PUSH_NONE, INLINE_FIELD , FLOW_NEXT) - - /** - * Replaces the value of a static field with a value from the evaluation stack. - */ - final val Stsfld = new OpCode() - opcode(Stsfld, CEE_STSFLD , "stsfld" , 0xFFFFFF80, POP_1 , PUSH_NONE, INLINE_FIELD , FLOW_NEXT) - - /** - * Copies a value of a specified type from the evaluation stack into a supplied memory address. - */ - final val Stobj = new OpCode() - opcode(Stobj, CEE_STOBJ , "stobj" , 0xFFFFFF81, POP_I_1, PUSH_NONE, INLINE_TYPE , FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to signed int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I1_Un = new OpCode() - opcode(Conv_Ovf_I1_Un, CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", 0xFFFFFF82, POP_1,PUSH_I,INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to signed int16 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I2_Un = new OpCode() - opcode(Conv_Ovf_I2_Un, CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", 0xFFFFFF83,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to signed int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I4_Un = new OpCode() - opcode(Conv_Ovf_I4_Un, CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", 0xFFFFFF84,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to signed int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I8_Un = new OpCode() - opcode(Conv_Ovf_I8_Un, CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", 0xFFFFFF85,POP_1,PUSH_I8, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to signed natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I_Un = new OpCode() - opcode(Conv_Ovf_I_Un, CEE_CONV_OVF_I_UN , "conv.ovf.i.un" , 0xFFFFFF8A,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U1_Un = new OpCode() - opcode(Conv_Ovf_U1_Un, CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", 0xFFFFFF86,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int16 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U2_Un = new OpCode() - opcode(Conv_Ovf_U2_Un, CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", 0xFFFFFF87,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U4_Un = new OpCode() - opcode(Conv_Ovf_U4_Un, CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", 0xFFFFFF88,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U8_Un = new OpCode() - opcode(Conv_Ovf_U8_Un, CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", 0xFFFFFF89,POP_1,PUSH_I8, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U_Un = new OpCode() - opcode(Conv_Ovf_U_Un, CEE_CONV_OVF_U_UN , "conv.ovf.u.un" , 0xFFFFFF8B,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Converts a value type to an object reference (type O). - */ - final val Box = new OpCode() - opcode(Box, CEE_BOX , "box" , 0xFFFFFF8C, POP_1 , PUSH_REF , INLINE_TYPE , FLOW_NEXT) - - /** - * Pushes an object reference to a new zero-based, one-dimensional array whose elements - * are of a specific type onto the evaluation stack. - */ - final val Newarr = new OpCode() - opcode(Newarr, CEE_NEWARR, "newarr" , 0xFFFFFF8D, POP_I , PUSH_REF , INLINE_TYPE , FLOW_NEXT) - - /** - * Pushes the number of elements of a zero-based, one-dimensional array - * onto the evaluation stack. - */ - final val Ldlen = new OpCode() - opcode(Ldlen, CEE_LDLEN, "ldlen", 0xFFFFFF8E, POP_REF, PUSH_I,INLINE_NONE , FLOW_NEXT) - - /** - * Loads the address of the array element at a specified array index onto - * the top of the evaluation stack as type & (managed pointer). - */ - final val Ldelema = new OpCode() - opcode(Ldelema, CEE_LDELEMA, "ldelema" , 0xFFFFFF8F, POP_REF_I, PUSH_I, INLINE_TYPE , FLOW_NEXT) - - /** - * Loads the element with type natural int at a specified array index onto the top - * of the evaluation stack as a natural int. - */ - final val Ldelem_I = new OpCode() - opcode(Ldelem_I, CEE_LDELEM_I, "ldelem.i" , 0xFFFFFF97, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type int8 at a specified array index onto the top of the - * evaluation stack as an int32. - */ - final val Ldelem_I1 = new OpCode() - opcode(Ldelem_I1, CEE_LDELEM_I1, "ldelem.i1" , 0xFFFFFF90, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type int16 at a specified array index onto the top of - * the evaluation stack as an int32. - */ - final val Ldelem_I2 = new OpCode() - opcode(Ldelem_I2, CEE_LDELEM_I2, "ldelem.i2" , 0xFFFFFF92, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type int32 at a specified array index onto the top of the - * evaluation stack as an int32. - */ - final val Ldelem_I4 = new OpCode() - opcode(Ldelem_I4, CEE_LDELEM_I4, "ldelem.i4" , 0xFFFFFF94, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type int64 at a specified array index onto the top of the - * evaluation stack as an int64. - */ - final val Ldelem_I8 = new OpCode() - opcode(Ldelem_I8, CEE_LDELEM_I8, "ldelem.i8" , 0xFFFFFF96, POP_REF_I, PUSH_I8, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type float32 at a specified array index onto the top of the - * evaluation stack as type F (float) - */ - final val Ldelem_R4 = new OpCode() - opcode(Ldelem_R4, CEE_LDELEM_R4, "ldelem.r4" , 0xFFFFFF98, POP_REF_I, PUSH_R4, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type float64 at a specified array index onto the top of the - * evaluation stack as type F (float) . - */ - final val Ldelem_R8 = new OpCode() - opcode(Ldelem_R8, CEE_LDELEM_R8, "ldelem.r8" , 0xFFFFFF99, POP_REF_I, PUSH_R8, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element containing an object reference at a specified array index onto - * the top of the evaluation stack as type O (object reference). - */ - final val Ldelem_Ref = new OpCode() - opcode(Ldelem_Ref, CEE_LDELEM_REF, "ldelem.ref", 0xFFFFFF9A, POP_REF_I, PUSH_REF, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type unsigned int8 at a specified array index onto the top - * of the evaluation stack as an int32. - */ - final val Ldelem_U1 = new OpCode() - opcode(Ldelem_U1, CEE_LDELEM_U1, "ldelem.u1" , 0xFFFFFF91, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type unsigned int16 at a specified array index onto the top - * of the evaluation stack as an int32. - */ - final val Ldelem_U2 = new OpCode() - opcode(Ldelem_U2, CEE_LDELEM_U2, "ldelem.u2" , 0xFFFFFF93, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Loads the element with type unsigned int32 at a specified array index onto the top - * of the evaluation stack as an int32. - */ - final val Ldelem_U4 = new OpCode() - opcode(Ldelem_U4, CEE_LDELEM_U4, "ldelem.u4" , 0xFFFFFF95, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Replaces the array element at a given index with the natural int value on - * the evaluation stack. - */ - final val Stelem_I = new OpCode() - opcode(Stelem_I, CEE_STELEM_I, "stelem.i", 0xFFFFFF9B, POP_REF_I_I, PUSH_NONE, INLINE_NONE , FLOW_NEXT) - - /** - * Replaces the array element at a given index with the int8 value on the evaluation stack. - */ - final val Stelem_I1 = new OpCode() - opcode(Stelem_I1, CEE_STELEM_I1, "stelem.i1", 0xFFFFFF9C, POP_REF_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Replaces the array element at a given index with the int16 value on the evaluation stack. - */ - final val Stelem_I2 = new OpCode() - opcode(Stelem_I2, CEE_STELEM_I2, "stelem.i2", 0xFFFFFF9D, POP_REF_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Replaces the array element at a given index with the int32 value on the evaluation stack. - */ - final val Stelem_I4 = new OpCode() - opcode(Stelem_I4, CEE_STELEM_I4, "stelem.i4", 0xFFFFFF9E, POP_REF_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Replaces the array element at a given index with the int64 value on the evaluation stack. - */ - final val Stelem_I8 = new OpCode() - opcode(Stelem_I8, CEE_STELEM_I8,"stelem.i8", 0xFFFFFF9F, POP_REF_I_I8, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Replaces the array element at a given index with the float32 value on the evaluation stack. - */ - final val Stelem_R4 = new OpCode() - opcode(Stelem_R4, CEE_STELEM_R4,"stelem.r4", 0xFFFFFFA0, POP_REF_I_R4, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Replaces the array element at a given index with the float64 value on the evaluation stack. - */ - final val Stelem_R8 = new OpCode() - opcode(Stelem_R8, CEE_STELEM_R8,"stelem.r8", 0xFFFFFFA1, POP_REF_I_R8, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Replaces the array element at a given index with the object ref value (type O) - * on the evaluation stack. - */ - final val Stelem_Ref = new OpCode() - opcode(Stelem_Ref, CEE_STELEM_REF,"stelem.ref",0xFFFFFFA2,POP_REF_I_REF,PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to signed int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I1 = new OpCode() - opcode(Conv_Ovf_I1, CEE_CONV_OVF_I1, "conv.ovf.i1", 0xFFFFFFB3, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to signed int16 and - * extending it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I2 = new OpCode() - opcode(Conv_Ovf_I2, CEE_CONV_OVF_I2, "conv.ovf.i2", 0xFFFFFFB5, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to signed int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I4 = new OpCode() - opcode(Conv_Ovf_I4, CEE_CONV_OVF_I4, "conv.ovf.i4", 0xFFFFFFB7, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to signed int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I8 = new OpCode() - opcode(Conv_Ovf_I8, CEE_CONV_OVF_I8, "conv.ovf.i8", 0xFFFFFFB9, POP_1, PUSH_I8, INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to unsigned int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U1 = new OpCode() - opcode(Conv_Ovf_U1, CEE_CONV_OVF_U1, "conv.ovf.u1", 0xFFFFFFB4, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to unsigned int16 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U2 = new OpCode() - opcode(Conv_Ovf_U2, CEE_CONV_OVF_U2, "conv.ovf.u2", 0xFFFFFFB6, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to unsigned int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U4 = new OpCode() - opcode(Conv_Ovf_U4, CEE_CONV_OVF_U4, "conv.ovf.u4", 0xFFFFFFB8, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to unsigned int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U8 = new OpCode() - opcode(Conv_Ovf_U8, CEE_CONV_OVF_U8, "conv.ovf.u8", 0xFFFFFFBA, POP_1, PUSH_I8, INLINE_NONE , FLOW_NEXT) - - /** - * Retrieves the address (type &) embedded in a typed reference. - */ - final val Refanyval = new OpCode() - opcode(Refanyval, CEE_REFANYVAL, "refanyval", 0xFFFFFFC2, POP_1, PUSH_I , INLINE_TYPE , FLOW_NEXT) - - /** - * Retrieves the type token embedded in a typed reference . - */ - final val Refanytype = new OpCode() - opcode(Refanytype, CEE_REFANYTYPE, "refanytype", 0xFFFFFE1D, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Throws ArithmeticException if value is not a finite number. - */ - final val Ckfinite = new OpCode() - opcode(Ckfinite, CEE_CKFINITE, "ckfinite" , 0xFFFFFFC3, POP_1, PUSH_R8 , INLINE_NONE , FLOW_NEXT) - - /** - * Pushes a typed reference to an instance of a specific type onto the evaluation stack. - */ - final val Mkrefany = new OpCode() - opcode(Mkrefany, CEE_MKREFANY, "mkrefany" , 0xFFFFFFC6, POP_I, PUSH_1 , INLINE_TYPE , FLOW_NEXT) - - /** - * Converts a metadata token to its runtime representation, pushing it onto the evaluation stack. - */ - final val Ldtoken = new OpCode() - opcode(Ldtoken, CEE_LDTOKEN , "ldtoken" , 0xFFFFFFD0, POP_NONE, PUSH_I, INLINE_TOKEN , FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to unsigned int8, and extends it to int32. - */ - final val Conv_U1 = new OpCode() - opcode(Conv_U1, CEE_CONV_U1 , "conv.u1" , 0xFFFFFFD2, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to unsigned int16, and extends it to int32. - */ - final val Conv_U2 = new OpCode() - opcode(Conv_U2, CEE_CONV_U2 , "conv.u2" , 0xFFFFFFD1, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to natural int. - */ - final val Conv_I = new OpCode() - opcode(Conv_I, CEE_CONV_I , "conv.i" , 0xFFFFFFD3, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to signed natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I = new OpCode() - opcode(Conv_Ovf_I, CEE_CONV_OVF_I , "conv.ovf.i", 0xFFFFFFD4, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Converts the signed value on top of the evaluation stack to unsigned natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U = new OpCode() - opcode(Conv_Ovf_U, CEE_CONV_OVF_U , "conv.ovf.u", 0xFFFFFFD5, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT) - - /** - * Adds two integers, performs an overflow check, and pushes the result - * onto the evaluation stack. - */ - final val Add_Ovf = new OpCode() - opcode(Add_Ovf, CEE_ADD_OVF , "add.ovf" , 0xFFFFFFD6, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT) - - /** - * Adds two unsigned integer values, performs an overflow check, and pushes the result - * onto the evaluation stack. - */ - final val Add_Ovf_Un = new OpCode() - opcode(Add_Ovf_Un, CEE_ADD_OVF_UN , "add.ovf.un", 0xFFFFFFD7, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT) - - /** - * Multiplies two integer values, performs an overflow check, and pushes the result - * onto the evaluation stack. - */ - final val Mul_Ovf = new OpCode() - opcode(Mul_Ovf, CEE_MUL_OVF , "mul.ovf" , 0xFFFFFFD8, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT) - - /** - * Multiplies two unsigned integer values , performs an overflow check , - * and pushes the result onto the evaluation stack. - */ - final val Mul_Ovf_Un = new OpCode() - opcode(Mul_Ovf_Un, CEE_MUL_OVF_UN , "mul.ovf.un", 0xFFFFFFD9, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT) - - /** - * Subtracts one integer value from another, performs an overflow check, - * and pushes the result onto the evaluation stack. - */ - final val Sub_Ovf = new OpCode() - opcode(Sub_Ovf, CEE_SUB_OVF , "sub.ovf" , 0xFFFFFFDA, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT) - - /** - * Subtracts one unsigned integer value from another, performs an overflow check, - * and pushes the result onto the evaluation stack. - */ - final val Sub_Ovf_Un = new OpCode() - opcode(Sub_Ovf_Un, CEE_SUB_OVF_UN, "sub.ovf.un", 0xFFFFFFDB, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT) - - /** - * Transfers control from the fault or finally clause of an exception block back to - * the Common Language Infrastructure (CLI) exception handler. - */ - final val Endfinally = new OpCode() - opcode(Endfinally, CEE_ENDFINALLY, "endfinally", 0xFFFFFFDC, POP_NONE, PUSH_NONE, INLINE_NONE, FLOW_RETURN) - - /** - * Exits a protected region of code, unconditionally tranferring control - * to a specific target instruction. - */ - final val Leave = new OpCode() - opcode(Leave, CEE_LEAVE, "leave", 0xFFFFFFDD, POP_NONE, PUSH_NONE, INLINE_TARGET, FLOW_BRANCH) - - /** - * Exits a protected region of code, unconditionally tranferring control - * to a target instruction (short form). - */ - final val Leave_S = new OpCode() - opcode(Leave_S, CEE_LEAVE_S, "leave.s", 0xFFFFFFDE, POP_NONE, PUSH_NONE, INLINE_TARGET_S, FLOW_BRANCH) - - /** - * Stores a value of type natural int at a supplied address. - */ - final val Stind_I = new OpCode() - opcode(Stind_I, CEE_STIND_I, "stind.i", 0xFFFFFFDF, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Converts the value on top of the evaluation stack to unsigned natural int, - * and extends it to natural int. - */ - final val Conv_U = new OpCode() - opcode(Conv_U, CEE_CONV_U, "conv.u", 0xFFFFFFE0, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Returns an unmanaged pointer to the argument list of the current method. - */ - final val Arglist = new OpCode() - opcode(Arglist, CEE_ARGLIST, "arglist" , 0xFFFFFE00, POP_NONE, PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Compares two values. If they are equal, the integer value 1 (int32) is pushed - * onto the evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Ceq = new OpCode() - opcode(Ceq, CEE_CEQ, "ceq", 0xFFFFFE01, POP_1_1 , PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Compares two values. If the first value is greater than the second, - * the integer value 1 (int32) is pushed onto the evaluation stack - * otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Cgt = new OpCode() - opcode(Cgt, CEE_CGT, "cgt", 0xFFFFFE02, POP_1_1 , PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Compares two unsigned or unordered values. If the first value is greater than - * the second, the integer value 1 (int32) is pushed onto the evaluation stack - * otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Cgt_Un = new OpCode() - opcode(Cgt_Un, CEE_CGT_UN, "cgt.un", 0xFFFFFE03, POP_1_1 , PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Compares two values. If the first value is less than the second, - * the integer value 1 (int32) is pushed onto the evaluation stack - * otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Clt = new OpCode() - opcode(Clt, CEE_CLT, "clt" , 0xFFFFFE04, POP_1_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Compares the unsigned or unordered values value1 and value2. If value1 is - * less than value2, then the integer value 1 (int32) is pushed onto the - * evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Clt_Un = new OpCode() - opcode(Clt_Un, CEE_CLT_UN , "clt.un" , 0xFFFFFE05, POP_1_1 , PUSH_I , INLINE_NONE, FLOW_NEXT) - - /** - * Pushes an unmanaged pointer (type natural int) to the native code implementing - * a specific method onto the evaluation stack. - */ - final val Ldftn = new OpCode() - opcode(Ldftn, CEE_LDFTN , "ldftn" , 0xFFFFFE06, POP_NONE, PUSH_I , INLINE_METHOD, FLOW_NEXT) - - /** - * Pushes an unmanaged pointer (type natural int) to the native code implementing - * a particular virtual method associated with a specified object onto the evaluation stack. - */ - final val Ldvirtftn = new OpCode() - opcode(Ldvirtftn, CEE_LDVIRTFTN, "ldvirtftn", 0xFFFFFE07, POP_REF , PUSH_I , INLINE_METHOD, FLOW_NEXT) - - /** - * Loads an argument (referenced by a specified index value) onto the stack. - */ - final val Ldarg = new OpCode() - opcode(Ldarg, CEE_LDARG , "ldarg" , 0xFFFFFE09, POP_NONE, PUSH_1 , INLINE_VARIABLE , FLOW_NEXT) - - /** - * Load an argument address onto the evaluation stack. - */ - final val Ldarga = new OpCode() - opcode(Ldarga, CEE_LDARGA , "ldarga", 0xFFFFFE0A, POP_NONE, PUSH_I, INLINE_VARIABLE , FLOW_NEXT) - - /** - * Loads the local variable at a specific index onto the evaluation stack. - */ - final val Ldloc = new OpCode() - opcode(Ldloc, CEE_LDLOC, "ldloc", 0xFFFFFE0C, POP_NONE, PUSH_1 , INLINE_VARIABLE , FLOW_NEXT) - - /** - * Loads the address of the local variable at a specific index onto the evaluation stack. - */ - final val Ldloca = new OpCode() - opcode(Ldloca, CEE_LDLOCA, "ldloca", 0xFFFFFE0D, POP_NONE, PUSH_I, INLINE_VARIABLE , FLOW_NEXT) - - /** - * Stores the value on top of the evaluation stack in the argument slot at a specified index. - */ - final val Starg = new OpCode() - opcode(Starg, CEE_STARG, "starg", 0xFFFFFE0B, POP_1 , PUSH_NONE, INLINE_VARIABLE , FLOW_NEXT) - - /** - * Pops the current value from the top of the evaluation stack and stores it in a - * the local variable list at a specified index. - */ - final val Stloc = new OpCode() - opcode(Stloc, CEE_STLOC, "stloc", 0xFFFFFE0E, POP_1 , PUSH_NONE, INLINE_VARIABLE , FLOW_NEXT) - - /** - * Allocates a certain number of bytes from the local dynamic memory pool and pushes the - * address (a transient pointer, type *) of the first allocated Byte onto the evaluation stack. - */ - final val Localloc = new OpCode() - opcode(Localloc, CEE_LOCALLOC, "localloc" , 0xFFFFFE0F, POP_I, PUSH_I, INLINE_NONE, FLOW_NEXT) - - /** - * Transfers control from the filter clause of an exception back to the - * Common Language Infrastructure (CLI) exception handler. - */ - final val Endfilter = new OpCode() - opcode(Endfilter, CEE_ENDFILTER, "endfilter" , 0xFFFFFE11, POP_I , PUSH_NONE, INLINE_NONE, FLOW_RETURN) - - /** - * Indicates that an address currently atop the evaluation stack might not be aligned - * to the natural size of the immediately following ldind, stind, ldfld, stfld, ldobj, - * stobj, initblk, or cpblk instruction. - */ - final val Unaligned = new OpCode() - opcode(Unaligned, CEE_UNALIGNED, "unaligned.", 0xFFFFFE12, POP_NONE, PUSH_NONE, INLINE_I_S , FLOW_META) - - /** - * Specifies that an address currently atop the evaluation stack might be volatile, - * and the results of reading that location cannot be cached or that multiple stores - * to that location cannot be suppressed. - */ - final val Volatile = new OpCode() - opcode(Volatile, CEE_VOLATILE, "volatile." , 0xFFFFFE13, POP_NONE, PUSH_NONE, INLINE_NONE, FLOW_META) - - /** - * Performs a postfixed method call instruction such that the current method's stack - * frame is removed before the actual call instruction is executed. - */ - final val Tailcall = new OpCode() - opcode(Tailcall, CEE_TAILCALL, "tail." , 0xFFFFFE14, POP_NONE, PUSH_NONE, INLINE_NONE, FLOW_META) - - /** - * Initializes all the fields of the object at a specific address to a null reference - * or a 0 of the appropriate primitive type. - */ - final val Initobj = new OpCode() - opcode(Initobj, CEE_INITOBJ , "initobj" , 0xFFFFFE15, POP_I , PUSH_NONE, INLINE_TYPE, FLOW_NEXT) - - /** - * Copies a specified number bytes from a source address to a destination address . - */ - final val Cpblk = new OpCode() - opcode(Cpblk, CEE_CPBLK , "cpblk" , 0xFFFFFE17, POP_I_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Initializes a specified block of memory at a specific address to a given size - * and initial value. - */ - final val Initblk = new OpCode() - opcode(Initblk, CEE_INITBLK , "initblk" , 0xFFFFFE18, POP_I_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT) - - /** - * Rethrows the current exception. - */ - final val Rethrow = new OpCode() - opcode(Rethrow, CEE_RETHROW , "rethrow", 0xFFFFFE1A, POP_NONE , PUSH_NONE, INLINE_NONE, FLOW_THROW) - - /** - * Pushes the size, in bytes, of a supplied value type onto the evaluation stack. - */ - final val Sizeof = new OpCode() - opcode(Sizeof, CEE_SIZEOF, "sizeof", 0xFFFFFE1C, POP_NONE , PUSH_I , INLINE_TYPE, FLOW_NEXT) - - - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala deleted file mode 100644 index 80e42674360e..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala +++ /dev/null @@ -1,1205 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - - -/** - * Provides field representations of the Microsoft Intermediate Language (MSIL) - * instructions for emission by the ILGenerator class members (such as Emit). - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -object OpCodes { - - //########################################################################## - - /** - * Adds two values and pushes the result onto the evaluation stack. - */ - final val Add = OpCode.Add - - /** - * Fills space if bytecodes are patched. No meaningful operation is performed - * although a processing cycle can be consumed. - */ - final val Nop = OpCode.Nop - - /** - * Signals the Common Language Infrastructure (CLI) to inform the debugger that - * a break point has been tripped. - */ - final val Break = OpCode.Break - - /** - * Loads the argument at index 0 onto the evaluation stack. - */ - final val Ldarg_0 = OpCode.Ldarg_0 - - /** - * Loads the argument at index 1 onto the evaluation stack. - */ - final val Ldarg_1 = OpCode.Ldarg_1 - - /** - * Loads the argument at index 2 onto the evaluation stack. - */ - final val Ldarg_2 = OpCode.Ldarg_2 - - /** - * Loads the argument at index 3 onto the evaluation stack. - */ - final val Ldarg_3 = OpCode.Ldarg_3 - - /** - * Loads the local variable at index 0 onto the evaluation stack. - */ - final val Ldloc_0 = OpCode.Ldloc_0 - - /** - * Loads the local variable at index 1 onto the evaluation stack. - */ - final val Ldloc_1 = OpCode.Ldloc_1 - - /** - * Loads the local variable at index 2 onto the evaluation stack. - */ - final val Ldloc_2 = OpCode.Ldloc_2 - - /** - * Loads the local variable at index 3 onto the evaluation stack. - */ - final val Ldloc_3 = OpCode.Ldloc_3 - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 0. - */ - final val Stloc_0 = OpCode.Stloc_0 - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 1. - */ - final val Stloc_1 = OpCode.Stloc_1 - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 2. - */ - final val Stloc_2 = OpCode.Stloc_2 - - /** - * Pops the current value from the top of the evaluation stack and - * stores it in a the local variable list at index 3. - */ - final val Stloc_3 = OpCode.Stloc_3 - - /** - * Loads the argument (referenced by a specified short form index) - * onto the evaluation stack. - */ - final val Ldarg_S = OpCode.Ldarg_S - - /** - * Load an argument address, in short form, onto the evaluation stack. - */ - final val Ldarga_S = OpCode.Ldarga_S - - /** - * Loads the local variable at a specific index onto the evaluation stack, - * short form. - */ - final val Ldloc_S = OpCode.Ldloc_S - - /** - * Loads the address of the local variable at a specific index onto - * the evaluation stack, short form. - */ - final val Ldloca_S = OpCode.Ldloca_S - - /** - * Stores the value on top of the evaluation stack in the argument slot - * at a specified index, short form. - */ - final val Starg_S = OpCode.Starg_S - - /** - * Pops the current value from the top of the evaluation stack and stores it - * in a the local variable list at index (short form). - */ - final val Stloc_S = OpCode.Stloc_S - - /** - * Pushes a null reference (type O) onto the evaluation stack. - */ - final val Ldnull = OpCode.Ldnull - - /** - * Pushes the integer value of -1 onto the evaluation stack as an int32. - */ - final val Ldc_I4_M1 = OpCode.Ldc_I4_M1 - - /** - * Pushes the integer value of 0 onto the evaluation stack as an int32. - */ - final val Ldc_I4_0 = OpCode.Ldc_I4_0 - - /** - * Pushes the integer value of 1 onto the evaluation stack as an int32. - */ - final val Ldc_I4_1 = OpCode.Ldc_I4_1 - - /** - * Pushes the integer value of 2 onto the evaluation stack as an int32. - */ - final val Ldc_I4_2 = OpCode.Ldc_I4_2 - - /** - * Pushes the integer value of 3 onto the evaluation stack as an int32. - */ - final val Ldc_I4_3 = OpCode.Ldc_I4_3 - - /** - * Pushes the integer value of 4 onto the evaluation stack as an int32. - */ - final val Ldc_I4_4 = OpCode.Ldc_I4_4 - - /** - * Pushes the integer value of 5 onto the evaluation stack as an int32. - */ - final val Ldc_I4_5 = OpCode.Ldc_I4_5 - - /** - * Pushes the integer value of 6 onto the evaluation stack as an int32. - */ - final val Ldc_I4_6 = OpCode.Ldc_I4_6 - - /** - * Pushes the integer value of 7 onto the evaluation stack as an int32. - */ - final val Ldc_I4_7 = OpCode.Ldc_I4_7 - - /** - * Pushes the integer value of 8 onto the evaluation stack as an int32. - */ - final val Ldc_I4_8 = OpCode.Ldc_I4_8 - - /** - * Pushes the supplied int8 value onto the evaluation stack as an int32, short form. - */ - final val Ldc_I4_S = OpCode.Ldc_I4_S - - /** - * Pushes a supplied value of type int32 onto the evaluation stack as an int32. - */ - final val Ldc_I4 = OpCode.Ldc_I4 - - /** - * Pushes a supplied value of type int64 onto the evaluation stack as an int64. - */ - final val Ldc_I8 = OpCode.Ldc_I8 - - /** - * Pushes a supplied value of type float32 onto the evaluation stack as type F (float). - */ - final val Ldc_R4 = OpCode.Ldc_R4 - - /** - * Pushes a supplied value of type float64 onto the evaluation stack as type F (float). - */ - final val Ldc_R8 = OpCode.Ldc_R8 - - /** - * Copies the current topmost value on the evaluation stack, and then pushes the copy - * onto the evaluation stack. - */ - final val Dup = OpCode.Dup - - /** - * Removes the value currently on top of the evaluation stack. - */ - final val Pop = OpCode.Pop - - /** - * Exits current method and jumps to specified method. - */ - final val Jmp = OpCode.Jmp - - /** - * Calls the method indicated by the passed method descriptor. - */ - final val Call = OpCode.Call - - /** - * constrained. prefix - */ - final val Constrained = OpCode.Constrained - - /** - * readonly. prefix - */ - final val Readonly = OpCode.Readonly - - /** - * Calls the method indicated on the evaluation stack (as a pointer to an entry point) - * with arguments described by a calling convention. - */ - final val Calli = OpCode.Calli - - /** - * Returns from the current method, pushing a return value (if present) from the caller's - * evaluation stack onto the callee's evaluation stack. - */ - final val Ret = OpCode.Ret - - /** - * Unconditionally transfers control to a target instruction (short form). - */ - final val Br_S = OpCode.Br_S - - /** - * Transfers control to a target instruction if value is false, a null reference, or zero. - */ - final val Brfalse_S = OpCode.Brfalse_S - - /** - * Transfers control to a target instruction (short form) if value is true, not null, or non-zero. - */ - final val Brtrue_S = OpCode.Brtrue_S - - /** - * Transfers control to a target instruction (short form) if two values are equal. - */ - final val Beq_S = OpCode.Beq_S - - /** - * Transfers control to a target instruction (short form) if the first value is greater than - * or equal to the second value. - */ - final val Bge_S = OpCode.Bge_S - - /** - * Transfers control to a target instruction (short form) if the first value is greater than - * the second value. - */ - final val Bgt_S = OpCode.Bgt_S - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * or equal to the second value. - */ - final val Ble_S = OpCode.Ble_S - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * the second value. - */ - final val Blt_S = OpCode.Blt_S - - /** - * Transfers control to a target instruction (short form) when two unsigned integer values - * or unordered float values are not equal. - */ - final val Bne_Un_S = OpCode.Bne_Un_S - - /** - * Transfers control to a target instruction (short form) if the first value is greather - * than the second value, when comparing unsigned integer values or unordered float values. - */ - final val Bge_Un_S = OpCode.Bge_Un_S - - /** - * Transfers control to a target instruction (short form) if the first value is greater than - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Bgt_Un_S = OpCode.Bgt_Un_S - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * or equal to the second value, when comparing unsigned integer values or unordered float values. - */ - final val Ble_Un_S = OpCode.Ble_Un_S - - /** - * Transfers control to a target instruction (short form) if the first value is less than - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Blt_Un_S = OpCode.Blt_Un_S - - /** - * Unconditionally transfers control to a target instruction. - */ - final val Br = OpCode.Br - - /** - * Transfers control to a target instruction if value is false, a null reference - * (Nothing in Visual Basic), or zero. - */ - final val Brfalse = OpCode.Brfalse - - /** - * Transfers control to a target instruction if value is true, not null, or non-zero. - */ - final val Brtrue = OpCode.Brtrue - - /** - * Transfers control to a target instruction if two values are equal. - */ - final val Beq = OpCode.Beq - - /** - * Transfers control to a target instruction if the first value is greater than or - * equal to the second value. - */ - final val Bge = OpCode.Bge - - /** - * Transfers control to a target instruction if the first value is greater than the second value. - */ - final val Bgt = OpCode.Bgt - - /** - * Transfers control to a target instruction if the first value is less than or equal - * to the second value. - */ - final val Ble = OpCode.Ble - - /** - * Transfers control to a target instruction if the first value is less than the second value. - */ - final val Blt = OpCode.Blt - - /** - * Transfers control to a target instruction when two unsigned integer values or - * unordered float values are not equal. - */ - final val Bne_Un = OpCode.Bne_Un - - /** - * Transfers control to a target instruction if the first value is greather than - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Bge_Un = OpCode.Bge_Un - - /** - * Transfers control to a target instruction if the first value is greater than the - * second value, when comparing unsigned integer values or unordered float values. - */ - final val Bgt_Un = OpCode.Bgt_Un - - /** - * Transfers control to a target instruction if the first value is less than or equal to - * the second value, when comparing unsigned integer values or unordered float values. - */ - final val Ble_Un = OpCode.Ble_Un - - /** - * Transfers control to a target instruction if the first value is less than the second value, - * when comparing unsigned integer values or unordered float values. - */ - final val Blt_Un = OpCode.Blt_Un - - /** - * Implements a jump table. - */ - final val Switch = OpCode.Switch - - /** - * Loads a value of type int8 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_I1 = OpCode.Ldind_I1 - - /** - * Loads a value of type int16 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_I2 = OpCode.Ldind_I2 - - /** - * Loads a value of type int32 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_I4 = OpCode.Ldind_I4 - - /** - * Loads a value of type int64 as an int64 onto the evaluation stack indirectly. - */ - final val Ldind_I8 = OpCode.Ldind_I8 - - /** - * Loads a value of type natural int as a natural int onto the evaluation stack indirectly. - */ - final val Ldind_I = OpCode.Ldind_I - - /** - * Loads a value of type float32 as a type F (float) onto the evaluation stack indirectly. - */ - final val Ldind_R4 = OpCode.Ldind_R4 - - /** - * Loads a value of type float64 as a type F (float) onto the evaluation stack indirectly. - */ - final val Ldind_R8 = OpCode.Ldind_R8 - - /** - * Loads an object reference as a type O (object reference) onto the evaluation stack indirectly. - */ - final val Ldind_Ref = OpCode.Ldind_Ref - - /** - * Loads a value of type unsigned int8 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_U1 = OpCode.Ldind_U1 - - /** - * Loads a value of type unsigned int16 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_U2 = OpCode.Ldind_U2 - - /** - * Loads a value of type unsigned int32 as an int32 onto the evaluation stack indirectly. - */ - final val Ldind_U4 = OpCode.Ldind_U4 - - /** - * Stores a object reference value at a supplied address. - */ - final val Stind_Ref = OpCode.Stind_Ref - - /** - * Stores a value of type int8 at a supplied address. - */ - final val Stind_I1 = OpCode.Stind_I1 - - /** - * Stores a value of type int16 at a supplied address. - */ - final val Stind_I2 = OpCode.Stind_I2 - - /** - * Stores a value of type int32 at a supplied address. - */ - final val Stind_I4 = OpCode.Stind_I4 - - /** - * Stores a value of type int64 at a supplied address. - */ - final val Stind_I8 = OpCode.Stind_I8 - - /** - * Stores a value of type float32 at a supplied address. - */ - final val Stind_R4 = OpCode.Stind_R4 - - /** - * Stores a value of type float64 at a supplied address. - */ - final val Stind_R8 = OpCode.Stind_R8 - - /** - * Subtracts one value from another and pushes the result onto the evaluation stack. - */ - final val Sub = OpCode.Sub - - /** - * Multiplies two values and pushes the result on the evaluation stack. - */ - final val Mul = OpCode.Mul - - /** - * Divides two values and pushes the result as a floating-point (type F) or - * quotient (type int32) onto the evaluation stack. - */ - final val Div = OpCode.Div - - /** - * Divides two unsigned integer values and pushes the result (int32) onto the evaluation stack. - */ - final val Div_Un = OpCode.Div_Un - - /** - * Divides two values and pushes the remainder onto the evaluation stack. - */ - final val Rem = OpCode.Rem - - /** - * Divides two unsigned values and pushes the remainder onto the evaluation stack. - */ - final val Rem_Un = OpCode.Rem_Un - - /** - * Computes the bitwise AND of two values and pushes the result onto the evaluation stack. - */ - final val And = OpCode.And - - /** - * Compute the bitwise complement of the two integer values on top of the stack and - * pushes the result onto the evaluation stack. - */ - final val Or = OpCode.Or - - /** - * Computes the bitwise XOR of the top two values on the evaluation stack, - * pushing the result onto the evaluation stack. - */ - final val Xor = OpCode.Xor - - /** - * Shifts an integer value to the left (in zeroes) by a specified number of bits, - * pushing the result onto the evaluation stack. - */ - final val Shl = OpCode.Shl - - /** - * Shifts an integer value (in sign) to the right by a specified number of bits, - * pushing the result onto the evaluation stack. - */ - final val Shr = OpCode.Shr - - /** - * Shifts an unsigned integer value (in zeroes) to the right by a specified number of bits, - * pushing the result onto the evaluation stack. - */ - final val Shr_Un = OpCode.Shr_Un - - /** - * Negates a value and pushes the result onto the evaluation stack. - */ - final val Neg = OpCode.Neg - - /** - * Computes the bitwise complement of the integer value on top of the stack and pushes - * the result onto the evaluation stack as the same type. - */ - final val Not = OpCode.Not - - /** - * Converts the value on top of the evaluation stack to int8, then extends (pads) it to int32. - */ - final val Conv_I1 = OpCode.Conv_I1 - - /** - * Converts the value on top of the evaluation stack to int16, then extends (pads) it to int32. - */ - final val Conv_I2 = OpCode.Conv_I2 - - /** - * Converts the value on top of the evaluation stack to int32. - */ - final val Conv_I4 = OpCode.Conv_I4 - - /** - * Converts the value on top of the evaluation stack to int64. - */ - final val Conv_I8 = OpCode.Conv_I8 - - /** - * Converts the value on top of the evaluation stack to float32. - */ - final val Conv_R4 = OpCode.Conv_R4 - - /** - * Converts the value on top of the evaluation stack to float64. - */ - final val Conv_R8 = OpCode.Conv_R8 - - /** - * Converts the value on top of the evaluation stack to unsigned int32, and extends it to int32. - */ - final val Conv_U4 = OpCode.Conv_U4 - - /** - * Converts the value on top of the evaluation stack to unsigned int64, and extends it to int64. - */ - final val Conv_U8 = OpCode.Conv_U8 - - /** - * Calls a late-bound method on an object, pushing the return value onto the evaluation stack. - */ - final val Callvirt = OpCode.Callvirt - - /** - * Copies the value type located at the address of an object (type &, * or natural int) - * to the address of the destination object (type &, * or natural int). - */ - final val Cpobj = OpCode.Cpobj - - /** - * Copies the value type object pointed to by an address to the top of the evaluation stack. - */ - final val Ldobj = OpCode.Ldobj - - /** - * Pushes a new object reference to a string literal stored in the metadata. - */ - final val Ldstr = OpCode.Ldstr - - /** - * Creates a new object or a new instance of a value type, pushing an object reference - * (type O) onto the evaluation stack. - */ - final val Newobj = OpCode.Newobj - - /** - * Attempts to cast an object passed by reference to the specified class. - */ - final val Castclass = OpCode.Castclass - - /** - * Tests whether an object reference (type O) is an instance of a particular class. - */ - final val Isinst = OpCode.Isinst - - /** - * Converts the unsigned integer value on top of the evaluation stack to float32. - */ - final val Conv_R_Un = OpCode.Conv_R_Un - - /** - * Converts the boxed representation of a value type to its unboxed form. - */ - final val Unbox = OpCode.Unbox - - /** - * Throws the exception object currently on the evaluation stack. - */ - final val Throw = OpCode.Throw - - /** - * Finds the value of a field in the object whose reference is currently - * on the evaluation stack. - */ - final val Ldfld = OpCode.Ldfld - - /** - * Finds the address of a field in the object whose reference is currently - * on the evaluation stack. - */ - final val Ldflda = OpCode.Ldflda - - /** - * Pushes the value of a static field onto the evaluation stack. - */ - final val Ldsfld = OpCode.Ldsfld - - /** - * Pushes the address of a static field onto the evaluation stack. - */ - final val Ldsflda = OpCode.Ldsflda - - /** - * Replaces the value stored in the field of an object reference or pointer with a new value. - */ - final val Stfld = OpCode.Stfld - - /** - * Replaces the value of a static field with a value from the evaluation stack. - */ - final val Stsfld = OpCode.Stsfld - - /** - * Copies a value of a specified type from the evaluation stack into a supplied memory address. - */ - final val Stobj = OpCode.Stobj - - /** - * Converts the unsigned value on top of the evaluation stack to signed int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I1_Un = OpCode.Conv_Ovf_I1_Un - - /** - * Converts the unsigned value on top of the evaluation stack to signed int16 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I2_Un = OpCode.Conv_Ovf_I2_Un - - /** - * Converts the unsigned value on top of the evaluation stack to signed int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I4_Un = OpCode.Conv_Ovf_I4_Un - - /** - * Converts the unsigned value on top of the evaluation stack to signed int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I8_Un = OpCode.Conv_Ovf_I8_Un - - /** - * Converts the unsigned value on top of the evaluation stack to signed natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I_Un = OpCode.Conv_Ovf_I_Un - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U1_Un = OpCode.Conv_Ovf_U1_Un - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int16 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U2_Un = OpCode.Conv_Ovf_U2_Un - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U4_Un = OpCode.Conv_Ovf_U4_Un - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U8_Un = OpCode.Conv_Ovf_U8_Un - - /** - * Converts the unsigned value on top of the evaluation stack to unsigned natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U_Un = OpCode.Conv_Ovf_U_Un - - /** - * Converts a value type to an object reference (type O). - */ - final val Box = OpCode.Box - - /** - * Pushes an object reference to a new zero-based, one-dimensional array whose elements - * are of a specific type onto the evaluation stack. - */ - final val Newarr = OpCode.Newarr - - /** - * Pushes the number of elements of a zero-based, one-dimensional array - * onto the evaluation stack. - */ - final val Ldlen = OpCode.Ldlen - - /** - * Loads the address of the array element at a specified array index onto - * the top of the evaluation stack as type & (managed pointer). - */ - final val Ldelema = OpCode.Ldelema - - /** - * Loads the element with type natural int at a specified array index onto the top - * of the evaluation stack as a natural int. - */ - final val Ldelem_I = OpCode.Ldelem_I - - /** - * Loads the element with type int8 at a specified array index onto the top of the - * evaluation stack as an int32. - */ - final val Ldelem_I1 = OpCode.Ldelem_I1 - - /** - * Loads the element with type int16 at a specified array index onto the top of - * the evaluation stack as an int32. - */ - final val Ldelem_I2 = OpCode.Ldelem_I2 - - /** - * Loads the element with type int32 at a specified array index onto the top of the - * evaluation stack as an int32. - */ - final val Ldelem_I4 = OpCode.Ldelem_I4 - - /** - * Loads the element with type int64 at a specified array index onto the top of the - * evaluation stack as an int64. - */ - final val Ldelem_I8 = OpCode.Ldelem_I8 - - /** - * Loads the element with type float32 at a specified array index onto the top of the - * evaluation stack as type F (float) - */ - final val Ldelem_R4 = OpCode.Ldelem_R4 - - /** - * Loads the element with type float64 at a specified array index onto the top of the - * evaluation stack as type F (float) . - */ - final val Ldelem_R8 = OpCode.Ldelem_R8 - - /** - * Loads the element containing an object reference at a specified array index onto - * the top of the evaluation stack as type O (object reference). - */ - final val Ldelem_Ref = OpCode.Ldelem_Ref - - /** - * Loads the element with type unsigned int8 at a specified array index onto the top - * of the evaluation stack as an int32. - */ - final val Ldelem_U1 = OpCode.Ldelem_U1 - - /** - * Loads the element with type unsigned int16 at a specified array index onto the top - * of the evaluation stack as an int32. - */ - final val Ldelem_U2 = OpCode.Ldelem_U2 - - /** - * Loads the element with type unsigned int32 at a specified array index onto the top - * of the evaluation stack as an int32. - */ - final val Ldelem_U4 = OpCode.Ldelem_U4 - - /** - * Replaces the array element at a given index with the natural int value on - * the evaluation stack. - */ - final val Stelem_I = OpCode.Stelem_I - - /** - * Replaces the array element at a given index with the int8 value on the evaluation stack. - */ - final val Stelem_I1 = OpCode.Stelem_I1 - - /** - * Replaces the array element at a given index with the int16 value on the evaluation stack. - */ - final val Stelem_I2 = OpCode.Stelem_I2 - - /** - * Replaces the array element at a given index with the int32 value on the evaluation stack. - */ - final val Stelem_I4 = OpCode.Stelem_I4 - - /** - * Replaces the array element at a given index with the int64 value on the evaluation stack. - */ - final val Stelem_I8 = OpCode.Stelem_I8 - - /** - * Replaces the array element at a given index with the float32 value on the evaluation stack. - */ - final val Stelem_R4 = OpCode.Stelem_R4 - - /** - * Replaces the array element at a given index with the float64 value on the evaluation stack. - */ - final val Stelem_R8 = OpCode.Stelem_R8 - - /** - * Replaces the array element at a given index with the object ref value (type O) - * on the evaluation stack. - */ - final val Stelem_Ref = OpCode.Stelem_Ref - - /** - * Converts the signed value on top of the evaluation stack to signed int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I1 = OpCode.Conv_Ovf_I1 - - /** - * Converts the signed value on top of the evaluation stack to signed int16 and - * extending it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_I2 = OpCode.Conv_Ovf_I2 - - /** - * Converts the signed value on top of the evaluation stack to signed int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I4 = OpCode.Conv_Ovf_I4 - - /** - * Converts the signed value on top of the evaluation stack to signed int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I8 = OpCode.Conv_Ovf_I8 - - /** - * Converts the signed value on top of the evaluation stack to unsigned int8 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U1 = OpCode.Conv_Ovf_U1 - - /** - * Converts the signed value on top of the evaluation stack to unsigned int16 and - * extends it to int32, throwing OverflowException on overflow. - */ - final val Conv_Ovf_U2 = OpCode.Conv_Ovf_U2 - - /** - * Converts the signed value on top of the evaluation stack to unsigned int32, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U4 = OpCode.Conv_Ovf_U4 - - /** - * Converts the signed value on top of the evaluation stack to unsigned int64, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U8 = OpCode.Conv_Ovf_U8 - - /** - * Retrieves the address (type &) embedded in a typed reference. - */ - final val Refanyval = OpCode.Refanyval - - /** - * Retrieves the type token embedded in a typed reference . - */ - final val Refanytype = OpCode.Refanytype - - /** - * Throws ArithmeticException if value is not a finite number. - */ - final val Ckfinite = OpCode.Ckfinite - - /** - * Pushes a typed reference to an instance of a specific type onto the evaluation stack. - */ - final val Mkrefany = OpCode.Mkrefany - - /** - * Converts a metadata token to its runtime representation, pushing it onto the evaluation stack. - */ - final val Ldtoken = OpCode.Ldtoken - - /** - * Converts the value on top of the evaluation stack to unsigned int8, and extends it to int32. - */ - final val Conv_U1 = OpCode.Conv_U1 - - /** - * Converts the value on top of the evaluation stack to unsigned int16, and extends it to int32. - */ - final val Conv_U2 = OpCode.Conv_U2 - - /** - * Converts the value on top of the evaluation stack to natural int. - */ - final val Conv_I = OpCode.Conv_I - - /** - * Converts the signed value on top of the evaluation stack to signed natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_I = OpCode.Conv_Ovf_I - - /** - * Converts the signed value on top of the evaluation stack to unsigned natural int, - * throwing OverflowException on overflow. - */ - final val Conv_Ovf_U = OpCode.Conv_Ovf_U - - /** - * Adds two integers, performs an overflow check, and pushes the result - * onto the evaluation stack. - */ - final val Add_Ovf = OpCode.Add_Ovf - - /** - * Adds two unsigned integer values, performs an overflow check, and pushes the result - * onto the evaluation stack. - */ - final val Add_Ovf_Un = OpCode.Add_Ovf_Un - - /** - * Multiplies two integer values, performs an overflow check, and pushes the result - * onto the evaluation stack. - */ - final val Mul_Ovf = OpCode.Mul_Ovf - - /** - * Multiplies two unsigned integer values , performs an overflow check , - * and pushes the result onto the evaluation stack. - */ - final val Mul_Ovf_Un = OpCode.Mul_Ovf_Un - - /** - * Subtracts one integer value from another, performs an overflow check, - * and pushes the result onto the evaluation stack. - */ - final val Sub_Ovf = OpCode.Sub_Ovf - - /** - * Subtracts one unsigned integer value from another, performs an overflow check, - * and pushes the result onto the evaluation stack. - */ - final val Sub_Ovf_Un = OpCode.Sub_Ovf_Un - - /** - * Transfers control from the fault or finally clause of an exception block back to - * the Common Language Infrastructure (CLI) exception handler. - */ - final val Endfinally = OpCode.Endfinally - - /** - * Exits a protected region of code, unconditionally tranferring control - * to a specific target instruction. - */ - final val Leave = OpCode.Leave - - /** - * Exits a protected region of code, unconditionally tranferring control - * to a target instruction (short form). - */ - final val Leave_S = OpCode.Leave_S - - /** - * Stores a value of type natural int at a supplied address. - */ - final val Stind_I = OpCode.Stind_I - - /** - * Converts the value on top of the evaluation stack to unsigned natural int, - * and extends it to natural int. - */ - final val Conv_U = OpCode.Conv_U - - /** - * Returns an unmanaged pointer to the argument list of the current method. - */ - final val Arglist = OpCode.Arglist - - /** - * Compares two values. If they are equal, the integer value 1 (int32) is pushed - * onto the evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Ceq = OpCode.Ceq - - /** - * Compares two values. If the first value is greater than the second, - * the integer value 1 (int32) is pushed onto the evaluation stack - * otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Cgt = OpCode.Cgt - - /** - * Compares two unsigned or unordered values. If the first value is greater than - * the second, the integer value 1 (int32) is pushed onto the evaluation stack - * otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Cgt_Un = OpCode.Cgt_Un - - /** - * Compares two values. If the first value is less than the second, - * the integer value 1 (int32) is pushed onto the evaluation stack - * otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Clt = OpCode.Clt - - /** - * Compares the unsigned or unordered values value1 and value2. If value1 is - * less than value2, then the integer value 1 (int32) is pushed onto the - * evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack. - */ - final val Clt_Un = OpCode.Clt_Un - - /** - * Pushes an unmanaged pointer (type natural int) to the native code implementing - * a specific method onto the evaluation stack. - */ - final val Ldftn = OpCode.Ldftn - - /** - * Pushes an unmanaged pointer (type natural int) to the native code implementing - * a particular virtual method associated with a specified object onto the evaluation stack. - */ - final val Ldvirtftn = OpCode.Ldvirtftn - - /** - * Loads an argument (referenced by a specified index value) onto the stack. - */ - final val Ldarg = OpCode.Ldarg - - /** - * Load an argument address onto the evaluation stack. - */ - final val Ldarga = OpCode.Ldarga - - /** - * Loads the local variable at a specific index onto the evaluation stack. - */ - final val Ldloc = OpCode.Ldloc - - /** - * Loads the address of the local variable at a specific index onto the evaluation stack. - */ - final val Ldloca = OpCode.Ldloca - - /** - * Stores the value on top of the evaluation stack in the argument slot at a specified index. - */ - final val Starg = OpCode.Starg - - /** - * Pops the current value from the top of the evaluation stack and stores it in a - * the local variable list at a specified index. - */ - final val Stloc = OpCode.Stloc - - /** - * Allocates a certain number of bytes from the local dynamic memory pool and pushes the - * address (a transient pointer, type *) of the first allocated Byte onto the evaluation stack. - */ - final val Localloc = OpCode.Localloc - - /** - * Transfers control from the filter clause of an exception back to the - * Common Language Infrastructure (CLI) exception handler. - */ - final val Endfilter = OpCode.Endfilter - - /** - * Indicates that an address currently atop the evaluation stack might not be aligned - * to the natural size of the immediately following ldind, stind, ldfld, stfld, ldobj, - * stobj, initblk, or cpblk instruction. - */ - final val Unaligned = OpCode.Unaligned - - /** - * Specifies that an address currently atop the evaluation stack might be volatile, - * and the results of reading that location cannot be cached or that multiple stores - * to that location cannot be suppressed. - */ - final val Volatile = OpCode.Volatile - - /** - * Performs a postfixed method call instruction such that the current method's stack - * frame is removed before the actual call instruction is executed. - */ - final val Tailcall = OpCode.Tailcall - - /** - * Initializes all the fields of the object at a specific address to a null reference - * or a 0 of the appropriate primitive type. - */ - final val Initobj = OpCode.Initobj - - /** - * Copies a specified number bytes from a source address to a destination address . - */ - final val Cpblk = OpCode.Cpblk - - /** - * Initializes a specified block of memory at a specific address to a given size - * and initial value. - */ - final val Initblk = OpCode.Initblk - - /** - * Rethrows the current exception. - */ - final val Rethrow = OpCode.Rethrow - - /** - * Pushes the size, in bytes, of a supplied value type onto the evaluation stack. - */ - final val Sizeof = OpCode.Sizeof - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ParameterBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ParameterBuilder.scala deleted file mode 100644 index 8f9d81a8b085..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ParameterBuilder.scala +++ /dev/null @@ -1,44 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil.Type -import ch.epfl.lamp.compiler.msil.ConstructorInfo -import ch.epfl.lamp.compiler.msil.ParameterInfo -import java.io.IOException - -/** - * Creates or associates parameter information. - * Parameter attributes need to consistent with the method signature. - * If you specify Out attributes for a parameter, you should ensure that - * the type of that method parameter is a ByRef type - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class ParameterBuilder(name: String, tpe: Type, attr: Int, pos: Int) - extends ParameterInfo(name, tpe, attr, pos) - with ICustomAttributeSetter - with Visitable -{ - - //########################################################################## - - /** Sets a custom attribute. */ - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) { - addCustomAttribute(constr, value) - } - - //########################################################################## - - /** The apply method for a visitor */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseParameterBuilder(this) - } - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala deleted file mode 100644 index 50e9f45373c9..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala +++ /dev/null @@ -1,93 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies in MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import java.io.FileWriter -import java.io.BufferedWriter -import java.io.PrintWriter -import java.io.IOException -import java.util.Iterator -import java.util.HashMap -import java.util.Arrays - -import ch.epfl.lamp.compiler.msil._ -import ch.epfl.lamp.compiler.msil.emit -import ch.epfl.lamp.compiler.msil.util.Table - -/** - * The MSIL printer Visitor. It prints a complete - * assembly in a single file that can be compiled by ilasm. - * - * @author Nikolay Mihaylov - * @author Daniel Lorch - * @version 1.0 - */ -final class SingleFileILPrinterVisitor(_fileName: String) extends ILPrinterVisitor { - var fileName: String = _fileName - - out = new PrintWriter(new BufferedWriter(new FileWriter(fileName))) - - /** - * Visit an AssemblyBuilder - */ - @throws(classOf[IOException]) - def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) { - ILPrinterVisitor.currAssembly = assemblyBuilder - - // first get the entryPoint - this.entryPoint = assemblyBuilder.EntryPoint - - // all external assemblies - as = assemblyBuilder.getExternAssemblies() - scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator) - - assemblyBuilder.generatedFiles += fileName - printAssemblyBoilerplate() - - // print each module - val m: Array[Module] = assemblyBuilder.GetModules() - nomembers = true - for(i <- 0 until m.length) { - print(m(i).asInstanceOf[ModuleBuilder]) - } - - nomembers = false - for(i <- 0 until m.length) { - print(m(i).asInstanceOf[ModuleBuilder]) - } - // close out file - out.close() - ILPrinterVisitor.currAssembly = null - } - - /** - * Visit a ModuleBuilder - */ - @throws(classOf[IOException]) - def caseModuleBuilder(module: ModuleBuilder) { - // print module declaration - currentModule = module - if (nomembers) { - print(".module \'"); print(module.Name); println("\'") - printAttributes(module) - } - - if (!module.globalsCreated) - module.CreateGlobalFunctions() - - val m: Array[MethodInfo] = module.GetMethods() - for(i <- 0 until m.length) { - print(m(i).asInstanceOf[MethodBuilder]) - } - - val t: Array[Type] = module.GetTypes() - for(i <- 0 until t.length) { - print(t(i).asInstanceOf[TypeBuilder]) - } - currentModule = null - } - -} // class SingleFileILPrinterVisitor diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala deleted file mode 100644 index 0b0b16da6560..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala +++ /dev/null @@ -1,261 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import ch.epfl.lamp.compiler.msil._ - -import ch.epfl.lamp.compiler.msil.util.PECustomMod - -import java.io.IOException - -/** - * Defines and creates new instances of classes during runtime. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType: Type, interfaces: Array[Type], declType: Type) - extends Type(module, attributes, fullName, baseType, interfaces, declType, 0) - with ICustomAttributeSetter - with Visitable -{ - import TypeBuilder._ - - //########################################################################## - // public members - - /** 'Bakes' the type. */ - def CreateType(): Type = { - fields = fieldBuilders.toArray // (new Array[FieldInfo](fieldBuilders.size())).asInstanceOf[Array[FieldInfo]] - methods = methodBuilders.toArray // (new Array[MethodInfo](methodBuilders.size())).asInstanceOf[Array[MethodInfo]] - constructors = constructorBuilders.toArray // (new Array[ConstructorInfo](constructorBuilders.size())).asInstanceOf[Array[ConstructorInfo]] - nestedTypes = nestedTypeBuilders.toArray // (new Array[Type](nestedTypeBuilders.size())).asInstanceOf[Array[Type]] - - raw = false - if (DeclaringType == null) - Module.asInstanceOf[ModuleBuilder].addType(this) - return this - } - - /** - * Adds a new field to the class, with the given name, attributes and field type. The location has no custom mods. - */ - def DefineField(name: String, fieldType: Type, attrs: Short): FieldBuilder = { - val fieldTypeWithCustomMods = new PECustomMod(fieldType, null) - DefineField(name, fieldTypeWithCustomMods, attrs) - } - - /** - * Adds a new field to the class, with the given name, attributes and (field type , custom mods) combination. - */ - def DefineField(name: String, fieldTypeWithMods: PECustomMod, attrs: Short): FieldBuilder = { - val field: FieldBuilder = new FieldBuilder(name, this, attrs, fieldTypeWithMods) - fieldBuilders += field - return field - } - - /** - * Adds a new method to the class, with the given name and - * method signature. - */ - def DefineMethod(name: String, attrs: Short, returnType: Type, paramTypes: Array[Type]): MethodBuilder = { - val method = new MethodBuilder(name, this, attrs, returnType, paramTypes) - val methods = methodBuilders.iterator - while(methods.hasNext) { - val m = methods.next().asInstanceOf[MethodInfo] - if (methodsEqual(m, method)) { - throw new RuntimeException("["+ Assembly() + "] Method has already been defined: " + m) - } - } - methodBuilders += method - return method - } - - /** - * Adds a new constructor to the class, with the given attributes - * and signature. - */ - def DefineConstructor(attrs: Short, callingConvention: Short, paramTypes: Array[Type]): ConstructorBuilder = { - val constr = new ConstructorBuilder(this, attrs, paramTypes) - val iter = constructorBuilders.iterator - while(iter.hasNext) { - val c = iter.next().asInstanceOf[ConstructorInfo] - if (constructorsEqual(c, constr)) { - throw new RuntimeException("["+ Assembly() + "] Constructor has already been defined: " + c) - } - } - constructorBuilders += constr - return constr - } - - /** - * Defines a nested type given its name. - */ - def DefineNestedType(name: String, attributes: Int, baseType: Type, interfaces: Array[Type]): TypeBuilder = { - val nested = nestedTypeBuilders.iterator - while(nested.hasNext) { - val nt = nested.next - if (nt.Name.equals(name)) { - val message = "Nested type " + name + " has already been defined: " + nt - throw new RuntimeException(message) - } - } - val t = new TypeBuilder(Module, attributes, name, baseType, interfaces, this) - nestedTypeBuilders += t - return t - } - - /** Get the field with the corresponding name. */ - override def GetField(name: String): FieldInfo = { - testRaw(name) - return super.GetField(name) - } - - /** Get all fields of the current Type. */ - override def GetFields(): Array[FieldInfo] = { - testRaw("") - return super.GetFields() - } - - /** - * Searches for a public instance constructor whose parameters - * match the types in the specified array. - */ - override def GetConstructor(params: Array[Type]): ConstructorInfo = { - testRaw(".ctor" + types2String(params)) - return super.GetConstructor(params) - } - - /** - * Returns all the public constructors defined for the current Type. - */ - override def GetConstructors(): Array[ConstructorInfo] = { - testRaw("") - return super.GetConstructors() - } - - /** - * Searches for the specified public method whose parameters - * match the specified argument types. - */ - override def GetMethod(name: String, params: Array[Type]): MethodInfo = { - testRaw(name + types2String(params)) - return super.GetMethod(name, params) - } - - /** Returns all the public methods of the current Type. */ - override def GetMethods(): Array[MethodInfo] = { - testRaw("") - return super.GetMethods() - } - - /** Searches for the nested type with the specified name. */ - override def GetNestedType(name: String): Type = { - testRaw(name) - super.GetNestedType(name) - } - - /** Returns all the types nested within the current Type. */ - override def GetNestedTypes(): Array[Type] = { - testRaw("") - super.GetNestedTypes() - } - - /** Returns a Type object that represents a one-dimensional array of the current type */ - def MakeArrayType(): Type = { - Type.mkArray(this, 1) - } - - /** Sets a custom attribute. */ - def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) { - addCustomAttribute(constr, value) - } - - def setPosition(sourceLine: Int, sourceFilename: String) { - this.sourceLine = sourceLine - this.sourceFilename = sourceFilename - } - - def setSourceFilepath(sourceFilepath: String) { - this.sourceFilepath = sourceFilepath - } - - //########################################################################## - // protected members - - var sourceLine: Int = _ - var sourceFilename: String = _ - var sourceFilepath: String = _ - - var fieldBuilders = scala.collection.mutable.ArrayBuffer.empty[FieldBuilder] - var methodBuilders = scala.collection.mutable.ArrayBuffer.empty[MethodBuilder] - var constructorBuilders = scala.collection.mutable.ArrayBuffer.empty[ConstructorBuilder] - var nestedTypeBuilders = scala.collection.mutable.ArrayBuffer.empty[TypeBuilder] - - // shows if the type is 'raw', i.e. still subject to changes - private var raw = true - - // throws an exception if the type is 'raw', - // i.e. not finalized by call to CreateType - protected def testRaw(member: String) { - if (raw) - throw new RuntimeException("Not supported for TypeBuilder before CreateType(): " + - FullName + "::" + member) - } - - //########################################################################## - // public members not part of the Reflection.Emit.TypeBuilder interface. - - /** The apply method for a visitor. */ - @throws(classOf[IOException]) - def apply(v: Visitor) { - v.caseTypeBuilder(this) - } - - //########################################################################## - -} // class TypeBuilder - -object TypeBuilder { - def types2String(types: Array[Type]): String = { - val s = new StringBuffer("(") - for(i <- 0 until types.length) { - if (i > 0) s.append(", ") - s.append(types(i)) - } - s.append(")") - return s.toString() - } - - def methodsEqual(m1: MethodInfo, m2: MethodInfo): Boolean = { - if (!m1.Name.equals(m2.Name)) - return false - if (m1.ReturnType != m2.ReturnType) - return false - val p1 = m1.GetParameters() - val p2 = m2.GetParameters() - if (p1.length != p2.length) - return false - for(i <- 0 until p1.length) - if (p1(i).ParameterType != p2(i).ParameterType) - return false - return true - } - - def constructorsEqual(c1: ConstructorInfo, c2: ConstructorInfo): Boolean = { - if (c1.IsStatic != c2.IsStatic) - return false - val p1 = c1.GetParameters() - val p2 = c2.GetParameters() - if (p1.length != p2.length) - return false - for(i <- 0 until p1.length) - if (p1(i).ParameterType != p2(i).ParameterType) - return false - return true -} - -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitable.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitable.scala deleted file mode 100644 index 28ec801dd4cc..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitable.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import java.io.IOException - -/** - * The Visitable interface - */ -trait Visitable { - - //########################################################################## - - /** - * the visitable method to apply a visitor - */ - @throws(classOf[IOException]) - def apply(v: Visitor): Unit - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitor.scala deleted file mode 100644 index d4b84cdd4e04..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitor.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies to MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import java.io.IOException - -/** - * The Visitor interface to walk through the MSIL code Builder hierarchy. - */ -trait Visitor { - - //########################################################################## - - /** Visit an AssemblyBuilder */ - @throws(classOf[IOException]) - def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder): Unit - - /** Visit a ModuleBuilder */ - @throws(classOf[IOException]) - def caseModuleBuilder(moduleBuilder: ModuleBuilder): Unit - - /** Visit a TypeBuilder */ - @throws(classOf[IOException]) - def caseTypeBuilder(typeBuilder: TypeBuilder): Unit - - /** Visit a FieldBuilder */ - @throws(classOf[IOException]) - def caseFieldBuilder(fieldBuilder: FieldBuilder): Unit - - /** Visit a ConstructorBuilder */ - @throws(classOf[IOException]) - def caseConstructorBuilder(constructorBuilder: ConstructorBuilder): Unit - - /** Visit a MethodBuilder */ - @throws(classOf[IOException]) - def caseMethodBuilder(methodBuilder: MethodBuilder): Unit - - /** Visit a ParameterBuilder */ - @throws(classOf[IOException]) - def caseParameterBuilder(parameterBuilder: ParameterBuilder): Unit - - /** Visit an ILGenerator */ - @throws(classOf[IOException]) - def caseILGenerator(iLGenerator: ILGenerator): Unit - - /** Visit an OpCode */ - @throws(classOf[IOException]) - def caseOpCode(opCode: OpCode): Unit - - /** Visit a LocalBuilder */ - @throws(classOf[IOException]) - def caseLocalBuilder(localBuilder: LocalBuilder): Unit - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/CustomAttributesTest.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/CustomAttributesTest.java deleted file mode 100644 index 9a6e28a545fd..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/tests/CustomAttributesTest.java +++ /dev/null @@ -1,31 +0,0 @@ - -package ch.epfl.lamp.compiler.msil.tests; - -import ch.epfl.lamp.compiler.msil.*; -import ch.epfl.lamp.compiler.msil.util.Table; - -import java.io.PrintStream; - -public class CustomAttributesTest { - public static void main(String[] args) { - if (args.length < 1) { - System.err.println("You must supply a filename!"); - System.exit(1); - } - - Assembly assem = Assembly.LoadFrom(args[0]); - Type.initMSCORLIB(assem); - - testCustomAttributes(); - } - - public static void testCustomAttributes() { - Object[] attrs = Type.GetType("System.ObsoleteAttribute") - .GetCustomAttributes(false); - assert attrs != null; - for (int i = 0; i < attrs.length; i++) { - System.out.println("\t" + attrs[i]); - } - } - -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/JavaTypeTest.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/JavaTypeTest.java deleted file mode 100644 index 96ec1bfeeac8..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/tests/JavaTypeTest.java +++ /dev/null @@ -1,18 +0,0 @@ - -package ch.epfl.lamp.compiler.msil.tests; - -import ch.epfl.lamp.compiler.msil.*; -import ch.epfl.lamp.compiler.msil.util.VJSAssembly; - -public class JavaTypeTest { - - public static void main(String[] args) { - if (args.length < 1) { - System.err.println("usage: java test.JavaTypeTest classname"); - System.exit(1); - } - - Type type = VJSAssembly.VJSLIB.GetType(args[0]); - MembersTest.dumpType(System.out, type); - } -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/MembersTest.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/MembersTest.java deleted file mode 100644 index 37a5c6ea907f..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/tests/MembersTest.java +++ /dev/null @@ -1,100 +0,0 @@ - -package ch.epfl.lamp.compiler.msil.tests; - -import ch.epfl.lamp.compiler.msil.*; -import ch.epfl.lamp.compiler.msil.util.Table; - -import java.io.PrintStream; - -public class MembersTest { - - public static void main(String[] args) { - if (args.length < 1) { - System.err.println - ("usage: java test.MembersTest assembly [classname]"); - System.exit(1); - } - - Assembly mscorlib = Assembly.LoadFrom("mscorlib.dll"); - Type.initMSCORLIB(mscorlib); - Assembly assem = Assembly.LoadFrom(args[0]); - if (args.length > 1) { - Type type = assem.GetType(args[1]); - if (type != null) - dumpMember(System.out, type); - else System.err.println("Cannot find type " + args[1] - + " in " + assem); - } else { - Type[] types = assem.GetTypes(); - System.out.println("Number of types in assembly " + assem - + " -> " + types.length); - dumpCustomAttributes(System.out, "assembly: ", assem); - Module[] modules = assem.GetModules(); - for (int i = 0; i < modules.length; i++) { - dumpCustomAttributes(System.out, "module " + modules[i] + ": ", - modules[i]); - } - dumpMembers(System.out, types); - } - } - - public static final void dumpMember(PrintStream out, MemberInfo member) { - try { - if (member.MemberType() == MemberTypes.TypeInfo - || member.MemberType() == MemberTypes.NestedType) { - Type type = (Type)member; - dumpCustomAttributes(out, "", type); - out.print(TypeAttributes.accessModsToString(type.Attributes)); - out.print(type.IsInterface() ? " interface " : " class "); - out.print(type); - if (type.BaseType() != null) - out.println(" extends " + type.BaseType()); - Type[] ifaces = type.GetInterfaces(); - if (ifaces.length > 0) { - out.print("\timplements "); - for (int i = 0; i < ifaces.length; i++) { - out.print(ifaces[i]); - if (i < (ifaces.length - 1)) - out.print(", "); - } - out.println(); - } - out.println("{"); - int all = BindingFlags.Public | BindingFlags.DeclaredOnly// | BindingFlags.NonPublic - | BindingFlags.Instance | BindingFlags.Static; - dumpMembers(out, type.GetNestedTypes()); - dumpMembers(out, type.GetFields(all)); - dumpMembers(out, type.GetConstructors(all)); - dumpMembers(out, type.GetMethods(all)); - dumpMembers(out, type.GetProperties(all)); - dumpMembers(out, type.GetEvents()); - out.println("}"); - } else { - dumpCustomAttributes(out, "", member); - out.print(MemberTypes.toString(member.MemberType())); - out.print(": "); out.print(member); - out.println(); - } - } catch (Throwable e) { - String message = MemberTypes.toString(member.MemberType()) - + ": " + member; - throw new RuntimeException(message, e); - } - } - - public static void dumpCustomAttributes(PrintStream out, - String prefix, - ICustomAttributeProvider att) - { - Object[] attrs = att.GetCustomAttributes(false); - for (int j = 0; j < attrs.length; j++) - out.println(prefix + attrs[j]); - } - - public static void dumpMembers(PrintStream out, MemberInfo[] members) { - for (int i = 0; i < members.length; i++) { - dumpMember(out, members[i]); - } - } - -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/TableDump.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/TableDump.java deleted file mode 100644 index 1df389b011bc..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/tests/TableDump.java +++ /dev/null @@ -1,311 +0,0 @@ - -package ch.epfl.lamp.compiler.msil.tests; - -import ch.epfl.lamp.compiler.msil.PEFile; -import ch.epfl.lamp.compiler.msil.util.Table; -import ch.epfl.lamp.compiler.msil.util.Table.*; - -import java.io.PrintStream; -import java.io.FileNotFoundException; - -public class TableDump extends PEFile { - - //########################################################################## - - public TableDump(String filename) throws FileNotFoundException { - super(filename); - } - - /***/ - public void dump(PrintStream out) { - out.println("CLI RVA: " + CLI_RVA); - out.println("Optional header size: " + optHeaderSize); - out.println("Number of sections: " + numOfSections); - out.println(); - - for (int i = 0; i < sections.length; i++) { - sections[i].dump(out); - out.println(); - } - - out.println("MetaData Offset: 0x" + Integer.toHexString(posMetadata)); - out.println("Number of streams: " + numOfStreams); - - out.println("#~ stream"); Meta.dump(out); out.println(); - out.println("#Strings stream"); Strings.dump(out); out.println(); - if (US != null) { - out.println("#US stream"); US.dump(out); out.println(); - } - out.println("#GUID stream"); GUID.dump(out); out.println(); - out.println("#Blob stream"); Blob.dump(out); out.println(); - - out.println("Heap Sizes IndexedSeq = 0x0" + Integer.toHexString(heapSizes)); - out.println(); - - for(int i = 0; i < Table.MAX_NUMBER; i++) - if(getTable(i).rows > 0) { - dump(out, getTable(i)); - out.println(); - } - - } - - /** Dumps the contents of this table. */ - public void dump(PrintStream out, Table table) { - out.println("Table:" + " ID = 0x" + byte2hex(table.id)); - out.println("\tname = " + table.getTableName()); - out.println("\trows = " + table.rows); - //out.println("\tStart pos in file = 0x" + Long.toHexString(table.start)); - for (int i = 1; i <= table.rows; i++) - dumpRow(out, table, i); - } - - public void dumpIndex(PrintStream out, int tableSetId, int index) { - int tableId = Table.getTableId(tableSetId, index); - int row = Table.getTableIndex(tableSetId, index); - out.print(getTable(tableId).getTableName()); - out.print('['); - out.print(getTable(tableId).isShort ? short2hex(row) : int2hex(row)); - out.print(']'); - } - - public void dumpRow(PrintStream out, Table table, int row) { - table.readRow(row); - out.print(table.getTableName()); - out.print("[" + short2hex(row) + "]: "); - dumpRow(out, table); - out.println(); - } - - /** Prints the current content of the fields of the class. */ - public void dumpRow(PrintStream out, Table table) { - if (table instanceof ModuleDef) { - ModuleDef t = (ModuleDef)table; - out.print("Generation = 0x" + short2hex(t.Generation)); - out.print("; Name = " + getString(t.Name)); - //out.print("; Mvid = (" + bytes2hex(getGUID(Mvid)) + ")"); - } else if (table instanceof TypeRef) { - TypeRef t = (TypeRef)table; - out.print("FullName = " + t.getFullName()); - out.print("; ResolutionScope = 0x" + int2hex(t.ResolutionScope)); - } else if (table instanceof TypeDef) { - TypeDef t = (TypeDef)table; - out.print("Flags = 0x"); out.print(int2hex(t.Flags)); - out.print("; FullName = "); out.print(t.getFullName()); - out.print("; Extends = "); - dumpIndex(out, Table._TypeDefOrRef, t.Extends); - out.print("; FieldList = "); out.print(t.FieldList); - out.print("; MethodList = "); out.print(t.MethodList); - } else if (table instanceof FieldTrans) { - FieldTrans t = (FieldTrans)table; - out.print("Field = "); out.print(t.Field); - } else if (table instanceof FieldDef) { - FieldDef t = (FieldDef)table; - out.print("Flags = 0x" + short2hex(t.Flags)); - out.print("; Name = " + t.getName()); - out.print("; Signature = (" + - bytes2hex(getBlob(t.Signature)) + ")"); - } else if (table instanceof MethodTrans) { - MethodTrans t = (MethodTrans)table; - out.print("Method = "); out.print(t.Method); - } else if (table instanceof MethodDef) { - MethodDef t = (MethodDef)table; - out.print("Flags = 0x" + short2hex(t.Flags)); - out.print("; Name = " + t.getName()); - out.print("; ParamList = " + t.ParamList); - out.print("; Signature = (" + - bytes2hex(getBlob(t.Signature)) + ")"); - } else if (table instanceof ParamDef) { - ParamDef t = (ParamDef)table; - out.print("Flags = 0x" + short2hex(t.Flags)); - out.print("; Name = " + t.getName()); - out.print("; Sequence = " + t.Sequence); - } else if (table instanceof InterfaceImpl) { - InterfaceImpl t = (InterfaceImpl)table; - out.print("Class = 0x" + short2hex(t.Class));// + " (ref to: "); - //TypeDef td = (TypeDef) getTable(TypeDef.ID); - //td.readRow(Class); - //td.dumpRow(out); - out.print("; Interface = 0x" + short2hex(t.Interface)); - } else if (table instanceof MemberRef) { - MemberRef t = (MemberRef)table; - out.print("Name = " + t.getName()); - out.print("; Signature = (" + - bytes2hex(getBlob(t.Signature)) + ")"); - out.print("; Class = " + t.Class); - } else if (table instanceof Constant) { - Constant t = (Constant)table; - out.print("Parent = "); dumpIndex(out, Table._HasConstant, t.Parent); - out.print("; Type = 0x" + byte2hex(t.Type)); - out.print("; Value = (" + bytes2hex(getBlob(t.Value))); - out.print("); Value = " + t.getValue()); - } else if (table instanceof CustomAttribute) { - CustomAttribute t = (CustomAttribute)table; - //out.print("Parent = 0x" + int2hex(t.Parent)); - out.print("Parent = "); - dumpIndex(out, Table._HasCustomAttribute, t.Parent); - //out.print("; Type = 0x" + short2hex(t.Type)); - out.print("; Type = "); - dumpIndex(out, Table._CustomAttributeType, t.Type); - out.print("; Value = (" + bytes2hex(t.getValue()) + ")"); - } else if (table instanceof FieldMarshal) { - FieldMarshal t = (FieldMarshal)table; - out.print("NativeType = ("); - out.print(bytes2hex(getBlob(t.NativeType)) + ")"); - } else if (table instanceof DeclSecurity) { - DeclSecurity t = (DeclSecurity)table; - out.print("Action = 0x" + short2hex(t.Action)); - out.print("; PermissionSet = (" + - bytes2hex(getBlob(t.PermissionSet)) + ")"); - } else if (table instanceof ClassLayout) { - ClassLayout t = (ClassLayout)table; - out.print("PackingSize = 0x" + short2hex(t.PackingSize)); - out.print("; ClassSize = 0x" + int2hex(t.ClassSize)); - out.print(": Parent = " + t.Parent + " (ref to: "); - dumpRow(out, this.TypeDef(t.Parent)); - out.print(")"); - } else if (table instanceof FieldLayout) { - FieldLayout t = (FieldLayout)table; - out.print("Offset = 0x" + int2hex(t.Offset)); - out.print("; Field = (ref to: "); - dumpRow(out, this.FieldDef(t.Field)); - out.print(")"); - } else if (table instanceof StandAloneSig) { - StandAloneSig t = (StandAloneSig)table; - out.print("StandAloneSig: Signature = (" + - bytes2hex(getBlob(t.Signature)) + ")"); - } else if (table instanceof EventMap) { - EventMap t = (EventMap)table; - out.print("Parent = 0x" + int2hex(t.Parent) + " (ref to: "); - dumpRow(out, this.TypeDef(t.Parent)); - out.print("); EventList = 0x"); out.print(int2hex(t.EventList)); - } else if (table instanceof EventDef) { - EventDef t = (EventDef)table; - out.print("EventFlags = 0x" + short2hex(t.EventFlags)); - out.print("; Name = " + t.getName()); - out.print("; EventType = 0x" + int2hex(t.EventType)); - } else if (table instanceof PropertyMap) { - PropertyMap t = (PropertyMap)table; - out.print("Parent = " + t.Parent + " (ref to: "); - dumpRow(out, this.TypeDef(t.Parent)); - out.print(")"); - } else if (table instanceof PropertyDef) { - PropertyDef t = (PropertyDef)table; - out.print("Flags = 0x" + short2hex(t.Flags)); - out.print("; Name = " + t.getName()); - out.print("; Type = (" + bytes2hex(getBlob(t.Type)) + ")"); - } else if (table instanceof MethodSemantics) { - MethodSemantics t = (MethodSemantics)table; - out.print("Semantics = 0x" + short2hex(t.Semantics)); - out.print("; Method = 0x" + int2hex(t.Method) + " (ref to: "); - dumpRow(out, this.MethodDef(t.Method)); - out.print("); Association = 0x" + int2hex(t.Association)); - } else if (table instanceof MethodImpl) { - MethodImpl t = (MethodImpl)table; - out.print("Class = (ref to: "); - dumpRow(out, this.TypeDef(t.Class)); - out.print(")"); - } else if (table instanceof ModuleRef) { - ModuleRef t = (ModuleRef)table; - out.print("Name = " + t.getName()); - } else if (table instanceof TypeSpec) { - TypeSpec t = (TypeSpec)table; - out.print("Signature = (" + - bytes2hex(getBlob(t.Signature)) + ")"); - } else if (table instanceof ImplMap) { - ImplMap t = (ImplMap)table; - out.print("ImportName = " + getString(t.ImportName)); - } else if (table instanceof FieldRVA) { - FieldRVA t = (FieldRVA)table; - out.print("RVA = 0x" + int2hex(t.RVA)); - out.print("; Field = (ref to: "); - dumpRow(out, this.FieldDef(t.Field)); - out.print(")"); - } else if (table instanceof AssemblyDef) { - AssemblyDef t = (AssemblyDef)table; - out.print("Flags = 0x" + int2hex(t.Flags)); - out.print(" ; Name = " + getString(t.Name)); - out.print("; Culture = " + getString(t.Culture)); - out.print(" ; Version = " + t.MajorVersion + "."); - out.print(t.MinorVersion + "." + t.BuildNumber); - out.print("." + t.RevisionNumber); - out.print("; HashAlgId = 0x" + int2hex(t.HashAlgId)); - out.print("; PublicKey = ("); - out.print(bytes2hex(getBlob(t.PublicKey)) + ")"); - } else if (table instanceof AssemblyProcessor) { - AssemblyProcessor t = (AssemblyProcessor)table; - out.print("Processor = 0x" + int2hex(t.Processor)); - } else if (table instanceof AssemblyOS) { - AssemblyOS t = (AssemblyOS)table; - out.print("!?!"); - } else if (table instanceof AssemblyRef) { - AssemblyRef t = (AssemblyRef)table; - out.print("Flags = 0x" + int2hex(t.Flags)); - out.print("; Name = " + getString(t.Name)); - out.print("; Culture = " + getString(t.Culture)); - out.print("; Version = " + t.MajorVersion + "." + t.MinorVersion); - out.print("." + t.BuildNumber + "." + t.RevisionNumber); - out.print("; PublicKeyOrToken = (" + - bytes2hex(getBlob(t.PublicKeyOrToken)) + ")"); - out.print("; HashValue = (" + - bytes2hex(getBlob(t.HashValue)) + ")"); - } else if (table instanceof AssemblyRefProcessor) { - AssemblyRefProcessor t = (AssemblyRefProcessor)table; - out.print("!?!"); - } else if (table instanceof AssemblyRefOS) { - AssemblyRefOS t = (AssemblyRefOS)table; - out.print("!?!"); - } else if (table instanceof FileDef) { - FileDef t = (FileDef)table; - out.print("Flags = 0x" + int2hex(t.Flags)); - out.print("; Name = " + t.getName()); - out.print("; HashValue = (" + bytes2hex(getBlob(t.HashValue)) +")"); - } else if (table instanceof ExportedType) { - ExportedType t = (ExportedType)table; - out.print("FullName = " + t.getFullName()); - } else if (table instanceof ManifestResource) { - ManifestResource t = (ManifestResource)table; - out.print("Name = " + getString(t.Name)); - out.print("; Flags = 0x" + int2hex(t.Flags)); - } else if (table instanceof NestedClass) { - NestedClass t = (NestedClass)table; - out.print(this.TypeDef(t.EnclosingClass).getFullName()); - out.print("/"); - out.print(this.TypeDef(t.NestedClass).getFullName()); - } else - throw new RuntimeException("Unknown table " + table.getClass()); - } - - //########################################################################## - - public static void main(String[] args) { - if (args.length < 1) { - System.err.println("You must supply a filename!"); - System.exit(1); - } - - TableDump file = null; - try { - file = new TableDump(args[0]); - } catch (FileNotFoundException e) { e.printStackTrace(); } - - if (args.length > 1) { - nextarg: - for (int i = 1; i < args.length; i++) { - String name = args[i]; - for (int tableId = 0; tableId < Table.MAX_NUMBER; tableId++) { - Table table = file.getTable(tableId); - if ((table.rows > 0) && name.equals(table.getTableName())) { - file.dump(System.out, table); - System.out.println(); - continue nextarg; - } - } - System.err.println("No such table: " + name); - } - } else - file.dump(System.out); - } - - //########################################################################## -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/Test.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/Test.java deleted file mode 100644 index 2c5946a73441..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/tests/Test.java +++ /dev/null @@ -1,92 +0,0 @@ - -package test; - -import ch.epfl.lamp.compiler.msil.*; -import ch.epfl.lamp.compiler.msil.util.Table; - -import java.io.PrintStream; - -public class Test { - public static void main(String[] args) { - if (args.length < 1) { - System.err.println("You must supply a filename!"); - System.exit(1); - } - - Assembly assem = Assembly.LoadFrom(args[0]); - Type.initMSCORLIB(assem); - - //"System.Collections.ArrayList" - if (args.length >= 2) { - Type t = Type.GetType(args[1]); - dumpType(System.out, t); - } else { - dumpAssembly(assem); - } - } - - - public static void dumpAssembly(Assembly assem) { - Module[] modules = assem.GetModules(); -// System.out.println("Modules in assembly " + assem + -// " (" + modules.length + ")"); -// for (int i = 0; i < modules.length; i++) { -// System.out.println("\t" + modules[i]); -// } - - Type[] types = modules[0].GetTypes(); -// System.out.println("Types in assembly " + assem + -// " (" + types.length + ")"); - for (int i = 0; i < types.length; i++) { - System.out.println("#" + i + " -> " + types[i]); - types[i].completeType(); - } - } - - public static final void dumpType(PrintStream out, Type type) { - out.println("Type = " + type); - out.println("Name = " + type.Name); - out.println("Namespace = " + type.Namespace); - out.println("FullName = " + type.FullName); - out.println("Attributes = " + TypeAttributes.toString(type.Attributes)); - out.println("BaseType = " + type.BaseType); - Type[] ifaces = type.GetInterfaces(); - if (ifaces != null) { - for (int i = 0; i < ifaces.length; i++) - out.println("\timplements " + ifaces[i]); - } - out.println("Assembly = " + type.Assembly); - out.println("Module = " + type.Module); - out.println("DeclaringType = " + type.DeclaringType); - out.println("IsInterface = " + type.IsInterface); - out.println("IsAbstract = " + type.IsAbstract); - - FieldInfo[] fields = type.GetFields(BindingFlags.Instance - | BindingFlags.Static - | BindingFlags.NonPublic); - out.println("\nFields (" + fields.length + "):"); - for (int i = 0; i < fields.length; i++) { - out.println("\t" + fields[i]); - out.println("\t\tDeclaringType = " + fields[i].DeclaringType); - out.println("\t\tReflectedType = " + fields[i].ReflectedType); - } - - ConstructorInfo[] constrs = type.GetConstructors(); - out.println("\nConstructors (" + constrs.length + "):"); - for (int i = 0; i < constrs.length; i++) { - out.println("\t" + constrs[i]); - } - -// MethodInfo[] methods = type.GetMethods(BindingFlags.Instance -// | BindingFlags.Static -// | BindingFlags.Public -// | BindingFlags.NonPublic); - MethodInfo[] methods = type.GetMethods(); - out.println("\nMethods (" + methods.length + "):"); - for (int i = 0; i < methods.length; i++) { - out.println("\t" + methods[i]); - out.println("\t\tDeclaringType = " + methods[i].DeclaringType); - out.println("\t\tReflectedType = " + methods[i].ReflectedType); - } - } -} diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java b/src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java deleted file mode 100644 index 56519e8487a1..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/util/PECustomMod.java +++ /dev/null @@ -1,23 +0,0 @@ -package ch.epfl.lamp.compiler.msil.util; - -import ch.epfl.lamp.compiler.msil.Type; -import ch.epfl.lamp.compiler.msil.CustomModifier; - -/** - * A PECustomMod holds the info parsed from metadata per the CustomMod production in Sec. 23.2.7, Partition II. - * */ -public final class PECustomMod { - - public final Type marked; - public final CustomModifier[] cmods; - - /** Terminology: - the CustomModifier(s) are markers, - and the msil.Type is a type marked by those markers. */ - public PECustomMod(Type marked, CustomModifier[] cmods) { - this.marked = marked; - this.cmods = cmods; - } - -} - diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/PESection.java b/src/msil/ch/epfl/lamp/compiler/msil/util/PESection.java deleted file mode 100644 index 454a94e55c67..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/util/PESection.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * System.Reflection-like API for acces to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil.util; - -import ch.epfl.lamp.compiler.msil.PEFile; - -import java.io.PrintStream; - -/** Describes a section from a PE/COFF file - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class PESection { - - private final PEFile file; - private final long sectionStart; - - public final String name; - public final int virtAddr; - public final int virtSize; - public final int realAddr; - public final int realSize; - public final int flags; - - private static final byte[] buf = new byte[8]; - - public PESection(PEFile file) { - this.file = file; - sectionStart = file.pos(); - file.read(buf); - int i; - for(i = 7; (i >= 0) && (0 == buf[i]); i--); - name = new String(buf, 0, i + 1); - virtSize = file.readInt(); - virtAddr = file.readInt(); - realSize = file.readInt(); - realAddr = file.readInt(); - file.skip(3 * PEFile.INT_SIZE); - flags = file.readInt(); - } - - - public void dump(PrintStream out) { - out.println("Section name: " + name + - " (name.length=" + name.length() + ")"); - out.println("Virtual Address: 0x" + PEFile.int2hex(virtAddr)); - out.println("Virtual Size: 0x" + PEFile.int2hex(virtSize)); - out.println("Real Address: 0x" + PEFile.int2hex(realAddr)); - out.println("Real Size: 0x" + PEFile.int2hex(realSize)); - out.println("Flags: 0x" + PEFile.int2hex(flags)); - } - -} // class PESection diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/PEStream.java b/src/msil/ch/epfl/lamp/compiler/msil/util/PEStream.java deleted file mode 100644 index 649d9e74f2bd..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/util/PEStream.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * System.Reflection-like API for acces to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil.util; - -import ch.epfl.lamp.compiler.msil.PEFile; -import ch.epfl.lamp.compiler.msil.PEFile.Sig; - -import java.io.PrintStream; -import java.io.IOException; - -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; - -/** - * Implements support for CLI streams within a PE file. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public final class PEStream implements Signature { - - //########################################################################## - // Members - - /** The name of the stream. */ - public final String name; - - /** The offset of the stream from the beginning of the file. */ - public final int offset; - - /** The size of the stream in bytes; shall be multiple of 4. */ - public final int size; - - private final PEFile file; - - private final ByteBuffer buffer; - - //########################################################################## - - /** The PEStream class constructor. - * @param file - the PEFile to which this stream belongs - */ - public PEStream(PEFile file) { - this.file = file; - offset = file.fromRVA(file.rvaMetadata + file.readInt()); - size = file.readInt(); - buffer = file.getBuffer(offset, size); - - int i = 0; - byte [] _buf = new byte [16]; - do { - _buf[i] = (byte) file.readByte(); - i++; - } while(0 != _buf[i-1]); - name = new String(_buf, 0, i - 1); - - file.align(PEFile.INT_SIZE, file.posMetadata); - //assert size % 4 == 0; - } - - /** Move to the specified position in the stream. */ - private void seek(int pos) { - try { - buffer.position(pos); - } catch (IllegalArgumentException e) { - System.err.println("\nSeek failed in file " + file - + " for position " + pos - + " of stream " + name + " (" + buffer + ")"); - throw e; - } - } - - /** Return a string from the specified position in the stream. */ - public String getString(int pos) { - seek(pos); - buffer.mark(); - int i; - for (i = 0; getByte() != 0; i++); - byte[] buf = new byte[i]; - buffer.reset(); // go back to the marked position - buffer.get(buf); - try { - return new String(buf, "UTF-8"); - } catch (java.io.UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - /** Read a byte from the stream. */ - public int getByte() { - return (buffer.get() + 0x0100) & 0xff; - } - - /** Return the GUID at the given position in the stream. */ - public byte[] getGUID(int pos) { - seek(pos); - byte[] buf = new byte[32]; // 128-bit GUID - try { - buffer.get(buf); - } catch (Exception e) { - System.err.println(); - System.err.println("PEStream.getBlob(): Exception for pos = " + - pos + " and buf.length = " + buf.length); - System.err.println("\tbuffer = " + buffer); - e.printStackTrace(); - throw new RuntimeException(); - } - return buf; - } - - public int readLength() { - int length = getByte(); - if ((length & 0x80) != 0) { - length = ((length & 0x7f) << 8) | getByte(); - if ((length & 0x4000) != 0) - length = ((length & 0x3fff) << 16) | (getByte()<<8) | getByte(); - } - return length; - } - - /** Return a blob from the specified position in the stream. */ - public byte[] getBlob(int pos) { - seek(pos); - // the length indicates the number of bytes - // AFTER the encoded size of the blob - int length = readLength(); - byte[] buf = new byte[length]; - buffer.get(buf); - return buf; - } - - /***/ - public Sig getSignature(int pos) { - seek(pos); - return file.newSignature(buffer); - } - - /** - */ - public Object getConstant(int type, int pos) { - Object val = null; - seek(pos); - int length = readLength(); // skip over the blob length field - switch (type) { - case ELEMENT_TYPE_BOOLEAN: - assert length == 1; - return buffer.get() == 0 ? Boolean.FALSE : Boolean.TRUE; - case ELEMENT_TYPE_CHAR: - assert length == 2 : "length == " + length; - return new Character(buffer.getChar()); - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: // TODO U1 not the same as I1 - assert length == 1; - return new Byte(buffer.get()); - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - assert length == 2; - return new Short(buffer.getShort()); - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - assert length == 4; - return new Integer(buffer.getInt()); - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - assert length == 8; - return new Long(buffer.getLong()); - case ELEMENT_TYPE_R4: - assert length == 4; - return new Float(buffer.getFloat()); - case ELEMENT_TYPE_R8: - assert length == 8; - return new Double(buffer.getDouble()); - case ELEMENT_TYPE_STRING: -// length /= 2; -// char[] chars = new char[length]; -// for (int i = 0; i < length; i++) -// chars[i] = buffer.getChar(); -// val = new String(chars); - try { - return new String(getBlob(pos), "UTF-16LE"); - } catch(java.io.UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - default: throw new RuntimeException("Illegal constant type: " + type); - } - } - - public void dump(PrintStream out) { - out.println("Stream name: " + name + " (length " + - name.length() + " characters)"); - out.println("Stream offset: 0x" + PEFile.int2hex(offset)); - out.println("Stream size: 0x" + PEFile.int2hex(size)); - } - - //########################################################################## -} // class PEStream diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/Signature.java b/src/msil/ch/epfl/lamp/compiler/msil/util/Signature.java deleted file mode 100644 index d5dc0ff32ccd..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/util/Signature.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * System.Reflection-like API for acces to .NET assemblies (DLL & EXE) - */ - - -package ch.epfl.lamp.compiler.msil.util; - -import ch.epfl.lamp.compiler.msil.Type; - -/** - * Signatures - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public interface Signature { - - //########################################################################## - - /** Marks end of a list. */ - public static final int ELEMENT_TYPE_END = 0x00; - /** void */ - public static final int ELEMENT_TYPE_VOID = 0x01; - /** boolean */ - public static final int ELEMENT_TYPE_BOOLEAN = 0x02; - /** char */ - public static final int ELEMENT_TYPE_CHAR = 0x03; - /** signed byte */ - public static final int ELEMENT_TYPE_I1 = 0x04; - /** byte */ - public static final int ELEMENT_TYPE_U1 = 0x05; - /** short */ - public static final int ELEMENT_TYPE_I2 = 0x06; - /** unsigned short */ - public static final int ELEMENT_TYPE_U2 = 0x07; - /** int */ - public static final int ELEMENT_TYPE_I4 = 0x08; - /** unsigned int */ - public static final int ELEMENT_TYPE_U4 = 0x09; - /** long */ - public static final int ELEMENT_TYPE_I8 = 0x0a; - /** unsigned long */ - public static final int ELEMENT_TYPE_U8 = 0x0b; - /** float */ - public static final int ELEMENT_TYPE_R4 = 0x0c; - /** double */ - public static final int ELEMENT_TYPE_R8 = 0x0d; - /** string */ - public static final int ELEMENT_TYPE_STRING = 0x0e; - /** Followed by token. */ - public static final int ELEMENT_TYPE_PTR = 0x0f; - /** Followed by token. */ - public static final int ELEMENT_TYPE_BYREF = 0x10; - /** Followed by token */ - public static final int ELEMENT_TYPE_VALUETYPE = 0x11; - /** Followed by token */ - public static final int ELEMENT_TYPE_CLASS = 0x12; - - public static final int ELEMENT_TYPE_VAR = 0x13; - - /** - * ... ... - */ - public static final int ELEMENT_TYPE_ARRAY = 0x14; - - public static final int ELEMENT_TYPE_GENERICINST = 0x15; - /***/ - public static final int ELEMENT_TYPE_TYPEDBYREF = 0x16; - /** System.IntPtr */ - public static final int ELEMENT_TYPE_I = 0x18; - /** System.UIntPtr */ - public static final int ELEMENT_TYPE_U = 0x19; - /** Followed by full method signature. */ - public static final int ELEMENT_TYPE_FNPTR = 0x1b; - /** System.Object. */ - public static final int ELEMENT_TYPE_OBJECT = 0x1c; - /** Single-dim array with 0 lower bound. */ - public static final int ELEMENT_TYPE_SZARRAY = 0x1d; - - public static final int ELEMENT_TYPE_MVAR = 0x1e; - - /** Required modifier : followed by a TypeDef or TypeRef token. */ - public static final int ELEMENT_TYPE_CMOD_REQD = 0x1f; - /** Optional modifier : followed by a TypeDef or TypeRef token. */ - public static final int ELEMENT_TYPE_CMOD_OPT = 0x20; - /** Implemented within the CLI. */ - public static final int ELEMENT_TYPE_INTERNAL = 0x21; - /** Or'd with following element types. */ - public static final int ELEMENT_TYPE_MODIFIER = 0x40; - /** Sentinel for varargs method signature. */ - public static final int ELEMENT_TYPE_SENTINEL = 0x41; - /**Denotes a local variable that points at a pinned object. */ - public static final int ELEMENT_TYPE_PINNED = 0x45; - - //########################################################################## - // signature designators - - public static final int HASTHIS = 0x20; - public static final int EXPLICITTHIS = 0x40; - public static final int DEFAULT = 0x00; - public static final int VARARG = 0x05; - public static final int GENERIC = 0x10; - public static final int SENTINEL = 0x41; - public static final int C = 0x01; - public static final int STDCALL = 0x02; - public static final int THISCALL = 0x03; - public static final int FASTCALL = 0x04; - public static final int FIELD = 0x06; - public static final int PROPERTY = 0x08; - public static final int LOCAL_SIG = 0x07; - - //########################################################################## - // extra IDs used in the serialization format of named arguments - // to custom attributes. Reverse-engineered from compiled C# example - - /** What follows is a string with the full name of the type. */ - public static final int X_ELEMENT_TYPE_TYPE = 0x50; - - /** What follows is a string with the full name of the enumeration type*/ - public static final int X_ELEMENT_TYPE_ENUM = 0x55; - - /** The named argument specifies a field. */ - public static final int X_ELEMENT_KIND_FIELD = 0x53; - - /** The named argument specifies a property. */ - public static final int X_ELEMENT_KIND_PROPERTY = 0x54; - - //########################################################################## -} // interface Signature diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/Table.java b/src/msil/ch/epfl/lamp/compiler/msil/util/Table.java deleted file mode 100644 index 1f43b8c2fa7f..000000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/util/Table.java +++ /dev/null @@ -1,1859 +0,0 @@ -/* - * System.Reflection-like API for acces to .NET Assemblies - */ - - -package ch.epfl.lamp.compiler.msil.util; - -import ch.epfl.lamp.compiler.msil.PEFile; -import ch.epfl.lamp.compiler.msil.PEFile.Sig; - -import java.io.PrintStream; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; - -/** - * Represents a table in a .NET assembly - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -public abstract class Table { - - //########################################################################## - - public static final int MAX_NUMBER = 64; - - public static final long VALID_TABLES_MASK = 0x03ff3fb7ff57L; - - //########################################################################## - // fields and methods for handling predefined sets of tables - - public static final int TABLE_SET_LENGTH = 13; - - public static final int _TypeDefOrRef = 0; - public static final int _HasConstant = 1; - public static final int _HasCustomAttribute = 2; - public static final int _HasFieldMarshal = 3; - public static final int _HasDeclSecurity = 4; - public static final int _MemberRefParent = 5; - public static final int _HasSemantics = 6; - public static final int _MethodDefOrRef = 7; - public static final int _MemberForwarded = 8; - public static final int _Implementation = 9; - public static final int _CustomAttributeType = 10; - public static final int _ResolutionScope = 11; - public static final int _TypeOrMethodDef = 12; - - - public static final int[][] TableSet = new int[TABLE_SET_LENGTH][]; - - static { - TableSet[_TypeDefOrRef] = - new int[] {TypeDef.ID, TypeRef.ID, TypeSpec.ID}; - TableSet[_HasConstant] = - new int[] {FieldDef.ID, ParamDef.ID, PropertyDef.ID}; - TableSet[_HasCustomAttribute] = - new int[] {MethodDef.ID, FieldDef.ID, TypeRef.ID, TypeDef.ID, - ParamDef.ID, InterfaceImpl.ID, MemberRef.ID, ModuleDef.ID, - -1, PropertyDef.ID, EventDef.ID, -1, ModuleRef.ID, - TypeSpec.ID, AssemblyDef.ID, AssemblyRef.ID, - FileDef.ID, ExportedType.ID, ManifestResource.ID}; - TableSet[_HasFieldMarshal] = - new int[] {FieldDef.ID, ParamDef.ID}; - TableSet[_HasDeclSecurity] = - new int[] {TypeDef.ID, MethodDef.ID, AssemblyDef.ID}; - TableSet[_MemberRefParent] = - new int[] {-1, TypeRef.ID, ModuleRef.ID, MethodDef.ID, TypeSpec.ID}; - TableSet[_HasSemantics] = - new int[] {EventDef.ID, PropertyDef.ID}; - TableSet[_MethodDefOrRef] = - new int[] {MethodDef.ID, MemberRef.ID}; - TableSet[_MemberForwarded] = - new int[] {FieldDef.ID, MethodDef.ID}; - TableSet[_Implementation] = - new int[] {FileDef.ID, AssemblyRef.ID, ExportedType.ID}; - TableSet[_CustomAttributeType] = - new int[] {-1, -1, MethodDef.ID, MemberRef.ID, -1}; - TableSet[_ResolutionScope] = - new int[] {ModuleDef.ID, ModuleRef.ID, AssemblyRef.ID, TypeRef.ID}; - TableSet[_TypeOrMethodDef] = - new int[]{TypeDef.ID, MethodDef.ID}; - } - - public static final int[] NoBits = - new int[]{2, 2, 5, 1, 2, 3, 1, 1, 1, 2, 3, 2, 1}; - - public static int getMask(int tableSetId) { - return (1 << NoBits[tableSetId]) - 1; - } - - public static int getTableId(int tableSet, int index) { - return TableSet[tableSet][index & getMask(tableSet)]; - } - - public static int getTableIndex(int tableSet, int index) { - return index >> NoBits[tableSet]; - } - - public static int encodeIndex(int index, int tableSetId, int tableId) { - int[] tableSet = TableSet[tableSetId]; - for (int i = 0; i < tableSet.length; i++) { - if (tableSet[i] == tableId) - return (index << NoBits[tableSetId]) | i; - } - throw new RuntimeException("Cannot find table #" + tableId + - " in table set #" + tableSetId); - } - - //########################################################################## - - private static final String [] tableName = { - "Module", "TypeRef", "TypeDef", " FieldTrans", - "Field", "MethodTrans", "Method", "", - "Param", "InterfaceImpl", "MemberRef", "Constant", - "CustomAttribute", "FieldMarshal", "DeclSecurity","ClassLayout", - "FieldLayout", "StandAloneSig", "EventMap", "", - "Event", "PropertyMap", "", "Property", - "MethodSemantics", "MethodImpl", "ModuleRef", "TypeSpec", - "ImplMap", "FieldRVA", "", "", - "Assembly", "AssemblyProcessor","AssemblyOS", "AssemblyRef", - "AssemblyRefProcessor","AssemblyRefOS", "File", "ExportedType", - "ManifestResource", "NestedClass", "GenericParam", "MethodSpec", - "GenericParamConstraint", "", "", "", - "", "", "", "", - "", "", "", "",//0x30-0x37 - "", "", "", "", - "", "", "", "" //0x37-0x3f - }; - - /** Creates a table with the given id and number of rows. - */ - public static Table newTable(PEFile file, int id, int rows) { - Table table = null; - switch(id) { - case ModuleDef.ID: table = new ModuleDef(file, rows); break; - case TypeRef.ID: table = new TypeRef(file, rows); break; - case TypeDef.ID: table = new TypeDef(file, rows); break; - case FieldTrans.ID: table = new FieldTrans(file, rows); break; - case FieldDef.ID: table = new FieldDef(file, rows); break; - case MethodTrans.ID: table = new MethodTrans(file, rows); break; - case MethodDef.ID: table = new MethodDef(file, rows); break; - case ParamDef.ID: table = new ParamDef(file, rows); break; - case InterfaceImpl.ID: table = new InterfaceImpl(file, rows); break; - case MemberRef.ID: table = new MemberRef(file, rows); break; - case Constant.ID: table = new Constant(file, rows); break; - case CustomAttribute.ID: table = new CustomAttribute(file, rows); break; - case FieldMarshal.ID: table = new FieldMarshal(file, rows); break; - case DeclSecurity.ID: table = new DeclSecurity(file, rows); break; - case ClassLayout.ID: table = new ClassLayout(file, rows); break; - case FieldLayout.ID: table = new FieldLayout(file, rows); break; - case StandAloneSig.ID: table = new StandAloneSig(file, rows); break; - case EventMap.ID: table = new EventMap(file, rows); break; - case EventDef.ID: table = new EventDef(file, rows); break; - case PropertyMap.ID: table = new PropertyMap(file, rows); break; - case PropertyDef.ID: table = new PropertyDef(file, rows); break; - case MethodSemantics.ID: table = new MethodSemantics(file, rows); break; - case MethodImpl.ID: table = new MethodImpl(file, rows); break; - case ModuleRef.ID: table = new ModuleRef(file, rows); break; - case TypeSpec.ID: table = new TypeSpec(file, rows); break; - case ImplMap.ID: table = new ImplMap(file, rows); break; - case FieldRVA.ID: table = new FieldRVA(file, rows); break; - case AssemblyDef.ID: table = new AssemblyDef(file, rows); break; - case AssemblyProcessor.ID: table = new AssemblyProcessor(file, rows); break; - case AssemblyOS.ID: table = new AssemblyOS(file, rows); break; - case AssemblyRef.ID: table = new AssemblyRef(file, rows); break; - case AssemblyRefProcessor.ID: - table = new AssemblyRefProcessor(file, rows); break; - case AssemblyRefOS.ID: table = new AssemblyRefOS(file, rows); break; - case FileDef.ID: table = new FileDef(file, rows); break; - case ExportedType.ID: table = new ExportedType(file, rows); break; - case ManifestResource.ID: table = new ManifestResource(file, rows); break; - case NestedClass.ID: table = new NestedClass(file, rows); break; - case GenericParam.ID: - table = new GenericParam(file, rows); - break; - case MethodSpec.ID: - table = new MethodSpec(file, rows); - break; - case GenericParamConstraint.ID: - table = new GenericParamConstraint(file, rows); - break; - default: - table = new Empty(id); - } -// System.out.println("created table " + table.getName() + " with " -// + table.rows + " rows"); - return table; - } - - - //########################################################################## - // public fields - - /** Number of rows in the table. */ - public final int rows; - - /** Table ID as specified in Partition II. */ - public final int id; - - /** The file to which the table belongs. */ - protected final PEFile file; - - /** Memory mapped buffer wrapping the table. */ - protected ByteBuffer buffer; - - /** - * specified wheter a new memory-mapped byte buffer should be created - * for this table. - */ - protected boolean newMapping = false; - - /** Tells wheter the table is indexed by 2-byte (short) integer - * or by 4-byte integer. */ - public final boolean isShort; - - private int rowSize = -1; - - // the starting position of the table relative to the beginning of the file - private long start = -1; - - // the number of the row who can be accessed via the fields of the table - private int currentRow = 0; - - //########################################################################## - - protected Table(PEFile file, int id, int rows) { - this.file = file; - this.id = id; - this.rows = rows;//file.readInt(); - this.isShort = rows < (1 << 16); -// assert ((1L << id) & VALID_TABLES_MASK) != 0 -// : "Table does not have a vaid ID: " + byte2hex(id); - } - - /** - * Additional table initialization. - * @return the starting position of the next table in the stream. - */ - public final long init(long start) { - if (rows < 1) - return start; - if (this.start == -1) - this.start = start; - else throw new RuntimeException - ("Cannot re-initialize table \'" + getTableName() + "\'"); - rowSize = getRowSize(); - int size = rows * rowSize(); - buffer = this.newMapping ? file.mapBuffer(start, size) - : file.getBuffer(start, size); - return start + size; - } - - - public final String getTableName() { - return 0 <= id && id < MAX_NUMBER ? tableName[id] : ""; - } - - /** - * @return the size of the row in bytes - */ - public final int rowSize() { - return rowSize; - } - - /** - * if the underlying buffer is memory-mapped, load its contents into memory - */ - public void load() { - if (buffer instanceof MappedByteBuffer) - ((MappedByteBuffer)buffer).load(); - } - - /***/ - public final int readByte() { - return (buffer.get() + 0x100) & 0xff; - } - - /***/ - public final int readShort() { - return (buffer.getShort() + 0x10000) & 0xffff; - } - - /***/ - public final int readInt() { - return buffer.getInt(); - } - - /***/ - public final int readStringIndex() { - return file.StringIsShort ? readShort() : readInt(); - } - - /***/ - public final int readBlobIndex() { - return file.BlobIsShort ? readShort() : readInt(); - } - - /***/ - public final int readGUIDIndex() { - return file.GUIDIsShort ? readShort() : readInt(); - } - - /***/ - public final int readTableIndex(int tableId) { - return file.getTable(tableId).isShort ? readShort() : readInt(); - } - - /***/ - public final int readTableSetIndex(int tableSetId) { - return file.indexSize[tableSetId] == 2 ? readShort() : readInt(); - } - - /** Read the specified row and populate the fields of the instance. */ - public final void readRow(int row) { - seekRow(row); - int lastSeek = buffer.position(); - populateFields(); - int rowSizeRead = (int) (buffer.position() - lastSeek); - if (rowSizeRead != rowSize()) - throw new RuntimeException("Table ID=0x" + PEFile.byte2hex(id) + - ": read row size = " + rowSizeRead + - "; expected row size = " + rowSize()); - currentRow = row; - } - - /** Seeks in the file the position of the specified row. */ - protected final void seekRow(int row) { - assert row > 0 && row <= rows - : "Index " + row + " is not within the table with #rows = " + rows; - buffer.position((row - 1)* rowSize()); - } - - public final int currentRow() { return currentRow; } - - public final void nextRow() { readRow(currentRow() + 1); } - - //########################################################################## - // abstract members - - /** Assigns values to the fields of the class. */ - protected abstract void populateFields(); - - /** Returns the size of a row in bytes. */ - protected abstract int getRowSize(); - - //########################################################################## - // a table with 0 rows - - private static final class Empty extends Table { - public Empty(int id) { - super(null, id, 0); - } - protected int getRowSize() { return 0; } - protected void populateFields() { - throw new RuntimeException("Table 0x" + PEFile.byte2hex(id)); - } - } - - //########################################################################## - // table Module; ID=0x00; p115, 21.27 - - public static final class ModuleDef extends Table { - public static final int ID = 0x00; - - /** 2-byte value; reserved - shall be 0. */ - public int Generation; - - /** Index into #String. */ - public int Name; - - /** Index into #GUID; used to distinguish between - * two version of the same module. */ - public int Mvid; - - /** Index into #GUID; reserved - shall be 0. */ - public int EncId; - - /** Index into #GUID; reseved - shall be 0. */ - public int EncBaseId; - - public ModuleDef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Generation = readShort(); - Name = readStringIndex(); - Mvid = readGUIDIndex(); - EncId = readGUIDIndex(); - EncBaseId = readGUIDIndex(); - } - - protected int getRowSize() { - return 2 + file.getStringIndexSize() + 3*file.getGUIDIndexSize(); - } - - public String getName() { - return file.getString(Name); - } - - } // class ModuleDef - - //########################################################################## - // table TypeRef; ID=0x01; p125, 21.35 - - public static final class TypeRef extends Table { - public static final int ID = 0x1; - - /** A ResolutionScope coded index. */ - public int ResolutionScope; - - /** Index into #String. */ - public int Name; - - /** Index into #String. */ - public int Namespace; - - public TypeRef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - ResolutionScope = readTableSetIndex(_ResolutionScope); - Name = readStringIndex(); - Namespace = readStringIndex(); - } - - protected int getRowSize() { - return file.getTableSetIndexSize(_ResolutionScope) + - 2 * file.getStringIndexSize(); - } - - public String getFullName() { - String namespace = file.getString(Namespace); - return namespace.length() == 0 ? file.getString(Name) - : namespace + "." + file.getString(Name); - } - - } // class TypeRef - - //########################################################################## - // table TypeDef; ID=0x02; p120, 21.34 - - public static final class TypeDef extends Table { - public static final int ID = 0x02; - - /** 4-byte bitmask of type TypeAttributes (22.1.14). */ - public int Flags; - - /** Index into #String. */ - public int Name; - - /** Index into #String. */ - public int Namespace; - - /** TypeDefOrRef coded index. */ - public int Extends; - - /** Index into Field table. - */ - public int FieldList; - - /** Index into Method table. */ - public int MethodList; - - - public TypeDef(PEFile file, int rows) { - super(file, ID, rows); - this.newMapping = true; - } - - public String getFullName() { - String namespace = file.getString(Namespace); - return namespace.length() == 0 ? file.getString(Name) - : namespace + "." + file.getString(Name); - } - - protected void populateFields() { - Flags = readInt(); - Name = readStringIndex(); - Namespace = readStringIndex(); - Extends = readTableSetIndex(_TypeDefOrRef); - FieldList = readTableIndex(FieldDef.ID); - MethodList = readTableIndex(MethodDef.ID); - } - - protected int getRowSize() { - return 4 + 2*file.getStringIndexSize() + - file.getTableSetIndexSize(_TypeDefOrRef) + - file.getTableIndexSize(FieldDef.ID) + - file.getTableIndexSize(MethodDef.ID); - } - - } // class TypeDef - - //########################################################################## - // Table FieldTrans; ID=0x03; undocumented - - /** - * Undocumented table. Appears to be used for translating the Field entry - * in the TypeDef(0x02) table into the real entry in the Fields(0x06) table - */ - public static final class FieldTrans extends Table { - public static final int ID = 0x03; - - public int Field; - - public FieldTrans(PEFile file, int rows) { - super(file, ID, rows); - newMapping = true; - } - - protected void populateFields() { - Field = readTableIndex(FieldDef.ID); - } - - protected int getRowSize() { - return file.getTableIndexSize(FieldDef.ID); - } - - } - - //########################################################################## - // table Field; ID=0x04; p102, 21.15 - - public static final class FieldDef extends Table { - public static final int ID = 0x04; - - /** 2-byte bitmask of type FieldAttributes (22.1.5). */ - public int Flags; - - /** Index into #String. */ - public int Name; - - /** Index into #Blob. */ - public int Signature; - - public FieldDef(PEFile file, int rows) { - super(file, ID, rows); - newMapping = true; - } - - protected void populateFields() { - Flags = readShort(); - Name = readStringIndex(); - Signature = readBlobIndex(); - } - - protected int getRowSize() { - return 2 + file.getStringIndexSize() + file.getBlobIndexSize(); - } - - public String getName() { return file.getString(Name); } - - public Sig getSignature() { return file.getSignature(Signature); } - - } //class FieldDef - - //########################################################################## - // Table MethodTrans; ID=0x05; undocumented - - /** - * Undocumented table. Appears to be used for translating the Method entry - * in the TypeDef(0x02) table into the real entry in the Methods(0x06) table - */ - public static final class MethodTrans extends Table { - public static final int ID = 0x05; - - public int Method; - - public MethodTrans(PEFile file, int rows) { - super(file, ID, rows); - newMapping = true; - } - - protected void populateFields() { - Method = readTableIndex(FieldDef.ID); - } - - protected int getRowSize() { - return file.getTableIndexSize(MethodDef.ID); - } - - } - - //########################################################################## - // table MethodDef; ID=0x06; p110, 21.24 - - public static final class MethodDef extends Table { - public static final int ID = 0x06; - - /** 4-byte constant. */ - public int RVA; - - /** 2-byte bitmask of type MethodImplAttributes (22.1.10). */ - public int ImplFlags; - - /** 2-byte bitmask of type MethodAttributes (22.1.9). */ - public int Flags; - - /** Index into #String. */ - public int Name; - - /** Index into #Blob. */ - public int Signature; - - /** Index into Param Table. */ - public int ParamList; - - public MethodDef(PEFile file, int rows) { - super(file, ID, rows); - newMapping = true; - } - - protected void populateFields() { - RVA = readInt(); - ImplFlags = readShort(); - Flags = readShort(); - Name = readStringIndex(); - Signature = readBlobIndex(); - ParamList = readTableIndex(ParamDef.ID); - } - - protected int getRowSize() { - return 8 + file.getStringIndexSize() + file.getBlobIndexSize() + - file.getTableIndexSize(ParamDef.ID); - } - - public String getName() { return file.getString(Name); } - - public Sig getSignature() { return file.getSignature(Signature); } - } // class Method - - //########################################################################## - // table Param; ID=0x08; p116, 21.30 - - public static final class ParamDef extends Table { - public static final int ID = 0x08; - - /** 2-byte bitmask of type ParamAttributes (22.1.12). */ - public int Flags; - - /** 2-byte constant. */ - public int Sequence; - - /** Index into #String. */ - public int Name; - - public ParamDef(PEFile file, int rows) { - super(file, ID, rows); - newMapping = true; - } - - protected void populateFields() { - Flags = readShort(); - Sequence = readShort(); - Name = readStringIndex(); - } - - protected int getRowSize() { return 4 + file.getStringIndexSize(); } - - public String getName() { return file.getString(Name); } - - } // class Param - - //########################################################################## - // table InterfaceImpl, ID=0x09; p107, 21.21 - - public static final class InterfaceImpl extends Table { - public static final int ID = 0x09; - - /** Index into TypeDef table. */ - public int Class; - - /** Index into TypeDefOrRef table set. */ - public int Interface; - - public InterfaceImpl(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Class = readTableIndex(TypeDef.ID); - Interface = readTableSetIndex(_TypeDefOrRef); - } - - protected int getRowSize() { - return file.getTableIndexSize(TypeDef.ID) + - file.getTableSetIndexSize(_TypeDefOrRef); - } - - /** finds the index of the first entry - * @param targetIndex - index in the TypeDef table - the type to look for - * @return the index of the first interface for the given type; - * 0 if the type doesn't implement any interfaces - */ - - // binary search implementation -// public int findType(int targetIndex) { -// int l = 1, h = rows; -// int classIndex; -// while (l <= h) { -// int mid = (l + h) / 2; -// seekRow(mid); -// classIndex = readTableIndex(TypeDef.ID); -// if (targetIndex <= classIndex) h = mid - 1; -// else l = mid + 1; -// } -// return (targetIndex == classIndex) ? h : 0; -// } - - //linear search implementation - public int findType(int targetIndex) { - for (int i = 1; i <= rows; i++) { - seekRow(i); - if (targetIndex == readTableIndex(TypeDef.ID)) - return i; - } - return 0; - } - - } // class InterfaceImpl - - //########################################################################## - // table MemberRef; ID=0x0a; p109, 21.23 - - public static final class MemberRef extends Table { - public static final int ID = 0x0a; - - /** Index into MemberRefParent table set. */ - public int Class; - - /** Index into #String. */ - public int Name; - - /** Index into #Blob. */ - public int Signature; - - public MemberRef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Class = readTableSetIndex(_MemberRefParent); - Name = readStringIndex(); - Signature = readBlobIndex(); - } - - protected int getRowSize() { - return file.getTableSetIndexSize(_MemberRefParent) + - file.getStringIndexSize() + file.getBlobIndexSize(); - } - - public String getName() { - return file.getString(Name); - } - - public Sig getSignature() { - return file.getSignature(Signature); - } - - } // class MemberRef - - //########################################################################## - // table Constant; ID=0x0b; p95, 21.9 - - public static final class Constant extends Table { - public static final int ID = 0x0b; - - /** 1-byte constant followed by 1-byte padding 0 (see 22.1.15). */ - public int Type; - - /** Index into HasConst table set. */ - public int Parent; - - /** Index into #Blob. */ - public int Value; - - public Constant(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Type = readShort(); - Parent = readTableSetIndex(_HasConstant); - Value = readBlobIndex(); - } - - protected int getRowSize() { - return 2 + file.getTableSetIndexSize(_HasConstant) + - file.getBlobIndexSize(); - } - - public Object getValue() { - if (Type == Signature.ELEMENT_TYPE_CLASS) - return null; - return file.Blob.getConstant(Type, Value); - } - - - } // class Constant - - //########################################################################## - // table CustomAttribute; ID=0x0c; p95, 21.10 - - public static final class CustomAttribute extends Table { - public static final int ID = 0x0c; - - /** Index into any metadata table, except the CustomAttribute itself; - * more precisely - index into HasCustomAttribute table set. - */ - public int Parent; - - /** Index into the CustomAttributeType table set. */ - public int Type; - - /** Index into #Blob. */ - public int Value; - - public CustomAttribute(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Parent = readTableSetIndex(_HasCustomAttribute); - Type = readTableSetIndex(_CustomAttributeType); - Value = readBlobIndex(); - } - - protected int getRowSize() { - return file.getTableSetIndexSize(_HasCustomAttribute) + - file.getTableSetIndexSize(_CustomAttributeType) + - file.getBlobIndexSize(); - } - - public byte[] getValue() { - return Value == 0 ? null : file.getBlob(Value); - } - } // class CustomAttribute - - //########################################################################## - // table FieldMarshal; ID=0x0d; p105, 21.17 - - public static final class FieldMarshal extends Table { - public static final int ID = 0x0d; - - /** Index into HasFieldMarshal table set. */ - public int Parent; - - /** Index into #Blob. */ - public int NativeType; - - public FieldMarshal(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Parent = readTableSetIndex(_HasFieldMarshal); - NativeType = readBlobIndex(); - } - - protected int getRowSize() { - return file.getTableSetIndexSize(_HasFieldMarshal) + - file.getBlobIndexSize(); - } - - } // class FieldMarshal - - //########################################################################## - // table DeclSecurity; ID=0x0e; p97, 21.11 - - public static final class DeclSecurity extends Table { - public static final int ID = 0x0e; - - /** 2-byte value. */ - public int Action; - - /** Index into HasDeclSecurity table set. */ - public int Parent; - - /** Index into #Blob. */ - public int PermissionSet; - - public DeclSecurity(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Action = readShort(); - Parent = readTableSetIndex(_HasDeclSecurity); - PermissionSet = readBlobIndex(); - } - - protected int getRowSize() { - return 2 + file.getTableSetIndexSize(_HasDeclSecurity) + - file.getBlobIndexSize(); - } - - } // class DeclSecurity - - //########################################################################## - // table ClassLayout; ID=0x0f, p92, 21.8 - - public static final class ClassLayout extends Table { - public static final int ID = 0x0f; - - /** 2-byte constant. */ - public int PackingSize; - - /** 4-byte constant. */ - public int ClassSize; - - /** Index into TypeDef table. */ - public int Parent; - - public ClassLayout(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - PackingSize = readShort(); - ClassSize = readInt(); - Parent = readTableIndex(TypeDef.ID); - } - - protected int getRowSize() { - return 6 + file.getTableIndexSize(TypeDef.ID); - } - - } // class ClassLayout - - //########################################################################## - // table FieldLayout; ID=0x10; p104, 21.16 - - public static final class FieldLayout extends Table { - public static final int ID = 0x10; - - /** 4-byte constant. */ - public int Offset; - - /** Index into the Field table. */ - public int Field; - - public FieldLayout(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Offset = readInt(); - Field = readTableIndex(FieldDef.ID); - } - - protected int getRowSize() { - return 4 + file.getTableIndexSize(FieldDef.ID); - } - - } // class FieldLayout - - //########################################################################## - // table StandAloneSig; ID=0x11; p119, 21.33 - - public static final class StandAloneSig extends Table { - public static final int ID = 0x11; - - /** Index into #Blob. */ - public int Signature; - - public StandAloneSig(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Signature = readBlobIndex(); - } - - protected int getRowSize() { return file.getBlobIndexSize(); } - - } // class StandAloneSig - - //########################################################################## - // table EventMap; ID=0x12; p99, 21.12 - - public static final class EventMap extends Table { - public static final int ID = 0x12; - - /** Index into the TypeDef table. */ - public int Parent; - - /** Index into the Event table. */ - public int EventList; - - public EventMap(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Parent = readTableIndex(TypeDef.ID); - EventList = readTableIndex(EventDef.ID); - } - - protected int getRowSize() { - return file.getTableIndexSize(TypeDef.ID) + - file.getTableIndexSize(EventDef.ID); - } - - } // class EventMap - - //########################################################################## - // table Event; ID=0x14; p99, 21.13 - - public static final class EventDef extends Table { - public static final int ID = 0x14; - - /** 2-byte bitmask of type EventAttribute (22.1.4). */ - public int EventFlags; - - /** Index into #String. */ - public int Name; - - /** Index into TypeDefOrRef table set. [This corresponds to the Type - * of the event; it is not the Type that owns the event] - */ - public int EventType; - - public EventDef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - EventFlags = readShort(); - Name = readStringIndex(); - EventType = readTableSetIndex(_TypeDefOrRef); - } - - protected int getRowSize() { - return 2 + file.getStringIndexSize() + - file.getTableSetIndexSize(_TypeDefOrRef); - } - - public String getName() { return file.getString(Name); } - - } // class EventDef - - //########################################################################## - // table PropertyMap; ID=0x15; p119, 21.32 - - public static final class PropertyMap extends Table { - public static final int ID = 0x15; - - /** Index into the TypeDef table. */ - public int Parent; - - /** Index into the Property table. */ - public int PropertyList; - - public PropertyMap(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Parent = readTableIndex(TypeDef.ID); - PropertyList = readTableIndex(PropertyDef.ID); - } - - protected int getRowSize() { - return file.getTableIndexSize(TypeDef.ID) + - file.getTableIndexSize(PropertyDef.ID); - } - - } // class PropertyMap - - //########################################################################## - // table Property; ID=0x17; p117, 21.31 - - public static final class PropertyDef extends Table { - public static final int ID = 0x17; - - /** 2-byte bitmask of type PropertyAttributes (22.1.13). */ - public int Flags; - - /** Index into #String. */ - public int Name; - - /** Index into #Blob. (Indexes the signature in the #Blob) */ - public int Type; - - public PropertyDef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Flags = readShort(); - Name = readStringIndex(); - Type = readBlobIndex(); - } - - protected int getRowSize() { - return 2 + file.getStringIndexSize() + - file.getBlobIndexSize(); - } - - public String getName() { return file.getString(Name); } - - public Sig getSignature() { return file.getSignature(Type); } - - } // class PropertyDef - - //########################################################################## - // table MethodSemantics; ID=0x18; p114, 21.26 - - public static final class MethodSemantics extends Table { - public static final int ID = 0x18; - - /** 2-byte bitmaks of type MethodSemanticsAttribute (22.1.11). */ - public int Semantics; - - /** Index into the Method table. */ - public int Method; - - /** Index into Event or Property table (HasSemantics table set). */ - public int Association; - - public MethodSemantics(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Semantics = readShort(); - Method = readTableIndex(MethodDef.ID); - Association = readTableSetIndex(_HasSemantics); - } - - protected int getRowSize() { - return 2 + file.getTableIndexSize(MethodDef.ID) + - file.getTableSetIndexSize(_HasSemantics); - } - - public boolean isGetter() { return (Semantics & Getter) != 0; } - public boolean isSetter() { return (Semantics & Setter) != 0; } - public boolean isOther() { return (Semantics & Other) != 0; } - public boolean isAddOn() { return (Semantics & AddOn) != 0; } - public boolean isRemoveOn() { return (Semantics & RemoveOn) != 0; } - public boolean isFire() { return (Semantics & Fire) != 0; } - - private static final short Setter = (short)0x0001; - private static final short Getter = (short)0x0002; - private static final short Other = (short)0x0004; - private static final short AddOn = (short)0x0008; - private static final short RemoveOn = (short)0x0010; - private static final short Fire = (short)0x0020; - - } // class MethodSemantics - - - //########################################################################## - // table MethodImpl; ID=0x19; p113, 21.25 - - public static final class MethodImpl extends Table { - public static final int ID = 0x19; - - /** Index into the TypeDef table. */ - public int Class; - - /** Index into MethodDefOrRef table set. */ - public int MethodBody; - - /** Index into MethodDefOrRef table set. */ - public int MethodDeclaration; - - public MethodImpl(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Class = readTableIndex(TypeDef.ID); - MethodBody = readTableSetIndex(_MethodDefOrRef); - MethodDeclaration = readTableSetIndex(_MethodDefOrRef); - } - - protected int getRowSize() { - return file.getTableIndexSize(TypeDef.ID) + - 2 * file.getTableSetIndexSize(_MethodDefOrRef); - } - - } // class MethodImpl - - //########################################################################## - // table ModuleRef; ID=0x1a; p116, 21.28 - - public static final class ModuleRef extends Table { - public static final int ID = 0x1a; - - /** Index into #String. */ - public int Name; - - public ModuleRef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Name = readStringIndex(); - } - - protected int getRowSize() { return file.getStringIndexSize(); } - - public String getName() { return file.getString(Name); } - - } // class ModuleRef - - //########################################################################## - // table TypeSpec; ID=0x1b; p126, 21.36 - - public static final class TypeSpec extends Table { - public static final int ID = 0x1b; - - /** Index into #Blob, where the blob is formatted - * as specified in 22.2.15 - */ - public int Signature; - - public TypeSpec(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Signature = readBlobIndex(); - } - - protected int getRowSize() { return file.getBlobIndexSize(); } - - public Sig getSignature() { return file.getSignature(Signature); } - } // class TypeSpec - - //########################################################################## - // table ImplMap; ID=0x1c; p107, 21.20 - - public static final class ImplMap extends Table { - public static final int ID = 0x1c; - - /** 2-byte bitmask of type PInvokeAttributes (22.1.7). */ - public int MappingFlags; - - /** Index into MemberForwarded table set. */ - public int MemberForwarded; - - /** Index into #String. */ - public int ImportName; - - /** Index into the ModuleRef table. */ - public int ImportScope; - - public ImplMap(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - MappingFlags = readShort(); - MemberForwarded = readTableSetIndex(_MemberForwarded); - ImportName = readStringIndex(); - ImportScope = readTableIndex(ModuleRef.ID); - } - - protected int getRowSize() { - return 2 + file.getTableSetIndexSize(_MemberForwarded) + - file.getStringIndexSize() + - file.getTableIndexSize(ModuleRef.ID); - } - - } // class ImplMap - - //########################################################################## - // table FieldRVA; ID=0x1d; p106, 21.18 - - public static final class FieldRVA extends Table { - public static final int ID = 0x1d; - - /** 4-byte constant. */ - public int RVA; - - /** Index into the Field table. */ - public int Field; - - public FieldRVA(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - RVA = readInt(); - Field = readTableIndex(Table.FieldDef.ID); - } - - protected int getRowSize() { - return 4 + file.getTableIndexSize(FieldDef.ID); - } - - } - - //########################################################################## - // table Assembly; ID=0x20; p90, 21.2 - - public static final class AssemblyDef extends Table { - public static final int ID = 0x20; - - /** 4-byte constatnt of type AssemblyHashAlgorithm, clause 22.1.1 */ - public int HashAlgId; - - /** 2-byte constant */ - public int MajorVersion; - - /** 2-byte constant */ - public int MinorVersion; - - /** 2-byte constant */ - public int BuildNumber; - - /** 2-byte constant */ - public int RevisionNumber; - - /** 4-byte constant */ - public int Flags; - - /** index into #Blob */ - public int PublicKey; - - /** index into #String */ - public int Name; - - /** index into #String */ - public int Culture; - - public AssemblyDef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - HashAlgId = readInt(); - MajorVersion = readShort(); - MinorVersion = readShort(); - BuildNumber = readShort(); - RevisionNumber = readShort(); - Flags = readInt(); - PublicKey = readBlobIndex(); - Name = readStringIndex(); - Culture = readStringIndex(); - } - - protected int getRowSize() { - return 16 + file.getBlobIndexSize() + 2*file.getStringIndexSize(); - } - - } // class AssemblyDef - - //########################################################################## - // table AssemblyProcessor; ID=0x21; p91, 21.4 - - public static final class AssemblyProcessor extends Table { - public static final int ID = 0x21; - - /** 4-byte constant. */ - public int Processor; - - public AssemblyProcessor(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Processor = readInt(); - } - - protected int getRowSize() { return 4; } - - } - - //########################################################################## - // table AssemblyOS; ID = 0x22; p90, 21.3 - - public static final class AssemblyOS extends Table { - public static final int ID = 0x22; - - /** 4-byte constant. */ - public int OSPlatformID; - - /** 4-byte constant. */ - public int OSMajorVersion; - - /** 4-byte constant. */ - public int OSMinorVersion; - - public AssemblyOS(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - OSPlatformID = readInt(); - OSMajorVersion = readInt(); - OSMinorVersion = readInt(); - } - - protected int getRowSize() { return 12; } - - } - - //########################################################################## - // table AssemblyRef; ID = 0x23; pp91, 21.5 - - public static final class AssemblyRef extends Table { - public static final int ID = 0x23; - - /** 2-byte constant. */ - public int MajorVersion; - - /** 2-byte constant. */ - public int MinorVersion; - - /** 2-byte constant. */ - public int BuildNumber; - - /** 2-byte constant. */ - public int RevisionNumber; - - /** 4-byte bitmask of type AssemblyFlags (22.1.2). */ - public int Flags; - - /** index into #Blob. */ - public int PublicKeyOrToken; - - /** index into #String. */ - public int Name; - - /** index into #String. */ - public int Culture; - - /** index into #Blob. */ - public int HashValue; - - public AssemblyRef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - MajorVersion = readShort(); - MinorVersion = readShort(); - BuildNumber = readShort(); - RevisionNumber = readShort(); - Flags = readInt(); - PublicKeyOrToken = readBlobIndex(); - Name = readStringIndex(); - Culture = readStringIndex(); - HashValue = readBlobIndex(); - } - - protected int getRowSize() { - return 12 + 2*file.getBlobIndexSize() + 2*file.getStringIndexSize(); - } - - public String getName() { return file.getString(Name); } - } - - //########################################################################## - // table AssemblyRefProcessor; ID=0x24; p92, 21.7 - - public static final class AssemblyRefProcessor extends Table { - public static final int ID = 0x24; - - /** 4-byte constant. */ - public int Processor; - - /** Index into the AssemblyRef table. */ - public int AssemblyRef; - - public AssemblyRefProcessor(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Processor = readInt(); - AssemblyRef = readTableIndex(Table.AssemblyRef.ID); - } - - protected int getRowSize() { - return 4 + file.getTableIndexSize(Table.AssemblyRef.ID); - } - - } // class AssemblyRefProcessor - - //########################################################################## - // table AssemblyRefOS; ID=0x25; p92, 21.6 - - public static final class AssemblyRefOS extends Table { - public static final int ID = 0x25; - - /** 4-byte constant. */ - public int OSPlatformId; - - /** 4-byte constant. */ - public int OSMajorVersion; - - /** 4-byte constant. */ - public int OSMinorVersion; - - /** Index into the AssemblyRef table. */ - public int AssemblyRef; - - public AssemblyRefOS(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - OSPlatformId = readInt(); - OSMajorVersion = readInt(); - OSMinorVersion = readInt(); - AssemblyRef = readTableIndex(Table.AssemblyRef.ID); - } - - protected int getRowSize() { - return 12 + file.getTableIndexSize(Table.AssemblyRef.ID); - } - - } // class AssemblyRefOS - - //########################################################################## - // table File; ID=0x26; p106, 21.19 - - public static final class FileDef extends Table { - public static final int ID = 0x26; - - /** 4-byte bitmask of type FileAttributes (22.1.6). */ - public int Flags; - - /** Index into #String. */ - public int Name; - - /** Index into #Blob. */ - public int HashValue; - - public FileDef(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Flags = readInt(); - Name = readStringIndex(); - HashValue = readBlobIndex(); - } - - protected int getRowSize() { - return 4 + file.getStringIndexSize() + file.getBlobIndexSize(); - } - - public String getName() { - return file.getString(Name); - } - - } // class FileDef - - //########################################################################## - // table ExportedType; ID=0x27; p100, 21.14 - - public static final class ExportedType extends Table { - public static final int ID = 0x27; - - /** 4-byte bitmask of type TypeAttribute (22.1.6). */ - public int Flags; - - /** 4-byte index into a TypeDef table of - * another module in this assembly. - */ - public int TypeDefId; - - /** Index into #String. */ - public int TypeName; - - /** Index into #Stream. */ - public int TypeNamespace; - - /** Index into one of two tables as follows: - * - 'File' table, where that entry says which module - * in the current assembly holds the TypeDef - * - 'ExportedType' table, where that entry is - * the enclosing Type of the current nested Type - */ - public int Implementation; - - public ExportedType(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Flags = readInt(); - TypeDefId = readInt(); - TypeName = readStringIndex(); - TypeNamespace = readStringIndex(); - Implementation = readTableSetIndex(_Implementation); - } - - protected int getRowSize() { - return 8 + 2*file.getStringIndexSize() + - file.getTableSetIndexSize(_Implementation); - } - - public String getFullName() { - String namespace = file.getString(TypeNamespace); - return namespace.length() == 0 ? file.getString(TypeName) - : namespace + "." + file.getString(TypeName); - } - - } // class ExportedType - - //########################################################################## - // table ManifestResource; ID=0x28; p108, 21.22 - - public static final class ManifestResource extends Table { - public static final int ID = 0x28; - - /** 4-byte constant. */ - public int Offset; - - /** 4-byte bitmask of type ManifestResourceAttributes (22.1.8). */ - public int Flags; - - /** Index into #String. */ - public int Name; - - /** Index into the Implementation table set. */ - public int Implementation; - - public ManifestResource(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - Offset = readInt(); - Flags = readInt(); - Name = readStringIndex(); - Implementation = readTableSetIndex(_Implementation); - } - - protected int getRowSize() { - return 8 + file.getStringIndexSize() + - file.getTableSetIndexSize(_Implementation); - } - - } // class ManifestResource - - //########################################################################## - // table NestedClass; ID=0x29; p116, 21.29 - - public static final class NestedClass extends Table { - public static final int ID = 0x29; - - /** Index into the TypeDef table. */ - public int NestedClass; - - /** Index into the TypeDef table. */ - public int EnclosingClass; - - public NestedClass(PEFile file, int rows) { super(file, ID, rows); } - - protected void populateFields() { - NestedClass = readTableIndex(TypeDef.ID); - EnclosingClass = readTableIndex(TypeDef.ID); - } - - protected int getRowSize() { - return 2 * file.getTableIndexSize(TypeDef.ID); - } - - } // class NestedClass - - //########################################################################## - // table GenericParam; ID=0x2a; p137, 22.20 - - public static final class GenericParam extends Table { - public static final int ID = 0x2a; - - public int Number; - public int Flags; - public int Owner; // a TypeOrMethodDef (Sec 24.2.6) coded index - public int Name; // a non-null index into the String heap - - private java.util.Map /*>*/ GenericParamIdxesForMethodDefIdx = - new java.util.HashMap(); - private java.util.Map /*>*/ GenericParamIdxesForTypeDefIdx = - new java.util.HashMap(); - - private void addToMap(int key, int value, java.util.Map IdxesForIdx) { - java.util.Set /**/ bucket = (java.util.Set)IdxesForIdx.get(Integer.valueOf(key)); - if(bucket == null) { - bucket = new java.util.HashSet(); - IdxesForIdx.put(Integer.valueOf(key), bucket); - } - bucket.add(Integer.valueOf(value)); - } - - /** Indexes of rows in the GenericParam table representing type parameters defined by the type given by - * its row index TypeDefIdx (in the TypeDef table). - * No need to position the current record before invoking this method. */ - public int[] getTVarIdxes(int TypeDefIdx) { - if(!mapsPopulated) { - initMaps(); - } - java.util.Set bucket = (java.util.Set)GenericParamIdxesForTypeDefIdx.get(Integer.valueOf(TypeDefIdx)); - if(bucket == null) { - bucket = java.util.Collections.EMPTY_SET; - } - int[] res = new int[bucket.size()]; - java.util.Iterator /**/ it = bucket.iterator(); - for(int i = 0; i < bucket.size(); i++) { - res[i] = ((Integer)it.next()).intValue(); - } - return res; - } - - /** Indexes of rows in the GenericParam table representing type parameters defined by the method given by - * its row index MethodDefIdx (in the MethodDef table) - * No need to position the current record before invoking this method. */ - public int[] getMVarIdxes(int MethodDefIdx) { - if(!mapsPopulated) { - initMaps(); - } - java.util.Set bucket = (java.util.Set)GenericParamIdxesForMethodDefIdx.get(Integer.valueOf(MethodDefIdx)); - if(bucket == null) { - bucket = java.util.Collections.EMPTY_SET; - } - int[] res = new int[bucket.size()]; - java.util.Iterator /**/ it = bucket.iterator(); - for(int i = 0; i < bucket.size(); i++) { - res[i] = ((Integer)it.next()).intValue(); - } - return res; - } - - private boolean mapsPopulated = false; - - private void initMaps() { - mapsPopulated = true; - for (int currentParamRow = 1; currentParamRow <= rows; currentParamRow++) { - int currentOwner = file.GenericParam(currentParamRow).Owner; - int targetTableId = Table.getTableId(Table._TypeOrMethodDef, currentOwner); - int targetRow = currentOwner >> Table.NoBits[Table._TypeOrMethodDef]; - if(targetTableId == TypeDef.ID){ - addToMap(targetRow, currentParamRow, GenericParamIdxesForTypeDefIdx); - } else if(targetTableId == MethodDef.ID) { - addToMap(targetRow, currentParamRow, GenericParamIdxesForMethodDefIdx); - } else { - throw new RuntimeException(); - } - } - } - - public GenericParam(PEFile file, int rows) { - super(file, ID, rows); - this.newMapping = true; - } - - protected void populateFields() { - Number = readShort(); - Flags = readShort(); - Owner = readTableSetIndex(_TypeOrMethodDef); - Name = readStringIndex(); - } - - /** This method assumes populateFields() has been just called to set Flags for the current record */ - public boolean isInvariant() { - /* 23.1.7 Flags for Generic Parameters [GenericParamAttributes tributes] */ - return (Flags & 0x0003) == 0; - } - - /** This method assumes populateFields() has been just called to set Flags for the current record */ - public boolean isCovariant() { - /* 23.1.7 Flags for Generic Parameters [GenericParamAttributes tributes] */ - return (Flags & 0x0003) == 1; - } - - /** This method assumes populateFields() has been just called to set Flags for the current record */ - public boolean isContravariant() { - /* 23.1.7 Flags for Generic Parameters [GenericParamAttributes tributes] */ - return (Flags & 0x0003) == 2; - } - - /** This method assumes populateFields() has been just called to set Flags for the current record */ - public boolean isReferenceType() { - /* 23.1.7 Flags for Generic Parameters [GenericParamAttributes tributes] */ - return (Flags & 0x001C) == 4; - } - - /** This method assumes populateFields() has been just called to set Flags for the current record */ - public boolean isValueType() { - /* 23.1.7 Flags for Generic Parameters [GenericParamAttributes tributes] */ - return (Flags & 0x001C) == 8; - } - - /** This method assumes populateFields() has been just called to set Flags for the current record */ - public boolean hasDefaultConstructor() { - /* 23.1.7 Flags for Generic Parameters [GenericParamAttributes tributes] */ - return (Flags & 0x001C) == 0x0010; - } - - protected int getRowSize() { - return 2 + 2 + file.getTableSetIndexSize(_TypeOrMethodDef) + file.getStringIndexSize(); - /* Columns: - Number (2 bytes), - Flags (2 bytes), - Owner (coded token of type TypeOrMethodDef), - Name (offset in the #Strings stream). - */ - } - - public String getName() { - return file.getString(Name); - } - - } // class GenericParam - - - //########################################################################## - // table GenericParamConstraint; ID=0x2c; p139, 22.20 - - public static final class GenericParamConstraint extends Table { - public static final int ID = 0x2c; - - public int Owner; // an index into the GenericParam table - public int Constraint; // a TypeDefOrRef (Sec 24.2.6) coded index - - public GenericParamConstraint(PEFile file, int rows) { - super(file, ID, rows); - this.newMapping = true; - } - - protected void populateFields() { - Owner = readTableIndex(GenericParam.ID); - Constraint = readTableSetIndex(_TypeDefOrRef); - } - - protected int getRowSize() { - return file.getTableIndexSize(GenericParam.ID) + file.getTableSetIndexSize(_TypeDefOrRef); - /* Columns: - Owner (RID in the GenericParam table), - Constraint (coded token of type TypeDefOrRef). - */ - } - - private boolean mapPopulated = false; - - /** Indexes of rows (in the TypeDef, TypeRef, or TypeSpec tables) denoting the base class (if any) - * and interfaces (if any) that the generic parameter (of TVar or MVar kind) should support, where - * that generic parameter is represented by its index into the GenericParam table. */ - public int[] getTypeDefOrRefIdxes(int genParamIdx) { - if(!mapPopulated) { - initMap(); - } - java.util.Set bucket = (java.util.Set)TypeDefOrRefIdxesForGenParamIdx.get(Integer.valueOf(genParamIdx)); - if(bucket == null) { - bucket = java.util.Collections.EMPTY_SET; - } - int[] res = new int[bucket.size()]; - java.util.Iterator /**/ it = bucket.iterator(); - for(int i = 0; i < bucket.size(); i++) { - res[i] = ((Integer)it.next()).intValue(); - } - return res; - } - - - private void initMap() { - mapPopulated = true; - for (int currentConstraintRow = 1; currentConstraintRow <= rows; currentConstraintRow++) { - int targetGenericParam = file.GenericParamConstraint(currentConstraintRow).Owner; - int value = file.GenericParamConstraint.Constraint; - addToMap(targetGenericParam, value); - } - } - - private java.util.Map /*>*/ TypeDefOrRefIdxesForGenParamIdx = - new java.util.HashMap(); - - private void addToMap(int key, int value) { - java.util.Set /**/ bucket = (java.util.Set)TypeDefOrRefIdxesForGenParamIdx.get(Integer.valueOf(key)); - if(bucket == null) { - bucket = new java.util.HashSet(); - TypeDefOrRefIdxesForGenParamIdx.put(Integer.valueOf(key), bucket); - } - bucket.add(Integer.valueOf(value)); - } - - } // class GenericParamConstraint - - //########################################################################## - // table MethodSpec; ID=0x2b; p149, in Sec. 22.29 of Partition II - - public static final class MethodSpec extends Table { - public static final int ID = 0x2b; - - /* an index into the MethodDef or MemberRef table, specifying which generic method this row is an instantiation of. - A MethodDefOrRef (Sec. 24.2.6) coded index */ - public int Method; - - /* an index into the Blob heap (Sec. 23.2.15), holding the signature of this instantiation */ - public int Instantiation; - - public MethodSpec(PEFile file, int rows) { - super(file, ID, rows); - this.newMapping = true; - } - - protected void populateFields() { - Method = readTableSetIndex(_MethodDefOrRef); - Instantiation = readBlobIndex(); - } - - protected int getRowSize() { - return file.getTableSetIndexSize(_MethodDefOrRef) + file.getBlobIndexSize(); - } - - - } // class MethodSpec - //########################################################################## - -} // class Table diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala index 7000e8280b87..0ec3f60bf5ef 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala @@ -84,7 +84,6 @@ class ConsoleFileManager extends FileManager { latestReflectFile = testClassesDir / "reflect" latestCompFile = testClassesDir / "compiler" latestPartestFile = testClassesDir / "partest" - latestFjbgFile = testParent / "lib" / "fjbg.jar" } else if (testBuild.isDefined) { val dir = Path(testBuild.get) @@ -94,7 +93,6 @@ class ConsoleFileManager extends FileManager { latestReflectFile = dir / "lib/scala-reflect.jar" latestCompFile = dir / "lib/scala-compiler.jar" latestPartestFile = dir / "lib/scala-partest.jar" - latestFjbgFile = testParent / "lib" / "fjbg.jar" } else { def setupQuick() { @@ -152,8 +150,6 @@ class ConsoleFileManager extends FileManager { // run setup based on most recent time pairs(pairs.keys max)() - - latestFjbgFile = prefixFile("lib/fjbg.jar") } LATEST_LIB = latestLibFile.getAbsolutePath @@ -174,7 +170,6 @@ class ConsoleFileManager extends FileManager { var latestReflectFile: File = _ var latestCompFile: File = _ var latestPartestFile: File = _ - var latestFjbgFile: File = _ def latestScalapFile: File = (latestLibFile.parent / "scalap.jar").jfile var testClassesDir: Directory = _ // initialize above fields diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala index 4b0ed1f82a14..d3a40718c670 100644 --- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -51,9 +51,9 @@ class ReflectiveRunner { new ConsoleFileManager import fileManager. - { latestCompFile, latestReflectFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile } + { latestCompFile, latestReflectFile, latestLibFile, latestPartestFile, latestScalapFile, latestActorsFile } val files = - Array(latestCompFile, latestReflectFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile, latestActorsFile) map (x => io.File(x)) + Array(latestCompFile, latestReflectFile, latestLibFile, latestPartestFile, latestScalapFile, latestActorsFile) map (x => io.File(x)) val sepUrls = files map (_.toURL) var sepLoader = new URLClassLoader(sepUrls, null) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 37c61735d6e5..8c048ed7f80b 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -684,9 +684,7 @@ trait Definitions extends api.StandardDefinitions { def scalaRepeatedType(arg: Type) = appliedType(RepeatedParamClass, arg) def seqType(arg: Type) = appliedType(SeqClass, arg) - def ClassType(arg: Type) = - if (phase.erasedTypes || forMSIL) ClassClass.tpe - else appliedType(ClassClass, arg) + def ClassType(arg: Type) = if (phase.erasedTypes) ClassClass.tpe else appliedType(ClassClass, arg) def EnumType(sym: Symbol) = // given (in java): "class A { enum E { VAL1 } }" @@ -704,34 +702,6 @@ trait Definitions extends api.StandardDefinitions { def classExistentialType(clazz: Symbol): Type = newExistentialType(clazz.typeParams, clazz.tpe_*) - // - // .NET backend - // - - lazy val ComparatorClass = getRequiredClass("scala.runtime.Comparator") - // System.MulticastDelegate - lazy val DelegateClass: ClassSymbol = getClassByName(sn.Delegate) - var Delegate_scalaCallers: List[Symbol] = List() // Syncnote: No protection necessary yet as only for .NET where reflection is not supported. - // Symbol -> (Symbol, Type): scalaCaller -> (scalaMethodSym, DelegateType) - // var Delegate_scalaCallerInfos: HashMap[Symbol, (Symbol, Type)] = _ - lazy val Delegate_scalaCallerTargets: mutable.HashMap[Symbol, Symbol] = mutable.HashMap() - - def isCorrespondingDelegate(delegateType: Type, functionType: Type): Boolean = { - isSubType(delegateType, DelegateClass.tpe) && - (delegateType.member(nme.apply).tpe match { - case MethodType(delegateParams, delegateReturn) => - isFunctionType(functionType) && - (functionType.normalize match { - case TypeRef(_, _, args) => - (delegateParams.map(pt => { - if (pt.tpe == AnyClass.tpe) definitions.ObjectClass.tpe else pt}) - ::: List(delegateReturn)) == args - case _ => false - }) - case _ => false - }) - } - // members of class scala.Any lazy val Any_== = enterNewMethod(AnyClass, nme.EQ, anyparam, booltype, FINAL) lazy val Any_!= = enterNewMethod(AnyClass, nme.NE, anyparam, booltype, FINAL) @@ -1164,27 +1134,5 @@ trait Definitions extends api.StandardDefinitions { val _ = symbolsNotPresentInBytecode isInitialized = true } //init - - var nbScalaCallers: Int = 0 - def newScalaCaller(delegateType: Type): MethodSymbol = { - assert(forMSIL, "scalaCallers can only be created if target is .NET") - // object: reference to object on which to call (scala-)method - val paramTypes: List[Type] = List(ObjectClass.tpe) - val name = newTermName("$scalaCaller$$" + nbScalaCallers) - // tparam => resultType, which is the resultType of PolyType, i.e. the result type after applying the - // type parameter =-> a MethodType in this case - // TODO: set type bounds manually (-> MulticastDelegate), see newTypeParam - val newCaller = enterNewMethod(DelegateClass, name, paramTypes, delegateType, FINAL | STATIC) - // val newCaller = newPolyMethod(DelegateClass, name, - // tparam => MethodType(paramTypes, tparam.typeConstructor)) setFlag (FINAL | STATIC) - Delegate_scalaCallers = Delegate_scalaCallers ::: List(newCaller) - nbScalaCallers += 1 - newCaller - } - - def addScalaCallerInfo(scalaCaller: Symbol, methSym: Symbol) { - assert(Delegate_scalaCallers contains scalaCaller) - Delegate_scalaCallerTargets += (scalaCaller -> methSym) - } } } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index a1e8ada3022f..f7b4b87570b6 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -584,7 +584,7 @@ trait StdNames { val canEqual_ : NameType = "canEqual" val checkInitialized: NameType = "checkInitialized" val classOf: NameType = "classOf" - val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure + val clone_ : NameType = "clone" val conforms: NameType = "conforms" val copy: NameType = "copy" val currentMirror: NameType = "currentMirror" @@ -598,20 +598,20 @@ trait StdNames { val equalsNumChar : NameType = "equalsNumChar" val equalsNumNum : NameType = "equalsNumNum" val equalsNumObject : NameType = "equalsNumObject" - val equals_ : NameType = if (forMSIL) "Equals" else "equals" + val equals_ : NameType = "equals" val error: NameType = "error" val ex: NameType = "ex" val experimental: NameType = "experimental" val f: NameType = "f" val false_ : NameType = "false" val filter: NameType = "filter" - val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize" + val finalize_ : NameType = "finalize" val find_ : NameType = "find" val flagsFromBits : NameType = "flagsFromBits" val flatMap: NameType = "flatMap" val foreach: NameType = "foreach" val get: NameType = "get" - val hashCode_ : NameType = if (forMSIL) "GetHashCode" else "hashCode" + val hashCode_ : NameType = "hashCode" val hash_ : NameType = "hash" val implicitly: NameType = "implicitly" val in: NameType = "in" @@ -675,7 +675,7 @@ trait StdNames { val thisPrefix : NameType = "thisPrefix" val toArray: NameType = "toArray" val toObjectArray : NameType = "toObjectArray" - val toString_ : NameType = if (forMSIL) "ToString" else "toString" + val toString_ : NameType = "toString" val toTypeConstructor: NameType = "toTypeConstructor" val tpe : NameType = "tpe" val tree : NameType = "tree" @@ -929,33 +929,6 @@ trait StdNames { @deprecated("Use a method in tpnme", "2.10.0") def interfaceName(implname: Name): TypeName = tpnme.interfaceName(implname) } - abstract class SymbolNames { - protected val stringToTermName = null - protected val stringToTypeName = null - protected implicit def createNameType(s: String): TypeName = newTypeNameCached(s) - - val BoxedBoolean : TypeName - val BoxedCharacter : TypeName - val BoxedNumber : TypeName - val Delegate : TypeName - val IOOBException : TypeName // IndexOutOfBoundsException - val InvTargetException : TypeName // InvocationTargetException - val MethodAsObject : TypeName - val NPException : TypeName // NullPointerException - val Object : TypeName - val Throwable : TypeName - val ValueType : TypeName - - val GetCause : TermName - val GetClass : TermName - val GetClassLoader : TermName - val GetMethod : TermName - val Invoke : TermName - val JavaLang : TermName - - val Boxed: immutable.Map[TypeName, TypeName] - } - class JavaKeywords { private val kw = new KeywordSetBuilder @@ -1013,7 +986,11 @@ trait StdNames { final val keywords = kw.result } - private abstract class JavaNames extends SymbolNames { + sealed abstract class SymbolNames { + protected val stringToTermName = null + protected val stringToTypeName = null + protected implicit def createNameType(s: String): TypeName = newTypeNameCached(s) + final val BoxedBoolean: TypeName = "java.lang.Boolean" final val BoxedByte: TypeName = "java.lang.Byte" final val BoxedCharacter: TypeName = "java.lang.Character" @@ -1023,14 +1000,12 @@ trait StdNames { final val BoxedLong: TypeName = "java.lang.Long" final val BoxedNumber: TypeName = "java.lang.Number" final val BoxedShort: TypeName = "java.lang.Short" - final val Delegate: TypeName = tpnme.NO_NAME final val IOOBException: TypeName = "java.lang.IndexOutOfBoundsException" final val InvTargetException: TypeName = "java.lang.reflect.InvocationTargetException" final val MethodAsObject: TypeName = "java.lang.reflect.Method" final val NPException: TypeName = "java.lang.NullPointerException" final val Object: TypeName = "java.lang.Object" final val Throwable: TypeName = "java.lang.Throwable" - final val ValueType: TypeName = tpnme.NO_NAME final val GetCause: TermName = newTermName("getCause") final val GetClass: TermName = newTermName("getClass") @@ -1051,39 +1026,5 @@ trait StdNames { ) } - private class MSILNames extends SymbolNames { - final val BoxedBoolean: TypeName = "System.IConvertible" - final val BoxedCharacter: TypeName = "System.IConvertible" - final val BoxedNumber: TypeName = "System.IConvertible" - final val Delegate: TypeName = "System.MulticastDelegate" - final val IOOBException: TypeName = "System.IndexOutOfRangeException" - final val InvTargetException: TypeName = "System.Reflection.TargetInvocationException" - final val MethodAsObject: TypeName = "System.Reflection.MethodInfo" - final val NPException: TypeName = "System.NullReferenceException" - final val Object: TypeName = "System.Object" - final val Throwable: TypeName = "System.Exception" - final val ValueType: TypeName = "System.ValueType" - - final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */ - final val GetClass: TermName = newTermName("GetType") - final lazy val GetClassLoader: TermName = throw new UnsupportedOperationException("Scala reflection is not supported on this platform"); - final val GetMethod: TermName = newTermName("GetMethod") - final val Invoke: TermName = newTermName("Invoke") - final val JavaLang: TermName = newTermName("System") - - val Boxed = immutable.Map[TypeName, TypeName]( - tpnme.Boolean -> "System.Boolean", - tpnme.Byte -> "System.SByte", // a scala.Byte is signed and a System.SByte too (unlike a System.Byte) - tpnme.Char -> "System.Char", - tpnme.Short -> "System.Int16", - tpnme.Int -> "System.Int32", - tpnme.Long -> "System.Int64", - tpnme.Float -> "System.Single", - tpnme.Double -> "System.Double" - ) - } - - lazy val sn: SymbolNames = - if (forMSIL) new MSILNames - else new JavaNames { } + lazy val sn: SymbolNames = new SymbolNames { } } diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 1298fc17edcd..540338dca7d7 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -117,12 +117,6 @@ abstract class SymbolTable extends macros.Universe @elidable(elidable.WARNING) def assertCorrectThread() {} - /** Are we compiling for Java SE? */ - // def forJVM: Boolean - - /** Are we compiling for .NET? */ - def forMSIL: Boolean = false - /** A last effort if symbol in a select . is not found. * This is overridden by the reflection compiler to make up a package * when it makes sense (i.e. is a package and is a term name). diff --git a/test/attic/files/cli/test1/Main.check.scalac b/test/attic/files/cli/test1/Main.check.scalac index 8465810d0b10..5561cc1ead5d 100644 --- a/test/attic/files/cli/test1/Main.check.scalac +++ b/test/attic/files/cli/test1/Main.check.scalac @@ -1,7 +1,7 @@ scalac error: bad option: '-dd' scalac -help gives more information Usage: scalac -where possible options include: +where possible options include: -doc Generate documentation -g: Generate debugging info (none,source,line,vars,notc) -nowarn Generate no warnings @@ -15,10 +15,8 @@ where possible options include: -encoding Specify character encoding used by source files -windowtitle Specify window title of generated HTML documentation -documenttitle Specify document title of generated HTML documentation - -target: Specify which backend to use (jvm-1.5,msil) + -target: Specify which backend to use (jvm-1.5) -migrate Assist in migrating from Scala version 1.0 - -o Name of the output assembly (only relevant with -target:msil) - -r List of assemblies referenced by the program (only relevant with -target:msil) -debug Output debugging messages -deprecation enable detailed deprecation warnings -unchecked enable detailed unchecked warnings diff --git a/test/attic/files/cli/test2/Main.check.scalac b/test/attic/files/cli/test2/Main.check.scalac index 8465810d0b10..5561cc1ead5d 100644 --- a/test/attic/files/cli/test2/Main.check.scalac +++ b/test/attic/files/cli/test2/Main.check.scalac @@ -1,7 +1,7 @@ scalac error: bad option: '-dd' scalac -help gives more information Usage: scalac -where possible options include: +where possible options include: -doc Generate documentation -g: Generate debugging info (none,source,line,vars,notc) -nowarn Generate no warnings @@ -15,10 +15,8 @@ where possible options include: -encoding Specify character encoding used by source files -windowtitle Specify window title of generated HTML documentation -documenttitle Specify document title of generated HTML documentation - -target: Specify which backend to use (jvm-1.5,msil) + -target: Specify which backend to use (jvm-1.5) -migrate Assist in migrating from Scala version 1.0 - -o Name of the output assembly (only relevant with -target:msil) - -r List of assemblies referenced by the program (only relevant with -target:msil) -debug Output debugging messages -deprecation enable detailed deprecation warnings -unchecked enable detailed unchecked warnings diff --git a/test/attic/files/cli/test3/Main.check.scalac b/test/attic/files/cli/test3/Main.check.scalac index 8465810d0b10..5561cc1ead5d 100644 --- a/test/attic/files/cli/test3/Main.check.scalac +++ b/test/attic/files/cli/test3/Main.check.scalac @@ -1,7 +1,7 @@ scalac error: bad option: '-dd' scalac -help gives more information Usage: scalac -where possible options include: +where possible options include: -doc Generate documentation -g: Generate debugging info (none,source,line,vars,notc) -nowarn Generate no warnings @@ -15,10 +15,8 @@ where possible options include: -encoding Specify character encoding used by source files -windowtitle Specify window title of generated HTML documentation -documenttitle Specify document title of generated HTML documentation - -target: Specify which backend to use (jvm-1.5,msil) + -target: Specify which backend to use (jvm-1.5) -migrate Assist in migrating from Scala version 1.0 - -o Name of the output assembly (only relevant with -target:msil) - -r List of assemblies referenced by the program (only relevant with -target:msil) -debug Output debugging messages -deprecation enable detailed deprecation warnings -unchecked enable detailed unchecked warnings diff --git a/test/disabled/presentation/akka.flags b/test/disabled/presentation/akka.flags index 56d026a62d67..9bf2878f6278 100644 --- a/test/disabled/presentation/akka.flags +++ b/test/disabled/presentation/akka.flags @@ -12,7 +12,7 @@ # running partest from. Run it from the root scala checkout for these files to resolve correctly # (by default when running 'ant test', or 'test/partest'). Paths use Unix separators, the test # framework translates them to the platform dependent representation. -# -bootclasspath lib/scala-compiler.jar:lib/scala-library.jar:lib/fjbg.jar +# -bootclasspath lib/scala-compiler.jar:lib/scala-library.jar # the following line would test using the quick compiler -# -bootclasspath build/quick/classes/compiler:build/quick/classes/library:lib/fjbg.jar +# -bootclasspath build/quick/classes/compiler:build/quick/classes/library diff --git a/test/disabled/presentation/simple-tests.opts b/test/disabled/presentation/simple-tests.opts index 8529bbf1a072..d651316984ce 100644 --- a/test/disabled/presentation/simple-tests.opts +++ b/test/disabled/presentation/simple-tests.opts @@ -12,7 +12,7 @@ # running partest from. Run it from the root scala checkout for these files to resolve correctly # (by default when running 'ant test', or 'test/partest'). Paths use Unix separators, the test # framework translates them to the platform dependent representation. --bootclasspath lib/scala-compiler.jar:lib/scala-library.jar:lib/fjbg.jar +-bootclasspath lib/scala-compiler.jar:lib/scala-library.jar # the following line would test using the quick compiler -# -bootclasspath build/quick/classes/compiler:build/quick/classes/library:lib/fjbg.jar +# -bootclasspath build/quick/classes/compiler:build/quick/classes/library diff --git a/test/files/ant/imported.xml b/test/files/ant/imported.xml index 5a4dfc319bd2..182c80aadfe9 100644 --- a/test/files/ant/imported.xml +++ b/test/files/ant/imported.xml @@ -56,7 +56,6 @@ INITIALISATION - @@ -67,7 +66,6 @@ INITIALISATION - @@ -78,7 +76,6 @@ INITIALISATION - @@ -89,7 +86,6 @@ INITIALISATION - @@ -98,7 +94,6 @@ INITIALISATION - diff --git a/test/pending/jvm/cf-attributes.scala b/test/pending/jvm/cf-attributes.scala index 9e0e9d95de03..f4964b63b103 100644 --- a/test/pending/jvm/cf-attributes.scala +++ b/test/pending/jvm/cf-attributes.scala @@ -52,14 +52,14 @@ object anonymousFunctions { } object anonymousClasses { - //InnerClass: + //InnerClass: // public abstract #_= #_ of #_; //Foo=class anonymousClasses$Foo of class anonymousClasses$ // public abstract #_= #_ of #_; //Foo$class=class anonymousClasses$Foo$class of class anonymousClasses$ trait Foo { def foo() { println("foo"); } override def toString = getClass.getName } - //InnerClass: + //InnerClass: // public final #_; //class anonymousClasses$$anon$1 of class anonymousClasses$ val x = new Foo() { override def foo() { println("foo (overriden)"); } @@ -88,16 +88,16 @@ trait Test1 { trait Test2 { @throws(classOf[Exception]) - def printInnerClasses(cls: Class[_]) { - import java.io._, ch.epfl.lamp.fjbg._ - val fjbgContext = new FJBGContext(49, 0) - val outDir = System.getProperty("partest.output", "cf-attributes.obj") - val fileName = outDir+File.separator+cls.getName+".class" - val in = new DataInputStream(new FileInputStream(fileName)) - val jclass = fjbgContext.JClass(in) - println(jclass.getInnerClasses) - in.close() - } + // def printInnerClasses(cls: Class[_]) { + // import java.io._, ch.epfl.lamp.fjbg._ + // val fjbgContext = new FJBGContext(49, 0) + // val outDir = System.getProperty("partest.output", "cf-attributes.obj") + // val fileName = outDir+File.separator+cls.getName+".class" + // val in = new DataInputStream(new FileInputStream(fileName)) + // val jclass = fjbgContext.JClass(in) + // println(jclass.getInnerClasses) + // in.close() + // } def printClass(name: String) { try { printClass(Class.forName(name)) } catch { case e: Exception => println(e) } @@ -105,7 +105,7 @@ trait Test2 { def printClass(cls: Class[_]) { println("\n[[ "+cls.getName+" ]]"); try { printInnerClasses(cls) } - catch { case e: Exception => println(e) } + catch { case e: Exception => println(e) } } } diff --git a/tools/buildcp b/tools/buildcp index 766ab81f9057..3ae70e10a372 100755 --- a/tools/buildcp +++ b/tools/buildcp @@ -8,4 +8,4 @@ lib=$($dir/abspath $dir/../lib) build=$($dir/abspath $dir/../build) cp=$($dir/cpof $build/$1/classes):$build/asm/classes -echo $cp:$lib/fjbg.jar:$lib/msil.jar:$lib/forkjoin.jar:$lib/jline.jar:$lib/extra/'*' +echo $cp:$lib/forkjoin.jar:$lib/jline.jar:$lib/extra/'*' diff --git a/tools/strapcp b/tools/strapcp index 6a46b4e1c8f5..6a4044ae2460 100755 --- a/tools/strapcp +++ b/tools/strapcp @@ -6,7 +6,6 @@ strap="$dir/../build/strap/classes" [[ -d $strap ]] || { echo "Error: no directory at $strap"; exit 1; } cp=$($dir/cpof $strap) -fjbg=$($dir/abspath $dir/../lib/fjbg.jar) asm=$($dir/abspath $dir/../build/asm/classes) -echo $cp:$fjbg:$asm +echo $cp:$asm