Skip to content

Commit

Permalink
Fix handling of x86 managed calling convention for hidden parameters (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
filipnavara authored and pull[bot] committed May 17, 2024
1 parent 5abf68a commit 9058800
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 17 deletions.
15 changes: 12 additions & 3 deletions src/coreclr/tools/Common/TypeSystem/Common/ArrayType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,18 @@ public override MethodSignature Signature
case ArrayMethodKind.AddressWithHiddenArg:
{
var parameters = new TypeDesc[_owningType.Rank + 1];
parameters[0] = Context.GetPointerType(Context.GetWellKnownType(WellKnownType.Void));
for (int i = 0; i < _owningType.Rank; i++)
parameters[i + 1] = _owningType.Context.GetWellKnownType(WellKnownType.Int32);
if (Context.Target.Architecture == TargetArchitecture.X86)
{
for (int i = 0; i < _owningType.Rank; i++)
parameters[i] = _owningType.Context.GetWellKnownType(WellKnownType.Int32);
parameters[_owningType.Rank] = Context.GetPointerType(Context.GetWellKnownType(WellKnownType.Void));
}
else
{
parameters[0] = Context.GetPointerType(Context.GetWellKnownType(WellKnownType.Void));
for (int i = 0; i < _owningType.Rank; i++)
parameters[i + 1] = _owningType.Context.GetWellKnownType(WellKnownType.Int32);
}
_signature = new MethodSignature(0, 0, _owningType.ElementType.MakeByRefType(), parameters, MethodSignature.EmbeddedSignatureMismatchPermittedFlag);
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ private void EmitILForAccessor()

int pointerSize = context.Target.PointerSize;

int argStartOffset = _method.Kind == ArrayMethodKind.AddressWithHiddenArg ? 2 : 1;
bool isX86 = context.Target.Architecture == TargetArchitecture.X86;
int argStartOffset = !isX86 && _method.Kind == ArrayMethodKind.AddressWithHiddenArg ? 2 : 1;
int hiddenArg = !isX86 ? 1 : 1 + _rank;

var rangeExceptionLabel = _emitter.NewCodeLabel();
ILCodeLabel typeMismatchExceptionLabel = null;
Expand Down Expand Up @@ -112,7 +114,7 @@ private void EmitILForAccessor()
// As per ECMA-335 III.2.3, the prefix suppresses the type check.
// if (hiddenArg == IntPtr.Zero)
// goto TypeCheckPassed;
codeStream.EmitLdArg(1);
codeStream.EmitLdArg(hiddenArg);
codeStream.Emit(ILOpcode.brfalse, typeCheckPassedLabel);

// MethodTable* actualElementType = this.m_pEEType->RelatedParameterType; // ArrayElementType
Expand All @@ -122,7 +124,7 @@ private void EmitILForAccessor()
_emitter.NewToken(eetypeType.GetKnownMethod("get_RelatedParameterType", null)));

// MethodTable* expectedElementType = hiddenArg->RelatedParameterType; // ArrayElementType
codeStream.EmitLdArg(1);
codeStream.EmitLdArg(hiddenArg);
codeStream.Emit(ILOpcode.call,
_emitter.NewToken(eetypeType.GetKnownMethod("get_RelatedParameterType", null)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,21 +442,34 @@ public override MethodIL EmitIL()
ILEmitter emit = new ILEmitter();
ILCodeStream codeStream = emit.NewCodeStream();

bool isX86 = Context.Target.Architecture == TargetArchitecture.X86;

FieldDesc eeTypeField = Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType");

// Load ByRef to the field with the value of the boxed valuetype
codeStream.EmitLdArg(0);
codeStream.Emit(ILOpcode.ldflda, emit.NewToken(Context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "RawData").GetField("Data")));

if (isX86)
{
for (int i = 0; i < _targetMethod.Signature.Length; i++)
{
codeStream.EmitLdArg(i + 1);
}
}

// Load the MethodTable of the boxed valuetype (this is the hidden generic context parameter expected
// by the (canonical) instance method, but normally not part of the signature in IL).
codeStream.EmitLdArg(0);
codeStream.Emit(ILOpcode.ldfld, emit.NewToken(eeTypeField));

// Load rest of the arguments
for (int i = 0; i < _targetMethod.Signature.Length; i++)
if (!isX86)
{
codeStream.EmitLdArg(i + 1);
for (int i = 0; i < _targetMethod.Signature.Length; i++)
{
codeStream.EmitLdArg(i + 1);
}
}

// Call an instance method on the target valuetype that has a fake instantiation parameter
Expand Down Expand Up @@ -608,9 +621,18 @@ public override MethodSignature Signature

// Shared instance methods on generic valuetypes have a hidden parameter with the generic context.
// We add it to the signature so that we can refer to it from IL.
parameters[0] = Context.GetWellKnownType(WellKnownType.Void).MakePointerType();
for (int i = 0; i < _methodRepresented.Signature.Length; i++)
parameters[i + 1] = _methodRepresented.Signature[i];
if (Context.Target.Architecture == TargetArchitecture.X86)
{
for (int i = 0; i < _methodRepresented.Signature.Length; i++)
parameters[i] = _methodRepresented.Signature[i];
parameters[_methodRepresented.Signature.Length] = Context.GetWellKnownType(WellKnownType.Void).MakePointerType();
}
else
{
parameters[0] = Context.GetWellKnownType(WellKnownType.Void).MakePointerType();
for (int i = 0; i < _methodRepresented.Signature.Length; i++)
parameters[i + 1] = _methodRepresented.Signature[i];
}

_signature = new MethodSignature(_methodRepresented.Signature.Flags,
_methodRepresented.Signature.GenericParameterCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,19 @@ public override MethodIL EmitIL()
MethodDesc getOrdinalInterfaceMethod = Context.GetHelperEntryPoint("SharedCodeHelpers", "GetOrdinalInterface");
MethodDesc getCurrentContext = Context.GetHelperEntryPoint("SharedCodeHelpers", "GetCurrentSharedThunkContext");

bool isX86 = Context.Target.Architecture == TargetArchitecture.X86;

// Load "this"
codeStream.EmitLdArg(0);

if (isX86)
{
for (int i = 0; i < _targetMethod.Signature.Length; i++)
{
codeStream.EmitLdArg(i + 1);
}
}

// Load the instantiating argument.
if (_interfaceIndex == UseContextFromRuntime)
{
Expand All @@ -232,10 +242,13 @@ public override MethodIL EmitIL()
codeStream.Emit(ILOpcode.call, emit.NewToken(getOrdinalInterfaceMethod));
}

// Load rest of the arguments
for (int i = 0; i < _targetMethod.Signature.Length; i++)
if (!isX86)
{
codeStream.EmitLdArg(i + 1);
// Load rest of the arguments
for (int i = 0; i < _targetMethod.Signature.Length; i++)
{
codeStream.EmitLdArg(i + 1);
}
}

// Call an instance method on the target interface that has a fake instantiation parameter
Expand Down Expand Up @@ -292,9 +305,18 @@ public override MethodSignature Signature

// Shared instance methods on generic interfaces have a hidden parameter with the generic context.
// We add it to the signature so that we can refer to it from IL.
parameters[0] = Context.GetWellKnownType(WellKnownType.IntPtr);
for (int i = 0; i < _methodRepresented.Signature.Length; i++)
parameters[i + 1] = _methodRepresented.Signature[i];
if (Context.Target.Architecture == TargetArchitecture.X86)
{
for (int i = 0; i < _methodRepresented.Signature.Length; i++)
parameters[i] = _methodRepresented.Signature[i];
parameters[_methodRepresented.Signature.Length] = Context.GetWellKnownType(WellKnownType.Void).MakePointerType();
}
else
{
parameters[0] = Context.GetWellKnownType(WellKnownType.IntPtr);
for (int i = 0; i < _methodRepresented.Signature.Length; i++)
parameters[i + 1] = _methodRepresented.Signature[i];
}

_signature = new MethodSignature(_methodRepresented.Signature.Flags,
_methodRepresented.Signature.GenericParameterCount,
Expand Down

0 comments on commit 9058800

Please sign in to comment.