Bug 60298 - LayoutKind.Explicit, Size = 12 ignored with 64bit alignment
Summary: LayoutKind.Explicit, Size = 12 ignored with 64bit alignment
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: Interop (show other bugs)
Version: master
Hardware: PC Mac OS
: --- normal
Target Milestone: Future Cycle (TBD)
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2017-10-20 19:55 UTC by David Karlaš
Modified: 2018-01-24 18:26 UTC (History)
5 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description David Karlaš 2017-10-20 19:55:23 UTC
Example below outputs on .NET 64bit:
8
12
but on Mono 64bit(32bit works fine) it outputs:
8
16

```

using System;
using System.Runtime.InteropServices;

class MainClass
{
    [StructLayout(LayoutKind.Explicit, Size = 12)]
    private struct Sha1Hash
    {
        [FieldOffset(0)]
        private long Data1;

        [FieldOffset(8)]
        private int Data3;
    }

    public static void Main(string[] args)
    {
        unsafe
        {
            var size = sizeof(Sha1Hash);
            Console.WriteLine(IntPtr.Size);
            Console.WriteLine(size);
        }
    }
}
```

This was uncovered by https://github.com/dotnet/roslyn/blob/f629039/src/Workspaces/Core/Portable/Workspace/Solution/Checksum.cs#L28
Comment 1 Ludovic Henry 2017-10-20 19:57:21 UTC
I can reproduce with Mono 5.8.0.2 (2017-10/a3943e28cf8)
Comment 2 Zoltan Varga 2017-10-22 21:02:05 UTC
This is caused by:
https://github.com/mono/mono/blob/master/mono/metadata/class.c#L2078
Comment 3 Zoltan Varga 2017-10-23 18:56:45 UTC
The explicit layout directive is supposed to only affect unmanaged layout, so the sizeof (T) should still return the managed size imho.
Comment 4 Zoltan Varga 2017-10-23 19:03:21 UTC
According to the ecma spec:

[Rationale: The definition of a value type can change between the time the CIL is generated and the time that it is loaded for execution. Thus, the size of the type is not always known when the CIL is generated. The sizeof instruction allows CIL code to determine the size at runtime without the need to call into the Framework class library. The computation can occur entirely at runtime or at CIL-to-native-code compilation time. sizeof returns the total size that would be occupied by each element in an array of this type – including any padding the implementation chooses to add. Specifically, array elements lie sizeof bytes apart. end rationale]

So the implementation is free to add padding, like mono does. I don't think it is a bug, more like roslyn is depending on an implementation detail.
Comment 5 Zoltan Varga 2017-12-11 22:43:05 UTC
https://github.com/mono/mono/pull/6223
Comment 6 Dustin Campbell 2017-12-12 17:11:10 UTC
Adding some details from a mail thread with Sam Harwell to ensure they're documented:

> The explicit layout directive is supposed to only affect unmanaged layout …

This is an incorrect statement. In ECMA-335 §II.10.7 there are two statements which make this clear:

* Fields can be accessed using pointer arithmetic and ldind to load the field indirectly or stind to store the field indirectly …
* Note: Metadata that controls instance layout is not a “hint,” it is an integral part of the VES that shall be supported by all conforming implementations of the CLI.

> So the implementation is free to add padding, like mono does.

I’m finding it hard to believe this. The most direct evidence that padding was not intended here comes from the following statement in the informative text of §II.22.8:

* If Parent indexes an ExplicitLayout type, then … PackingSize shall be 0. (It makes no sense to provide explicit offsets for each field, as well as a packing size.) [ERROR]

This interpretation is further supported by §I.9.5 (Class layout). This section explicitly provides for the CLI to modify the layout according to limitations defined in source code. The definitions of autolayout and sequentiallayout provide for the runtime to modify alignments, but no such provision is provided for explicitlayout. Rather, explicitlayout provides only for the alignment of instances of the type itself (using .size), an interpretation of the wording which is confirmed by the informative text of §II.22.8.
Comment 7 Ludovic Henry 2018-01-24 18:26:00 UTC
This landed in master with https://github.com/mono/mono/commit/6b58f1317732b9cbf6ec61921e76d7d48e362104.

It is being backported to mono:2017-12 with https://github.com/mono/mono/pull/6653

Note You need to log in before you can comment on or make changes to this bug.