summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Garcia <magarcia@epfl.ch>2011-04-20 10:32:30 +0000
committerMiguel Garcia <magarcia@epfl.ch>2011-04-20 10:32:30 +0000
commit5485932c5a822c2761682326381217697eb2ae4e (patch)
tree241ad21d5c0ff4f982049e518d7ef92ab69b4e4b
parent3fce9dfd7f786303582cbdbd6b7060f44d90471f (diff)
downloadscala-5485932c5a822c2761682326381217697eb2ae4e.tar.gz
scala-5485932c5a822c2761682326381217697eb2ae4e.tar.bz2
scala-5485932c5a822c2761682326381217697eb2ae4e.zip
[MSIL] finer-grain debugging (steps one sub-exp...
[MSIL] finer-grain debugging (steps one sub-expression at time).
-rw-r--r--lib/msil.jar.desired.sha12
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala64
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Assembly.java6
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEFile.java23
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala14
5 files changed, 60 insertions, 49 deletions
diff --git a/lib/msil.jar.desired.sha1 b/lib/msil.jar.desired.sha1
index 6a95abf8e6..7dd6b5d66b 100644
--- a/lib/msil.jar.desired.sha1
+++ b/lib/msil.jar.desired.sha1
@@ -1 +1 @@
-411bfee5f3b2b6bae5f6ac06f84b4f4624370492 ?msil.jar
+58f64cd00399c724e7d526e5bdcbce3e2b79f78b ?msil.jar
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index a38916b8e4..d593a13d8b 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -108,14 +108,14 @@ abstract class GenMSIL extends SubComponent {
val objParam = Array(MOBJECT)
-// val toBool: MethodInfo = SystemConvert.GetMethod("ToBoolean", objParam)
- val toSByte: MethodInfo = SystemConvert.GetMethod("ToSByte", objParam)
- val toShort: MethodInfo = SystemConvert.GetMethod("ToInt16", objParam)
- val toChar: MethodInfo = SystemConvert.GetMethod("ToChar", objParam)
- val toInt: MethodInfo = SystemConvert.GetMethod("ToInt32", objParam)
- val toLong: MethodInfo = SystemConvert.GetMethod("ToInt64", objParam)
- val toFloat: MethodInfo = SystemConvert.GetMethod("ToSingle", objParam)
- val toDouble: MethodInfo = SystemConvert.GetMethod("ToDouble", objParam)
+ 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)
@@ -460,9 +460,8 @@ abstract class GenMSIL extends SubComponent {
}
private[GenMSIL] def ilasmFileName(iclass: IClass) : String = {
- val singleBackslashed = iclass.cunit.source.file.toString
- val doubleBackslashed = singleBackslashed.replace("\\", "\\\\")
- doubleBackslashed
+ // method.sourceFile contains just the filename
+ iclass.cunit.source.file.toString.replace("\\", "\\\\")
}
private[GenMSIL] def genClass(iclass: IClass) {
@@ -564,6 +563,10 @@ abstract class GenMSIL extends SubComponent {
val labels: HashMap[BasicBlock, Label] = new HashMap()
+ /* 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]) = {
@@ -587,6 +590,7 @@ abstract class GenMSIL extends SubComponent {
// 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
@@ -897,6 +901,7 @@ abstract class GenMSIL extends SubComponent {
var previousWasNEW = false
var lastLineNr: Int = 0
+ var lastPos: Position = NoPosition
// EndExceptionBlock must happen before MarkLabel because it adds the
@@ -932,18 +937,24 @@ abstract class GenMSIL extends SubComponent {
}
for (instr <- block) {
- val currentLineNr = try {
- instr.pos.line
- } catch {
- case _: UnsupportedOperationException =>
- log("Warning: wrong position in: " + method)
- lastLineNr
- }
-
- if (currentLineNr != lastLineNr) {
- mcode.setPosition(currentLineNr, ilasmFileName(clasz)) // method.sourceFile contains just the filename
- lastLineNr = currentLineNr
- }
+ 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)
@@ -2194,7 +2205,12 @@ abstract class GenMSIL extends SubComponent {
def emitUnbox(code: ILGenerator, boxType: TypeKind) = (boxType: @unchecked) match {
case UNIT => code.Emit(OpCodes.Pop)
- case BOOL => code.Emit(OpCodes.Unbox, MBOOL); code.Emit(OpCodes.Ldind_I1)
+ /* (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)
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java b/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java
index d2adf3750a..59bbeee3a4 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java
@@ -45,13 +45,11 @@ public abstract class Assembly extends CustomAttributeProvider {
// dir = dir.getCanonicalFile();
// } catch (java.io.IOException e) {}
- if (name.endsWith(".exe") || name.endsWith(".EXE") ||
- name.endsWith(".dll") || name.endsWith(".DLL"))
- {
+ 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;
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
index 481d5f2116..3eb22b9985 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
@@ -95,7 +95,7 @@ public class PEFile {
/** 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."
+ * be placed at the front of the module."
*
* We are only checking for MZ (Mark Zbikowski)
*/
@@ -107,13 +107,13 @@ public class PEFile {
/** 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.
+ * 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
@@ -125,26 +125,19 @@ public class PEFile {
PE_HEADER_OFFSET = COFF_HEADER_OFFSET + 20;
seek(COFF_HEADER_OFFSET);
- skip(2);
- /** Ecma 335, 25.2.2: "Number of sections; indicates size of the Section Table" */
- numOfSections = readShort();
- //trace("Number of sections = " + numOfSections);
- /** Ecma 335, 25.2.2: "Time and date the file was created in seconds since
- * January 1st 1970 00:00:00 or 0."
- */
+ /* 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);
- //trace("Time stamp = " + timeStamp);
-
- skip(2 * INT_SIZE);
+ 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;
- //trace("Characteristics = " + Integer.toHexString(characteristics));
seek(PE_HEADER_OFFSET + 208); // p.157, Partition II
- CLI_RVA = readInt();
+ 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));
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
index c7899c7f54..2223a6db0f 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
@@ -402,16 +402,20 @@ import ILGenerator._
* 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))
+ if (line != 0) lineNums.put(lastLabel, Integer.toString(line))
}
def setPosition(line: Int, filename: String) {
- if (line != 0)
- lineNums.put(lastLabel, line + " '" + filename + "'")
+ if (line != 0) lineNums.put(lastLabel, line + " '" + filename + "'")
}
- def getLocals(): Array[LocalBuilder] = localList.toArray
+ 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