Fix large version bubble field offset computation (#34401)
authorJan Vorlicek <janvorli@microsoft.com>
Thu, 2 Apr 2020 13:11:13 +0000 (15:11 +0200)
committerGitHub <noreply@github.com>
Thu, 2 Apr 2020 13:11:13 +0000 (15:11 +0200)
commitc8b9cf1bf6654d5d1ad3fdab1a966590d707de4e
treeed7508d0e7478bdd5f9a54af82a0e925c7b10f51
parenta95705d60c5616c8fe95ec7d2253953bdfd34a22
Fix large version bubble field offset computation (#34401)

This change fixes two bugs in field offset computation where the results
that crossgen2 was getting was different from what runtime computes. In
both cases, the problem was caused by alignment of a derived class being
done differently.
The first issue was happening for the case when the base and derived
classes are in different assemblies. Runtime detect if two assemblies
are in the same version bubble using the native manifest metadata table
containing a list of assemblies that was supposed to contain all
assemblies that the assembly being compiled was found to reference.
However, it contained only assemblies that were not in the original
assembly reference list, e.g. ones pulled in by inlining. So runtime
wasn't getting the same view on what's in the bubble.
The second issue happened for the case when both the base and derived
class were from the same assembly, but one of the ancestor classes had a
field of a value class type that was from another assembly and could be
transitively decomposed to fields of types from the same assembly or types
like primitive types, object, pointer or enums. The alignment of a derived
class members is determined based on that and runtime decision is to
align if there is any type from another assembly in the type hierarchy
of a class or in fields of any ancestors.
For example, the decision would be different for the following scenario:
Assembly A:
struct AA
{
    int a;
}
Assembly B:
class B1
{
    AA aa;
}
class B2 : B1
{
    int x;
}
Here crossgen2 would not align the first member but runtime would. So the
layout of B2 produced by crossgen2 would be:
```
Offset  Field
0       MethodTable
8       a
12      x
```
Layout produced by the runtime would be
```
Offset  Field
0       MethodTable
8       a
16      x
```

The fix for the first issue is to put all referenced assemblies into the
native manifest metadata.
The fix for the second issue is to stop decomposing members of value
classes once we hit a value class that's from another module.
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/CompilationModuleGroup.ReadyToRun.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunSingleAssemblyCompilationModuleGroup.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/SingleMethodCompilationModuleGroup.cs
src/coreclr/src/tools/crossgen2/crossgen2/Program.cs