示例#1
0
        public void LayoutIntTests()
        {
            Assert.Throws <ArgumentException>(() => { return(new LayoutInt(int.MinValue)); });
            Assert.Throws <ArgumentException>(() => { return(new LayoutInt(-1)); });

            Assert.Equal(LayoutInt.Zero, new LayoutInt(0));
            Assert.Equal(LayoutInt.One, new LayoutInt(1));

            Assert.True(LayoutInt.Zero == new LayoutInt(0));
            Assert.True(LayoutInt.One == new LayoutInt(1));
            Assert.False(LayoutInt.Zero == new LayoutInt(1));
            Assert.False(LayoutInt.One == new LayoutInt(0));
#pragma warning disable 1718 // Allow comparison to same variable
            Assert.True(LayoutInt.Indeterminate == LayoutInt.Indeterminate);
#pragma warning restore 1718

            Assert.False(LayoutInt.Zero != new LayoutInt(0));
            Assert.False(LayoutInt.One != new LayoutInt(1));
            Assert.True(LayoutInt.Zero != new LayoutInt(1));
            Assert.True(LayoutInt.One != new LayoutInt(0));
#pragma warning disable 1718 // Allow comparison to same variable
            Assert.False(LayoutInt.Indeterminate != LayoutInt.Indeterminate);
#pragma warning restore 1718

            Assert.Equal(0, new LayoutInt(0).AsInt);
            Assert.Equal(1, new LayoutInt(1).AsInt);
            Assert.Equal(Int32.MaxValue, new LayoutInt(Int32.MaxValue).AsInt);
            Assert.Throws <InvalidOperationException>(() => { return(LayoutInt.Indeterminate.AsInt); });

            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Indeterminate + LayoutInt.Indeterminate);
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.One + LayoutInt.Indeterminate);
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Indeterminate + LayoutInt.One);
            Assert.Equal(new LayoutInt(2), LayoutInt.One + LayoutInt.One);
            Assert.Throws <OverflowException>(() => { return(new LayoutInt(int.MaxValue) + LayoutInt.One); });
            Assert.Throws <OverflowException>(() => { return(new LayoutInt(int.MaxValue) + LayoutInt.One); });

            Assert.Equal(LayoutInt.One, LayoutInt.Max(LayoutInt.One, LayoutInt.Zero));
            Assert.Equal(LayoutInt.One, LayoutInt.Max(LayoutInt.Zero, LayoutInt.One));
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Max(LayoutInt.Indeterminate, LayoutInt.Zero));
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Max(LayoutInt.Zero, LayoutInt.Indeterminate));
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Max(LayoutInt.Indeterminate, LayoutInt.Indeterminate));

            Assert.Equal(LayoutInt.Zero, LayoutInt.Min(LayoutInt.One, LayoutInt.Zero));
            Assert.Equal(LayoutInt.Zero, LayoutInt.Min(LayoutInt.Zero, LayoutInt.One));
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Min(LayoutInt.Indeterminate, LayoutInt.Zero));
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Min(LayoutInt.Zero, LayoutInt.Indeterminate));
            Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Min(LayoutInt.Indeterminate, LayoutInt.Indeterminate));
        }
示例#2
0
        // The layout algorithm should probably compute results and let the caller set things
        internal unsafe LayoutInt[] ComputeTypeSizeAndAlignment(TypeDesc type, FieldLoadState loadRequested, out LowLevelList <LayoutInt> fieldOffsets)
        {
            fieldOffsets = null;
            TypeLoaderLogger.WriteLine("Laying out type " + type.ToString() + ". IsValueType: " + (type.IsValueType ? "true" : "false") + ". LoadRequested = " + ((int)loadRequested).LowLevelToString());

            Debug.Assert(loadRequested != FieldLoadState.None);
            Debug.Assert(type is ArrayType || (type is DefType && ((DefType)type).HasInstantiation));

            bool isArray = type is ArrayType;

            LayoutInt[] position      = new LayoutInt[5];
            LayoutInt   alignRequired = LayoutInt.One;

            if ((loadRequested & FieldLoadState.Instance) == FieldLoadState.Instance)
            {
                ComputeTypeSizeBeforeFields(type, out position[(int)NativeFormat.FieldStorage.Instance], out alignRequired);
            }

            if (!isArray)
            {
                // Once this is done, the NativeLayoutFields on the type are initialized
                EnsureFieldLayoutLoadedForGenericType((DefType)type);
                Debug.Assert(type.NativeLayoutFields != null);
            }

            int instanceFields = 0;

            if (!isArray && type.NativeLayoutFields.Length > 0)
            {
                fieldOffsets = new LowLevelList <LayoutInt>(type.NativeLayoutFields.Length);
                for (int i = 0; i < type.NativeLayoutFields.Length; i++)
                {
                    TypeDesc fieldType    = type.NativeLayoutFields[i].FieldType;
                    int      fieldStorage = (int)type.NativeLayoutFields[i].FieldStorage;

                    if (!ShouldProcessField((NativeFormat.FieldStorage)fieldStorage, loadRequested))
                    {
                        continue;
                    }

                    // For value types, we will attempt to get the size and alignment from
                    // the runtime if possible, otherwise GetFieldSizeAndAlignment will
                    // recurse to lay out nested struct fields.
                    LayoutInt alignment;
                    LayoutInt size;
                    GetFieldSizeAlignment(fieldType, out size, out alignment);

                    Debug.Assert(alignment.AsInt > 0);

                    if (fieldStorage == (int)NativeFormat.FieldStorage.Instance)
                    {
                        instanceFields++;

                        // Ensure alignment of type is sufficient for this field
                        alignRequired = LayoutInt.Max(alignRequired, alignment);
                    }

                    position[fieldStorage] = LayoutInt.AlignUp(position[fieldStorage], alignment);
                    TypeLoaderLogger.WriteLine(" --> Field type " + fieldType.ToString() +
                                               " storage " + ((uint)(type.NativeLayoutFields[i].FieldStorage)).LowLevelToString() +
                                               " offset " + position[fieldStorage].LowLevelToString() +
                                               " alignment " + alignment.LowLevelToString());

                    fieldOffsets.Add(position[fieldStorage]);
                    position[fieldStorage] += size;
                }
            }

            // Pad the length of structs to be 1 if they are empty so we have no zero-length structures
            if ((position[(int)NativeFormat.FieldStorage.Instance] == LayoutInt.Zero) && type.IsValueType)
            {
                position[(int)NativeFormat.FieldStorage.Instance] = LayoutInt.One;
            }

            Debug.Assert(alignRequired == new LayoutInt(1) ||
                         alignRequired == new LayoutInt(2) ||
                         alignRequired == new LayoutInt(4) ||
                         alignRequired == new LayoutInt(8));

            position[InstanceAlignmentEntry] = alignRequired;

            return(position);
        }