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

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Lapounov <antonl@microsoft.com>2017-06-16 22:02:07 +0300
committerAnton Lapounov <antonl@microsoft.com>2017-06-16 22:02:07 +0300
commit9b5108849025b1d1ea5f780c8bfefbf1783eee36 (patch)
tree7489aa0563d74a968f0f5a5bacd52dbc91e12aec
parent98c8b4a802146172aa1955467c2fbe6bb3760b69 (diff)
Distinguish positive and negative zeros in metadata writer.
Bug: https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/442050 CR: JKotas [tfs-changeset: 1661975]
-rw-r--r--src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs41
-rw-r--r--src/Common/src/Internal/Metadata/NativeFormat/Generator/WriterGen.cs20
-rw-r--r--src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs8
-rw-r--r--src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs37
4 files changed, 63 insertions, 43 deletions
diff --git a/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs b/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs
index 54d049aa6..d5da54db8 100644
--- a/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs
+++ b/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs
@@ -26,25 +26,23 @@ public enum RecordDefFlags
[Flags]
public enum MemberDefFlags
{
- Map = 0x0001, // => Dictionary<string, RecordType> for MetadataWriter
- // => List<RecordType> for MetadataReader
- List = 0x0002, // => List<RecordType>
- Array = 0x0004, // => RecordType[]
+ Map = 0x0001, // => List<RecordType> for writer
+ List = 0x0002, // => List<RecordType> for writer
+ Array = 0x0004, // => RecordType[] for writer
Collection = MemberDefFlags.Map | MemberDefFlags.List | MemberDefFlags.Array,
Sequence = MemberDefFlags.List | MemberDefFlags.Array,
- RecordRef = 0x0008, // => RecordTypeHandle
-
- Ref = MemberDefFlags.RecordRef,
+ RecordRef = 0x0008,
Child = 0x0010, // Member instance is logically defined and owned by record;
// otherwise instance may be shared (such as a TypeRef).
- Name = 0x0020, // May be used as the member"s simple name for diagnostics.
+ Name = 0x0020, // May be used as the member's simple name for diagnostics.
NotPersisted = 0x0040, // Indicates member is not written to or read from metadata.
Compare = 0x0080, // Indicates member should be used for equality functionality.
EnumerateForHashCode = 0x0100, // Indicates that the collection is safe to be enumerated in GetHashCode
// without causing reentrancy
+ CustomCompare = 0x0200, // Indicates that this member uses a custom comparer
}
public enum MemberTypeKind
@@ -86,14 +84,14 @@ public class MemberDef
else
{
typeName = (kind == MemberTypeKind.WriterField) ?
- (TypeName != null ? (string)TypeName : "MetadataRecord"): $"{ TypeName}Handle";
+ (TypeName != null ? (string)TypeName : "MetadataRecord"): $"{TypeName}Handle";
}
}
else
{
typeName = (string)TypeName;
}
- if ((Flags & (MemberDefFlags.Array | MemberDefFlags.List | MemberDefFlags.Map)) != 0)
+ if ((Flags & MemberDefFlags.Collection) != 0)
{
if (kind == MemberTypeKind.WriterField)
{
@@ -119,10 +117,7 @@ public class MemberDef
if (typeSet == null)
return null;
- string result = "One of: " + typeSet[0];
- for (int i = 1; i < typeSet.Length; i++)
- result += ", " + typeSet[i];
- return result;
+ return "One of: " + String.Join(", ", typeSet);
}
}
@@ -161,14 +156,16 @@ public class EnumType
public class PrimitiveType
{
- public PrimitiveType(string name, string typeName)
+ public PrimitiveType(string name, string typeName, bool customCompare = false)
{
Name = name;
TypeName = typeName;
+ CustomCompare = customCompare;
}
readonly public string Name;
readonly public string TypeName;
+ readonly public bool CustomCompare;
}
/// <summary>
@@ -208,8 +205,8 @@ class SchemaDef
new PrimitiveType("uint", "UInt32"),
new PrimitiveType("long", "Int64"),
new PrimitiveType("ulong", "UInt64"),
- new PrimitiveType("float", "Single"),
- new PrimitiveType("double", "Double"),
+ new PrimitiveType("float", "Single", customCompare: true),
+ new PrimitiveType("double", "Double", customCompare: true),
};
// These enums supplement those defined by System.Reflection.Primitives.
@@ -292,7 +289,8 @@ class SchemaDef
new RecordDef(
name: "Constant" + primitiveType.TypeName + "Value",
members: new MemberDef[] {
- new MemberDef(name: "Value", typeName: primitiveType.Name)
+ new MemberDef(name: "Value", typeName: primitiveType.Name,
+ flags: primitiveType.CustomCompare ? MemberDefFlags.CustomCompare : 0)
}
)
)
@@ -326,7 +324,8 @@ class SchemaDef
new RecordDef(
name: "Constant" + primitiveType.TypeName + "Array",
members: new MemberDef[] {
- new MemberDef(name: "Value", flags: MemberDefFlags.Array, typeName: primitiveType.TypeName)
+ new MemberDef(name: "Value", typeName: primitiveType.TypeName,
+ flags: MemberDefFlags.Array | (primitiveType.CustomCompare ? MemberDefFlags.CustomCompare : 0))
}
)
)
@@ -782,9 +781,7 @@ class SchemaDef
from member in r.Members
let memberTypeName = member.TypeName as string
where memberTypeName != null &&
- ((member.Flags & MemberDefFlags.Array) != 0 ||
- (member.Flags & MemberDefFlags.List) != 0 ||
- (member.Flags & MemberDefFlags.Map) != 0) &&
+ (member.Flags & MemberDefFlags.Collection) != 0 &&
!PrimitiveTypes.Any(pt => pt.TypeName == memberTypeName)
select memberTypeName
).Concat(new[] { "ScopeDefinition" }).Distinct().ToArray();
diff --git a/src/Common/src/Internal/Metadata/NativeFormat/Generator/WriterGen.cs b/src/Common/src/Internal/Metadata/NativeFormat/Generator/WriterGen.cs
index 25f18c15e..fe1daca06 100644
--- a/src/Common/src/Internal/Metadata/NativeFormat/Generator/WriterGen.cs
+++ b/src/Common/src/Internal/Metadata/NativeFormat/Generator/WriterGen.cs
@@ -61,14 +61,7 @@ class WriterGen : CsWriter
if ((member.Flags & MemberDefFlags.RecordRef) == 0)
continue;
- if ((member.Flags & (MemberDefFlags.Map | MemberDefFlags.Sequence)) != 0)
- {
- WriteLine($"{member.Name} = visitor.Visit(this, {member.Name});");
- }
- else
- {
- WriteLine($"{member.Name} = visitor.Visit(this, {member.Name});");
- }
+ WriteLine($"{member.Name} = visitor.Visit(this, {member.Name});");
}
CloseScope("Visit");
@@ -94,17 +87,20 @@ class WriterGen : CsWriter
if ((member.Flags & MemberDefFlags.Sequence) != 0)
{
- WriteLine($"if (!{member.Name}.SequenceEqual(other.{member.Name})) return false;");
+ if ((member.Flags & MemberDefFlags.CustomCompare) != 0)
+ WriteLine($"if (!{member.Name}.SequenceEqual(other.{member.Name}, {member.TypeName}Comparer.Instance)) return false;");
+ else
+ WriteLine($"if (!{member.Name}.SequenceEqual(other.{member.Name})) return false;");
}
else
- if ((member.Flags & (MemberDefFlags.List | MemberDefFlags.Map)) != 0)
+ if ((member.Flags & (MemberDefFlags.Map | MemberDefFlags.RecordRef)) != 0)
{
WriteLine($"if (!Object.Equals({member.Name}, other.{member.Name})) return false;");
}
else
- if ((member.Flags & MemberDefFlags.RecordRef) != 0)
+ if ((member.Flags & MemberDefFlags.CustomCompare) != 0)
{
- WriteLine($"if (!Object.Equals({member.Name}, other.{member.Name})) return false;");
+ WriteLine($"if (!CustomComparer.Equals({member.Name}, other.{member.Name})) return false;");
}
else
{
diff --git a/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs b/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs
index eee6cd3ea..d503e858e 100644
--- a/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs
+++ b/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs
@@ -676,7 +676,7 @@ namespace Internal.Metadata.NativeFormat.Writer
if (Object.ReferenceEquals(this, obj)) return true;
var other = obj as ConstantDoubleArray;
if (other == null) return false;
- if (!Value.SequenceEqual(other.Value)) return false;
+ if (!Value.SequenceEqual(other.Value, DoubleComparer.Instance)) return false;
return true;
} // Equals
@@ -745,7 +745,7 @@ namespace Internal.Metadata.NativeFormat.Writer
if (Object.ReferenceEquals(this, obj)) return true;
var other = obj as ConstantDoubleValue;
if (other == null) return false;
- if (Value != other.Value) return false;
+ if (!CustomComparer.Equals(Value, other.Value)) return false;
return true;
} // Equals
@@ -1527,7 +1527,7 @@ namespace Internal.Metadata.NativeFormat.Writer
if (Object.ReferenceEquals(this, obj)) return true;
var other = obj as ConstantSingleArray;
if (other == null) return false;
- if (!Value.SequenceEqual(other.Value)) return false;
+ if (!Value.SequenceEqual(other.Value, SingleComparer.Instance)) return false;
return true;
} // Equals
@@ -1596,7 +1596,7 @@ namespace Internal.Metadata.NativeFormat.Writer
if (Object.ReferenceEquals(this, obj)) return true;
var other = obj as ConstantSingleValue;
if (other == null) return false;
- if (Value != other.Value) return false;
+ if (!CustomComparer.Equals(Value, other.Value)) return false;
return true;
} // Equals
diff --git a/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs b/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs
index 0dec3aad3..5f486ab6d 100644
--- a/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs
+++ b/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeMetadataWriter.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#pragma warning disable 649
-
using System;
using System.IO;
using System.Collections.Generic;
@@ -567,7 +565,7 @@ namespace Internal.Metadata.NativeFormat.Writer
/// </summary>
public partial class ConstantStringValue
{
- public static explicit operator string (ConstantStringValue value)
+ public static explicit operator string(ConstantStringValue value)
{
if (value == null)
return null;
@@ -929,7 +927,7 @@ namespace Internal.Metadata.NativeFormat.Writer
ReturnType.ToString(false),
name
+ (GenericParameterCount == 0 ? "" : "`" + GenericParameterCount.ToString())
- + "(" + String.Join(", ", Parameters.Select(p => p.ToString(false))) +
+ + "(" + String.Join(", ", Parameters.Select(p => p.ToString(false))) +
String.Join(", ", VarArgParameters.Select(p => p.ToString(false))) + ")"}.Where(e => !String.IsNullOrWhiteSpace(e)));
}
}
@@ -1120,5 +1118,34 @@ namespace Internal.Metadata.NativeFormat.Writer
return true;
}
}
-}
+ // Distinguishes positive and negative zeros for float and double values
+ public static class CustomComparer
+ {
+ public static unsafe bool Equals(float x, float y)
+ {
+ return *(int*)&x == *(int*)&y;
+ }
+
+ public static bool Equals(double x, double y)
+ {
+ return BitConverter.DoubleToInt64Bits(x) == BitConverter.DoubleToInt64Bits(y);
+ }
+ }
+
+ public sealed class SingleComparer : IEqualityComparer<float>
+ {
+ public static readonly SingleComparer Instance = new SingleComparer();
+
+ public bool Equals(float x, float y) => CustomComparer.Equals(x, y);
+ public int GetHashCode(float obj) => obj.GetHashCode();
+ }
+
+ public sealed class DoubleComparer : IEqualityComparer<double>
+ {
+ public static readonly DoubleComparer Instance = new DoubleComparer();
+
+ public bool Equals(double x, double y) => CustomComparer.Equals(x, y);
+ public int GetHashCode(double obj) => obj.GetHashCode();
+ }
+}