Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaja R Harinath <harinath@hurrynot.org>2006-02-15 14:29:58 +0300
committerRaja R Harinath <harinath@hurrynot.org>2006-02-15 14:29:58 +0300
commitd02c00d24a7494e30179437b4150725560d06144 (patch)
tree3d424d9753478ea859cf9a6ea6ec6befcbc29159 /mcs/class/PEAPI
parent5a71d6eba1f3f4615f35eca90ab07a40a39f0a13 (diff)
* Metadata.cs (BoundArray.CompressSignedNum): Document the
transformation. Avoid a few casts. svn path=/trunk/mcs/; revision=56888
Diffstat (limited to 'mcs/class/PEAPI')
-rw-r--r--mcs/class/PEAPI/ChangeLog5
-rw-r--r--mcs/class/PEAPI/Metadata.cs47
2 files changed, 42 insertions, 10 deletions
diff --git a/mcs/class/PEAPI/ChangeLog b/mcs/class/PEAPI/ChangeLog
index dae5b1005e0..e2b2e9e0fde 100644
--- a/mcs/class/PEAPI/ChangeLog
+++ b/mcs/class/PEAPI/ChangeLog
@@ -1,3 +1,8 @@
+2006-02-15 Raja R Harinath <rharinath@novell.com>
+
+ * Metadata.cs (BoundArray.CompressSignedNum): Document the
+ transformation. Avoid a few casts.
+
2006-02-15 Ankit Jain <jankit@novell.com>
* Metadata.cs (BoundArray.CompressSignedNum): New. Encode signed values,
diff --git a/mcs/class/PEAPI/Metadata.cs b/mcs/class/PEAPI/Metadata.cs
index 98759fc0493..083f8ba8fbe 100644
--- a/mcs/class/PEAPI/Metadata.cs
+++ b/mcs/class/PEAPI/Metadata.cs
@@ -2352,20 +2352,47 @@ namespace PEAPI {
private void CompressSignedNum (int val, MemoryStream str)
{
uint uval = (uint) val;
- int sign = val < 0 ? 1 : 0;
- uint fval = (uint) ((uval << 1) | sign);
- int sval = (((val < 0 ? - val : val)) << 1) - sign;
-
- if (sval < 0x80)
+ byte sign = 0;
+ if (val < 0) {
+ val = -val;
+ sign = 1;
+ }
+
+ /* Map the signed number to an unsigned number in two ways.
+
+ fval: left-rotated 2's complement representation
+ sval: map the signed number to unsigned as follows: 0 -> 0, -1 -> 1, 1 -> 2, -2 -> 3, 2 -> 4, ....
+ the mapping is: x -> 2*|x| - signbit(x)
+ */
+ uint fval = (uval << 1) | sign;
+ int sval = (val << 1) - sign;
+
+ /* An overly clever transformation:
+
+ a. sval is used to determine the number of bytes in the compressed representation.
+ b. fval is truncated to the appropriate number of bits and output using the
+ normal unsigned-int compressor.
+
+ However, or certain values, the truncated fval doesn't carry enough information to round trip.
+
+ (fval & 0x3FFF) <= 0x7F => compressor emits 1 byte, not 2 => there is aliasing of values
+
+ So, we use full 4 bytes to encode such values.
+
+ LAMESPEC: The Microsoft implementation doesn't appear to handle this subtle case.
+ e.g., it ends up encoding -8192 as the byte 0x01, which decodes to -64
+ */
+ if (sval <= 0x7F)
MetaData.CompressNum (fval & 0x7F, str);
- else if (sval < 0x4000 && (fval & 0x3fff) >= 0x80)
- /* If (fval & 0x3fff) < 0x80, then
- encode with full 4 bytes */
+ else if (sval <= 0x3FFF && (fval & 0x3FFF) > 0x7F)
MetaData.CompressNum (fval & 0x3FFF, str);
+ else if (sval <= 0x1FFFFFFF && (fval & 0x1FFFFFFF) > 0x3FFF)
+ MetaData.CompressNum (fval & 0x1FFFFFFF, str);
else
- MetaData.CompressNum ((uint) (fval & 0x1FFFFFFF), str);
+ /* FIXME: number cannot be represented. Report a warning. */
+ // throw new Exception ("cannot represent signed value" + -val);
+ MetaData.CompressNum (fval, str);
}
-
}
#endregion