Skip to content

Commit

Permalink
Implement System.Runtime.CompilerServices.DisabledRuntimeMarshallingA…
Browse files Browse the repository at this point in the history
…ttribute on CoreCLR-family of runtimes/type systems (#63320)

* Add the DisableRuntimeMarshallingAttribute to the build.

* Add initial test suite

* Implement support in IL stubs for the "disabled runtime marshalling" feature.

* Add testing for inlining IL stubs.

* Block SetLastError and LCID support when DisableRuntimeMarshallingAttribute is applied.

* Bump NativeAOT-only R2R version header (missed previously)

* Implement support in crossgen2 and NativeAOT

* Clean up the test tree and update the tests to fail more reliably when bugs are present.

Fix a bug that was uncovered when the tests were refactored.

* Fix NativeAOT and clean up crossgen2

* Add a test for NoPreserveSig with DisableRuntimeMarshalling

* Assign hr in SUCCEEDED macro.

* PR feedback.

* Block varargs in disabled marshalling mode.

* Fix typo

* Block types that have a field that is auto-layout somewhere in their layout.

* Fix typo

* Revert the AutoLayoutOrHasAutoLayoutFIeld check in the "marshalling enabled" case

* Only set scope when it isn't null (it's null for some cases).

* Fix narrowing conversion failure.

* First pass simple implementation in Mono

* Fix assert to still work for the built-in marshalling system

* S_FALSE is a thing

* Fix type load failures caused by eager type handle loading.

* Get MethodILScope from the calling method when available (this covers all cases where we need it)

* Add const modifier.

* Try 2 to fix const modifiers

* Fix compilation of NativeAOT jitinterface

* Fix type lookup in Mono

* Use try_get model for getting the attribute type in the case of failure. Fix mono implementation for looking up the attribute.

* Handle void and generic instantiations

* Update auto-layout check to check recursively in layout.

* Enhance test suite with more tests for UnmanagedCallersOnly, generics, and the like. Fix AutoLayout test.

* Fix IL and a few typos

* Set a value in the padding for easier debugging.

* Create sig->marshalling_disabled to track when marshalling is disabled, which is separate from the concept of "is this signature a P/Invoke"

* Fix running test suite on Mono + Mini JIT

* Fix recursive type load failure by only checking the "has auto-layout or field with auto-layout" for value types.

* Fix mono windows build.

* Feedback from Michal.

* Fix bug in EcmaAssembly.HasAssemblyCustomAttribute

* Make the runtime flavor check in the wrapper generator case-invariant

* Use helper method since various different platforms/configurations throw different exceptions for these scenarios.

* Fix AutoLayout test refactor and use a dummy value for the padding field in both enabled and disabled scenarios.

* Add an explicit test for using enums as they're a little weird and needed some special-casing.

* Fix build-time test filtering in xunit wrapper generator.

* Fix some x86-specific issues

* Add a nice big comment block.

* Fix x86

* Refactor tests so we can skip one on Mono since Char->char lossy conversion is not supported.

* Disable test in issues.targets until an alternative solution is reached.

* Add another SkipOnMono attribute in the "Enabled" test suite.

* Apply UnmangedFunctionPointerAttribute to help hint to the Mono LLVM AOT compiler to compile the managed->native thunks at aot-time

* Unify on "runtime marshalling" terminology

* Clean up unused usings.

* Address Jan's feedback except for applying the attribute to CoreLib.

* PR feedback.

* Mono throws an InvalidProgramException for varargs

* Fix copy-paste issue.

* Make sure we use the P/Invoke's Module and not the caller's module when deciding if runtime marshalling is enabled for a varargs P/Invoke call.

* Handle how LLVM AOT reports the failure to handle varargs (EEE)
  • Loading branch information
jkoritzinsky authored Jan 21, 2022
1 parent d7b6689 commit 358ee3c
Show file tree
Hide file tree
Showing 83 changed files with 1,997 additions and 262 deletions.
5 changes: 5 additions & 0 deletions src/coreclr/dlls/mscorrc/mscorrc.rc
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ BEGIN
IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL "Unable to find an entry point named '%1' in DLL."
IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO "Unable to find an entry point named '%1' in shared library."
IDS_EE_NDIRECT_GETPROCADDRESS_NONAME "A library name must be specified in a DllImport attribute applied to non-IJW methods."
IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR "Setting SetLastError to 'true' is not supported when runtime marshalling is disabled."
IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID "The LCIDConversionAttribute is not supported when runtime marshalling is disabled."
IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG "Setting PreserveSig to false for a P/Invoke is not supported when runtime marshalling is disabled."
IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS "Using a variable argument list in a P/Invoke is not supported when runtime marshalling is disabled."
IDS_EE_CLASS_CONSTRAINTS_VIOLATION "GenericArguments[%1], '%2', on '%3' violates the constraint of type parameter '%4'."
IDS_EE_METHOD_CONSTRAINTS_VIOLATION "Method %1.%2: type argument '%3' violates the constraint of type parameter '%4'."
IDS_EE_NOSYNCHRONIZED "Synchronized attribute cannot be used with this method type."
Expand Down Expand Up @@ -297,6 +301,7 @@ BEGIN
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_AUTOLAYOUT "Structures marked with [StructLayout(LayoutKind.Auto)] cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."
IDS_EE_BADMARSHAL_MARSHAL_DISABLED "Cannot marshal managed types when the runtime marshalling system is disabled."

IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
IDS_EE_BADMARSHALPARAM_NO_LPTSTR "Invalid managed/unmanaged type combination (Strings cannot be paired with LPTStr for parameters and return types of methods in interfaces exposed to COM)."
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/dlls/mscorrc/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -588,3 +588,8 @@
#define IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE 0x2649
#define IDS_EE_THREAD_APARTMENT_NOT_SUPPORTED 0x264A
#define IDS_EE_NO_IINSPECTABLE 0x264B
#define IDS_EE_BADMARSHAL_MARSHAL_DISABLED 0x264C
#define IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR 0x264D
#define IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID 0x264E
#define IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG 0x264F
#define IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS 0x2650
18 changes: 9 additions & 9 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN
methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_FROM_METHODTABLE;
}
methodInfo->regionKind = CorInfoRegionKind.CORINFO_REGION_NONE;
Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args);
Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args, methodIL);
Get_CORINFO_SIG_INFO(methodIL.GetLocals(), &methodInfo->locals);

return true;
Expand All @@ -683,9 +683,9 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN
return (CORINFO_CLASS_STRUCT_**)GetPin(jitVisibleInstantiation);
}

private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, bool suppressHiddenArgument = false)
private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, MethodILScope scope, bool suppressHiddenArgument = false)
{
Get_CORINFO_SIG_INFO(method.Signature, sig);
Get_CORINFO_SIG_INFO(method.Signature, sig, scope);

// Does the method have a hidden parameter?
bool hasHiddenParameter = !suppressHiddenArgument && method.RequiresInstArg();
Expand Down Expand Up @@ -845,7 +845,7 @@ private static CorInfoCallConvExtension GetMemberFunctionCallingConventionVarian
var c => c
};

private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* sig)
private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* sig, MethodILScope scope)
{
sig->callConv = (CorInfoCallConv)(signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask);

Expand Down Expand Up @@ -875,7 +875,7 @@ private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* s
sig->pSig = null;
sig->cbSig = 0; // Not used by the JIT
sig->methodSignature = ObjectToHandle(signature);
sig->scope = null;
sig->scope = scope is not null ? ObjectToHandle(scope) : null; // scope can be null for internal calls and COM methods.
sig->token = 0; // Not used by the JIT
}

Expand Down Expand Up @@ -1149,7 +1149,7 @@ private void getMethodSig(CORINFO_METHOD_STRUCT_* ftn, CORINFO_SIG_INFO* sig, CO
}
}

Get_CORINFO_SIG_INFO(method, sig: sig);
Get_CORINFO_SIG_INFO(method, sig: sig, scope: null);
}

private bool getMethodInfo(CORINFO_METHOD_STRUCT_* ftn, CORINFO_METHOD_INFO* info)
Expand Down Expand Up @@ -1795,7 +1795,7 @@ private void findSig(CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEX
var methodIL = HandleToObject(module);
var methodSig = (MethodSignature)methodIL.GetObject((int)sigTOK);

Get_CORINFO_SIG_INFO(methodSig, sig);
Get_CORINFO_SIG_INFO(methodSig, sig, methodIL);

#if !READYTORUN
// Check whether we need to report this as a fat pointer call
Expand All @@ -1811,7 +1811,7 @@ private void findSig(CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEX
private void findCallSiteSig(CORINFO_MODULE_STRUCT_* module, uint methTOK, CORINFO_CONTEXT_STRUCT* context, CORINFO_SIG_INFO* sig)
{
var methodIL = HandleToObject(module);
Get_CORINFO_SIG_INFO(((MethodDesc)methodIL.GetObject((int)methTOK)), sig: sig);
Get_CORINFO_SIG_INFO(((MethodDesc)methodIL.GetObject((int)methTOK)), sig: sig, methodIL);
}

private CORINFO_CLASS_STRUCT_* getTokenTypeAsHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken)
Expand Down Expand Up @@ -3745,7 +3745,7 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes)

#if READYTORUN
// TODO: enable this check in full AOT
if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, Array.Empty<ParameterMetadata>())) // Only blittable arguments
if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, Array.Empty<ParameterMetadata>(), ((MetadataType)this.MethodBeingCompiled.OwningType).Module)) // Only blittable arguments
{
ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramNonBlittableTypes, this.MethodBeingCompiled);
}
Expand Down
24 changes: 24 additions & 0 deletions src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ private static class FieldLayoutFlags
/// True if type transitively has UnsafeValueTypeAttribute
/// </summary>
public const int IsUnsafeValueType = 0x200;

/// <summary>
/// True if the type transitively has any types with LayoutKind.Auto in its layout.
/// </summary>
public const int IsAutoLayoutOrHasAutoLayoutFields = 0x400;
}

private class StaticBlockInfo
Expand Down Expand Up @@ -115,6 +120,21 @@ public bool IsUnsafeValueType
}
}

/// <summary>
/// Does a type have auto-layout or transitively have any fields of a type with auto-layout.
/// </summary>
public virtual bool IsAutoLayoutOrHasAutoLayoutFields
{
get
{
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeLayout))
{
ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields);
}
return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields);
}
}


/// <summary>
/// The number of bytes required to hold a field of this type
Expand Down Expand Up @@ -406,6 +426,10 @@ public void ComputeInstanceLayout(InstanceLayoutKind layoutKind)
{
_fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedInstanceLayoutAbiUnstable);
}
if (computedLayout.IsAutoLayoutOrHasAutoLayoutFields)
{
_fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields);
}

if (computedLayout.Offsets != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public struct ComputedInstanceFieldLayout
public LayoutInt ByteCountUnaligned;
public LayoutInt ByteCountAlignment;
public bool LayoutAbiStable; // Is the layout stable such that it can safely be used in function calling conventions
public bool IsAutoLayoutOrHasAutoLayoutFields;

/// <summary>
/// If Offsets is non-null, then all field based layout is complete.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ out instanceByteSizeAndAlignment
ByteCountAlignment = instanceByteSizeAndAlignment.Alignment,
FieldAlignment = sizeAndAlignment.Alignment,
FieldSize = sizeAndAlignment.Size,
LayoutAbiStable = true
LayoutAbiStable = true,
IsAutoLayoutOrHasAutoLayoutFields = false,
};

if (numInstanceFields > 0)
Expand Down Expand Up @@ -214,7 +215,7 @@ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defTy
}

ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field);
SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _);
SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _);

block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment, context.Target);
result.Offsets[index] = new FieldAndOffset(field, block.Size);
Expand Down Expand Up @@ -305,13 +306,16 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty
var offsets = new FieldAndOffset[numInstanceFields];
int fieldOrdinal = 0;
bool layoutAbiStable = true;
bool hasAutoLayoutField = false;

foreach (var fieldAndOffset in layoutMetadata.Offsets)
{
TypeDesc fieldType = fieldAndOffset.Field.FieldType;
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable);
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;
if (fieldHasAutoLayout)
hasAutoLayoutField = true;

largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired);

Expand Down Expand Up @@ -354,7 +358,10 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty
layoutMetadata.Size,
out instanceByteSizeAndAlignment);

ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout();
ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
{
IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField,
};
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size;
Expand Down Expand Up @@ -388,15 +395,18 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType
int fieldOrdinal = 0;
int packingSize = ComputePackingSize(type, layoutMetadata);
bool layoutAbiStable = true;
bool hasAutoLayoutField = false;

foreach (var field in type.GetFields())
{
if (field.IsStatic)
continue;

var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable);
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;
if (fieldHasAutoLayout)
hasAutoLayoutField = true;

largestAlignmentRequirement = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequirement);

Expand All @@ -415,7 +425,10 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType
layoutMetadata.Size,
out instanceByteSizeAndAlignment);

ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout();
ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
{
IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField,
};
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size;
Expand Down Expand Up @@ -470,7 +483,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
{
Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum);

var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _);
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _);
instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++;
}
}
Expand Down Expand Up @@ -507,7 +520,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,

TypeDesc fieldType = field.FieldType;

var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable);
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;

Expand Down Expand Up @@ -646,7 +659,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
for (int i = 0; i < instanceValueClassFieldsArr.Length; i++)
{
// Align the cumulative field offset to the indeterminate value
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable);
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;

Expand Down Expand Up @@ -694,7 +707,10 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
classLayoutSize: 0,
byteCount: out instanceByteSizeAndAlignment);

ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout();
ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
{
IsAutoLayoutOrHasAutoLayoutFields = true,
};
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size;
Expand All @@ -707,7 +723,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,

private static void PlaceInstanceField(FieldDesc field, bool hasLayout, int packingSize, FieldAndOffset[] offsets, ref LayoutInt instanceFieldPos, ref int fieldOrdinal, LayoutInt offsetBias)
{
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _);
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _);

instanceFieldPos = AlignUpInstanceFieldOffset(field.OwningType, instanceFieldPos, fieldSizeAndAlignment.Alignment, field.Context.Target);
offsets[fieldOrdinal] = new FieldAndOffset(field, instanceFieldPos + offsetBias);
Expand Down Expand Up @@ -767,10 +783,11 @@ public LayoutInt CalculateFieldBaseOffset(MetadataType type, bool requiresAlign8
return cumulativeInstanceFieldPos;
}

private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable)
private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout)
{
SizeAndAlignment result;
layoutAbiStable = true;
fieldTypeHasAutoLayout = true;

if (fieldType.IsDefType)
{
Expand All @@ -780,6 +797,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType,
result.Size = defType.InstanceFieldSize;
result.Alignment = defType.InstanceFieldAlignment;
layoutAbiStable = defType.LayoutAbiStable;
fieldTypeHasAutoLayout = defType.IsAutoLayoutOrHasAutoLayoutFields;
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public override string ToString()

public bool HasAssemblyCustomAttribute(string attributeNamespace, string attributeName)
{
return _metadataReader.GetCustomAttributeHandle(_assemblyDefinition.GetCustomAttributes(),
return !_metadataReader.GetCustomAttributeHandle(_assemblyDefinition.GetCustomAttributes(),
attributeNamespace, attributeName).IsNil;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ string IPrefixMangledSignature.Prefix
{
get
{
return "Calli";
return RuntimeMarshallingEnabled ? "CalliWithRuntimeMarshalling" : "Calli";
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ partial class CalliMarshallingMethodThunk
protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
{
var otherMethod = (CalliMarshallingMethodThunk)other;
int result = RuntimeMarshallingEnabled.CompareTo(otherMethod.RuntimeMarshallingEnabled);
if (result != 0)
{
return result;
}
return comparer.Compare(_targetSignature, otherMethod._targetSignature);
}
}
Expand Down
Loading

0 comments on commit 358ee3c

Please sign in to comment.