diff --git a/eng/intellisense.targets b/eng/intellisense.targets index a4ffedf6d790c..fe4c60862798b 100644 --- a/eng/intellisense.targets +++ b/eng/intellisense.targets @@ -13,12 +13,18 @@ - $(NoWarn);1591 $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.private.intellisense', '$(MicrosoftPrivateIntellisenseVersion)', 'IntellisenseFiles')) $([MSBuild]::NormalizePath('$(IntellisensePackageXmlRootFolder)', 'net', '1033', '$(AssemblyName).xml')) $([MSBuild]::NormalizePath('$(IntellisensePackageXmlRootFolder)', 'dotnet-plat-ext', '1033', '$(AssemblyName).xml')) $(IntellisensePackageXmlFilePathFromNetFolder) $(IntellisensePackageXmlFilePathFromDotNetPlatExtFolder) + + $(NoWarn);1591 diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 04a8f2fb898d4..83d007e5a436b 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -1761,7 +1761,6 @@ enum CORINFO_OS enum CORINFO_RUNTIME_ABI { - CORINFO_DESKTOP_ABI = 0x100, CORINFO_CORECLR_ABI = 0x200, CORINFO_NATIVEAOT_ABI = 0x300, }; @@ -2027,7 +2026,7 @@ class ICorStaticInfo virtual void getMethodSig ( CORINFO_METHOD_HANDLE ftn, /* IN */ CORINFO_SIG_INFO *sig, /* OUT */ - CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ + CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ ) = 0; /********************************************************************* @@ -2063,9 +2062,9 @@ class ICorStaticInfo // inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the // JIT. virtual void reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd, - CorInfoInline inlineResult, - const char * reason) = 0; + CORINFO_METHOD_HANDLE inlineeHnd, + CorInfoInline inlineResult, + const char * reason) = 0; // Returns false if the call is across security boundaries thus we cannot tailcall @@ -2075,23 +2074,23 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE callerHnd, /* IN */ CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */ CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */ - bool fIsTailPrefix /* IN */ + bool fIsTailPrefix /* IN */ ) = 0; // Reports whether or not a method can be tail called, and why. // canTailCall is responsible for reporting all results when it returns // false. All other results are reported by the JIT. virtual void reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd, - CORINFO_METHOD_HANDLE calleeHnd, - bool fIsTailPrefix, - CorInfoTailCall tailCallResult, - const char * reason) = 0; + CORINFO_METHOD_HANDLE calleeHnd, + bool fIsTailPrefix, + CorInfoTailCall tailCallResult, + const char * reason) = 0; // get individual exception handler virtual void getEHinfo( CORINFO_METHOD_HANDLE ftn, /* IN */ - unsigned EHnumber, /* IN */ - CORINFO_EH_CLAUSE* clause /* OUT */ + unsigned EHnumber, /* IN */ + CORINFO_EH_CLAUSE* clause /* OUT */ ) = 0; // return class it belongs to @@ -2099,11 +2098,6 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE method ) = 0; - // return module it belongs to - virtual CORINFO_MODULE_HANDLE getMethodModule ( - CORINFO_METHOD_HANDLE method - ) = 0; - // This function returns the offset of the specified method in the // vtable of it's owning class or interface. virtual void getMethodVTableOffset ( @@ -2123,7 +2117,7 @@ class ICorStaticInfo // Get the unboxed entry point for a method, if possible. virtual CORINFO_METHOD_HANDLE getUnboxedEntry( CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg + bool* requiresInstMethodTableArg ) = 0; // Given T, return the type of the default Comparer. @@ -2172,23 +2166,11 @@ class ICorStaticInfo ) = 0; // Check constraints on method type arguments (only). - // The parent class should be checked separately using satisfiesClassConstraints(parent). virtual bool satisfiesMethodConstraints( CORINFO_CLASS_HANDLE parent, // the exact parent of the method CORINFO_METHOD_HANDLE method ) = 0; - // Given a delegate target class, a target method parent class, a target method, - // a delegate class, check if the method signature is compatible with the Invoke method of the delegate - // (under the typical instantiation of any free type variables in the memberref signatures). - virtual bool isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */ - CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */ - CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */ - CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */ - bool *pfIsOpenDelegate /* is the delegate open */ - ) = 0; - // load and restore the method virtual void methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method @@ -2201,7 +2183,7 @@ class ICorStaticInfo // Returns the global cookie for the /GS unsafe buffer checks // The cookie might be a constant value (JIT), or a handle to memory location (Ngen) virtual void getGSCookie( - GSCookie * pCookieVal, // OUT + GSCookie * pCookieVal, // OUT GSCookie ** ppCookieVal // OUT ) = 0; @@ -2226,12 +2208,6 @@ class ICorStaticInfo // failures during token resolution. virtual void resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0; - // Attempt to resolve a metadata token into a runtime method handle. Returns true - // if resolution succeeded and false otherwise (e.g. if it encounters invalid metadata - // during token reoslution). This method should be used instead of `resolveToken` in - // situations that need to be resilient to invalid metadata. - virtual bool tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0; - // Signature information about the call sig virtual void findSig ( CORINFO_MODULE_HANDLE module, /* IN */ @@ -2253,18 +2229,6 @@ class ICorStaticInfo virtual CORINFO_CLASS_HANDLE getTokenTypeAsHandle ( CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */) = 0; - // Checks if the given metadata token is valid - virtual bool isValidToken ( - CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK /* IN */ - ) = 0; - - // Checks if the given metadata token is valid StringRef - virtual bool isValidStringRef ( - CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK /* IN */ - ) = 0; - // Returns (sub)string length and content (can be null for dynamic context) // for given metaTOK and module, length `-1` means input is incorrect virtual int getStringLiteral ( @@ -2380,8 +2344,8 @@ class ICorStaticInfo virtual size_t getClassModuleIdForStatics ( CORINFO_CLASS_HANDLE cls, - CORINFO_MODULE_HANDLE *pModule, - void **ppIndirection + CORINFO_MODULE_HANDLE * pModule, + void ** ppIndirection ) = 0; virtual bool getIsClassInitedFlagAddress( @@ -2398,17 +2362,17 @@ class ICorStaticInfo // return the number of bytes needed by an instance of the class virtual unsigned getClassSize ( - CORINFO_CLASS_HANDLE cls + CORINFO_CLASS_HANDLE cls ) = 0; // return the number of bytes needed by an instance of the class allocated on the heap virtual unsigned getHeapClassSize( - CORINFO_CLASS_HANDLE cls - ) = 0; + CORINFO_CLASS_HANDLE cls + ) = 0; virtual bool canAllocateOnStack( - CORINFO_CLASS_HANDLE cls - ) = 0; + CORINFO_CLASS_HANDLE cls + ) = 0; virtual unsigned getClassAlignmentRequirement ( CORINFO_CLASS_HANDLE cls, @@ -2435,21 +2399,21 @@ class ICorStaticInfo ) = 0; virtual CORINFO_FIELD_HANDLE getFieldInClass( - CORINFO_CLASS_HANDLE clsHnd, - int32_t num + CORINFO_CLASS_HANDLE clsHnd, + int32_t num ) = 0; virtual bool checkMethodModifier( - CORINFO_METHOD_HANDLE hMethod, - const char * modifier, - bool fOptional + CORINFO_METHOD_HANDLE hMethod, + const char * modifier, + bool fOptional ) = 0; // returns the "NEW" helper optimized for "newCls." virtual CorInfoHelpFunc getNewHelper( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - bool * pHasSideEffects + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + bool * pHasSideEffects ) = 0; // returns the newArr (1-Dim array) helper optimized for "arrayCls." @@ -2459,17 +2423,17 @@ class ICorStaticInfo // returns the optimized "IsInstanceOf" or "ChkCast" helper virtual CorInfoHelpFunc getCastingHelper( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - bool fThrowing + CORINFO_RESOLVED_TOKEN * pResolvedToken, + bool fThrowing ) = 0; // returns helper to trigger static constructor virtual CorInfoHelpFunc getSharedCCtorHelper( - CORINFO_CLASS_HANDLE clsHnd + CORINFO_CLASS_HANDLE clsHnd ) = 0; // Boxing nullable actually returns a boxed not a boxed Nullable. - virtual CORINFO_CLASS_HANDLE getTypeForBox( + virtual CORINFO_CLASS_HANDLE getTypeForBox( CORINFO_CLASS_HANDLE cls ) = 0; @@ -2528,7 +2492,8 @@ class ICorStaticInfo virtual bool getStringChar( CORINFO_OBJECT_HANDLE strObj, int index, - uint16_t* value) = 0; + uint16_t* value + ) = 0; //------------------------------------------------------------------------------ // getObjectType: obtains type handle for given object @@ -2551,10 +2516,10 @@ class ICorStaticInfo ) = 0; virtual void getReadyToRunDelegateCtorHelper( - CORINFO_RESOLVED_TOKEN * pTargetMethod, - mdToken targetConstraint, - CORINFO_CLASS_HANDLE delegateType, - CORINFO_LOOKUP * pLookup + CORINFO_RESOLVED_TOKEN * pTargetMethod, + mdToken targetConstraint, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_LOOKUP * pLookup ) = 0; // This function tries to initialize the class (run the class constructor). @@ -2600,7 +2565,7 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; - // TRUE if child is a subtype of parent + // `true` if child is a subtype of parent // if parent is an interface, then does child implement / extend parent virtual bool canCast( CORINFO_CLASS_HANDLE child, // subtype (extends parent) @@ -2621,12 +2586,6 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls2 ) = 0; - // Returns the intersection of cls1 and cls2. - virtual CORINFO_CLASS_HANDLE mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2 - ) = 0; - // Returns true if cls2 is known to be a more specific type // than cls1 (a subtype or more restrictive shared type) // for purposes of jit type tracking. This is a hint to the @@ -2659,13 +2618,8 @@ class ICorStaticInfo // Given an Array of Type Foo, returns Foo. // Given BYREF Foo, returns Foo virtual CorInfoType getChildType ( - CORINFO_CLASS_HANDLE clsHnd, - CORINFO_CLASS_HANDLE *clsRet - ) = 0; - - // Check constraints on type arguments of this class and parent classes - virtual bool satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls + CORINFO_CLASS_HANDLE clsHnd, + CORINFO_CLASS_HANDLE* clsRet ) = 0; // Check if this is a single dimensional array type @@ -2673,14 +2627,14 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; - // Get the numbmer of dimensions in an array + // Get the number of dimensions in an array virtual unsigned getArrayRank( CORINFO_CLASS_HANDLE cls ) = 0; // Get the index of runtime provided array method virtual CorInfoArrayIntrinsic getArrayIntrinsicID( - CORINFO_METHOD_HANDLE ftn + CORINFO_METHOD_HANDLE ftn ) = 0; // Get static field data for an array @@ -2691,11 +2645,11 @@ class ICorStaticInfo // Check Visibility rules. virtual CorInfoIsAccessAllowedResult canAccessClass( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_HELPER_DESC *pAccessHelper /* If canAccessMethod returns something other - than ALLOWED, then this is filled in. */ - ) = 0; + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_HELPER_DESC * pAccessHelper /* If canAccessMethod returns something other + than ALLOWED, then this is filled in. */ + ) = 0; /**********************************************************************************/ // @@ -2723,29 +2677,34 @@ class ICorStaticInfo // 'memberParent' is typically only set when verifying. It should be the // result of calling getMemberParent. virtual CorInfoType getFieldType( - CORINFO_FIELD_HANDLE field, - CORINFO_CLASS_HANDLE *structType = NULL, - CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ - ) = 0; + CORINFO_FIELD_HANDLE field, + CORINFO_CLASS_HANDLE * structType = NULL, + CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ + ) = 0; // return the data member's instance offset virtual unsigned getFieldOffset( - CORINFO_FIELD_HANDLE field - ) = 0; + CORINFO_FIELD_HANDLE field + ) = 0; - virtual void getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_ACCESS_FLAGS flags, - CORINFO_FIELD_INFO *pResult - ) = 0; + virtual void getFieldInfo( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_ACCESS_FLAGS flags, + CORINFO_FIELD_INFO * pResult + ) = 0; // Returns the index against which the field's thread static block in stored in TLS. virtual uint32_t getThreadLocalFieldInfo ( - CORINFO_FIELD_HANDLE field, bool isGCType) = 0; + CORINFO_FIELD_HANDLE field, + bool isGCType + ) = 0; // Returns the thread static block information like offsets, etc. from current TLS. virtual void getThreadLocalStaticBlocksInfo ( - CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) = 0; + CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, + bool isGCType + ) = 0; // Returns true iff "fldHnd" represents a static field. virtual bool isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) = 0; @@ -2768,12 +2727,12 @@ class ICorStaticInfo // be used only as a hint and the native compiler should not change its // code generation. virtual void getBoundaries( - CORINFO_METHOD_HANDLE ftn, // [IN] method of interest - unsigned int *cILOffsets, // [OUT] size of pILOffsets - uint32_t **pILOffsets, // [OUT] IL offsets of interest - // jit MUST free with freeArray! - ICorDebugInfo::BoundaryTypes *implicitBoundaries // [OUT] tell jit, all boundaries of this type - ) = 0; + CORINFO_METHOD_HANDLE ftn, // [IN] method of interest + unsigned int *cILOffsets, // [OUT] size of pILOffsets + uint32_t **pILOffsets, // [OUT] IL offsets of interest + // jit MUST free with freeArray! + ICorDebugInfo::BoundaryTypes *implicitBoundaries // [OUT] tell jit, all boundaries of this type + ) = 0; // Report back the mapping from IL to native code, // this map should include all boundaries that 'getBoundaries' @@ -2783,11 +2742,11 @@ class ICorStaticInfo // offsets form a contiguous block of memory, and that the // OffsetMapping is sorted in order of increasing native offset. virtual void setBoundaries( - CORINFO_METHOD_HANDLE ftn, // [IN] method of interest - uint32_t cMap, // [IN] size of pMap - ICorDebugInfo::OffsetMapping *pMap // [IN] map including all points of interest. - // jit allocated with allocateArray, EE frees - ) = 0; + CORINFO_METHOD_HANDLE ftn, // [IN] method of interest + uint32_t cMap, // [IN] size of pMap + ICorDebugInfo::OffsetMapping *pMap // [IN] map including all points of interest. + // jit allocated with allocateArray, EE frees + ) = 0; // Query the EE to find out the scope of local variables. // normally the JIT would trash variables after last use, but @@ -2800,16 +2759,15 @@ class ICorStaticInfo virtual void getVars( CORINFO_METHOD_HANDLE ftn, // [IN] method of interest uint32_t *cVars, // [OUT] size of 'vars' - ICorDebugInfo::ILVarInfo **vars, // [OUT] scopes of variables of interest + ICorDebugInfo::ILVarInfo **vars, // [OUT] scopes of variables of interest // jit MUST free with freeArray! - bool *extendOthers // [OUT] it TRUE, then assume the scope + bool *extendOthers // [OUT] if `true`, then assume the scope // of unmentioned vars is entire method ) = 0; // Report back to the EE the location of every variable. // note that the JIT might split lifetimes into different // locations etc. - virtual void setVars( CORINFO_METHOD_HANDLE ftn, // [IN] method of interest uint32_t cVars, // [IN] size of 'vars' @@ -2833,15 +2791,15 @@ class ICorStaticInfo // For eg, use this to allocated memory for reporting debug info, // which will be handed to the EE by setVars() and setBoundaries() virtual void * allocateArray( - size_t cBytes - ) = 0; + size_t cBytes + ) = 0; // JitCompiler will free arrays passed by the EE using this // For eg, The EE returns memory in getVars() and getBoundaries() // to the JitCompiler, which the JitCompiler should release using // freeArray() virtual void freeArray( - void *array + void * array ) = 0; /*********************************************************************************/ @@ -2868,17 +2826,17 @@ class ICorStaticInfo virtual CorInfoTypeWithMod getArgType ( CORINFO_SIG_INFO* sig, /* IN */ CORINFO_ARG_LIST_HANDLE args, /* IN */ - CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */ + CORINFO_CLASS_HANDLE* vcTypeRet /* OUT */ ) = 0; // Obtains a list of exact classes for a given base type. Returns 0 if the number of // the exact classes is greater than maxExactClasses or if more types might be loaded // in future. virtual int getExactClasses( - CORINFO_CLASS_HANDLE baseType, /* IN */ - int maxExactClasses, /* IN */ - CORINFO_CLASS_HANDLE* exactClsRet /* OUT */ - ) = 0; + CORINFO_CLASS_HANDLE baseType, /* IN */ + int maxExactClasses, /* IN */ + CORINFO_CLASS_HANDLE* exactClsRet /* OUT */ + ) = 0; // If the Arg is a CORINFO_TYPE_CLASS fetch the class handle associated with it virtual CORINFO_CLASS_HANDLE getArgClass ( @@ -2888,7 +2846,7 @@ class ICorStaticInfo // Returns type of HFA for valuetype virtual CorInfoHFAElemType getHFAType ( - CORINFO_CLASS_HANDLE hClass + CORINFO_CLASS_HANDLE hClass ) = 0; // Runs the given function under an error trap. This allows the JIT to make calls @@ -2897,18 +2855,18 @@ class ICorStaticInfo // successfully and false otherwise. typedef void (*errorTrapFunction)(void*); virtual bool runWithErrorTrap( - errorTrapFunction function, // The function to run - void* parameter // The context parameter that will be passed to the function and the handler - ) = 0; + errorTrapFunction function, // The function to run + void* parameter // The context parameter that will be passed to the function and the handler + ) = 0; // Runs the given function under an error trap. This allows the JIT to make calls // to interface functions that may throw exceptions without needing to be aware of // the EH ABI, exception types, etc. Returns true if the given function completed // successfully and false otherwise. This error trap checks for SuperPMI exceptions virtual bool runWithSPMIErrorTrap( - errorTrapFunction function, // The function to run - void* parameter // The context parameter that will be passed to the function and the handler - ) = 0; + errorTrapFunction function, // The function to run + void* parameter // The context parameter that will be passed to the function and the handler + ) = 0; /***************************************************************************** * ICorStaticInfo contains EE interface methods which return values that are @@ -2919,8 +2877,8 @@ class ICorStaticInfo // Return details about EE internal data structures virtual void getEEInfo( - CORINFO_EE_INFO *pEEInfoOut - ) = 0; + CORINFO_EE_INFO *pEEInfoOut + ) = 0; // Returns name of the JIT timer log virtual const char16_t *getJitTimeLogFilename() = 0; @@ -2944,7 +2902,8 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE ftn, char* buffer, size_t bufferSize, - size_t* pRequiredBufferSize = nullptr) = 0; + size_t* pRequiredBufferSize = nullptr + ) = 0; // Return method name as in metadata, or nullptr if there is none, // and optionally return the class, enclosing class, and namespace names @@ -2954,7 +2913,7 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE ftn, /* IN */ const char **className, /* OUT */ const char **namespaceName, /* OUT */ - const char **enclosingClassName /* OUT */ + const char **enclosingClassName /* OUT */ ) = 0; // this function is for debugging only. It returns a value that @@ -2964,19 +2923,11 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE ftn /* IN */ ) = 0; - // this function is for debugging only. - virtual size_t findNameOfToken ( - CORINFO_MODULE_HANDLE module, /* IN */ - mdToken metaTOK, /* IN */ - _Out_writes_ (FQNameCapacity) char * szFQName, /* OUT */ - size_t FQNameCapacity /* IN */ - ) = 0; - // returns whether the struct is enregisterable. Only valid on a System V VM. Returns true on success, false on failure. virtual bool getSystemVAmd64PassStructInRegisterDescriptor( - /* IN */ CORINFO_CLASS_HANDLE structHnd, - /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr - ) = 0; + CORINFO_CLASS_HANDLE structHnd, /* IN */ + SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr /* OUT */ + ) = 0; virtual uint32_t getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) = 0; virtual uint32_t getRISCV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) = 0; @@ -3015,70 +2966,68 @@ class ICorDynamicInfo : public ICorStaticInfo // Return details about EE internal data structures virtual uint32_t getThreadTLSIndex( - void **ppIndirection = NULL - ) = 0; - - virtual const void * getInlinedCallFrameVptr( - void **ppIndirection = NULL - ) = 0; + void **ppIndirection = NULL + ) = 0; virtual int32_t * getAddrOfCaptureThreadGlobal( - void **ppIndirection = NULL - ) = 0; + void **ppIndirection = NULL + ) = 0; // return the native entry point to an EE helper (see CorInfoHelpFunc) virtual void* getHelperFtn ( - CorInfoHelpFunc ftnNum, - void **ppIndirection = NULL - ) = 0; + CorInfoHelpFunc ftnNum, + void **ppIndirection = NULL + ) = 0; // return a callable address of the function (native code). This function // may return a different value (depending on whether the method has // been JITed or not. virtual void getFunctionEntryPoint( - CORINFO_METHOD_HANDLE ftn, /* IN */ - CORINFO_CONST_LOOKUP * pResult, /* OUT */ - CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY) = 0; + CORINFO_METHOD_HANDLE ftn, /* IN */ + CORINFO_CONST_LOOKUP * pResult, /* OUT */ + CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY + ) = 0; // return a directly callable address. This can be used similarly to the // value returned by getFunctionEntryPoint() except that it is // guaranteed to be multi callable entrypoint. virtual void getFunctionFixedEntryPoint( - CORINFO_METHOD_HANDLE ftn, - bool isUnsafeFunctionPointer, - CORINFO_CONST_LOOKUP * pResult) = 0; + CORINFO_METHOD_HANDLE ftn, + bool isUnsafeFunctionPointer, + CORINFO_CONST_LOOKUP * pResult + ) = 0; // get the synchronization handle that is passed to monXstatic function virtual void* getMethodSync( - CORINFO_METHOD_HANDLE ftn, - void **ppIndirection = NULL - ) = 0; + CORINFO_METHOD_HANDLE ftn, + void** ppIndirection = NULL + ) = 0; // get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*). // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used. virtual CorInfoHelpFunc getLazyStringLiteralHelper( - CORINFO_MODULE_HANDLE handle - ) = 0; + CORINFO_MODULE_HANDLE handle + ) = 0; virtual CORINFO_MODULE_HANDLE embedModuleHandle( - CORINFO_MODULE_HANDLE handle, - void **ppIndirection = NULL - ) = 0; + CORINFO_MODULE_HANDLE handle, + void **ppIndirection = NULL + ) = 0; virtual CORINFO_CLASS_HANDLE embedClassHandle( - CORINFO_CLASS_HANDLE handle, - void **ppIndirection = NULL - ) = 0; + CORINFO_CLASS_HANDLE handle, + void **ppIndirection = NULL + ) = 0; virtual CORINFO_METHOD_HANDLE embedMethodHandle( - CORINFO_METHOD_HANDLE handle, - void **ppIndirection = NULL - ) = 0; + CORINFO_METHOD_HANDLE handle, + void **ppIndirection = NULL + ) = 0; virtual CORINFO_FIELD_HANDLE embedFieldHandle( - CORINFO_FIELD_HANDLE handle, - void **ppIndirection = NULL - ) = 0; + CORINFO_FIELD_HANDLE handle, + void **ppIndirection = NULL + ) = 0; // Given a module scope (module), a method handle (context) and // a metadata token (metaTOK), fetch the handle @@ -3088,9 +3037,10 @@ class ICorDynamicInfo : public ICorStaticInfo // then indicate how the handle should be looked up at run-time. // virtual void embedGenericHandle( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - bool fEmbedParent, // TRUE - embeds parent type handle of the field/method handle - CORINFO_GENERICHANDLE_RESULT * pResult) = 0; + CORINFO_RESOLVED_TOKEN * pResolvedToken, + bool fEmbedParent, // `true` - embeds parent type handle of the field/method handle + CORINFO_GENERICHANDLE_RESULT * pResult + ) = 0; // Return information used to locate the exact enclosing type of the current method. // Used only to invoke .cctor method from code shared across generic instantiations @@ -3100,76 +3050,69 @@ class ICorDynamicInfo : public ICorStaticInfo // CORINFO_LOOKUP_CLASSPARAM use vtable hidden param // CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param virtual void getLocationOfThisType( - CORINFO_METHOD_HANDLE context, - CORINFO_LOOKUP_KIND* pLookupKind - ) = 0; + CORINFO_METHOD_HANDLE context, + CORINFO_LOOKUP_KIND* pLookupKind + ) = 0; // return the address of the PInvoke target. May be a fixup area in the // case of late-bound PInvoke calls. virtual void getAddressOfPInvokeTarget( - CORINFO_METHOD_HANDLE method, - CORINFO_CONST_LOOKUP *pLookup - ) = 0; + CORINFO_METHOD_HANDLE method, + CORINFO_CONST_LOOKUP * pLookup + ) = 0; // Generate a cookie based on the signature that would needs to be passed // to CORINFO_HELP_PINVOKE_CALLI virtual void* GetCookieForPInvokeCalliSig( - CORINFO_SIG_INFO* szMetaSig, - void ** ppIndirection = NULL + CORINFO_SIG_INFO* szMetaSig, + void** ppIndirection = NULL ) = 0; // returns true if a VM cookie can be generated for it (might be false due to cross-module // inlining, in which case the inlining should be aborted) virtual bool canGetCookieForPInvokeCalliSig( - CORINFO_SIG_INFO* szMetaSig - ) = 0; + CORINFO_SIG_INFO* szMetaSig + ) = 0; // Gets a handle that is checked to see if the current method is // included in "JustMyCode" virtual CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle( - CORINFO_METHOD_HANDLE method, - CORINFO_JUST_MY_CODE_HANDLE**ppIndirection = NULL - ) = 0; + CORINFO_METHOD_HANDLE method, + CORINFO_JUST_MY_CODE_HANDLE** ppIndirection = NULL + ) = 0; // Gets a method handle that can be used to correlate profiling data. // This is the IP of a native method, or the address of the descriptor struct // for IL. Always guaranteed to be unique per process, and not to move. */ virtual void GetProfilingHandle( - bool *pbHookFunction, - void **pProfilerHandle, - bool *pbIndirectedHandles - ) = 0; + bool *pbHookFunction, + void **pProfilerHandle, + bool *pbIndirectedHandles + ) = 0; // Returns instructions on how to make the call. See code:CORINFO_CALL_INFO for possible return values. virtual void getCallInfo( - // Token info - CORINFO_RESOLVED_TOKEN * pResolvedToken, - - //Generics info - CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, - - //Security info - CORINFO_METHOD_HANDLE callerHandle, + // Token info + CORINFO_RESOLVED_TOKEN * pResolvedToken, - //Jit info - CORINFO_CALLINFO_FLAGS flags, + // Generics info + CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, - //out params - CORINFO_CALL_INFO *pResult - ) = 0; + // Security info + CORINFO_METHOD_HANDLE callerHandle, - virtual bool canAccessFamily(CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) = 0; + // Jit info + CORINFO_CALLINFO_FLAGS flags, - // Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class - // except reflection emitted classes and generics) - virtual bool isRIDClassDomainID(CORINFO_CLASS_HANDLE cls) = 0; + // out params + CORINFO_CALL_INFO *pResult + ) = 0; - // returns the class's domain ID for accessing shared statics + // Returns the class's domain ID for accessing shared statics virtual unsigned getClassDomainID ( - CORINFO_CLASS_HANDLE cls, - void **ppIndirection = NULL - ) = 0; + CORINFO_CLASS_HANDLE cls, + void **ppIndirection = NULL + ) = 0; //------------------------------------------------------------------------------ // getStaticFieldContent: returns true and the actual field's value if the given @@ -3185,19 +3128,19 @@ class ICorDynamicInfo : public ICorStaticInfo // Returns true if field's constant value was available and successfully copied to buffer // virtual bool getStaticFieldContent( - CORINFO_FIELD_HANDLE field, - uint8_t *buffer, - int bufferSize, - int valueOffset = 0, - bool ignoreMovableObjects = true - ) = 0; + CORINFO_FIELD_HANDLE field, + uint8_t *buffer, + int bufferSize, + int valueOffset = 0, + bool ignoreMovableObjects = true + ) = 0; virtual bool getObjectContent( - CORINFO_OBJECT_HANDLE obj, - uint8_t* buffer, - int bufferSize, - int valueOffset - ) = 0; + CORINFO_OBJECT_HANDLE obj, + uint8_t* buffer, + int bufferSize, + int valueOffset + ) = 0; // If pIsSpeculative is NULL, return the class handle for the value of ref-class typed // static readonly fields, if there is a unique location for the static and the class @@ -3211,40 +3154,40 @@ class ICorDynamicInfo : public ICorStaticInfo // is readonly but class has not yet finished initialization). Set *pIsSpeculative false // if this type will not change. virtual CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( - CORINFO_FIELD_HANDLE field, - bool *pIsSpeculative = NULL - ) = 0; + CORINFO_FIELD_HANDLE field, + bool *pIsSpeculative = NULL + ) = 0; // registers a vararg sig & returns a VM cookie for it (which can contain other stuff) virtual CORINFO_VARARGS_HANDLE getVarArgsHandle( - CORINFO_SIG_INFO *pSig, - void **ppIndirection = NULL - ) = 0; + CORINFO_SIG_INFO *pSig, + void **ppIndirection = NULL + ) = 0; // returns true if a VM cookie can be generated for it (might be false due to cross-module // inlining, in which case the inlining should be aborted) virtual bool canGetVarArgsHandle( - CORINFO_SIG_INFO *pSig - ) = 0; + CORINFO_SIG_INFO *pSig + ) = 0; // Allocate a string literal on the heap and return a handle to it virtual InfoAccessType constructStringLiteral( - CORINFO_MODULE_HANDLE module, - mdToken metaTok, - void **ppValue - ) = 0; + CORINFO_MODULE_HANDLE module, + mdToken metaTok, + void **ppValue + ) = 0; virtual InfoAccessType emptyStringLiteral( - void **ppValue - ) = 0; + void **ppValue + ) = 0; // (static fields only) given that 'field' refers to thread local store, // return the ID (TLS index), which is used to find the beginning of the // TLS data area for the particular DLL 'field' is associated with. virtual uint32_t getFieldThreadLocalStoreID ( - CORINFO_FIELD_HANDLE field, - void **ppIndirection = NULL - ) = 0; + CORINFO_FIELD_HANDLE field, + void **ppIndirection = NULL + ) = 0; virtual CORINFO_METHOD_HANDLE GetDelegateCtor( CORINFO_METHOD_HANDLE methHnd, @@ -3254,34 +3197,34 @@ class ICorDynamicInfo : public ICorStaticInfo ) = 0; virtual void MethodCompileComplete( - CORINFO_METHOD_HANDLE methHnd - ) = 0; + CORINFO_METHOD_HANDLE methHnd + ) = 0; // Obtain tailcall help for the specified call site. virtual bool getTailCallHelpers( + // The resolved token for the call. Can be null for calli. + CORINFO_RESOLVED_TOKEN* callToken, - // The resolved token for the call. Can be null for calli. - CORINFO_RESOLVED_TOKEN* callToken, + // The signature at the callsite. + CORINFO_SIG_INFO* sig, - // The signature at the callsite. - CORINFO_SIG_INFO* sig, + // Flags for the tailcall site. + CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, - // Flags for the tailcall site. - CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, - - // The resulting help. - CORINFO_TAILCALL_HELPERS* pResult) = 0; + // The resulting help. + CORINFO_TAILCALL_HELPERS* pResult + ) = 0; // Optionally, convert calli to regular method call. This is for PInvoke argument marshalling. virtual bool convertPInvokeCalliToCall( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - bool fMustConvert - ) = 0; + CORINFO_RESOLVED_TOKEN * pResolvedToken, + bool fMustConvert + ) = 0; // Notify EE about intent to use or not to use instruction set in the method. Returns true if the instruction set is supported unconditionally. virtual bool notifyInstructionSetUsage( - CORINFO_InstructionSet instructionSet, - bool supportEnabled + CORINFO_InstructionSet instructionSet, + bool supportEnabled ) = 0; // Notify EE that JIT needs an entry-point that is tail-callable. diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index 344ca9a82bdd4..9cee9b1742125 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -191,11 +191,11 @@ class ICorJitCompiler // * For the 64 bit jit this is implemented by code:PreJit.compileMethod // Note: setTargetOS must be called before this api is used. virtual CorJitResult compileMethod ( - ICorJitInfo *comp, /* IN */ - struct CORINFO_METHOD_INFO *info, /* IN */ - unsigned /* code:CorJitFlag */ flags, /* IN */ - uint8_t **nativeEntry, /* OUT */ - uint32_t *nativeSizeOfCode /* OUT */ + ICorJitInfo* comp, /* IN */ + struct CORINFO_METHOD_INFO* info, /* IN */ + unsigned /* code:CorJitFlag */ flags, /* IN */ + uint8_t** nativeEntry, /* OUT */ + uint32_t* nativeSizeOfCode /* OUT */ ) = 0; // Do any appropriate work at process shutdown. Default impl is to do nothing. @@ -251,7 +251,7 @@ class ICorJitInfo : public ICorDynamicInfo virtual void reserveUnwindInfo ( bool isFunclet, /* IN */ bool isColdCode, /* IN */ - uint32_t unwindSize /* IN */ + uint32_t unwindSize /* IN */ ) = 0; // Allocate and initialize the .rdata and .pdata for this method or @@ -272,19 +272,18 @@ class ICorJitInfo : public ICorDynamicInfo // funcKind type of funclet (main method code, handler, filter) // virtual void allocUnwindInfo ( - uint8_t * pHotCode, /* IN */ - uint8_t * pColdCode, /* IN */ - uint32_t startOffset, /* IN */ - uint32_t endOffset, /* IN */ - uint32_t unwindSize, /* IN */ - uint8_t * pUnwindBlock, /* IN */ - CorJitFuncKind funcKind /* IN */ + uint8_t * pHotCode, /* IN */ + uint8_t * pColdCode, /* IN */ + uint32_t startOffset, /* IN */ + uint32_t endOffset, /* IN */ + uint32_t unwindSize, /* IN */ + uint8_t * pUnwindBlock, /* IN */ + CorJitFuncKind funcKind /* IN */ ) = 0; - // Get a block of memory needed for the code manager information, - // (the info for enumerating the GC pointers while crawling the - // stack frame). - // Note that allocMem must be called first + // Get a block of memory needed for the code manager information, + // (the info for enumerating the GC pointers while crawling the + // stack frame). Note that allocMem must be called first. virtual void * allocGCInfo ( size_t size /* IN */ ) = 0; @@ -293,7 +292,7 @@ class ICorJitInfo : public ICorDynamicInfo // This is guaranteed to be called before any 'setEHinfo' call. // Note that allocMem must be called before this method can be called. virtual void setEHcount ( - unsigned cEH /* IN */ + unsigned cEH /* IN */ ) = 0; // Set the values for one particular exception handler block. @@ -303,7 +302,7 @@ class ICorJitInfo : public ICorDynamicInfo // determine if a "finally" clause is executing. virtual void setEHinfo ( unsigned EHnumber, /* IN */ - const CORINFO_EH_CLAUSE *clause /* IN */ + const CORINFO_EH_CLAUSE* clause /* IN */ ) = 0; // Level -> fatalError, Level 2 -> Error, Level 3 -> Warning @@ -463,20 +462,19 @@ class ICorJitInfo : public ICorDynamicInfo // the call site has no signature information (e.g. a helper call) or has no method handle // (e.g. a CALLI P/Invoke), then null should be passed instead. virtual void recordCallSite( - uint32_t instrOffset, /* IN */ - CORINFO_SIG_INFO * callSig, /* IN */ - CORINFO_METHOD_HANDLE methodHandle /* IN */ + uint32_t instrOffset, /* IN */ + CORINFO_SIG_INFO * callSig, /* IN */ + CORINFO_METHOD_HANDLE methodHandle /* IN */ ) = 0; // A relocation is recorded if we are pre-jitting. // A jump thunk may be inserted if we are jitting virtual void recordRelocation( - void * location, /* IN */ - void * locationRW, /* IN */ - void * target, /* IN */ - uint16_t fRelocType, /* IN */ - uint16_t slotNum = 0, /* IN */ - int32_t addlDelta = 0 /* IN */ + void * location, /* IN */ + void * locationRW, /* IN */ + void * target, /* IN */ + uint16_t fRelocType, /* IN */ + int32_t addlDelta = 0 /* IN */ ) = 0; virtual uint16_t getRelocTypeHint(void * target) = 0; @@ -491,9 +489,9 @@ class ICorJitInfo : public ICorDynamicInfo // Fetches extended flags for a particular compilation instance. Returns // the number of bytes written to the provided buffer. virtual uint32_t getJitFlags( - CORJIT_FLAGS* flags, /* IN: Points to a buffer that will hold the extended flags. */ - uint32_t sizeInBytes /* IN: The size of the buffer. Note that this is effectively a - version number for the CORJIT_FLAGS value. */ + CORJIT_FLAGS* flags, /* IN: Points to a buffer that will hold the extended flags. */ + uint32_t sizeInBytes /* IN: The size of the buffer. Note that this is effectively a + version number for the CORJIT_FLAGS value. */ ) = 0; }; diff --git a/src/coreclr/inc/corjitflags.h b/src/coreclr/inc/corjitflags.h index 6f7b00cb6f919..dce9a9f00b399 100644 --- a/src/coreclr/inc/corjitflags.h +++ b/src/coreclr/inc/corjitflags.h @@ -22,97 +22,52 @@ class CORJIT_FLAGS { public: + // Note: these flags can be #ifdef'ed, but no number should be re-used between different #ifdef conditions, + // so platform-independent code can know uniquely which number corresponds to which flag. enum CorJitFlag { CORJIT_FLAG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). - CORJIT_FLAG_SPEED_OPT = 0, - CORJIT_FLAG_SIZE_OPT = 1, + + CORJIT_FLAG_SPEED_OPT = 0, // optimize for speed + CORJIT_FLAG_SIZE_OPT = 1, // optimize for code size CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necessarily debuggable code) - CORJIT_FLAG_ENABLE_CFG = 6, // generate control-flow guard checks - CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete - - #if defined(TARGET_X86) - CORJIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke - #else // !defined(TARGET_X86) - CORJIT_FLAG_UNUSED2 = 8, - #endif // !defined(TARGET_X86) - - CORJIT_FLAG_UNUSED3 = 9, - CORJIT_FLAG_UNUSED4 = 10, - CORJIT_FLAG_UNUSED5 = 11, - CORJIT_FLAG_UNUSED6 = 12, - - CORJIT_FLAG_OSR = 13, // Generate alternate method for On Stack Replacement - - CORJIT_FLAG_ALT_JIT = 14, // JIT should consider itself an ALT_JIT - CORJIT_FLAG_FROZEN_ALLOC_ALLOWED = 15, // JIT is allowed to use *_MAYBEFROZEN allocators - CORJIT_FLAG_UNUSED9 = 16, - CORJIT_FLAG_UNUSED10 = 17, - - CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. - CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation - CORJIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues - CORJIT_FLAG_UNUSED11 = 21, - CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining - CORJIT_FLAG_UNUSED12 = 23, - CORJIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. - CORJIT_FLAG_RELOC = 25, // Generate relocatable code - CORJIT_FLAG_UNUSED13 = 26, - CORJIT_FLAG_IL_STUB = 27, // method is an IL stub - CORJIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections - CORJIT_FLAG_BBINSTR = 29, // Collect basic block profile information - CORJIT_FLAG_BBOPT = 30, // Optimize method based on profile information - CORJIT_FLAG_FRAMED = 31, // All methods have an EBP frame - CORJIT_FLAG_BBINSTR_IF_LOOPS = 32, // JIT must instrument current method if it has loops - CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) - CORJIT_FLAG_UNUSED14 = 34, - CORJIT_FLAG_UNUSED37 = 35, - CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions - CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog - CORJIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the REVERSE_PINVOKE helper variants that track transitions. - CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible - CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code + CORJIT_FLAG_ENABLE_CFG = 6, // generate CFG enabled code + CORJIT_FLAG_OSR = 7, // Generate alternate version for On Stack Replacement + CORJIT_FLAG_ALT_JIT = 8, // JIT should consider itself an ALT_JIT + CORJIT_FLAG_FROZEN_ALLOC_ALLOWED = 9, // JIT is allowed to use *_MAYBEFROZEN allocators + CORJIT_FLAG_MAKEFINALCODE = 10, // Use the final code generator, i.e., not the interpreter. + CORJIT_FLAG_READYTORUN = 11, // Use version-resilient code generation + CORJIT_FLAG_PROF_ENTERLEAVE = 12, // Instrument prologues/epilogues + CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 13, // Disables PInvoke inlining + CORJIT_FLAG_PREJIT = 14, // prejit is the execution engine. + CORJIT_FLAG_RELOC = 15, // Generate relocatable code + CORJIT_FLAG_IL_STUB = 16, // method is an IL stub + CORJIT_FLAG_PROCSPLIT = 17, // JIT should separate code into hot and cold sections + CORJIT_FLAG_BBINSTR = 18, // Collect basic block profile information + CORJIT_FLAG_BBINSTR_IF_LOOPS = 19, // JIT must instrument current method if it has loops + CORJIT_FLAG_BBOPT = 20, // Optimize method based on profile information + CORJIT_FLAG_FRAMED = 21, // All methods have an EBP frame + CORJIT_FLAG_PUBLISH_SECRET_PARAM = 22, // JIT must place stub secret param into local 0. (used by IL stubs) + CORJIT_FLAG_USE_PINVOKE_HELPERS = 23, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions + CORJIT_FLAG_REVERSE_PINVOKE = 24, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog + CORJIT_FLAG_TRACK_TRANSITIONS = 25, // The JIT should insert the helper variants that track transitions. + CORJIT_FLAG_TIER0 = 26, // This is the initial tier for tiered compilation which should generate code as quickly as possible + CORJIT_FLAG_TIER1 = 27, // This is the final tier (for now) for tiered compilation which should generate high quality code + CORJIT_FLAG_NO_INLINING = 28, // JIT should not inline any called method into this method #if defined(TARGET_ARM) - CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records -#else // !defined(TARGET_ARM) - CORJIT_FLAG_UNUSED15 = 41, -#endif // !defined(TARGET_ARM) + CORJIT_FLAG_RELATIVE_CODE_RELOCS = 29, // JIT should generate PC-relative address computations instead of EE relocation records + CORJIT_FLAG_SOFTFP_ABI = 30, // Enable armel calling convention +#endif - CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method +#if defined(TARGET_X86) || defined(TARGET_AMD64) + CORJIT_FLAG_VECTOR512_THROTTLING = 31, // On x86/x64, 512-bit vector usage may incur CPU frequency throttling +#endif -#if defined(TARGET_ARM) - CORJIT_FLAG_SOFTFP_ABI = 43, // On ARM should enable armel calling convention -#elif defined(TARGET_X86) || defined(TARGET_AMD64) - CORJIT_FLAG_VECTOR512_THROTTLING = 43, // On Xarch, 512-bit vector usage may incur CPU frequency throttling -#else - CORJIT_FLAG_UNUSED16 = 43, -#endif // !defined(TARGET_ARM) - - CORJIT_FLAG_UNUSED17 = 44, - CORJIT_FLAG_UNUSED18 = 45, - CORJIT_FLAG_UNUSED19 = 46, - CORJIT_FLAG_UNUSED20 = 47, - CORJIT_FLAG_UNUSED21 = 48, - CORJIT_FLAG_UNUSED22 = 49, - CORJIT_FLAG_UNUSED23 = 50, - CORJIT_FLAG_UNUSED24 = 51, - CORJIT_FLAG_UNUSED25 = 52, - CORJIT_FLAG_UNUSED26 = 53, - CORJIT_FLAG_UNUSED27 = 54, - CORJIT_FLAG_UNUSED28 = 55, - CORJIT_FLAG_UNUSED29 = 56, - CORJIT_FLAG_UNUSED30 = 57, - CORJIT_FLAG_UNUSED31 = 58, - CORJIT_FLAG_UNUSED32 = 59, - CORJIT_FLAG_UNUSED33 = 60, - CORJIT_FLAG_UNUSED34 = 61, - CORJIT_FLAG_UNUSED35 = 62, - CORJIT_FLAG_UNUSED36 = 63 }; CORJIT_FLAGS() diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index f3d93194df258..5a7b737b85168 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -75,9 +75,6 @@ void getEHinfo( CORINFO_CLASS_HANDLE getMethodClass( CORINFO_METHOD_HANDLE method) override; -CORINFO_MODULE_HANDLE getMethodModule( - CORINFO_METHOD_HANDLE method) override; - void getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, @@ -117,13 +114,6 @@ bool satisfiesMethodConstraints( CORINFO_CLASS_HANDLE parent, CORINFO_METHOD_HANDLE method) override; -bool isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) override; - void methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method) override; @@ -143,9 +133,6 @@ PatchpointInfo* getOSRInfo( void resolveToken( CORINFO_RESOLVED_TOKEN* pResolvedToken) override; -bool tryResolveToken( - CORINFO_RESOLVED_TOKEN* pResolvedToken) override; - void findSig( CORINFO_MODULE_HANDLE module, unsigned sigTOK, @@ -161,14 +148,6 @@ void findCallSiteSig( CORINFO_CLASS_HANDLE getTokenTypeAsHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken) override; -bool isValidToken( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) override; - -bool isValidStringRef( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) override; - int getStringLiteral( CORINFO_MODULE_HANDLE module, unsigned metaTOK, @@ -347,10 +326,6 @@ TypeCompareState compareTypesForEquality( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) override; -CORINFO_CLASS_HANDLE mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) override; - bool isMoreSpecificType( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) override; @@ -366,9 +341,6 @@ CorInfoType getChildType( CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet) override; -bool satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls) override; - bool isSDArray( CORINFO_CLASS_HANDLE cls) override; @@ -509,12 +481,6 @@ const char* getMethodNameFromMetadata( unsigned getMethodHash( CORINFO_METHOD_HANDLE ftn) override; -size_t findNameOfToken( - CORINFO_MODULE_HANDLE moduleHandle, - mdToken token, - char* szFQName, - size_t FQNameCapacity) override; - bool getSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) override; @@ -528,9 +494,6 @@ uint32_t getRISCV64PassStructInRegisterFlags( uint32_t getThreadTLSIndex( void** ppIndirection) override; -const void* getInlinedCallFrameVptr( - void** ppIndirection) override; - int32_t* getAddrOfCaptureThreadGlobal( void** ppIndirection) override; @@ -607,13 +570,6 @@ void getCallInfo( CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO* pResult) override; -bool canAccessFamily( - CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) override; - -bool isRIDClassDomainID( - CORINFO_CLASS_HANDLE cls) override; - unsigned getClassDomainID( CORINFO_CLASS_HANDLE cls, void** ppIndirection) override; @@ -743,7 +699,6 @@ void recordRelocation( void* locationRW, void* target, uint16_t fRelocType, - uint16_t slotNum, int32_t addlDelta) override; uint16_t getRelocTypeHint( diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index ebcf4919cb6af..36f906df5e7ed 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* fda2f9dd-6b3e-4ecd-a7b8-79e5edf1f072 */ - 0xfda2f9dd, - 0x6b3e, - 0x4ecd, - {0xa7, 0xb8, 0x79, 0xe5, 0xed, 0xf1, 0xf0, 0x72} +constexpr GUID JITEEVersionIdentifier = { /* 88398e9f-093a-4212-85bc-bebb8c14cd24 */ + 0x88398e9f, + 0x093a, + 0x4212, + {0x85, 0xbc, 0xbe, 0xbb, 0x8c, 0x14, 0xcd, 0x24} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index b93f42dfba8ff..7a7f975e50f99 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -16,7 +16,6 @@ DEF_CLR_API(canTailCall) DEF_CLR_API(reportTailCallDecision) DEF_CLR_API(getEHinfo) DEF_CLR_API(getMethodClass) -DEF_CLR_API(getMethodModule) DEF_CLR_API(getMethodVTableOffset) DEF_CLR_API(resolveVirtualMethod) DEF_CLR_API(getUnboxedEntry) @@ -27,19 +26,15 @@ DEF_CLR_API(isIntrinsicType) DEF_CLR_API(getUnmanagedCallConv) DEF_CLR_API(pInvokeMarshalingRequired) DEF_CLR_API(satisfiesMethodConstraints) -DEF_CLR_API(isCompatibleDelegate) DEF_CLR_API(methodMustBeLoadedBeforeCodeIsRun) DEF_CLR_API(mapMethodDeclToMethodImpl) DEF_CLR_API(getGSCookie) DEF_CLR_API(setPatchpointInfo) DEF_CLR_API(getOSRInfo) DEF_CLR_API(resolveToken) -DEF_CLR_API(tryResolveToken) DEF_CLR_API(findSig) DEF_CLR_API(findCallSiteSig) DEF_CLR_API(getTokenTypeAsHandle) -DEF_CLR_API(isValidToken) -DEF_CLR_API(isValidStringRef) DEF_CLR_API(getStringLiteral) DEF_CLR_API(printObjectDescription) DEF_CLR_API(asCorInfoType) @@ -86,12 +81,10 @@ DEF_CLR_API(getTypeForPrimitiveNumericClass) DEF_CLR_API(canCast) DEF_CLR_API(compareTypesForCast) DEF_CLR_API(compareTypesForEquality) -DEF_CLR_API(mergeClasses) DEF_CLR_API(isMoreSpecificType) DEF_CLR_API(isEnum) DEF_CLR_API(getParentType) DEF_CLR_API(getChildType) -DEF_CLR_API(satisfiesClassConstraints) DEF_CLR_API(isSDArray) DEF_CLR_API(getArrayRank) DEF_CLR_API(getArrayIntrinsicID) @@ -126,12 +119,10 @@ DEF_CLR_API(getMethodDefFromMethod) DEF_CLR_API(printMethodName) DEF_CLR_API(getMethodNameFromMetadata) DEF_CLR_API(getMethodHash) -DEF_CLR_API(findNameOfToken) DEF_CLR_API(getSystemVAmd64PassStructInRegisterDescriptor) DEF_CLR_API(getLoongArch64PassStructInRegisterFlags) DEF_CLR_API(getRISCV64PassStructInRegisterFlags) DEF_CLR_API(getThreadTLSIndex) -DEF_CLR_API(getInlinedCallFrameVptr) DEF_CLR_API(getAddrOfCaptureThreadGlobal) DEF_CLR_API(getHelperFtn) DEF_CLR_API(getFunctionEntryPoint) @@ -150,8 +141,6 @@ DEF_CLR_API(canGetCookieForPInvokeCalliSig) DEF_CLR_API(getJustMyCodeHandle) DEF_CLR_API(GetProfilingHandle) DEF_CLR_API(getCallInfo) -DEF_CLR_API(canAccessFamily) -DEF_CLR_API(isRIDClassDomainID) DEF_CLR_API(getClassDomainID) DEF_CLR_API(getStaticFieldContent) DEF_CLR_API(getObjectContent) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index da369eda01a37..6d08b04259688 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -132,15 +132,6 @@ CORINFO_CLASS_HANDLE WrapICorJitInfo::getMethodClass( return temp; } -CORINFO_MODULE_HANDLE WrapICorJitInfo::getMethodModule( - CORINFO_METHOD_HANDLE method) -{ - API_ENTER(getMethodModule); - CORINFO_MODULE_HANDLE temp = wrapHnd->getMethodModule(method); - API_LEAVE(getMethodModule); - return temp; -} - void WrapICorJitInfo::getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, @@ -238,19 +229,6 @@ bool WrapICorJitInfo::satisfiesMethodConstraints( return temp; } -bool WrapICorJitInfo::isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - API_ENTER(isCompatibleDelegate); - bool temp = wrapHnd->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); - API_LEAVE(isCompatibleDelegate); - return temp; -} - void WrapICorJitInfo::methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method) { @@ -302,15 +280,6 @@ void WrapICorJitInfo::resolveToken( API_LEAVE(resolveToken); } -bool WrapICorJitInfo::tryResolveToken( - CORINFO_RESOLVED_TOKEN* pResolvedToken) -{ - API_ENTER(tryResolveToken); - bool temp = wrapHnd->tryResolveToken(pResolvedToken); - API_LEAVE(tryResolveToken); - return temp; -} - void WrapICorJitInfo::findSig( CORINFO_MODULE_HANDLE module, unsigned sigTOK, @@ -342,26 +311,6 @@ CORINFO_CLASS_HANDLE WrapICorJitInfo::getTokenTypeAsHandle( return temp; } -bool WrapICorJitInfo::isValidToken( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - API_ENTER(isValidToken); - bool temp = wrapHnd->isValidToken(module, metaTOK); - API_LEAVE(isValidToken); - return temp; -} - -bool WrapICorJitInfo::isValidStringRef( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - API_ENTER(isValidStringRef); - bool temp = wrapHnd->isValidStringRef(module, metaTOK); - API_LEAVE(isValidStringRef); - return temp; -} - int WrapICorJitInfo::getStringLiteral( CORINFO_MODULE_HANDLE module, unsigned metaTOK, @@ -813,16 +762,6 @@ TypeCompareState WrapICorJitInfo::compareTypesForEquality( return temp; } -CORINFO_CLASS_HANDLE WrapICorJitInfo::mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - API_ENTER(mergeClasses); - CORINFO_CLASS_HANDLE temp = wrapHnd->mergeClasses(cls1, cls2); - API_LEAVE(mergeClasses); - return temp; -} - bool WrapICorJitInfo::isMoreSpecificType( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) @@ -862,15 +801,6 @@ CorInfoType WrapICorJitInfo::getChildType( return temp; } -bool WrapICorJitInfo::satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls) -{ - API_ENTER(satisfiesClassConstraints); - bool temp = wrapHnd->satisfiesClassConstraints(cls); - API_LEAVE(satisfiesClassConstraints); - return temp; -} - bool WrapICorJitInfo::isSDArray( CORINFO_CLASS_HANDLE cls) { @@ -1206,18 +1136,6 @@ unsigned WrapICorJitInfo::getMethodHash( return temp; } -size_t WrapICorJitInfo::findNameOfToken( - CORINFO_MODULE_HANDLE moduleHandle, - mdToken token, - char* szFQName, - size_t FQNameCapacity) -{ - API_ENTER(findNameOfToken); - size_t temp = wrapHnd->findNameOfToken(moduleHandle, token, szFQName, FQNameCapacity); - API_LEAVE(findNameOfToken); - return temp; -} - bool WrapICorJitInfo::getSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) @@ -1255,15 +1173,6 @@ uint32_t WrapICorJitInfo::getThreadTLSIndex( return temp; } -const void* WrapICorJitInfo::getInlinedCallFrameVptr( - void** ppIndirection) -{ - API_ENTER(getInlinedCallFrameVptr); - const void* temp = wrapHnd->getInlinedCallFrameVptr(ppIndirection); - API_LEAVE(getInlinedCallFrameVptr); - return temp; -} - int32_t* WrapICorJitInfo::getAddrOfCaptureThreadGlobal( void** ppIndirection) { @@ -1441,25 +1350,6 @@ void WrapICorJitInfo::getCallInfo( API_LEAVE(getCallInfo); } -bool WrapICorJitInfo::canAccessFamily( - CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) -{ - API_ENTER(canAccessFamily); - bool temp = wrapHnd->canAccessFamily(hCaller, hInstanceType); - API_LEAVE(canAccessFamily); - return temp; -} - -bool WrapICorJitInfo::isRIDClassDomainID( - CORINFO_CLASS_HANDLE cls) -{ - API_ENTER(isRIDClassDomainID); - bool temp = wrapHnd->isRIDClassDomainID(cls); - API_LEAVE(isRIDClassDomainID); - return temp; -} - unsigned WrapICorJitInfo::getClassDomainID( CORINFO_CLASS_HANDLE cls, void** ppIndirection) @@ -1742,11 +1632,10 @@ void WrapICorJitInfo::recordRelocation( void* locationRW, void* target, uint16_t fRelocType, - uint16_t slotNum, int32_t addlDelta) { API_ENTER(recordRelocation); - wrapHnd->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); + wrapHnd->recordRelocation(location, locationRW, target, fRelocType, addlDelta); API_LEAVE(recordRelocation); } diff --git a/src/coreclr/jit/block.cpp b/src/coreclr/jit/block.cpp index 5284e747092bd..01c1e52b99613 100644 --- a/src/coreclr/jit/block.cpp +++ b/src/coreclr/jit/block.cpp @@ -846,7 +846,7 @@ BasicBlock* BasicBlock::GetUniquePred(Compiler* compiler) const // // Return Value: // The unique successor of a block, or nullptr if there is no unique successor. - +// BasicBlock* BasicBlock::GetUniqueSucc() const { if (bbJumpKind == BBJ_ALWAYS) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index b25f233ff1174..597b88709019b 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6137,6 +6137,7 @@ class Compiler PhaseStatus fgForwardSub(); bool fgForwardSubBlock(BasicBlock* block); bool fgForwardSubStatement(Statement* statement); + bool fgForwardSubHasStoreInterference(Statement* defStmt, Statement* nextStmt, GenTree* nextStmtUse); void fgForwardSubUpdateLiveness(GenTree* newSubListFirst, GenTree* newSubListLast); // The given local variable, required to be a struct variable, is being assigned via @@ -8072,9 +8073,7 @@ class Compiler WORD eeGetRelocTypeHint(void* target); - // ICorStaticInfo wrapper functions - - bool eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken); +// ICorStaticInfo wrapper functions #if defined(UNIX_AMD64_ABI) #ifdef DEBUG @@ -9758,7 +9757,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX STRESS_MODE(CATCH_ARG) /* Will spill catch arg */ \ STRESS_MODE(UNSAFE_BUFFER_CHECKS) \ STRESS_MODE(NULL_OBJECT_CHECK) \ - STRESS_MODE(PINVOKE_RESTORE_ESP) \ STRESS_MODE(RANDOM_INLINE) \ STRESS_MODE(SWITCH_CMP_BR_EXPANSION) \ STRESS_MODE(GENERIC_VARN) \ diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index 5d7c5b9b9c4eb..bbec124b4b1ac 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1361,11 +1361,6 @@ void Compiler::eeGetSystemVAmd64PassStructInRegisterDescriptor( #endif // UNIX_AMD64_ABI -bool Compiler::eeTryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken) -{ - return info.compCompHnd->tryResolveToken(resolvedToken); -} - bool Compiler::eeRunWithErrorTrapImp(void (*function)(void*), void* param) { return info.compCompHnd->runWithErrorTrap(function, param); diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 11407c9cabb1d..70a9e5ebb054f 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -10084,8 +10084,7 @@ void emitter::emitRecordRelocation(void* location, /* IN */ // late disassembly; maybe we'll need it? if (emitComp->info.compMatchedVM) { - // slotNum is unused on all supported platforms. - emitCmpHandle->recordRelocation(location, locationRW, target, fRelocType, /* slotNum */ 0, addlDelta); + emitCmpHandle->recordRelocation(location, locationRW, target, fRelocType, addlDelta); } #if defined(LATE_DISASM) codeGen->getDisAssembler().disRecordRelocation((size_t)location, (size_t)target); diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 8cb8d54513b31..50fd567e8a9fc 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -10222,10 +10222,10 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) assert(fmt == IF_BI_0A); assert((distVal & 1) == 0); - code_t code = emitInsCode(ins, fmt); - const bool recordRelocation = emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs); + code_t code = emitInsCode(ins, fmt); + const bool doRecordRelocation = emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs); - if (recordRelocation) + if (doRecordRelocation) { // dst isn't an actual final target location, just some intermediate // location. Thus we cannot make any guarantees about distVal (not @@ -10246,7 +10246,7 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) const unsigned instrSize = emitOutput_Instr(dst, code); - if (recordRelocation) + if (doRecordRelocation) { assert(id->idjKeepLong); if (emitComp->info.compMatchedVM) diff --git a/src/coreclr/jit/forwardsub.cpp b/src/coreclr/jit/forwardsub.cpp index eea19cabfdc8e..1f05ff1929e87 100644 --- a/src/coreclr/jit/forwardsub.cpp +++ b/src/coreclr/jit/forwardsub.cpp @@ -652,6 +652,14 @@ bool Compiler::fgForwardSubStatement(Statement* stmt) // // if the next tree can't change the value of fwdSubNode or be impacted by fwdSubNode effects // + if (((fsv.GetFlags() & GTF_ASG) != 0) && fgForwardSubHasStoreInterference(stmt, nextStmt, fsv.GetNode())) + { + // We execute a store before the substitution local; that + // store could interfere with some of the locals in the source of + // the candidate def. + JITDUMP(" cannot reorder with potential interfering store\n"); + return false; + } if (((fwdSubNode->gtFlags & GTF_CALL) != 0) && ((fsv.GetFlags() & GTF_ALL_EFFECT) != 0)) { JITDUMP(" cannot reorder call with any side effect\n"); @@ -871,6 +879,69 @@ bool Compiler::fgForwardSubStatement(Statement* stmt) return true; } +//------------------------------------------------------------------------ +// fgForwardSubHasStoreInterference: Check if a forward sub candidate +// interferes with stores in the statement it may be substituted into. +// +// Arguments: +// defStmt - The statement with the def +// nextStmt - The statement that is being substituted into +// nextStmtUse - Use of the local being substituted in the next statement +// +// Returns: +// True if there is interference. +// +// Remarks: +// We expect the caller to have checked for GTF_ASG before doing the precise +// check here. +// +bool Compiler::fgForwardSubHasStoreInterference(Statement* defStmt, Statement* nextStmt, GenTree* nextStmtUse) +{ + assert(defStmt->GetRootNode()->OperIsLocalStore()); + assert(nextStmtUse->OperIsLocalRead()); + + GenTreeLclVarCommon* defNode = defStmt->GetRootNode()->AsLclVarCommon(); + + for (GenTreeLclVarCommon* defStmtLcl : defStmt->LocalsTreeList()) + { + if (defStmtLcl == defNode) + { + break; + } + + unsigned defStmtLclNum = defStmtLcl->GetLclNum(); + LclVarDsc* defStmtLclDsc = lvaGetDesc(defStmtLclNum); + unsigned defStmtParentLclNum = BAD_VAR_NUM; + if (defStmtLclDsc->lvIsStructField) + { + defStmtParentLclNum = defStmtLclDsc->lvParentLcl; + } + + for (GenTreeLclVarCommon* useStmtLcl : nextStmt->LocalsTreeList()) + { + if (useStmtLcl == nextStmtUse) + { + break; + } + + if (!useStmtLcl->OperIsLocalStore()) + { + continue; + } + + // If the next statement has a store earlier than the use and that + // store affects a local on the RHS of the forward sub candidate, + // then we have interference. + if ((useStmtLcl->GetLclNum() == defStmtLclNum) || (useStmtLcl->GetLclNum() == defStmtParentLclNum)) + { + return true; + } + } + } + + return false; +} + //------------------------------------------------------------------------ // fgForwardSubUpdateLiveness: correct liveness after performing a forward // substitution that added a new sub list of locals in a statement. diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index f6089645f8c41..c568deaa7467f 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -18194,9 +18194,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, boo // for the result, unless it is an interface type. // // TODO-CQ: when we have default interface methods then - // this might not be the best assumption. We could also - // explore calling something like mergeClasses to identify - // the more specific class. A similar issue arises when + // this might not be the best assumption. A similar issue arises when // typing the temp in impCastClassOrIsInstToTree, when we // expand the cast inline. if (castHnd != nullptr) diff --git a/src/coreclr/jit/jitee.h b/src/coreclr/jit/jitee.h index ac51df952ab42..27963ac356efb 100644 --- a/src/coreclr/jit/jitee.h +++ b/src/coreclr/jit/jitee.h @@ -1,109 +1,56 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// This class wraps the CORJIT_FLAGS type in the JIT-EE interface (in corjit.h) such that the JIT can -// build with either the old flags (COR_JIT_EE_VERSION <= 460) or the new flags (COR_JIT_EE_VERSION > 460). -// It actually is exactly the same as the new definition, and must be kept up-to-date with the new definition. -// When built against an old JIT-EE interface, the old flags are converted into this structure. +// This class wraps the CORJIT_FLAGS type in the JIT-EE interface (in corjit.h). +// If this changes, also change spmidumphelper.cpp. class JitFlags { public: // clang-format off enum JitFlag { - JIT_FLAG_SPEED_OPT = 0, - JIT_FLAG_SIZE_OPT = 1, + JIT_FLAG_SPEED_OPT = 0, // optimize for speed + JIT_FLAG_SIZE_OPT = 1, // optimize for code size JIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) JIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode JIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info JIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necessarily debuggable code) JIT_FLAG_ENABLE_CFG = 6, // generate CFG enabled code - JIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete - - #if defined(TARGET_X86) - JIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke - #else // !defined(TARGET_X86) - JIT_FLAG_UNUSED2 = 8, - #endif // !defined(TARGET_X86) - - JIT_FLAG_UNUSED3 = 9, - JIT_FLAG_UNUSED4 = 10, - JIT_FLAG_UNUSED5 = 11, - JIT_FLAG_UNUSED6 = 12, - - JIT_FLAG_OSR = 13, // Generate alternate version for On Stack Replacement - - JIT_FLAG_ALT_JIT = 14, // JIT should consider itself an ALT_JIT - JIT_FLAG_FROZEN_ALLOC_ALLOWED = 15, // JIT is allowed to use *_MAYBEFROZEN allocators - JIT_FLAG_UNUSED9 = 16, - - #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) - JIT_FLAG_FEATURE_SIMD = 17, - #else - JIT_FLAG_UNUSED10 = 17, - #endif // !(defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64)) - - JIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. - JIT_FLAG_READYTORUN = 19, // Use version-resilient code generation - JIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues - JIT_FLAG_UNUSED11 = 21, - JIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining - JIT_FLAG_UNUSED12 = 23, - JIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. - JIT_FLAG_RELOC = 25, // Generate relocatable code - JIT_FLAG_IMPORT_ONLY = 26, // Only import the function - JIT_FLAG_IL_STUB = 27, // method is an IL stub - JIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections - JIT_FLAG_BBINSTR = 29, // Collect basic block profile information - JIT_FLAG_BBOPT = 30, // Optimize method based on profile information - JIT_FLAG_FRAMED = 31, // All methods have an EBP frame - JIT_FLAG_BBINSTR_IF_LOOPS = 32, // JIT must instrument current method if it has loops - JIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) - JIT_FLAG_UNUSED13 = 34, - JIT_FLAG_UNUSED14 = 35, - JIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions - JIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog - JIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the helper variants that track transitions. - JIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible - JIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code + JIT_FLAG_OSR = 7, // Generate alternate version for On Stack Replacement + JIT_FLAG_ALT_JIT = 8, // JIT should consider itself an ALT_JIT + JIT_FLAG_FROZEN_ALLOC_ALLOWED = 9, // JIT is allowed to use *_MAYBEFROZEN allocators + JIT_FLAG_MAKEFINALCODE = 10, // Use the final code generator, i.e., not the interpreter. + JIT_FLAG_READYTORUN = 11, // Use version-resilient code generation + JIT_FLAG_PROF_ENTERLEAVE = 12, // Instrument prologues/epilogues + JIT_FLAG_PROF_NO_PINVOKE_INLINE = 13, // Disables PInvoke inlining + JIT_FLAG_PREJIT = 14, // prejit is the execution engine. + JIT_FLAG_RELOC = 15, // Generate relocatable code + JIT_FLAG_IL_STUB = 16, // method is an IL stub + JIT_FLAG_PROCSPLIT = 17, // JIT should separate code into hot and cold sections + JIT_FLAG_BBINSTR = 18, // Collect basic block profile information + JIT_FLAG_BBINSTR_IF_LOOPS = 19, // JIT must instrument current method if it has loops + JIT_FLAG_BBOPT = 20, // Optimize method based on profile information + JIT_FLAG_FRAMED = 21, // All methods have an EBP frame + JIT_FLAG_PUBLISH_SECRET_PARAM = 22, // JIT must place stub secret param into local 0. (used by IL stubs) + JIT_FLAG_USE_PINVOKE_HELPERS = 23, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions + JIT_FLAG_REVERSE_PINVOKE = 24, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog + JIT_FLAG_TRACK_TRANSITIONS = 25, // The JIT should insert the helper variants that track transitions. + JIT_FLAG_TIER0 = 26, // This is the initial tier for tiered compilation which should generate code as quickly as possible + JIT_FLAG_TIER1 = 27, // This is the final tier (for now) for tiered compilation which should generate high quality code + JIT_FLAG_NO_INLINING = 28, // JIT should not inline any called method into this method #if defined(TARGET_ARM) - JIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records -#else // !defined(TARGET_ARM) - JIT_FLAG_UNUSED15 = 41, -#endif // !defined(TARGET_ARM) - - JIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method - -#if defined(TARGET_ARM) - JIT_FLAG_SOFTFP_ABI = 43, // On ARM should enable armel calling convention -#elif defined(TARGET_XARCH) - JIT_FLAG_VECTOR512_THROTTLING = 43, // On Xarch, 512-bit vector usage may incur CPU frequency throttling -#else - JIT_FLAG_UNUSED16 = 43, + JIT_FLAG_RELATIVE_CODE_RELOCS = 29, // JIT should generate PC-relative address computations instead of EE relocation records + JIT_FLAG_SOFTFP_ABI = 30, // Enable armel calling convention #endif - JIT_FLAG_UNUSED17 = 44, - JIT_FLAG_UNUSED18 = 45, - JIT_FLAG_UNUSED19 = 46, - JIT_FLAG_UNUSED20 = 47, - JIT_FLAG_UNUSED21 = 48, - JIT_FLAG_UNUSED22 = 49, - JIT_FLAG_UNUSED23 = 50, - JIT_FLAG_UNUSED24 = 51, - JIT_FLAG_UNUSED25 = 52, - JIT_FLAG_UNUSED26 = 53, - JIT_FLAG_UNUSED27 = 54, - JIT_FLAG_UNUSED28 = 55, - JIT_FLAG_UNUSED29 = 56, - JIT_FLAG_UNUSED30 = 57, - JIT_FLAG_UNUSED31 = 58, - JIT_FLAG_UNUSED32 = 59, - JIT_FLAG_UNUSED33 = 60, - JIT_FLAG_UNUSED34 = 61, - JIT_FLAG_UNUSED35 = 62, - JIT_FLAG_UNUSED36 = 63 +#if defined(TARGET_XARCH) + JIT_FLAG_VECTOR512_THROTTLING = 31, // On Xarch, 512-bit vector usage may incur CPU frequency throttling +#endif + // Note: the mcs tool uses the currently unused upper flags bits when outputting SuperPMI MC file flags. + // See EXTRA_JIT_FLAGS and spmidumphelper.cpp. Currently, these are bits 56 through 63. If they overlap, + // something needs to change. }; // clang-format on @@ -171,12 +118,7 @@ class JitFlags FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO, JIT_FLAG_DEBUG_INFO); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT, JIT_FLAG_MIN_OPT); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_ENABLE_CFG, JIT_FLAG_ENABLE_CFG); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND, JIT_FLAG_MCJIT_BACKGROUND); - -#if defined(TARGET_X86) - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PINVOKE_RESTORE_ESP, JIT_FLAG_PINVOKE_RESTORE_ESP); -#endif - + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_OSR, JIT_FLAG_OSR); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_ALT_JIT, JIT_FLAG_ALT_JIT); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_FROZEN_ALLOC_ALLOWED, JIT_FLAG_FROZEN_ALLOC_ALLOWED); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE, JIT_FLAG_MAKEFINALCODE); @@ -194,17 +136,18 @@ class JitFlags FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PUBLISH_SECRET_PARAM, JIT_FLAG_PUBLISH_SECRET_PARAM); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_PINVOKE_HELPERS, JIT_FLAG_USE_PINVOKE_HELPERS); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_REVERSE_PINVOKE, JIT_FLAG_REVERSE_PINVOKE); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TRACK_TRANSITIONS, JIT_FLAG_TRACK_TRANSITIONS); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TIER0, JIT_FLAG_TIER0); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TIER1, JIT_FLAG_TIER1); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_NO_INLINING, JIT_FLAG_NO_INLINING); #if defined(TARGET_ARM) FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS, JIT_FLAG_RELATIVE_CODE_RELOCS); + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SOFTFP_ABI, JIT_FLAG_SOFTFP_ABI); #endif // TARGET_ARM - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_NO_INLINING, JIT_FLAG_NO_INLINING); - -#if defined(TARGET_ARM) - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SOFTFP_ABI, JIT_FLAG_SOFTFP_ABI); +#if defined(TARGET_X86) || defined(TARGET_AMD64) + FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_VECTOR512_THROTTLING, JIT_FLAG_VECTOR512_THROTTLING); #endif // TARGET_ARM #undef FLAGS_EQUAL diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 64826c428b77f..25d07c53e0929 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -2579,7 +2579,7 @@ void Lowering::TryLowerCselToCinvOrCneg(GenTreeOp* select, GenTree* cond) assert(trueVal->OperIs(GT_NOT, GT_NEG) || falseVal->OperIs(GT_NOT, GT_NEG)); - if (trueVal->OperIs(GT_NOT) || trueVal->OperIs(GT_NEG)) + if ((isCneg && trueVal->OperIs(GT_NEG)) || (!isCneg && trueVal->OperIs(GT_NOT))) { shouldReverseCondition = true; invertedOrNegatedVal = trueVal->gtGetOp1(); diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp index 277f5fb9a29a7..ee2ba01e1bb0a 100644 --- a/src/coreclr/jit/promotion.cpp +++ b/src/coreclr/jit/promotion.cpp @@ -202,13 +202,28 @@ bool AggregateInfo::OverlappingReplacements(unsigned offset, return true; } +struct PrimitiveAccess +{ + weight_t CountWtd = 0; + unsigned Offset; + var_types AccessType; + + INDEBUG(unsigned Count = 0); + + PrimitiveAccess(unsigned offset, var_types accessType) : Offset(offset), AccessType(accessType) + { + } +}; + // Tracks all the accesses into one particular struct local. class LocalUses { - jitstd::vector m_accesses; + jitstd::vector m_accesses; + jitstd::vector m_inducedAccesses; public: - LocalUses(Compiler* comp) : m_accesses(comp->getAllocator(CMK_Promotion)) + LocalUses(Compiler* comp) + : m_accesses(comp->getAllocator(CMK_Promotion)), m_inducedAccesses(comp->getAllocator(CMK_Promotion)) { } @@ -307,6 +322,56 @@ class LocalUses #endif } + //------------------------------------------------------------------------ + // RecordInducedAccess: + // Record an induced access into this local with the specified offset and access type. + // + // Parameters: + // offs - The offset being accessed + // accessType - The type of the access + // weight - Weight of the block containing the access + // + // Remarks: + // Induced accesses are accesses that are induced by physical promotion + // due to assignment decompositon. They are always of primitive type. + // + void RecordInducedAccess(unsigned offs, var_types accessType, weight_t weight) + { + PrimitiveAccess* access = nullptr; + + size_t index = 0; + if (m_inducedAccesses.size() > 0) + { + index = Promotion::BinarySearch(m_inducedAccesses, offs); + if ((ssize_t)index >= 0) + { + do + { + PrimitiveAccess& candidateAccess = m_inducedAccesses[index]; + if (candidateAccess.AccessType == accessType) + { + access = &candidateAccess; + break; + } + + index++; + } while (index < m_inducedAccesses.size() && m_inducedAccesses[index].Offset == offs); + } + else + { + index = ~index; + } + } + + if (access == nullptr) + { + access = &*m_inducedAccesses.insert(m_inducedAccesses.begin() + index, PrimitiveAccess(offs, accessType)); + } + + access->CountWtd += weight; + INDEBUG(access->Count++); + } + //------------------------------------------------------------------------ // PickPromotions: // Pick specific replacements to make for this struct local after a set @@ -336,33 +401,121 @@ class LocalUses continue; } - if (!EvaluateReplacement(comp, lclNum, access)) + if (!EvaluateReplacement(comp, lclNum, access, 0)) { continue; } -#ifdef DEBUG - char buf[32]; - sprintf_s(buf, sizeof(buf), "V%02u.[%03u..%03u)", lclNum, access.Offset, - access.Offset + genTypeSize(access.AccessType)); - size_t len = strlen(buf) + 1; - char* bufp = new (comp, CMK_DebugOnly) char[len]; - strcpy_s(bufp, len, buf); -#endif - unsigned newLcl = comp->lvaGrabTemp(false DEBUGARG(bufp)); - LclVarDsc* dsc = comp->lvaGetDesc(newLcl); - dsc->lvType = access.AccessType; + if (*aggregateInfo == nullptr) + { + *aggregateInfo = new (comp, CMK_Promotion) AggregateInfo(comp->getAllocator(CMK_Promotion), lclNum); + } + + (*aggregateInfo)->Replacements.push_back(Replacement(access.Offset, access.AccessType)); + } + + JITDUMP("\n"); + } + + //------------------------------------------------------------------------ + // PickInducedPromotions: + // Pick additional promotions to make based on the fact that some + // accesses will be induced by assignment decomposition. + // + // Parameters: + // comp - Compiler instance + // lclNum - Local num for this struct local + // aggregateInfo - [out] Pointer to aggregate info to create and insert replacements into. + // + bool PickInducedPromotions(Compiler* comp, unsigned lclNum, AggregateInfo** aggregateInfo) + { + if (m_inducedAccesses.size() <= 0) + { + return false; + } + + bool any = false; + JITDUMP("Picking induced promotions for V%02u\n", lclNum); + for (PrimitiveAccess& inducedAccess : m_inducedAccesses) + { + bool overlapsOtherInducedAccess = false; + for (PrimitiveAccess& otherInducedAccess : m_inducedAccesses) + { + if (&otherInducedAccess == &inducedAccess) + { + continue; + } + + if (inducedAccess.Offset + genTypeSize(inducedAccess.AccessType) <= otherInducedAccess.Offset) + { + break; + } + + if (otherInducedAccess.Offset + genTypeSize(otherInducedAccess.AccessType) <= inducedAccess.Offset) + { + continue; + } + + overlapsOtherInducedAccess = true; + break; + } + + if (overlapsOtherInducedAccess) + { + continue; + } + + Access* access = FindAccess(inducedAccess.Offset, inducedAccess.AccessType); + + if (access == nullptr) + { + Access fakeAccess(inducedAccess.Offset, inducedAccess.AccessType, nullptr); + if (!EvaluateReplacement(comp, lclNum, fakeAccess, inducedAccess.CountWtd)) + { + continue; + } + } + else + { + if (!EvaluateReplacement(comp, lclNum, *access, inducedAccess.CountWtd)) + { + continue; + } + } if (*aggregateInfo == nullptr) { *aggregateInfo = new (comp, CMK_Promotion) AggregateInfo(comp->getAllocator(CMK_Promotion), lclNum); } + size_t insertionIndex; + if ((*aggregateInfo)->Replacements.size() > 0) + { +#ifdef DEBUG + Replacement* overlapRep; + assert(!(*aggregateInfo) + ->OverlappingReplacements(inducedAccess.Offset, genTypeSize(inducedAccess.AccessType), + &overlapRep, nullptr)); +#endif + + insertionIndex = + Promotion::BinarySearch((*aggregateInfo)->Replacements, + inducedAccess.Offset); + assert((ssize_t)insertionIndex < 0); + insertionIndex = ~insertionIndex; + } + else + { + insertionIndex = 0; + } + (*aggregateInfo) - ->Replacements.push_back(Replacement(access.Offset, access.AccessType, newLcl DEBUGARG(bufp))); + ->Replacements.insert((*aggregateInfo)->Replacements.begin() + insertionIndex, + Replacement(inducedAccess.Offset, inducedAccess.AccessType)); + any = true; } - JITDUMP("\n"); + return any; } //------------------------------------------------------------------------ @@ -370,14 +523,15 @@ class LocalUses // Evaluate legality and profitability of a single replacement candidate. // // Parameters: - // comp - Compiler instance - // lclNum - Local num for this struct local - // access - Access information for the candidate. + // comp - Compiler instance + // lclNum - Local num for this struct local + // access - Access information for the candidate. + // inducedCountWtd - Additional weighted count due to induced accesses. // // Returns: // True if we should promote this access and create a replacement; otherwise false. // - bool EvaluateReplacement(Compiler* comp, unsigned lclNum, const Access& access) + bool EvaluateReplacement(Compiler* comp, unsigned lclNum, const Access& access, weight_t inducedCountWtd) { weight_t countOverlappedCallArgWtd = 0; weight_t countOverlappedRetbufsWtd = 0; @@ -387,7 +541,9 @@ class LocalUses for (const Access& otherAccess : m_accesses) { if (&otherAccess == &access) + { continue; + } if (!otherAccess.Overlaps(access.Offset, genTypeSize(access.AccessType))) { @@ -407,14 +563,14 @@ class LocalUses weight_t costWithout = 0; // We cost any normal access (which is a struct load or store) without promotion at 3 cycles. - costWithout += access.CountWtd * 3; + costWithout += (access.CountWtd + inducedCountWtd) * 3; weight_t costWith = 0; // For promoted accesses we expect these to turn into reg-reg movs (and in many cases be fully contained in the // parent). // We cost these at 0.5 cycles. - costWith += access.CountWtd * 0.5; + costWith += (access.CountWtd + inducedCountWtd) * 0.5; // Now look at the overlapping struct uses that promotion will make more expensive. @@ -501,8 +657,24 @@ class LocalUses return false; } + //------------------------------------------------------------------------ + // ClearInducedAccesses: + // Clear the stored induced access metrics. + // + void ClearInducedAccesses() + { + m_inducedAccesses.clear(); + } + #ifdef DEBUG - void Dump(unsigned lclNum) + //------------------------------------------------------------------------ + // DumpAccesses: + // Dump the stored access metrics for a specified local. + // + // Parameters: + // lclNum - The local + // + void DumpAccesses(unsigned lclNum) { if (m_accesses.size() <= 0) { @@ -535,15 +707,85 @@ class LocalUses access.CountReturnsWtd); } } + + //------------------------------------------------------------------------ + // DumpInducedAccesses: + // Dump induced accesses for a specified struct local. + // + // Parameters: + // lclNum - The local + // + void DumpInducedAccesses(unsigned lclNum) + { + if (m_inducedAccesses.size() <= 0) + { + return; + } + + printf("Induced accesses for V%02u\n", lclNum); + for (PrimitiveAccess& access : m_inducedAccesses) + { + printf(" %s @ %03u\n", varTypeName(access.AccessType), access.Offset); + printf(" #: (%u, " FMT_WT ")\n", access.Count, access.CountWtd); + } + } #endif + +private: + //------------------------------------------------------------------------ + // FindAccess: + // Find access metrics information for the specified offset and access type. + // + // Parameters: + // offs - The offset + // accessType - Access type + // + // Returns: + // Pointer to a matching access, or nullptr if no match was found. + // + Access* FindAccess(unsigned offs, var_types accessType) + { + if (m_accesses.size() <= 0) + { + return nullptr; + } + + size_t index = Promotion::BinarySearch(m_accesses, offs); + if ((ssize_t)index < 0) + { + return nullptr; + } + + do + { + Access& candidateAccess = m_accesses[index]; + if (candidateAccess.AccessType == accessType) + { + return &candidateAccess; + } + + index++; + } while ((index < m_inducedAccesses.size()) && (m_inducedAccesses[index].Offset == offs)); + + return nullptr; + } +}; + +// Struct used to save all struct stores involving physical promotion candidates. +// These stores can induce new field accesses as part of assignment decomposition. +struct CandidateStore +{ + GenTreeLclVarCommon* Store; + BasicBlock* Block; }; // Visitor that records information about uses of struct locals. class LocalsUseVisitor : public GenTreeVisitor { - Promotion* m_prom; - LocalUses** m_uses; - BasicBlock* m_curBB = nullptr; + Promotion* m_prom; + LocalUses** m_uses; + BasicBlock* m_curBB = nullptr; + ArrayStack m_candidateStores; public: enum @@ -552,7 +794,10 @@ class LocalsUseVisitor : public GenTreeVisitor ComputeStack = true, }; - LocalsUseVisitor(Promotion* prom) : GenTreeVisitor(prom->m_compiler), m_prom(prom) + LocalsUseVisitor(Promotion* prom) + : GenTreeVisitor(prom->m_compiler) + , m_prom(prom) + , m_candidateStores(prom->m_compiler->getAllocator(CMK_Promotion)) { m_uses = new (prom->m_compiler, CMK_Promotion) LocalUses*[prom->m_compiler->lvaCount]{}; } @@ -570,21 +815,16 @@ class LocalsUseVisitor : public GenTreeVisitor } //------------------------------------------------------------------------ - // GetUsesByLocal: - // Get the uses information for a specified local. + // PreOrderVisit: + // Visit a node in preorder and add its use information to the metrics. // // Parameters: - // bb - The current basic block. + // use - The use edge + // user - The user // // Returns: - // Information about uses, or null if this local has no uses information - // associated with it. + // Visitor result // - LocalUses* GetUsesByLocal(unsigned lcl) - { - return m_uses[lcl]; - } - fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) { GenTree* tree = *use; @@ -629,6 +869,16 @@ class LocalsUseVisitor : public GenTreeVisitor accessType = lcl->TypeGet(); accessLayout = accessType == TYP_STRUCT ? lcl->GetLayout(m_compiler) : nullptr; accessFlags = ClassifyLocalAccess(lcl, effectiveUser); + + if (lcl->TypeIs(TYP_STRUCT) && + ((user != nullptr) && user->OperIsLocalStore() && user->Data()->OperIsLocalRead())) + { + // Make sure we add it only once if both the destination and source are candidates. + if ((m_candidateStores.Height() <= 0) || (m_candidateStores.Top().Store != user)) + { + m_candidateStores.Push(CandidateStore{user->AsLclVarCommon(), m_curBB}); + } + } } LocalUses* uses = GetOrCreateUses(lcl->GetLclNum()); @@ -640,6 +890,200 @@ class LocalsUseVisitor : public GenTreeVisitor return fgWalkResult::WALK_CONTINUE; } + //------------------------------------------------------------------------ + // PickPromotions: + // Pick promotions and create aggregate information for each promoted + // struct with promotions. + // + // Parameters: + // aggregates - Appropriately sized vector to create aggregate information in. + // + // Returns: + // True if any struct was physically promoted with at least one replacement; + // otherwise false. + // + bool PickPromotions(jitstd::vector& aggregates) + { + unsigned numLocals = (unsigned)aggregates.size(); + JITDUMP("Picking promotions\n"); + + bool any = false; + + for (unsigned lclNum = 0; lclNum < numLocals; lclNum++) + { + LocalUses* uses = m_uses[lclNum]; + if (uses == nullptr) + { + continue; + } + +#ifdef DEBUG + if (m_compiler->verbose) + { + uses->DumpAccesses(lclNum); + } +#endif + + uses->PickPromotions(m_compiler, lclNum, &aggregates[lclNum]); + + any |= aggregates[lclNum] != nullptr; + } + + if (!any) + { + return false; + } + + if (m_candidateStores.Height() > 0) + { + // Now look for induced accesses due to assignment decomposition. + + JITDUMP("Looking for induced accesses with %d stores between candidates\n", m_candidateStores.Height()); + // Expand the set of fields iteratively based on the current picked + // set. We put a limit on this fixpoint computation to avoid + // pathological cases. From measurements no methods in our own + // collections need more than 10 iterations and 99.5% of methods + // need fewer than 5 iterations. + for (int iters = 0; iters < 10; iters++) + { + for (int i = 0; i < m_candidateStores.Height(); i++) + { + const CandidateStore& candidateStore = m_candidateStores.BottomRef(i); + GenTreeLclVarCommon* store = candidateStore.Store; + + assert(store->TypeIs(TYP_STRUCT)); + assert(store->Data()->OperIsLocalRead()); + + GenTreeLclVarCommon* src = store->Data()->AsLclVarCommon(); + + LclVarDsc* dstDsc = m_compiler->lvaGetDesc(store); + LclVarDsc* srcDsc = m_compiler->lvaGetDesc(src); + + assert(Promotion::IsCandidateForPhysicalPromotion(dstDsc) || + Promotion::IsCandidateForPhysicalPromotion(srcDsc)); + + if (dstDsc->lvPromoted) + { + InduceAccessesFromRegularlyPromotedStruct(aggregates, src, store, candidateStore.Block); + } + else if (srcDsc->lvPromoted) + { + InduceAccessesFromRegularlyPromotedStruct(aggregates, store, src, candidateStore.Block); + } + else + { + if (Promotion::IsCandidateForPhysicalPromotion(dstDsc)) + { + InduceAccessesInCandidate(aggregates, store, src, candidateStore.Block); + } + + if (Promotion::IsCandidateForPhysicalPromotion(srcDsc)) + { + InduceAccessesInCandidate(aggregates, src, store, candidateStore.Block); + } + } + } + + bool any = false; + for (unsigned lclNum = 0; lclNum < numLocals; lclNum++) + { + LocalUses* uses = m_uses[lclNum]; + if (uses == nullptr) + { + continue; + } +#ifdef DEBUG + if (m_compiler->verbose) + { + uses->DumpInducedAccesses(lclNum); + } +#endif + + any |= uses->PickInducedPromotions(m_compiler, lclNum, &aggregates[lclNum]); + } + + if (!any) + { + break; + } + + for (unsigned lclNum = 0; lclNum < numLocals; lclNum++) + { + if (m_uses[lclNum] != nullptr) + { + m_uses[lclNum]->ClearInducedAccesses(); + } + } + } + } + + for (AggregateInfo* agg : aggregates) + { + if (agg == nullptr) + { + continue; + } + + jitstd::vector& reps = agg->Replacements; + + assert(reps.size() > 0); + // Create locals + for (Replacement& rep : reps) + { +#ifdef DEBUG + char buf[32]; + sprintf_s(buf, sizeof(buf), "V%02u.[%03u..%03u)", agg->LclNum, rep.Offset, + rep.Offset + genTypeSize(rep.AccessType)); + size_t len = strlen(buf) + 1; + char* bufp = new (m_compiler, CMK_DebugOnly) char[len]; + strcpy_s(bufp, len, buf); + rep.Description = bufp; +#endif + + rep.LclNum = m_compiler->lvaGrabTemp(false DEBUGARG(rep.Description)); + LclVarDsc* dsc = m_compiler->lvaGetDesc(rep.LclNum); + dsc->lvType = rep.AccessType; + } + +#ifdef DEBUG + JITDUMP("V%02u promoted with %d replacements\n", agg->LclNum, (int)reps.size()); + for (const Replacement& rep : reps) + { + JITDUMP(" [%03u..%03u) promoted as %s V%02u\n", rep.Offset, rep.Offset + genTypeSize(rep.AccessType), + varTypeName(rep.AccessType), rep.LclNum); + } +#endif + + JITDUMP("Computing unpromoted remainder for V%02u\n", agg->LclNum); + StructSegments unpromotedParts = + Promotion::SignificantSegments(m_compiler, m_compiler->lvaGetDesc(agg->LclNum)->GetLayout()); + for (Replacement& rep : reps) + { + unpromotedParts.Subtract(StructSegments::Segment(rep.Offset, rep.Offset + genTypeSize(rep.AccessType))); + } + + JITDUMP(" Remainder: "); + DBEXEC(m_compiler->verbose, unpromotedParts.Dump()); + JITDUMP("\n\n"); + + StructSegments::Segment unpromotedSegment; + if (unpromotedParts.CoveringSegment(&unpromotedSegment)) + { + agg->UnpromotedMin = unpromotedSegment.Start; + agg->UnpromotedMax = unpromotedSegment.End; + assert(unpromotedSegment.Start < unpromotedSegment.End); + } + else + { + // Aggregate is fully promoted, leave UnpromotedMin == UnpromotedMax to indicate this. + } + + any = true; + } + + return any; + } + private: //------------------------------------------------------------------------ // GetOrCreateUses: @@ -661,6 +1105,112 @@ class LocalsUseVisitor : public GenTreeVisitor return m_uses[lclNum]; } + //------------------------------------------------------------------------ + // InduceAccessesFromRegularlyPromotedStruct: + // Create induced accesses based on the fact that there is an assignment + // between a physical promotion candidate and regularly promoted struct. + // + // Parameters: + // aggregates - Aggregate information with current set of replacements + // for each struct local. + // candidateLcl - The local node for a physical promotion candidate. + // regPromLcl - The local node for the regularly promoted struct that + // may induce new LCL_FLD nodes in the candidate. + // block - The block that the assignment appears in. + // + void InduceAccessesFromRegularlyPromotedStruct(jitstd::vector& aggregates, + GenTreeLclVarCommon* candidateLcl, + GenTreeLclVarCommon* regPromLcl, + BasicBlock* block) + { + unsigned regPromOffs = regPromLcl->GetLclOffs(); + unsigned candidateOffs = candidateLcl->GetLclOffs(); + unsigned size = regPromLcl->GetLayout(m_compiler)->GetSize(); + + LclVarDsc* regPromDsc = m_compiler->lvaGetDesc(regPromLcl); + for (unsigned fieldLcl = regPromDsc->lvFieldLclStart, i = 0; i < regPromDsc->lvFieldCnt; fieldLcl++, i++) + { + LclVarDsc* fieldDsc = m_compiler->lvaGetDesc(fieldLcl); + if ((fieldDsc->lvFldOffset >= regPromOffs) && + (fieldDsc->lvFldOffset + genTypeSize(fieldDsc->lvType) <= (regPromOffs + size))) + { + InduceAccess(aggregates, candidateLcl->GetLclNum(), + candidateLcl->GetLclOffs() + (fieldDsc->lvFldOffset - regPromOffs), fieldDsc->lvType, + block); + } + } + } + + //------------------------------------------------------------------------ + // InduceAccessesInCandidate: + // Create induced accesses based on the fact that a specified candidate + // is being assigned from another struct local (the inducer). + // + // Parameters: + // aggregates - Aggregate information with current set of replacements + // for each struct local. + // candidate - The local node for the physical promotion candidate. + // inducer - The local node that may induce new LCL_FLD nodes in the candidate. + // block - The block that the assignment appears in. + // + void InduceAccessesInCandidate(jitstd::vector& aggregates, + GenTreeLclVarCommon* candidate, + GenTreeLclVarCommon* inducer, + BasicBlock* block) + { + unsigned candOffs = candidate->GetLclOffs(); + unsigned inducerOffs = inducer->GetLclOffs(); + unsigned size = candidate->GetLayout(m_compiler)->GetSize(); + + AggregateInfo* inducerAgg = aggregates[inducer->GetLclNum()]; + if (inducerAgg != nullptr) + { + Replacement* firstRep; + Replacement* endRep; + if (inducerAgg->OverlappingReplacements(inducerOffs, size, &firstRep, &endRep)) + { + for (Replacement* rep = firstRep; rep < endRep; rep++) + { + if ((rep->Offset >= inducerOffs) && + (rep->Offset + genTypeSize(rep->AccessType) <= (inducerOffs + size))) + { + InduceAccess(aggregates, candidate->GetLclNum(), candOffs + (rep->Offset - inducerOffs), + rep->AccessType, block); + } + } + } + } + } + + //------------------------------------------------------------------------ + // InduceAccessesInCandidate: + // Record an induced access in a candidate for physical promotion. + // + // Parameters: + // aggregates - Aggregate information with current set of replacements + // for each struct local. + // lclNum - Local that has the induced access. + // offset - Offset at which the induced access starts. + // type - Type of the induced access. + // block - The block with the induced access. + // + void InduceAccess( + jitstd::vector& aggregates, unsigned lclNum, unsigned offset, var_types type, BasicBlock* block) + { + AggregateInfo* agg = aggregates[lclNum]; + if (agg != nullptr) + { + Replacement* overlapRep; + if (agg->OverlappingReplacements(offset, genTypeSize(type), &overlapRep, nullptr)) + { + return; + } + } + + LocalUses* uses = GetOrCreateUses(lclNum); + uses->RecordInducedAccess(offset, type, block->getBBWeight(m_compiler)); + } + //------------------------------------------------------------------------ // ClassifyLocalAccess: // Given a local node and its user, classify information about it. @@ -1139,8 +1689,6 @@ StructSegments Promotion::SignificantSegments(Compiler* compiler, } #endif - // TODO-TP: Cache this per class layout, we call this for every struct - // operation on a promoted local. return segments; } @@ -1163,6 +1711,11 @@ GenTree* Promotion::CreateWriteBack(Compiler* compiler, unsigned structLclNum, c { GenTree* value = compiler->gtNewLclVarNode(replacement.LclNum); GenTree* store = compiler->gtNewStoreLclFldNode(structLclNum, replacement.AccessType, replacement.Offset, value); + + if (!compiler->lvaGetDesc(structLclNum)->lvDoNotEnregister) + { + compiler->lvaSetVarDoNotEnregister(structLclNum DEBUGARG(DoNotEnregisterReason::LocalField)); + } return store; } @@ -1185,9 +1738,85 @@ GenTree* Promotion::CreateReadBack(Compiler* compiler, unsigned structLclNum, co { GenTree* value = compiler->gtNewLclFldNode(structLclNum, replacement.AccessType, replacement.Offset); GenTree* store = compiler->gtNewStoreLclVarNode(replacement.LclNum, value); + + if (!compiler->lvaGetDesc(structLclNum)->lvDoNotEnregister) + { + compiler->lvaSetVarDoNotEnregister(structLclNum DEBUGARG(DoNotEnregisterReason::LocalField)); + } return store; } +//------------------------------------------------------------------------ +// StartBlock: +// Handle reaching the end of the currently started block by preparing +// internal state for upcoming basic blocks, and inserting any necessary +// readbacks. +// +// Parameters: +// block - The block +// +void ReplaceVisitor::StartBlock(BasicBlock* block) +{ + m_currentBlock = block; + +#ifdef DEBUG + // At the start of every block we expect all replacements to be in their + // local home. + for (AggregateInfo* agg : m_aggregates) + { + if (agg == nullptr) + { + continue; + } + + for (Replacement& rep : agg->Replacements) + { + assert(!rep.NeedsReadBack); + assert(rep.NeedsWriteBack); + } + } +#endif + + // OSR locals and parameters may need an initial read back, which we mark + // when we start the scratch BB. + if (!m_compiler->fgBBisScratch(block)) + { + return; + } + + for (AggregateInfo* agg : m_aggregates) + { + if (agg == nullptr) + { + continue; + } + + LclVarDsc* dsc = m_compiler->lvaGetDesc(agg->LclNum); + if (!dsc->lvIsParam && !dsc->lvIsOSRLocal) + { + continue; + } + + JITDUMP("Marking fields of %s V%02u as needing read-back in scratch " FMT_BB "\n", + dsc->lvIsParam ? "parameter" : "OSR-local", agg->LclNum, block->bbNum); + + for (size_t i = 0; i < agg->Replacements.size(); i++) + { + Replacement& rep = agg->Replacements[i]; + rep.NeedsWriteBack = false; + if (m_liveness->IsReplacementLiveIn(block, agg->LclNum, (unsigned)i)) + { + rep.NeedsReadBack = true; + JITDUMP(" V%02u (%s) marked\n", rep.LclNum, rep.Description); + } + else + { + JITDUMP(" V%02u (%s) not marked (not live-in to scratch BB)\n", rep.LclNum, rep.Description); + } + } + } +} + //------------------------------------------------------------------------ // EndBlock: // Handle reaching the end of the currently started block by preparing @@ -1229,11 +1858,27 @@ void ReplaceVisitor::EndBlock() } else { + // We only mark fields as requiring read-back if they are + // live at the point where the stack local was written, so + // at first glance we would not expect this case to ever + // happen. However, it is possible that the field is live + // because it has a future struct use, in which case we may + // not need to insert any readbacks anywhere. For example, + // consider: + // + // V03 = CALL() // V03 is a struct with promoted V03.[000..008) + // CALL(struct V03) // V03.[000.008) marked as live here + // + // While V03.[000.008) gets marked for readback at the + // assignment, no readback is necessary at the location of + // the call argument, and it may die after that. + JITDUMP("Skipping reading back dead replacement V%02u.[%03u..%03u) -> V%02u near the end of " FMT_BB "\n", agg->LclNum, rep.Offset, rep.Offset + genTypeSize(rep.AccessType), rep.LclNum, m_currentBlock->bbNum); } + rep.NeedsReadBack = false; } @@ -1244,6 +1889,18 @@ void ReplaceVisitor::EndBlock() m_hasPendingReadBacks = false; } +//------------------------------------------------------------------------ +// PostOrderVisit: +// Visit a node in post-order and make necessary changes for promoted field +// uses. +// +// Parameters: +// use - The use edge +// user - The user +// +// Returns: +// Visitor result. +// Compiler::fgWalkResult ReplaceVisitor::PostOrderVisit(GenTree** use, GenTree* user) { GenTree* tree = *use; @@ -1338,16 +1995,13 @@ GenTree** ReplaceVisitor::InsertMidTreeReadBacksIfNecessary(GenTree** use) for (Replacement& rep : agg->Replacements) { - // TODO-CQ: We should ensure we do not mark dead fields as - // requiring readback. Currently it is handled by querying liveness - // as part of end-of-block readback insertion, but for these - // mid-tree readbacks we cannot query liveness information for - // arbitrary locals. if (!rep.NeedsReadBack) { continue; } + JITDUMP(" V%02.[%03u..%03u) -> V%02u\n", agg->LclNum, rep.Offset, genTypeSize(rep.AccessType), rep.LclNum); + rep.NeedsReadBack = false; GenTree* readBack = Promotion::CreateReadBack(m_compiler, agg->LclNum, rep); *use = @@ -1411,10 +2065,7 @@ void ReplaceVisitor::LoadStoreAroundCall(GenTreeCall* call, GenTree* user) GenTreeLclVarCommon* retBufLcl = retBufArg->GetNode()->AsLclVarCommon(); unsigned size = m_compiler->typGetObjLayout(call->gtRetClsHnd)->GetSize(); - if (MarkForReadBack(retBufLcl->GetLclNum(), retBufLcl->GetLclOffs(), size)) - { - JITDUMP("Retbuf has replacements that were marked for read back\n"); - } + MarkForReadBack(retBufLcl, size DEBUGARG("used as retbuf")); } } @@ -1548,9 +2199,9 @@ void ReplaceVisitor::ReplaceLocal(GenTree** use, GenTree* user) Replacement& rep = replacements[index]; assert(accessType == rep.AccessType); - JITDUMP(" ..replaced with promoted lcl V%02u\n", rep.LclNum); bool isDef = lcl->OperIsLocalStore(); + if (isDef) { *use = m_compiler->gtNewStoreLclVarNode(rep.LclNum, lcl->Data()); @@ -1573,6 +2224,7 @@ void ReplaceVisitor::ReplaceLocal(GenTree** use, GenTree* user) } else if (rep.NeedsReadBack) { + JITDUMP(" ..needs a read back\n"); *use = m_compiler->gtNewOperNode(GT_COMMA, (*use)->TypeGet(), Promotion::CreateReadBack(m_compiler, lclNum, rep), *use); rep.NeedsReadBack = false; @@ -1603,6 +2255,8 @@ void ReplaceVisitor::ReplaceLocal(GenTree** use, GenTree* user) m_compiler->lvaGetDesc(rep.LclNum)->lvRedefinedInEmbeddedStatement = true; } + JITDUMP(" ..replaced with V%02u\n", rep.LclNum); + m_madeChanges = true; } @@ -1714,18 +2368,19 @@ void ReplaceVisitor::WriteBackBefore(GenTree** use, unsigned lcl, unsigned offs, // back before their next use. // // Parameters: -// lcl - The struct local -// offs - The starting offset of the range in the struct local that needs to be read back from. -// size - The size of the range +// lcl - Local node. Its offset is the start of the range. +// size - The size of the range +// reason - The reason the readback is required // -bool ReplaceVisitor::MarkForReadBack(unsigned lcl, unsigned offs, unsigned size) +void ReplaceVisitor::MarkForReadBack(GenTreeLclVarCommon* lcl, unsigned size DEBUGARG(const char* reason)) { - if (m_aggregates[lcl] == nullptr) + if (m_aggregates[lcl->GetLclNum()] == nullptr) { - return false; + return; } - jitstd::vector& replacements = m_aggregates[lcl]->Replacements; + unsigned offs = lcl->GetLclOffs(); + jitstd::vector& replacements = m_aggregates[lcl->GetLclNum()]->Replacements; size_t index = Promotion::BinarySearch(replacements, offs); if ((ssize_t)index < 0) @@ -1737,20 +2392,37 @@ bool ReplaceVisitor::MarkForReadBack(unsigned lcl, unsigned offs, unsigned size) } } - bool any = false; unsigned end = offs + size; - while ((index < replacements.size()) && (replacements[index].Offset < end)) + if ((index >= replacements.size()) || (replacements[index].Offset >= end)) + { + // No overlap with any field. + return; + } + + StructDeaths deaths = m_liveness->GetDeathsForStructLocal(lcl); + JITDUMP("Fields of [%06u] in range [%03u..%03u) need to be read back: %s\n", Compiler::dspTreeID(lcl), offs, + offs + size, reason); + + do { - any = true; Replacement& rep = replacements[index]; assert(rep.Overlaps(offs, size)); - rep.NeedsReadBack = true; - rep.NeedsWriteBack = false; - m_hasPendingReadBacks = true; - index++; - } - return any; + if (deaths.IsReplacementDying((unsigned)index)) + { + JITDUMP(" V%02u (%s) not marked (is dying)\n", rep.LclNum, rep.Description); + } + else + { + rep.NeedsReadBack = true; + m_hasPendingReadBacks = true; + JITDUMP(" V%02u (%s) marked\n", rep.LclNum, rep.Description); + } + + rep.NeedsWriteBack = false; + + index++; + } while ((index < replacements.size()) && (replacements[index].Offset < end)); } //------------------------------------------------------------------------ @@ -1786,94 +2458,51 @@ PhaseStatus Promotion::Run() } } - unsigned numLocals = m_compiler->lvaCount; - -#ifdef DEBUG - if (m_compiler->verbose) - { - for (unsigned lcl = 0; lcl < m_compiler->lvaCount; lcl++) - { - LocalUses* uses = localsUse.GetUsesByLocal(lcl); - if (uses != nullptr) - { - uses->Dump(lcl); - } - } - } -#endif - // Pick promotions based on the use information we just collected. - bool anyReplacements = false; jitstd::vector aggregates(m_compiler->lvaCount, nullptr, m_compiler->getAllocator(CMK_Promotion)); - for (unsigned i = 0; i < numLocals; i++) + if (!localsUse.PickPromotions(aggregates)) { - LocalUses* uses = localsUse.GetUsesByLocal(i); - if (uses == nullptr) - { - continue; - } - - uses->PickPromotions(m_compiler, i, &aggregates[i]); + // No promotions picked. + return PhaseStatus::MODIFIED_NOTHING; + } - if (aggregates[i] == nullptr) + // Check for parameters and OSR locals that need to be read back on entry + // to the function. + for (AggregateInfo* agg : aggregates) + { + if (agg == nullptr) { continue; } - jitstd::vector& reps = aggregates[i]->Replacements; - - assert(reps.size() > 0); - anyReplacements = true; -#ifdef DEBUG - JITDUMP("V%02u promoted with %d replacements\n", i, (int)reps.size()); - for (const Replacement& rep : reps) - { - JITDUMP(" [%03u..%03u) promoted as %s V%02u\n", rep.Offset, rep.Offset + genTypeSize(rep.AccessType), - varTypeName(rep.AccessType), rep.LclNum); - } -#endif - - JITDUMP("Computing unpromoted remainder for V%02u\n", i); - StructSegments unpromotedParts = SignificantSegments(m_compiler, m_compiler->lvaGetDesc(i)->GetLayout()); - for (size_t i = 0; i < reps.size(); i++) - { - unpromotedParts.Subtract( - StructSegments::Segment(reps[i].Offset, reps[i].Offset + genTypeSize(reps[i].AccessType))); - } - - JITDUMP(" Remainder: "); - DBEXEC(m_compiler->verbose, unpromotedParts.Dump()); - JITDUMP("\n\n"); - - StructSegments::Segment unpromotedSegment; - if (unpromotedParts.CoveringSegment(&unpromotedSegment)) - { - aggregates[i]->UnpromotedMin = unpromotedSegment.Start; - aggregates[i]->UnpromotedMax = unpromotedSegment.End; - assert(unpromotedSegment.Start < unpromotedSegment.End); - } - else + LclVarDsc* dsc = m_compiler->lvaGetDesc(agg->LclNum); + if (dsc->lvIsParam || dsc->lvIsOSRLocal) { - // Aggregate is fully promoted, leave UnpromotedMin == UnpromotedMax to indicate this. + // We will need an initial readback. We create the scratch BB ahead + // of time so that we get correct liveness and mark the + // parameters/OSR-locals as requiring read-back as part of + // ReplaceVisitor::StartBlock when we get to the scratch block. + m_compiler->fgEnsureFirstBBisScratch(); + break; } } - if (!anyReplacements) - { - return PhaseStatus::MODIFIED_NOTHING; - } - // Compute liveness for the fields and remainders. PromotionLiveness liveness(m_compiler, aggregates); liveness.Run(); JITDUMP("Making replacements\n\n"); + // Make all replacements we decided on. ReplaceVisitor replacer(this, aggregates, &liveness); for (BasicBlock* bb : m_compiler->Blocks()) { replacer.StartBlock(bb); + JITDUMP("\nReplacing in "); + DBEXEC(m_compiler->verbose, bb->dspBlockHeader(m_compiler)); + JITDUMP("\n"); + for (Statement* stmt : bb->Statements()) { DISPSTMT(stmt); @@ -1901,29 +2530,24 @@ PhaseStatus Promotion::Run() replacer.EndBlock(); } - // Insert initial IR to read arguments/OSR locals into replacement locals, - // and add necessary explicit zeroing. + // Add necessary explicit zeroing for some locals. Statement* prevStmt = nullptr; - for (unsigned lclNum = 0; lclNum < numLocals; lclNum++) + for (AggregateInfo* agg : aggregates) { - if (aggregates[lclNum] == nullptr) + if (agg == nullptr) { continue; } - LclVarDsc* dsc = m_compiler->lvaGetDesc(lclNum); - if (dsc->lvIsParam || dsc->lvIsOSRLocal) - { - InsertInitialReadBack(lclNum, aggregates[lclNum]->Replacements, &prevStmt); - } - else if (dsc->lvSuppressedZeroInit) + LclVarDsc* dsc = m_compiler->lvaGetDesc(agg->LclNum); + if (dsc->lvSuppressedZeroInit) { // We may have suppressed inserting an explicit zero init based on the // assumption that the entire local will be zero inited in the prolog. // Now that we are promoting some fields that assumption may be // invalidated for those fields, and we may need to insert explicit // zero inits again. - ExplicitlyZeroInitReplacementLocals(lclNum, aggregates[lclNum]->Replacements, &prevStmt); + ExplicitlyZeroInitReplacementLocals(agg->LclNum, agg->Replacements, &prevStmt); } } @@ -1962,27 +2586,6 @@ bool Promotion::IsCandidateForPhysicalPromotion(LclVarDsc* dsc) return (dsc->TypeGet() == TYP_STRUCT) && !dsc->lvPromoted && !dsc->IsAddressExposed(); } -//------------------------------------------------------------------------ -// Promotion::InsertInitialReadBack: -// Insert IR to initially read a struct local's value into its promoted field locals. -// -// Parameters: -// lclNum - The struct local -// replacements - Replacements for the struct local -// prevStmt - [in, out] Previous statement to insert after -// -void Promotion::InsertInitialReadBack(unsigned lclNum, - const jitstd::vector& replacements, - Statement** prevStmt) -{ - for (unsigned i = 0; i < replacements.size(); i++) - { - const Replacement& rep = replacements[i]; - GenTree* readBack = CreateReadBack(m_compiler, lclNum, rep); - InsertInitStatement(prevStmt, readBack); - } -} - //------------------------------------------------------------------------ // Promotion::ExplicitlyZeroInitReplacementLocals: // Insert IR to zero out replacement locals if necessary. diff --git a/src/coreclr/jit/promotion.h b/src/coreclr/jit/promotion.h index 2eb279c17a308..416d761fe1bb8 100644 --- a/src/coreclr/jit/promotion.h +++ b/src/coreclr/jit/promotion.h @@ -12,7 +12,7 @@ struct Replacement { unsigned Offset; var_types AccessType; - unsigned LclNum; + unsigned LclNum = BAD_VAR_NUM; // Is the replacement local (given by LclNum) fresher than the value in the struct local? bool NeedsWriteBack = true; // Is the value in the struct local fresher than the replacement local? @@ -21,16 +21,10 @@ struct Replacement // back before transferring control if necessary. bool NeedsReadBack = false; #ifdef DEBUG - const char* Description; + const char* Description = ""; #endif - Replacement(unsigned offset, var_types accessType, unsigned lclNum DEBUGARG(const char* description)) - : Offset(offset) - , AccessType(accessType) - , LclNum(lclNum) -#ifdef DEBUG - , Description(description) -#endif + Replacement(unsigned offset, var_types accessType) : Offset(offset), AccessType(accessType) { } @@ -118,7 +112,6 @@ class Promotion static StructSegments SignificantSegments(Compiler* compiler, ClassLayout* layout DEBUGARG(FixedBitVect** bitVectRepr = nullptr)); - void InsertInitialReadBack(unsigned lclNum, const jitstd::vector& replacements, Statement** prevStmt); void ExplicitlyZeroInitReplacementLocals(unsigned lclNum, const jitstd::vector& replacements, Statement** prevStmt); @@ -226,6 +219,7 @@ class PromotionLiveness } void Run(); + bool IsReplacementLiveIn(BasicBlock* bb, unsigned structLcl, unsigned replacement); bool IsReplacementLiveOut(BasicBlock* bb, unsigned structLcl, unsigned replacement); StructDeaths GetDeathsForStructLocal(GenTreeLclVarCommon* use); @@ -280,11 +274,7 @@ class ReplaceVisitor : public GenTreeVisitor return m_mayHaveForwardSub; } - void StartBlock(BasicBlock* block) - { - m_currentBlock = block; - } - + void StartBlock(BasicBlock* block); void EndBlock(); void StartStatement(Statement* stmt) @@ -305,7 +295,7 @@ class ReplaceVisitor : public GenTreeVisitor void CheckForwardSubForLastUse(unsigned lclNum); void StoreBeforeReturn(GenTreeUnOp* ret); void WriteBackBefore(GenTree** use, unsigned lcl, unsigned offs, unsigned size); - bool MarkForReadBack(unsigned lcl, unsigned offs, unsigned size); + void MarkForReadBack(GenTreeLclVarCommon* lcl, unsigned size DEBUGARG(const char* reason)); void HandleStore(GenTree** use, GenTree* user); bool OverlappingReplacements(GenTreeLclVarCommon* lcl, diff --git a/src/coreclr/jit/promotiondecomposition.cpp b/src/coreclr/jit/promotiondecomposition.cpp index 9be8ed9c8b095..3bdc88c5a4b3f 100644 --- a/src/coreclr/jit/promotiondecomposition.cpp +++ b/src/coreclr/jit/promotiondecomposition.cpp @@ -1202,10 +1202,7 @@ void ReplaceVisitor::HandleStore(GenTree** use, GenTree* user) { GenTreeLclVarCommon* lclStore = store->AsLclVarCommon(); unsigned size = lclStore->GetLayout(m_compiler)->GetSize(); - if (MarkForReadBack(lclStore->GetLclNum(), lclStore->GetLclOffs(), size)) - { - JITDUMP("Marked store destination replacements to be read back (could not decompose this store)\n"); - } + MarkForReadBack(lclStore, size DEBUGARG("cannot decompose store")); } } } diff --git a/src/coreclr/jit/promotionliveness.cpp b/src/coreclr/jit/promotionliveness.cpp index 71ac5a96b3b8d..43b3722614489 100644 --- a/src/coreclr/jit/promotionliveness.cpp +++ b/src/coreclr/jit/promotionliveness.cpp @@ -190,7 +190,7 @@ void PromotionLiveness::ComputeUseDefSets() // useSet - The use set to mark in. // defSet - The def set to mark in. // -void PromotionLiveness::MarkUseDef(GenTreeLclVarCommon* lcl, BitSetShortLongRep& useSet, BitSetShortLongRep& defSet) +void PromotionLiveness::MarkUseDef(GenTreeLclVarCommon* lcl, BitVec& useSet, BitVec& defSet) { AggregateInfo* agg = m_aggregates[lcl->GetLclNum()]; if (agg == nullptr) @@ -688,8 +688,19 @@ void PromotionLiveness::FillInLiveness(BitVec& life, BitVec volatileVars, GenTre if (lcl->OperIs(GT_LCL_ADDR)) { // Retbuf -- these are definitions but we do not know of how much. - // We never mark them as dead and we never treat them as killing anything. - assert(isDef); + // We never treat them as killing anything, but we do store liveness information for them. + BitVecTraits aggTraits(1 + (unsigned)agg->Replacements.size(), m_compiler); + BitVec aggDeaths(BitVecOps::MakeEmpty(&aggTraits)); + // Copy preexisting liveness information. + for (size_t i = 0; i <= agg->Replacements.size(); i++) + { + unsigned varIndex = baseIndex + (unsigned)i; + if (!BitVecOps::IsMember(m_bvTraits, life, varIndex)) + { + BitVecOps::AddElemD(&aggTraits, aggDeaths, (unsigned)i); + } + } + m_aggDeaths.Set(lcl, aggDeaths); return; } @@ -747,6 +758,24 @@ void PromotionLiveness::FillInLiveness(BitVec& life, BitVec volatileVars, GenTre } } +//------------------------------------------------------------------------ +// IsReplacementLiveIn: +// Check if a replacement field is live at the start of a basic block. +// +// Parameters: +// structLcl - The struct (base) local +// replacementIndex - Index of the replacement +// +// Returns: +// True if the field is in the live-in set. +// +bool PromotionLiveness::IsReplacementLiveIn(BasicBlock* bb, unsigned structLcl, unsigned replacementIndex) +{ + BitVec liveIn = m_bbInfo[bb->bbNum].LiveIn; + unsigned baseIndex = m_structLclToTrackedIndex[structLcl]; + return BitVecOps::IsMember(m_bvTraits, liveIn, baseIndex + 1 + replacementIndex); +} + //------------------------------------------------------------------------ // IsReplacementLiveOut: // Check if a replacement field is live at the end of a basic block. @@ -778,7 +807,8 @@ bool PromotionLiveness::IsReplacementLiveOut(BasicBlock* bb, unsigned structLcl, // StructDeaths PromotionLiveness::GetDeathsForStructLocal(GenTreeLclVarCommon* lcl) { - assert(lcl->OperIsLocal() && lcl->TypeIs(TYP_STRUCT) && (m_aggregates[lcl->GetLclNum()] != nullptr)); + assert((lcl->TypeIs(TYP_STRUCT) || (lcl->OperIs(GT_LCL_ADDR) && ((lcl->gtFlags & GTF_VAR_DEF) != 0))) && + (m_aggregates[lcl->GetLclNum()] != nullptr)); BitVec aggDeaths; bool found = m_aggDeaths.Lookup(lcl, &aggDeaths); assert(found); diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index c2cdf1613aaf8..edaae4c781177 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -112,7 +112,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 4948020c84965..bb2afb85cf22b 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -242,6 +242,7 @@ The .NET Foundation licenses this file to you under the MIT license. + diff --git a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S index 7faf58c75c45e..c2247d8be5e24 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S +++ b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S @@ -45,6 +45,7 @@ LOCAL_LABEL(ProbeLoop): ret NESTED_END RhpStackProbe, _TEXT +#ifndef TARGET_ANDROID NESTED_ENTRY RhpGetInlinedThreadStaticBase, _TEXT, NoHandler // On exit: // rax - the thread static base for the given type @@ -61,4 +62,4 @@ NESTED_ENTRY RhpGetInlinedThreadStaticBase, _TEXT, NoHandler // return it ret NESTED_END RhpGetInlinedThreadStaticBase, _TEXT - +#endif diff --git a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S index 6c70614f38136..34af83ccf0b98 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S +++ b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S @@ -4,6 +4,7 @@ #include #include "AsmOffsets.inc" +#ifndef TARGET_ANDROID NESTED_ENTRY RhpGetInlinedThreadStaticBase, _TEXT, NoHandler // On exit: // x0 - the thread static base for the given type @@ -22,3 +23,4 @@ HaveValue: ret NESTED_END RhpGetInlinedThreadStaticBase, _TEXT +#endif diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 1e3c312188395..39ee2daf5bf8f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -253,9 +253,6 @@ System\Runtime\InteropServices\Variant.cs - - Interop\Windows\Kernel32\Interop.GetCurrentThreadId.cs - Interop\Windows\Kernel32\Interop.IsDebuggerPresent.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs index 0f6614fd3ca7e..7f0fa52f98825 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs @@ -24,7 +24,8 @@ public static bool IsAttached { get { - return _isDebuggerAttached; + // Managed debugger is never attached because we don't have one + return false; } } @@ -38,11 +39,6 @@ public static void NotifyOfCrossThreadDependency() // nothing to do...yet } -#pragma warning disable 649 // Suppress compiler warning about _isDebuggerAttached never being assigned to. - // _isDebuggerAttached: Do not remove: This field is known to the debugger and modified directly by the debugger. - private static bool _isDebuggerAttached; -#pragma warning restore 649 - /// /// Constants representing the importance level of messages to be logged. /// diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index f831e74c904a8..5c3eb76470fa3 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1236,22 +1236,6 @@ private void getEHinfo(CORINFO_METHOD_STRUCT_* ftn, uint EHnumber, ref CORINFO_E return ObjectToHandle(m.OwningType); } - private CORINFO_MODULE_STRUCT_* getMethodModule(CORINFO_METHOD_STRUCT_* method) - { - MethodDesc m = HandleToObject(method); - if (m is UnboxingMethodDesc unboxingMethodDesc) - { - m = unboxingMethodDesc.Target; - } - - MethodIL methodIL = _compilation.GetMethodIL(m); - if (methodIL == null) - { - return null; - } - return ObjectToHandle(methodIL); - } - private bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info) { // Initialize OUT fields @@ -1565,8 +1549,6 @@ private static CorInfoCallConvExtension ToCorInfoCallConvExtension(UnmanagedCall private bool satisfiesMethodConstraints(CORINFO_CLASS_STRUCT_* parent, CORINFO_METHOD_STRUCT_* method) { throw new NotImplementedException("satisfiesMethodConstraints"); } - private bool isCompatibleDelegate(CORINFO_CLASS_STRUCT_* objCls, CORINFO_CLASS_STRUCT_* methodParentCls, CORINFO_METHOD_STRUCT_* method, CORINFO_CLASS_STRUCT_* delegateCls, ref bool pfIsOpenDelegate) - { throw new NotImplementedException("isCompatibleDelegate"); } private void setPatchpointInfo(PatchpointInfo* patchpointInfo) { throw new NotImplementedException("setPatchpointInfo"); } private PatchpointInfo* getOSRInfo(ref uint ilOffset) @@ -1813,12 +1795,6 @@ private void resolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken) pResolvedToken.cbMethodSpec = 0; } - private bool tryResolveToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken) - { - resolveToken(ref pResolvedToken); - return true; - } - private void findSig(CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEXT_STRUCT* context, CORINFO_SIG_INFO* sig) { var methodIL = HandleToObject(module); @@ -1865,11 +1841,6 @@ private static CorInfoCanSkipVerificationResult canSkipVerification(CORINFO_MODU return CorInfoCanSkipVerificationResult.CORINFO_VERIFICATION_CAN_SKIP; } - private bool isValidToken(CORINFO_MODULE_STRUCT_* module, uint metaTOK) - { throw new NotImplementedException("isValidToken"); } - private bool isValidStringRef(CORINFO_MODULE_STRUCT_* module, uint metaTOK) - { throw new NotImplementedException("isValidStringRef"); } - private int getStringLiteral(CORINFO_MODULE_STRUCT_* module, uint metaTOK, char* buffer, int size, int startIndex) { Debug.Assert(size >= 0); @@ -2675,58 +2646,6 @@ private TypeCompareState compareTypesForEquality(CORINFO_CLASS_STRUCT_* cls1, CO }; } - private CORINFO_CLASS_STRUCT_* mergeClasses(CORINFO_CLASS_STRUCT_* cls1, CORINFO_CLASS_STRUCT_* cls2) - { - TypeDesc type1 = HandleToObject(cls1); - TypeDesc type2 = HandleToObject(cls2); - - TypeDesc merged = TypeExtensions.MergeTypesToCommonParent(type1, type2); - -#if DEBUG - // Make sure the merge is reflexive in the cases we "support". - TypeDesc reflexive = TypeExtensions.MergeTypesToCommonParent(type2, type1); - - // If both sides are classes than either they have a common non-interface parent (in which case it is - // reflexive) - // OR they share a common interface, and it can be order dependent (if they share multiple interfaces - // in common) - if (!type1.IsInterface && !type2.IsInterface) - { - if (merged.IsInterface) - { - Debug.Assert(reflexive.IsInterface); - } - else - { - Debug.Assert(merged == reflexive); - } - } - // Both results must either be interfaces or classes. They cannot be mixed. - Debug.Assert(merged.IsInterface == reflexive.IsInterface); - - // If the result of the merge was a class, then the result of the reflexive merge was the same class. - if (!merged.IsInterface) - { - Debug.Assert(merged == reflexive); - } - - // If both sides are arrays, then the result is either an array or g_pArrayClass. The above is - // actually true for reference types as well, but it is a little excessive to deal with. - if (type1.IsArray && type2.IsArray) - { - TypeDesc arrayClass = _compilation.TypeSystemContext.GetWellKnownType(WellKnownType.Array); - Debug.Assert((merged.IsArray && reflexive.IsArray) - || ((merged == arrayClass) && (reflexive == arrayClass))); - } - - // The results must always be assignable - Debug.Assert(type1.CanCastTo(merged) && type2.CanCastTo(merged) && type1.CanCastTo(reflexive) - && type2.CanCastTo(reflexive)); -#endif - - return ObjectToHandle(merged); - } - private bool isMoreSpecificType(CORINFO_CLASS_STRUCT_* cls1, CORINFO_CLASS_STRUCT_* cls2) { TypeDesc type1 = HandleToObject(cls1); @@ -2802,9 +2721,6 @@ private CorInfoType getChildType(CORINFO_CLASS_STRUCT_* clsHnd, CORINFO_CLASS_ST return result; } - private bool satisfiesClassConstraints(CORINFO_CLASS_STRUCT_* cls) - { throw new NotImplementedException("satisfiesClassConstraints"); } - private bool isSDArray(CORINFO_CLASS_STRUCT_* cls) { var td = HandleToObject(cls); @@ -3228,9 +3144,6 @@ private uint getMethodHash(CORINFO_METHOD_STRUCT_* ftn) return (uint)HandleToObject(ftn).GetHashCode(); } - private UIntPtr findNameOfToken(CORINFO_MODULE_STRUCT_* moduleHandle, mdToken token, byte* szFQName, UIntPtr FQNameCapacity) - { throw new NotImplementedException("findNameOfToken"); } - private bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_STRUCT_* structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) { TypeDesc typeDesc = HandleToObject(structHnd); @@ -3253,8 +3166,6 @@ private uint getRISCV64PassStructInRegisterFlags(CORINFO_CLASS_STRUCT_* cls) private uint getThreadTLSIndex(ref void* ppIndirection) { throw new NotImplementedException("getThreadTLSIndex"); } - private void* getInlinedCallFrameVptr(ref void* ppIndirection) - { throw new NotImplementedException("getInlinedCallFrameVptr"); } private Dictionary _helperCache = new Dictionary(); private void* getHelperFtn(CorInfoHelpFunc ftnNum, ref void* ppIndirection) @@ -3369,10 +3280,6 @@ private CORINFO_CONST_LOOKUP CreateConstLookupToSymbol(ISymbolNode symbol) return constLookup; } - private bool canAccessFamily(CORINFO_METHOD_STRUCT_* hCaller, CORINFO_CLASS_STRUCT_* hInstanceType) - { throw new NotImplementedException("canAccessFamily"); } - private bool isRIDClassDomainID(CORINFO_CLASS_STRUCT_* cls) - { throw new NotImplementedException("isRIDClassDomainID"); } private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirection) { throw new NotImplementedException("getClassDomainID"); } @@ -3738,11 +3645,8 @@ private static RelocType GetRelocType(TargetArchitecture targetArchitecture, ush } } - private void recordRelocation(void* location, void* locationRW, void* target, ushort fRelocType, ushort slotNum, int addlDelta) + private void recordRelocation(void* location, void* locationRW, void* target, ushort fRelocType, int addlDelta) { - // slotNum is not used - Debug.Assert(slotNum == 0); - int relocOffset; BlockType locationBlock = findKnownBlock(location, out relocOffset); Debug.Assert(locationBlock != BlockType.Unknown, "BlockType.Unknown not expected"); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 772a97e0cfb82..b31a87daec7c7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -186,21 +186,6 @@ private static void _getEHinfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_M } } - [UnmanagedCallersOnly] - private static CORINFO_MODULE_STRUCT_* _getMethodModule(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method) - { - var _this = GetThis(thisHandle); - try - { - return _this.getMethodModule(method); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static void _getMethodVTableOffset(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method, uint* offsetOfIndirection, uint* offsetAfterIndirection, bool* isRelative) { @@ -349,21 +334,6 @@ private static byte _satisfiesMethodConstraints(IntPtr thisHandle, IntPtr* ppExc } } - [UnmanagedCallersOnly] - private static byte _isCompatibleDelegate(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* objCls, CORINFO_CLASS_STRUCT_* methodParentCls, CORINFO_METHOD_STRUCT_* method, CORINFO_CLASS_STRUCT_* delegateCls, bool* pfIsOpenDelegate) - { - var _this = GetThis(thisHandle); - try - { - return _this.isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, ref *pfIsOpenDelegate) ? (byte)1 : (byte)0; - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static void _methodMustBeLoadedBeforeCodeIsRun(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method) { @@ -450,21 +420,6 @@ private static void _resolveToken(IntPtr thisHandle, IntPtr* ppException, CORINF } } - [UnmanagedCallersOnly] - private static byte _tryResolveToken(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken) - { - var _this = GetThis(thisHandle); - try - { - return _this.tryResolveToken(ref *pResolvedToken) ? (byte)1 : (byte)0; - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static void _findSig(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEXT_STRUCT* context, CORINFO_SIG_INFO* sig) { @@ -508,36 +463,6 @@ private static void _findCallSiteSig(IntPtr thisHandle, IntPtr* ppException, COR } } - [UnmanagedCallersOnly] - private static byte _isValidToken(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK) - { - var _this = GetThis(thisHandle); - try - { - return _this.isValidToken(module, metaTOK) ? (byte)1 : (byte)0; - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - - [UnmanagedCallersOnly] - private static byte _isValidStringRef(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK) - { - var _this = GetThis(thisHandle); - try - { - return _this.isValidStringRef(module, metaTOK) ? (byte)1 : (byte)0; - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static int _getStringLiteral(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, char* buffer, int bufferSize, int startIndex) { @@ -1225,21 +1150,6 @@ private static TypeCompareState _compareTypesForEquality(IntPtr thisHandle, IntP } } - [UnmanagedCallersOnly] - private static CORINFO_CLASS_STRUCT_* _mergeClasses(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls1, CORINFO_CLASS_STRUCT_* cls2) - { - var _this = GetThis(thisHandle); - try - { - return _this.mergeClasses(cls1, cls2); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static byte _isMoreSpecificType(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls1, CORINFO_CLASS_STRUCT_* cls2) { @@ -1300,21 +1210,6 @@ private static CorInfoType _getChildType(IntPtr thisHandle, IntPtr* ppException, } } - [UnmanagedCallersOnly] - private static byte _satisfiesClassConstraints(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) - { - var _this = GetThis(thisHandle); - try - { - return _this.satisfiesClassConstraints(cls) ? (byte)1 : (byte)0; - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static byte _isSDArray(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) { @@ -1816,21 +1711,6 @@ private static uint _getMethodHash(IntPtr thisHandle, IntPtr* ppException, CORIN } } - [UnmanagedCallersOnly] - private static UIntPtr _findNameOfToken(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* moduleHandle, mdToken token, byte* szFQName, UIntPtr FQNameCapacity) - { - var _this = GetThis(thisHandle); - try - { - return _this.findNameOfToken(moduleHandle, token, szFQName, FQNameCapacity); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static byte _getSystemVAmd64PassStructInRegisterDescriptor(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) { @@ -1891,21 +1771,6 @@ private static uint _getThreadTLSIndex(IntPtr thisHandle, IntPtr* ppException, v } } - [UnmanagedCallersOnly] - private static void* _getInlinedCallFrameVptr(IntPtr thisHandle, IntPtr* ppException, void** ppIndirection) - { - var _this = GetThis(thisHandle); - try - { - return _this.getInlinedCallFrameVptr(ref *ppIndirection); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static int* _getAddrOfCaptureThreadGlobal(IntPtr thisHandle, IntPtr* ppException, void** ppIndirection) { @@ -2169,36 +2034,6 @@ private static void _getCallInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO } } - [UnmanagedCallersOnly] - private static byte _canAccessFamily(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* hCaller, CORINFO_CLASS_STRUCT_* hInstanceType) - { - var _this = GetThis(thisHandle); - try - { - return _this.canAccessFamily(hCaller, hInstanceType) ? (byte)1 : (byte)0; - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - - [UnmanagedCallersOnly] - private static byte _isRIDClassDomainID(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) - { - var _this = GetThis(thisHandle); - try - { - return _this.isRIDClassDomainID(cls) ? (byte)1 : (byte)0; - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static uint _getClassDomainID(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, void** ppIndirection) { @@ -2596,12 +2431,12 @@ private static void _recordCallSite(IntPtr thisHandle, IntPtr* ppException, uint } [UnmanagedCallersOnly] - private static void _recordRelocation(IntPtr thisHandle, IntPtr* ppException, void* location, void* locationRW, void* target, ushort fRelocType, ushort slotNum, int addlDelta) + private static void _recordRelocation(IntPtr thisHandle, IntPtr* ppException, void* location, void* locationRW, void* target, ushort fRelocType, int addlDelta) { var _this = GetThis(thisHandle); try { - _this.recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); + _this.recordRelocation(location, locationRW, target, fRelocType, addlDelta); } catch (Exception ex) { @@ -2657,7 +2492,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 179); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 168); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2671,173 +2506,162 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[9] = (delegate* unmanaged)&_reportTailCallDecision; callbacks[10] = (delegate* unmanaged)&_getEHinfo; callbacks[11] = (delegate* unmanaged)&_getMethodClass; - callbacks[12] = (delegate* unmanaged)&_getMethodModule; - callbacks[13] = (delegate* unmanaged)&_getMethodVTableOffset; - callbacks[14] = (delegate* unmanaged)&_resolveVirtualMethod; - callbacks[15] = (delegate* unmanaged)&_getUnboxedEntry; - callbacks[16] = (delegate* unmanaged)&_getDefaultComparerClass; - callbacks[17] = (delegate* unmanaged)&_getDefaultEqualityComparerClass; - callbacks[18] = (delegate* unmanaged)&_expandRawHandleIntrinsic; - callbacks[19] = (delegate* unmanaged)&_isIntrinsicType; - callbacks[20] = (delegate* unmanaged)&_getUnmanagedCallConv; - callbacks[21] = (delegate* unmanaged)&_pInvokeMarshalingRequired; - callbacks[22] = (delegate* unmanaged)&_satisfiesMethodConstraints; - callbacks[23] = (delegate* unmanaged)&_isCompatibleDelegate; - callbacks[24] = (delegate* unmanaged)&_methodMustBeLoadedBeforeCodeIsRun; - callbacks[25] = (delegate* unmanaged)&_mapMethodDeclToMethodImpl; - callbacks[26] = (delegate* unmanaged)&_getGSCookie; - callbacks[27] = (delegate* unmanaged)&_setPatchpointInfo; - callbacks[28] = (delegate* unmanaged)&_getOSRInfo; - callbacks[29] = (delegate* unmanaged)&_resolveToken; - callbacks[30] = (delegate* unmanaged)&_tryResolveToken; - callbacks[31] = (delegate* unmanaged)&_findSig; - callbacks[32] = (delegate* unmanaged)&_findCallSiteSig; - callbacks[33] = (delegate* unmanaged)&_getTokenTypeAsHandle; - callbacks[34] = (delegate* unmanaged)&_isValidToken; - callbacks[35] = (delegate* unmanaged)&_isValidStringRef; - callbacks[36] = (delegate* unmanaged)&_getStringLiteral; - callbacks[37] = (delegate* unmanaged)&_printObjectDescription; - callbacks[38] = (delegate* unmanaged)&_asCorInfoType; - callbacks[39] = (delegate* unmanaged)&_getClassNameFromMetadata; - callbacks[40] = (delegate* unmanaged)&_getTypeInstantiationArgument; - callbacks[41] = (delegate* unmanaged)&_printClassName; - callbacks[42] = (delegate* unmanaged)&_isValueClass; - callbacks[43] = (delegate* unmanaged)&_canInlineTypeCheck; - callbacks[44] = (delegate* unmanaged)&_getClassAttribs; - callbacks[45] = (delegate* unmanaged)&_getClassModule; - callbacks[46] = (delegate* unmanaged)&_getModuleAssembly; - callbacks[47] = (delegate* unmanaged)&_getAssemblyName; - callbacks[48] = (delegate* unmanaged)&_LongLifetimeMalloc; - callbacks[49] = (delegate* unmanaged)&_LongLifetimeFree; - callbacks[50] = (delegate* unmanaged)&_getClassModuleIdForStatics; - callbacks[51] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; - callbacks[52] = (delegate* unmanaged)&_getStaticBaseAddress; - callbacks[53] = (delegate* unmanaged)&_getClassSize; - callbacks[54] = (delegate* unmanaged)&_getHeapClassSize; - callbacks[55] = (delegate* unmanaged)&_canAllocateOnStack; - callbacks[56] = (delegate* unmanaged)&_getClassAlignmentRequirement; - callbacks[57] = (delegate* unmanaged)&_getClassGClayout; - callbacks[58] = (delegate* unmanaged)&_getClassNumInstanceFields; - callbacks[59] = (delegate* unmanaged)&_getFieldInClass; - callbacks[60] = (delegate* unmanaged)&_checkMethodModifier; - callbacks[61] = (delegate* unmanaged)&_getNewHelper; - callbacks[62] = (delegate* unmanaged)&_getNewArrHelper; - callbacks[63] = (delegate* unmanaged)&_getCastingHelper; - callbacks[64] = (delegate* unmanaged)&_getSharedCCtorHelper; - callbacks[65] = (delegate* unmanaged)&_getTypeForBox; - callbacks[66] = (delegate* unmanaged)&_getBoxHelper; - callbacks[67] = (delegate* unmanaged)&_getUnBoxHelper; - callbacks[68] = (delegate* unmanaged)&_getRuntimeTypePointer; - callbacks[69] = (delegate* unmanaged)&_isObjectImmutable; - callbacks[70] = (delegate* unmanaged)&_getStringChar; - callbacks[71] = (delegate* unmanaged)&_getObjectType; - callbacks[72] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[73] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; - callbacks[74] = (delegate* unmanaged)&_initClass; - callbacks[75] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; - callbacks[76] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[77] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[78] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[79] = (delegate* unmanaged)&_canCast; - callbacks[80] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[81] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[82] = (delegate* unmanaged)&_mergeClasses; - callbacks[83] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[84] = (delegate* unmanaged)&_isEnum; - callbacks[85] = (delegate* unmanaged)&_getParentType; - callbacks[86] = (delegate* unmanaged)&_getChildType; - callbacks[87] = (delegate* unmanaged)&_satisfiesClassConstraints; - callbacks[88] = (delegate* unmanaged)&_isSDArray; - callbacks[89] = (delegate* unmanaged)&_getArrayRank; - callbacks[90] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[91] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[92] = (delegate* unmanaged)&_canAccessClass; - callbacks[93] = (delegate* unmanaged)&_printFieldName; - callbacks[94] = (delegate* unmanaged)&_getFieldClass; - callbacks[95] = (delegate* unmanaged)&_getFieldType; - callbacks[96] = (delegate* unmanaged)&_getFieldOffset; - callbacks[97] = (delegate* unmanaged)&_getFieldInfo; - callbacks[98] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[99] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; - callbacks[100] = (delegate* unmanaged)&_isFieldStatic; - callbacks[101] = (delegate* unmanaged)&_getArrayOrStringLength; - callbacks[102] = (delegate* unmanaged)&_getBoundaries; - callbacks[103] = (delegate* unmanaged)&_setBoundaries; - callbacks[104] = (delegate* unmanaged)&_getVars; - callbacks[105] = (delegate* unmanaged)&_setVars; - callbacks[106] = (delegate* unmanaged)&_reportRichMappings; - callbacks[107] = (delegate* unmanaged)&_allocateArray; - callbacks[108] = (delegate* unmanaged)&_freeArray; - callbacks[109] = (delegate* unmanaged)&_getArgNext; - callbacks[110] = (delegate* unmanaged)&_getArgType; - callbacks[111] = (delegate* unmanaged)&_getExactClasses; - callbacks[112] = (delegate* unmanaged)&_getArgClass; - callbacks[113] = (delegate* unmanaged)&_getHFAType; - callbacks[114] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[115] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[116] = (delegate* unmanaged)&_getEEInfo; - callbacks[117] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[118] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[119] = (delegate* unmanaged)&_printMethodName; - callbacks[120] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[121] = (delegate* unmanaged)&_getMethodHash; - callbacks[122] = (delegate* unmanaged)&_findNameOfToken; - callbacks[123] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[124] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[125] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; - callbacks[126] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[127] = (delegate* unmanaged)&_getInlinedCallFrameVptr; - callbacks[128] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[129] = (delegate* unmanaged)&_getHelperFtn; - callbacks[130] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[131] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[132] = (delegate* unmanaged)&_getMethodSync; - callbacks[133] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[134] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[135] = (delegate* unmanaged)&_embedClassHandle; - callbacks[136] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[137] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[138] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[139] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[140] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[141] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[142] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[143] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[144] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[145] = (delegate* unmanaged)&_getCallInfo; - callbacks[146] = (delegate* unmanaged)&_canAccessFamily; - callbacks[147] = (delegate* unmanaged)&_isRIDClassDomainID; - callbacks[148] = (delegate* unmanaged)&_getClassDomainID; - callbacks[149] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[150] = (delegate* unmanaged)&_getObjectContent; - callbacks[151] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[152] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[153] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[154] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[155] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[156] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[157] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[158] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[159] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[160] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[161] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[162] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[163] = (delegate* unmanaged)&_allocMem; - callbacks[164] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[165] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[166] = (delegate* unmanaged)&_allocGCInfo; - callbacks[167] = (delegate* unmanaged)&_setEHcount; - callbacks[168] = (delegate* unmanaged)&_setEHinfo; - callbacks[169] = (delegate* unmanaged)&_logMsg; - callbacks[170] = (delegate* unmanaged)&_doAssert; - callbacks[171] = (delegate* unmanaged)&_reportFatalError; - callbacks[172] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[173] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[174] = (delegate* unmanaged)&_recordCallSite; - callbacks[175] = (delegate* unmanaged)&_recordRelocation; - callbacks[176] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[177] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[178] = (delegate* unmanaged)&_getJitFlags; + callbacks[12] = (delegate* unmanaged)&_getMethodVTableOffset; + callbacks[13] = (delegate* unmanaged)&_resolveVirtualMethod; + callbacks[14] = (delegate* unmanaged)&_getUnboxedEntry; + callbacks[15] = (delegate* unmanaged)&_getDefaultComparerClass; + callbacks[16] = (delegate* unmanaged)&_getDefaultEqualityComparerClass; + callbacks[17] = (delegate* unmanaged)&_expandRawHandleIntrinsic; + callbacks[18] = (delegate* unmanaged)&_isIntrinsicType; + callbacks[19] = (delegate* unmanaged)&_getUnmanagedCallConv; + callbacks[20] = (delegate* unmanaged)&_pInvokeMarshalingRequired; + callbacks[21] = (delegate* unmanaged)&_satisfiesMethodConstraints; + callbacks[22] = (delegate* unmanaged)&_methodMustBeLoadedBeforeCodeIsRun; + callbacks[23] = (delegate* unmanaged)&_mapMethodDeclToMethodImpl; + callbacks[24] = (delegate* unmanaged)&_getGSCookie; + callbacks[25] = (delegate* unmanaged)&_setPatchpointInfo; + callbacks[26] = (delegate* unmanaged)&_getOSRInfo; + callbacks[27] = (delegate* unmanaged)&_resolveToken; + callbacks[28] = (delegate* unmanaged)&_findSig; + callbacks[29] = (delegate* unmanaged)&_findCallSiteSig; + callbacks[30] = (delegate* unmanaged)&_getTokenTypeAsHandle; + callbacks[31] = (delegate* unmanaged)&_getStringLiteral; + callbacks[32] = (delegate* unmanaged)&_printObjectDescription; + callbacks[33] = (delegate* unmanaged)&_asCorInfoType; + callbacks[34] = (delegate* unmanaged)&_getClassNameFromMetadata; + callbacks[35] = (delegate* unmanaged)&_getTypeInstantiationArgument; + callbacks[36] = (delegate* unmanaged)&_printClassName; + callbacks[37] = (delegate* unmanaged)&_isValueClass; + callbacks[38] = (delegate* unmanaged)&_canInlineTypeCheck; + callbacks[39] = (delegate* unmanaged)&_getClassAttribs; + callbacks[40] = (delegate* unmanaged)&_getClassModule; + callbacks[41] = (delegate* unmanaged)&_getModuleAssembly; + callbacks[42] = (delegate* unmanaged)&_getAssemblyName; + callbacks[43] = (delegate* unmanaged)&_LongLifetimeMalloc; + callbacks[44] = (delegate* unmanaged)&_LongLifetimeFree; + callbacks[45] = (delegate* unmanaged)&_getClassModuleIdForStatics; + callbacks[46] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; + callbacks[47] = (delegate* unmanaged)&_getStaticBaseAddress; + callbacks[48] = (delegate* unmanaged)&_getClassSize; + callbacks[49] = (delegate* unmanaged)&_getHeapClassSize; + callbacks[50] = (delegate* unmanaged)&_canAllocateOnStack; + callbacks[51] = (delegate* unmanaged)&_getClassAlignmentRequirement; + callbacks[52] = (delegate* unmanaged)&_getClassGClayout; + callbacks[53] = (delegate* unmanaged)&_getClassNumInstanceFields; + callbacks[54] = (delegate* unmanaged)&_getFieldInClass; + callbacks[55] = (delegate* unmanaged)&_checkMethodModifier; + callbacks[56] = (delegate* unmanaged)&_getNewHelper; + callbacks[57] = (delegate* unmanaged)&_getNewArrHelper; + callbacks[58] = (delegate* unmanaged)&_getCastingHelper; + callbacks[59] = (delegate* unmanaged)&_getSharedCCtorHelper; + callbacks[60] = (delegate* unmanaged)&_getTypeForBox; + callbacks[61] = (delegate* unmanaged)&_getBoxHelper; + callbacks[62] = (delegate* unmanaged)&_getUnBoxHelper; + callbacks[63] = (delegate* unmanaged)&_getRuntimeTypePointer; + callbacks[64] = (delegate* unmanaged)&_isObjectImmutable; + callbacks[65] = (delegate* unmanaged)&_getStringChar; + callbacks[66] = (delegate* unmanaged)&_getObjectType; + callbacks[67] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[68] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[69] = (delegate* unmanaged)&_initClass; + callbacks[70] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; + callbacks[71] = (delegate* unmanaged)&_getBuiltinClass; + callbacks[72] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[73] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[74] = (delegate* unmanaged)&_canCast; + callbacks[75] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[76] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[77] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[78] = (delegate* unmanaged)&_isEnum; + callbacks[79] = (delegate* unmanaged)&_getParentType; + callbacks[80] = (delegate* unmanaged)&_getChildType; + callbacks[81] = (delegate* unmanaged)&_isSDArray; + callbacks[82] = (delegate* unmanaged)&_getArrayRank; + callbacks[83] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[84] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[85] = (delegate* unmanaged)&_canAccessClass; + callbacks[86] = (delegate* unmanaged)&_printFieldName; + callbacks[87] = (delegate* unmanaged)&_getFieldClass; + callbacks[88] = (delegate* unmanaged)&_getFieldType; + callbacks[89] = (delegate* unmanaged)&_getFieldOffset; + callbacks[90] = (delegate* unmanaged)&_getFieldInfo; + callbacks[91] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[92] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[93] = (delegate* unmanaged)&_isFieldStatic; + callbacks[94] = (delegate* unmanaged)&_getArrayOrStringLength; + callbacks[95] = (delegate* unmanaged)&_getBoundaries; + callbacks[96] = (delegate* unmanaged)&_setBoundaries; + callbacks[97] = (delegate* unmanaged)&_getVars; + callbacks[98] = (delegate* unmanaged)&_setVars; + callbacks[99] = (delegate* unmanaged)&_reportRichMappings; + callbacks[100] = (delegate* unmanaged)&_allocateArray; + callbacks[101] = (delegate* unmanaged)&_freeArray; + callbacks[102] = (delegate* unmanaged)&_getArgNext; + callbacks[103] = (delegate* unmanaged)&_getArgType; + callbacks[104] = (delegate* unmanaged)&_getExactClasses; + callbacks[105] = (delegate* unmanaged)&_getArgClass; + callbacks[106] = (delegate* unmanaged)&_getHFAType; + callbacks[107] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[108] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[109] = (delegate* unmanaged)&_getEEInfo; + callbacks[110] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[111] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[112] = (delegate* unmanaged)&_printMethodName; + callbacks[113] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[114] = (delegate* unmanaged)&_getMethodHash; + callbacks[115] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[116] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[117] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; + callbacks[118] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[119] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[120] = (delegate* unmanaged)&_getHelperFtn; + callbacks[121] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[122] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[123] = (delegate* unmanaged)&_getMethodSync; + callbacks[124] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[125] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[126] = (delegate* unmanaged)&_embedClassHandle; + callbacks[127] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[128] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[129] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[130] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[131] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[132] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[133] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[134] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[135] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[136] = (delegate* unmanaged)&_getCallInfo; + callbacks[137] = (delegate* unmanaged)&_getClassDomainID; + callbacks[138] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[139] = (delegate* unmanaged)&_getObjectContent; + callbacks[140] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[141] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[142] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[143] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[144] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[145] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[146] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[147] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[148] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[149] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[150] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[151] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[152] = (delegate* unmanaged)&_allocMem; + callbacks[153] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[154] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[155] = (delegate* unmanaged)&_allocGCInfo; + callbacks[156] = (delegate* unmanaged)&_setEHcount; + callbacks[157] = (delegate* unmanaged)&_setEHinfo; + callbacks[158] = (delegate* unmanaged)&_logMsg; + callbacks[159] = (delegate* unmanaged)&_doAssert; + callbacks[160] = (delegate* unmanaged)&_reportFatalError; + callbacks[161] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[162] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[163] = (delegate* unmanaged)&_recordCallSite; + callbacks[164] = (delegate* unmanaged)&_recordRelocation; + callbacks[165] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[166] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[167] = (delegate* unmanaged)&_getJitFlags; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index d2a792e25a0c1..0f0d974e76c97 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -819,7 +819,6 @@ public enum CORINFO_OS public enum CORINFO_RUNTIME_ABI { - CORINFO_DESKTOP_ABI = 0x100, CORINFO_CORECLR_ABI = 0x200, CORINFO_NATIVEAOT_ABI = 0x300, } @@ -1391,49 +1390,43 @@ public enum CorJitFlag : uint { CORJIT_FLAG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). - CORJIT_FLAG_SPEED_OPT = 0, - CORJIT_FLAG_SIZE_OPT = 1, - CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) - CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode - CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info - CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necessarily debuggable code) - CORJIT_FLAG_ENABLE_CFG = 6, // generate CFG enabled code - CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete - CORJIT_FLAG_UNUSED2 = 8, - CORJIT_FLAG_UNUSED3 = 9, - CORJIT_FLAG_UNUSED4 = 10, - CORJIT_FLAG_UNUSED5 = 11, - CORJIT_FLAG_UNUSED6 = 12, - CORJIT_FLAG_OSR = 13, // Generate alternate version for On Stack Replacement - CORJIT_FLAG_ALT_JIT = 14, // JIT should consider itself an ALT_JIT - CORJIT_FLAG_FROZEN_ALLOC_ALLOWED = 15, // JIT is allowed to use *_MAYBEFROZEN allocators - CORJIT_FLAG_UNUSED10 = 17, - CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. - CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation - CORJIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues - CORJIT_FLAG_UNUSED7 = 21, - CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining - CORJIT_FLAG_UNUSED8 = 23, - CORJIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. - CORJIT_FLAG_RELOC = 25, // Generate relocatable code - CORJIT_FLAG_IMPORT_ONLY = 26, // Only import the function - CORJIT_FLAG_IL_STUB = 27, // method is an IL stub - CORJIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections - CORJIT_FLAG_BBINSTR = 29, // Collect basic block profile information - CORJIT_FLAG_BBOPT = 30, // Optimize method based on profile information - CORJIT_FLAG_FRAMED = 31, // All methods have an EBP frame - CORJIT_FLAG_BBINSTR_IF_LOOPS = 32, // JIT must instrument current method if it has loops - CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) - CORJIT_FLAG_UNUSED9 = 34, - CORJIT_FLAG_UNUSED1 = 35, - CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions - CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog - CORJIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the helper variants that track transitions. - CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible - CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code - CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records - CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method - CORJIT_FLAG_SOFTFP_ABI = 43, // On ARM should enable armel calling convention + + CORJIT_FLAG_SPEED_OPT = 0, // optimize for speed + CORJIT_FLAG_SIZE_OPT = 1, // optimize for code size + CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) + CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode + CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info + CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necessarily debuggable code) + CORJIT_FLAG_ENABLE_CFG = 6, // generate CFG enabled code + CORJIT_FLAG_OSR = 7, // Generate alternate version for On Stack Replacement + CORJIT_FLAG_ALT_JIT = 8, // JIT should consider itself an ALT_JIT + CORJIT_FLAG_FROZEN_ALLOC_ALLOWED = 9, // JIT is allowed to use *_MAYBEFROZEN allocators + CORJIT_FLAG_MAKEFINALCODE = 10, // Use the final code generator, i.e., not the interpreter. + CORJIT_FLAG_READYTORUN = 11, // Use version-resilient code generation + CORJIT_FLAG_PROF_ENTERLEAVE = 12, // Instrument prologues/epilogues + CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 13, // Disables PInvoke inlining + CORJIT_FLAG_PREJIT = 14, // prejit is the execution engine. + CORJIT_FLAG_RELOC = 15, // Generate relocatable code + CORJIT_FLAG_IL_STUB = 16, // method is an IL stub + CORJIT_FLAG_PROCSPLIT = 17, // JIT should separate code into hot and cold sections + CORJIT_FLAG_BBINSTR = 18, // Collect basic block profile information + CORJIT_FLAG_BBINSTR_IF_LOOPS = 19, // JIT must instrument current method if it has loops + CORJIT_FLAG_BBOPT = 20, // Optimize method based on profile information + CORJIT_FLAG_FRAMED = 21, // All methods have an EBP frame + CORJIT_FLAG_PUBLISH_SECRET_PARAM = 22, // JIT must place stub secret param into local 0. (used by IL stubs) + CORJIT_FLAG_USE_PINVOKE_HELPERS = 23, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions + CORJIT_FLAG_REVERSE_PINVOKE = 24, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog + CORJIT_FLAG_TRACK_TRANSITIONS = 25, // The JIT should insert the helper variants that track transitions. + CORJIT_FLAG_TIER0 = 26, // This is the initial tier for tiered compilation which should generate code as quickly as possible + CORJIT_FLAG_TIER1 = 27, // This is the final tier (for now) for tiered compilation which should generate high quality code + CORJIT_FLAG_NO_INLINING = 28, // JIT should not inline any called method into this method + + // ARM only + CORJIT_FLAG_RELATIVE_CODE_RELOCS = 29, // JIT should generate PC-relative address computations instead of EE relocation records + CORJIT_FLAG_SOFTFP_ABI = 30, // Enable armel calling convention + + // x86/x64 only + CORJIT_FLAG_VECTOR512_THROTTLING = 31, // On x86/x64, 512-bit vector usage may incur CPU frequency throttling } public struct CORJIT_FLAGS diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 89d87da12f848..4bec715c809bd 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -171,7 +171,6 @@ FUNCTIONS void reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char * reason); void getEHinfo( CORINFO_METHOD_HANDLE ftn, unsigned EHnumber, CORINFO_EH_CLAUSE* clause ); CORINFO_CLASS_HANDLE getMethodClass( CORINFO_METHOD_HANDLE method ); - CORINFO_MODULE_HANDLE getMethodModule( CORINFO_METHOD_HANDLE method ); void getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection, bool* isRelative); bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info); CORINFO_METHOD_HANDLE getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); @@ -182,19 +181,15 @@ FUNCTIONS CorInfoCallConvExtension getUnmanagedCallConv( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig, bool* pSuppressGCTransition); bool pInvokeMarshalingRequired( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig ); bool satisfiesMethodConstraints( CORINFO_CLASS_HANDLE parent, CORINFO_METHOD_HANDLE method ); - bool isCompatibleDelegate( CORINFO_CLASS_HANDLE objCls, CORINFO_CLASS_HANDLE methodParentCls, CORINFO_METHOD_HANDLE method, CORINFO_CLASS_HANDLE delegateCls, bool *pfIsOpenDelegate ); void methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method ); CORINFO_METHOD_HANDLE mapMethodDeclToMethodImpl( CORINFO_METHOD_HANDLE method ); void getGSCookie( GSCookie * pCookieVal, GSCookie ** ppCookieVal ); void setPatchpointInfo(PatchpointInfo* patchpointInfo); PatchpointInfo* getOSRInfo(unsigned * ilOffset); void resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken); - bool tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken); void findSig( CORINFO_MODULE_HANDLE module, unsigned sigTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO *sig ); void findCallSiteSig( CORINFO_MODULE_HANDLE module,unsigned methTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO *sig) CORINFO_CLASS_HANDLE getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken) - bool isValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK) - bool isValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK) int getStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex) size_t printObjectDescription(CORINFO_OBJECT_HANDLE handle, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) CorInfoType asCorInfoType(CORINFO_CLASS_HANDLE cls) @@ -241,12 +236,10 @@ FUNCTIONS bool canCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent) TypeCompareState compareTypesForCast(CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass) TypeCompareState compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) - CORINFO_CLASS_HANDLE mergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) bool isMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) TypeCompareState isEnum(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) CORINFO_CLASS_HANDLE getParentType(CORINFO_CLASS_HANDLE cls) CorInfoType getChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet) - bool satisfiesClassConstraints(CORINFO_CLASS_HANDLE cls) bool isSDArray(CORINFO_CLASS_HANDLE cls) unsigned getArrayRank(CORINFO_CLASS_HANDLE cls) CorInfoArrayIntrinsic getArrayIntrinsicID(CORINFO_METHOD_HANDLE ftn) @@ -281,12 +274,10 @@ FUNCTIONS size_t printMethodName(CORINFO_METHOD_HANDLE ftn, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) const char* getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, const char **className, const char **namespaceName, const char **enclosingClassName); unsigned getMethodHash(CORINFO_METHOD_HANDLE ftn); - size_t findNameOfToken(CORINFO_MODULE_HANDLE moduleHandle,mdToken token, char * szFQName,size_t FQNameCapacity); bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); uint32_t getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd); uint32_t getRISCV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE structHnd); uint32_t getThreadTLSIndex(void **ppIndirection); - const void * getInlinedCallFrameVptr(void **ppIndirection); int32_t * getAddrOfCaptureThreadGlobal(void **ppIndirection); void* getHelperFtn (CorInfoHelpFunc ftnNum, void **ppIndirection); void getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP * pResult, CORINFO_ACCESS_FLAGS accessFlags); @@ -305,8 +296,6 @@ FUNCTIONS CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle(CORINFO_METHOD_HANDLE method, CORINFO_JUST_MY_CODE_HANDLE**ppIndirection); void GetProfilingHandle(bool* pbHookFunction, void **pProfilerHandle, bool* pbIndirectedHandles); void getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN_PTR pConstrainedResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO *pResult); - bool canAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType); - bool isRIDClassDomainID(CORINFO_CLASS_HANDLE cls); unsigned getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection); bool getStaticFieldContent(CORINFO_FIELD_HANDLE field, uint8_t *buffer, int bufferSize, int valueOffset, bool ignoreMovableObjects); bool getObjectContent(CORINFO_OBJECT_HANDLE obj, uint8_t *buffer, int bufferSize, int valueOffset); @@ -334,7 +323,7 @@ FUNCTIONS JITINTERFACE_HRESULT getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t**pInstrumentationData, ICorJitInfo::PgoSource* pgoSource) JITINTERFACE_HRESULT allocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData) void recordCallSite(uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle) - void recordRelocation(void* location, void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) + void recordRelocation(void* location, void* locationRW, void* target, uint16_t fRelocType, int32_t addlDelta) uint16_t getRelocTypeHint(void* target) uint32_t getExpectedTargetArchitecture() uint32_t getJitFlags(CORJIT_FLAGS* flags, uint32_t sizeInBytes) diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs index 743192ffbeba0..968f3e13c0e9c 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs +++ b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs @@ -80,6 +80,8 @@ internal sealed class ILCompilerRootCommand : RootCommand new(new[] { "--scan" }, "Use IL scanner to generate optimized code (implied by -O)"); public Option NoScanner { get; } = new(new[] { "--noscan" }, "Do not use IL scanner to generate optimized code"); + public Option NoInlineTls { get; } = + new(new[] { "--noinlinetls" }, "Do not generate inline thread local statics"); public Option IlDump { get; } = new(new[] { "--ildump" }, "Dump IL assembly listing for compiler-generated IL"); public Option EmitStackTraceData { get; } = @@ -205,6 +207,7 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler") AddOption(ScanReflection); AddOption(UseScanner); AddOption(NoScanner); + AddOption(NoInlineTls); AddOption(IlDump); AddOption(EmitStackTraceData); AddOption(MethodBodyFolding); diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index 5c54516e45dd0..ae5e9f1fbf53c 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -494,8 +494,7 @@ void RunScanner() // If we have a scanner, we can inline threadstatics storage using the information // we collected at scanning time. // Inlined storage implies a single type manager, thus we do not do it in multifile case. - // This could be a command line switch if we really wanted to. - if (!multiFile) + if (!multiFile && !Get(_command.NoInlineTls)) { builder.UseInlinedThreadStatics(scanResults.GetInlinedThreadStatics()); } diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 56fb164b35956..24c21759692ab 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -23,7 +23,6 @@ struct JitInterfaceCallbacks void (* reportTailCallDecision)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char* reason); void (* getEHinfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, unsigned EHnumber, CORINFO_EH_CLAUSE* clause); CORINFO_CLASS_HANDLE (* getMethodClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method); - CORINFO_MODULE_HANDLE (* getMethodModule)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method); void (* getMethodVTableOffset)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection, bool* isRelative); bool (* resolveVirtualMethod)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_DEVIRTUALIZATION_INFO* info); CORINFO_METHOD_HANDLE (* getUnboxedEntry)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); @@ -34,19 +33,15 @@ struct JitInterfaceCallbacks CorInfoCallConvExtension (* getUnmanagedCallConv)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig, bool* pSuppressGCTransition); bool (* pInvokeMarshalingRequired)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig); bool (* satisfiesMethodConstraints)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE parent, CORINFO_METHOD_HANDLE method); - bool (* isCompatibleDelegate)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE objCls, CORINFO_CLASS_HANDLE methodParentCls, CORINFO_METHOD_HANDLE method, CORINFO_CLASS_HANDLE delegateCls, bool* pfIsOpenDelegate); void (* methodMustBeLoadedBeforeCodeIsRun)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method); CORINFO_METHOD_HANDLE (* mapMethodDeclToMethodImpl)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method); void (* getGSCookie)(void * thisHandle, CorInfoExceptionClass** ppException, GSCookie* pCookieVal, GSCookie** ppCookieVal); void (* setPatchpointInfo)(void * thisHandle, CorInfoExceptionClass** ppException, PatchpointInfo* patchpointInfo); PatchpointInfo* (* getOSRInfo)(void * thisHandle, CorInfoExceptionClass** ppException, unsigned* ilOffset); void (* resolveToken)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken); - bool (* tryResolveToken)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken); void (* findSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned sigTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO* sig); void (* findCallSiteSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned methTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO* sig); CORINFO_CLASS_HANDLE (* getTokenTypeAsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken); - bool (* isValidToken)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK); - bool (* isValidStringRef)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK); int (* getStringLiteral)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex); size_t (* printObjectDescription)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE handle, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize); CorInfoType (* asCorInfoType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); @@ -93,12 +88,10 @@ struct JitInterfaceCallbacks bool (* canCast)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent); TypeCompareState (* compareTypesForCast)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass); TypeCompareState (* compareTypesForEquality)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); - CORINFO_CLASS_HANDLE (* mergeClasses)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); bool (* isMoreSpecificType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); TypeCompareState (* isEnum)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType); CORINFO_CLASS_HANDLE (* getParentType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoType (* getChildType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet); - bool (* satisfiesClassConstraints)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); bool (* isSDArray)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); unsigned (* getArrayRank)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoArrayIntrinsic (* getArrayIntrinsicID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn); @@ -133,12 +126,10 @@ struct JitInterfaceCallbacks size_t (* printMethodName)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize); const char* (* getMethodNameFromMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, const char** className, const char** namespaceName, const char** enclosingClassName); unsigned (* getMethodHash)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn); - size_t (* findNameOfToken)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE moduleHandle, unsigned int token, char* szFQName, size_t FQNameCapacity); bool (* getSystemVAmd64PassStructInRegisterDescriptor)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); uint32_t (* getLoongArch64PassStructInRegisterFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd); uint32_t (* getRISCV64PassStructInRegisterFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd); uint32_t (* getThreadTLSIndex)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); - const void* (* getInlinedCallFrameVptr)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); int32_t* (* getAddrOfCaptureThreadGlobal)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); void* (* getHelperFtn)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoHelpFunc ftnNum, void** ppIndirection); void (* getFunctionEntryPoint)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP* pResult, CORINFO_ACCESS_FLAGS accessFlags); @@ -157,8 +148,6 @@ struct JitInterfaceCallbacks CORINFO_JUST_MY_CODE_HANDLE (* getJustMyCodeHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, CORINFO_JUST_MY_CODE_HANDLE** ppIndirection); void (* GetProfilingHandle)(void * thisHandle, CorInfoExceptionClass** ppException, bool* pbHookFunction, void** pProfilerHandle, bool* pbIndirectedHandles); void (* getCallInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO* pResult); - bool (* canAccessFamily)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType); - bool (* isRIDClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); unsigned (* getClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, void** ppIndirection); bool (* getStaticFieldContent)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, int valueOffset, bool ignoreMovableObjects); bool (* getObjectContent)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE obj, uint8_t* buffer, int bufferSize, int valueOffset); @@ -186,7 +175,7 @@ struct JitInterfaceCallbacks JITINTERFACE_HRESULT (* getPgoInstrumentationResults)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, ICorJitInfo::PgoSource* pgoSource); JITINTERFACE_HRESULT (* allocPgoInstrumentationBySchema)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData); void (* recordCallSite)(void * thisHandle, CorInfoExceptionClass** ppException, uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle); - void (* recordRelocation)(void * thisHandle, CorInfoExceptionClass** ppException, void* location, void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta); + void (* recordRelocation)(void * thisHandle, CorInfoExceptionClass** ppException, void* location, void* locationRW, void* target, uint16_t fRelocType, int32_t addlDelta); uint16_t (* getRelocTypeHint)(void * thisHandle, CorInfoExceptionClass** ppException, void* target); uint32_t (* getExpectedTargetArchitecture)(void * thisHandle, CorInfoExceptionClass** ppException); uint32_t (* getJitFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORJIT_FLAGS* flags, uint32_t sizeInBytes); @@ -325,15 +314,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual CORINFO_MODULE_HANDLE getMethodModule( - CORINFO_METHOD_HANDLE method) -{ - CorInfoExceptionClass* pException = nullptr; - CORINFO_MODULE_HANDLE temp = _callbacks->getMethodModule(_thisHandle, &pException, method); - if (pException != nullptr) throw pException; - return temp; -} - virtual void getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, @@ -431,19 +411,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual bool isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->isCompatibleDelegate(_thisHandle, &pException, objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); - if (pException != nullptr) throw pException; - return temp; -} - virtual void methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method) { @@ -495,15 +462,6 @@ class JitInterfaceWrapper : public ICorJitInfo if (pException != nullptr) throw pException; } - virtual bool tryResolveToken( - CORINFO_RESOLVED_TOKEN* pResolvedToken) -{ - CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->tryResolveToken(_thisHandle, &pException, pResolvedToken); - if (pException != nullptr) throw pException; - return temp; -} - virtual void findSig( CORINFO_MODULE_HANDLE module, unsigned sigTOK, @@ -535,26 +493,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual bool isValidToken( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->isValidToken(_thisHandle, &pException, module, metaTOK); - if (pException != nullptr) throw pException; - return temp; -} - - virtual bool isValidStringRef( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->isValidStringRef(_thisHandle, &pException, module, metaTOK); - if (pException != nullptr) throw pException; - return temp; -} - virtual int getStringLiteral( CORINFO_MODULE_HANDLE module, unsigned metaTOK, @@ -1006,16 +944,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual CORINFO_CLASS_HANDLE mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - CorInfoExceptionClass* pException = nullptr; - CORINFO_CLASS_HANDLE temp = _callbacks->mergeClasses(_thisHandle, &pException, cls1, cls2); - if (pException != nullptr) throw pException; - return temp; -} - virtual bool isMoreSpecificType( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) @@ -1055,15 +983,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual bool satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls) -{ - CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->satisfiesClassConstraints(_thisHandle, &pException, cls); - if (pException != nullptr) throw pException; - return temp; -} - virtual bool isSDArray( CORINFO_CLASS_HANDLE cls) { @@ -1387,18 +1306,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual size_t findNameOfToken( - CORINFO_MODULE_HANDLE moduleHandle, - unsigned int token, - char* szFQName, - size_t FQNameCapacity) -{ - CorInfoExceptionClass* pException = nullptr; - size_t temp = _callbacks->findNameOfToken(_thisHandle, &pException, moduleHandle, token, szFQName, FQNameCapacity); - if (pException != nullptr) throw pException; - return temp; -} - virtual bool getSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) @@ -1436,15 +1343,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual const void* getInlinedCallFrameVptr( - void** ppIndirection) -{ - CorInfoExceptionClass* pException = nullptr; - const void* temp = _callbacks->getInlinedCallFrameVptr(_thisHandle, &pException, ppIndirection); - if (pException != nullptr) throw pException; - return temp; -} - virtual int32_t* getAddrOfCaptureThreadGlobal( void** ppIndirection) { @@ -1622,25 +1520,6 @@ class JitInterfaceWrapper : public ICorJitInfo if (pException != nullptr) throw pException; } - virtual bool canAccessFamily( - CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) -{ - CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->canAccessFamily(_thisHandle, &pException, hCaller, hInstanceType); - if (pException != nullptr) throw pException; - return temp; -} - - virtual bool isRIDClassDomainID( - CORINFO_CLASS_HANDLE cls) -{ - CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->isRIDClassDomainID(_thisHandle, &pException, cls); - if (pException != nullptr) throw pException; - return temp; -} - virtual unsigned getClassDomainID( CORINFO_CLASS_HANDLE cls, void** ppIndirection) @@ -1923,11 +1802,10 @@ class JitInterfaceWrapper : public ICorJitInfo void* locationRW, void* target, uint16_t fRelocType, - uint16_t slotNum, int32_t addlDelta) { CorInfoExceptionClass* pException = nullptr; - _callbacks->recordRelocation(_thisHandle, &pException, location, locationRW, target, fRelocType, slotNum, addlDelta); + _callbacks->recordRelocation(_thisHandle, &pException, location, locationRW, target, fRelocType, addlDelta); if (pException != nullptr) throw pException; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 0783fa52962a4..6b1b578b36ee3 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -474,14 +474,6 @@ struct Agnostic_GetStaticBaseAddress DWORD result; }; -struct Agnostic_IsCompatibleDelegate -{ - DWORDLONG objCls; - DWORDLONG methodParentCls; - DWORDLONG method; - DWORDLONG delegateCls; -}; - struct Agnostic_PgoInstrumentationSchema { DWORDLONG Offset; // size_t @@ -610,12 +602,6 @@ struct ResolveTokenValue DWORD exceptionCode; }; -struct TryResolveTokenValue -{ - Agnostic_CORINFO_RESOLVED_TOKENout tokenOut; - DWORD success; -}; - struct GetTokenTypeAsHandleValue { DWORDLONG hMethod; @@ -675,7 +661,6 @@ struct Agnostic_RecordRelocation DWORDLONG location; DWORDLONG target; DWORD fRelocType; - DWORD slotNum; DWORD addlDelta; }; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp index 6a2438c0f0b74..c703b4665fa21 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp @@ -645,9 +645,9 @@ void CompileResult::dmpReportFatalError(DWORD key, DWORD value) printf("ReportFatalError key Count-%u, value result-%08X", key, value); } -void CompileResult::recRecordRelocation(void* location, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) +void CompileResult::recRecordRelocation(void* location, void* target, uint16_t fRelocType, int32_t addlDelta) { - repRecordRelocation(location, target, fRelocType, slotNum, addlDelta); + repRecordRelocation(location, target, fRelocType, addlDelta); } const char* relocationTypeToString(uint16_t fRelocType) @@ -679,11 +679,11 @@ const char* relocationTypeToString(uint16_t fRelocType) } void CompileResult::dmpRecordRelocation(DWORD key, const Agnostic_RecordRelocation& value) { - printf("RecordRelocation key %u, value loc-%016" PRIX64 " tgt-%016" PRIX64 " fRelocType-%u(%s) slotNum-%u addlDelta:%d", key, + printf("RecordRelocation key %u, value loc-%016" PRIX64 " tgt-%016" PRIX64 " fRelocType-%u(%s) addlDelta:%d", key, value.location, value.target, value.fRelocType, relocationTypeToString((uint16_t)value.fRelocType), - value.slotNum, (int32_t)value.addlDelta); + (int32_t)value.addlDelta); } -void CompileResult::repRecordRelocation(void* location, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) +void CompileResult::repRecordRelocation(void* location, void* target, uint16_t fRelocType, int32_t addlDelta) { if (RecordRelocation == nullptr) RecordRelocation = new DenseLightWeightMap(); @@ -693,11 +693,8 @@ void CompileResult::repRecordRelocation(void* location, void* target, uint16_t f value.location = CastPointer(location); value.target = CastPointer(target); value.fRelocType = (DWORD)fRelocType; - value.slotNum = (DWORD)slotNum; value.addlDelta = (DWORD)addlDelta; - Assert(value.slotNum == 0); - RecordRelocation->Append(value); } @@ -872,7 +869,7 @@ void CompileResult::applyRelocs(RelocContext* rc, unsigned char* block1, ULONG b { if (relocType == IMAGE_REL_BASED_DIR64) { - DWORDLONG fixupLocation = tmp.location + tmp.slotNum; + DWORDLONG fixupLocation = tmp.location; // Write 64-bits into location size_t address = section_begin + (size_t)fixupLocation - (size_t)originalAddr; @@ -893,7 +890,7 @@ void CompileResult::applyRelocs(RelocContext* rc, unsigned char* block1, ULONG b // Now do all-platform relocations. if (tmp.fRelocType == IMAGE_REL_BASED_REL32) { - DWORDLONG fixupLocation = tmp.location + tmp.slotNum; + DWORDLONG fixupLocation = tmp.location; size_t address = section_begin + (size_t)fixupLocation - (size_t)originalAddr; if ((section_begin <= address) && (address < section_end)) // A reloc for our section? diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h index 97331720e79ba..a4d129c3e0880 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h @@ -178,9 +178,9 @@ class CompileResult void recReportFatalError(CorJitResult result); void dmpReportFatalError(DWORD key, DWORD value); - void recRecordRelocation(void* location, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta); + void recRecordRelocation(void* location, void* target, uint16_t fRelocType, int32_t addlDelta); void dmpRecordRelocation(DWORD key, const Agnostic_RecordRelocation& value); - void repRecordRelocation(void* location, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta); + void repRecordRelocation(void* location, void* target, uint16_t fRelocType, int32_t addlDelta); void applyRelocs(RelocContext* rc, unsigned char* block1, ULONG blocksize1, void* originalAddr); void recProcessName(const char* name); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index 9ea8c6ada013c..3eb6ddd698fd5 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -20,7 +20,6 @@ LWM(AllocPgoInstrumentationBySchema, DWORDLONG, Agnostic_AllocPgoInstrumentation LWM(GetPgoInstrumentationResults, DWORDLONG, Agnostic_GetPgoInstrumentationResults) LWM(AsCorInfoType, DWORDLONG, DWORD) LWM(CanAccessClass, Agnostic_CanAccessClassIn, Agnostic_CanAccessClassOut) -LWM(CanAccessFamily, DLDL, DWORD) LWM(CanCast, DLDL, DWORD) LWM(CanGetCookieForPInvokeCalliSig, CanGetCookieForPInvokeCalliSigValue, DWORD) LWM(CanGetVarArgsHandle, CanGetVarArgsHandleValue, DWORD) @@ -43,7 +42,6 @@ LWM(GetThreadLocalStaticBlocksInfo, DWORD, Agnostic_GetThreadLocalStaticBlocksIn DENSELWM(EmptyStringLiteral, DLD) DENSELWM(ErrorList, DWORD) LWM(FindCallSiteSig, Agnostic_FindCallSiteSig, Agnostic_CORINFO_SIG_INFO) -LWM(FindNameOfToken, DLD, DLD) LWM(FindSig, Agnostic_FindSig, Agnostic_CORINFO_SIG_INFO) LWM(GetAddressOfPInvokeTarget, DWORDLONG, DLD) LWM(GetAddrOfCaptureThreadGlobal, DWORD, DLDL) @@ -93,7 +91,6 @@ LWM(GetFunctionFixedEntryPoint, DWORDLONG, Agnostic_CORINFO_CONST_LOOKUP) LWM(GetGSCookie, DWORD, DLDL) LWM(GetHelperFtn, DWORD, DLDL) LWM(GetHFAType, DWORDLONG, DWORD) -LWM(GetInlinedCallFrameVptr, DWORD, DLDL) LWM(GetIntConfigValue, Agnostic_ConfigIntInfo, DWORD) LWM(GetJitFlags, DWORD, DD) LWM(GetJitTimeLogFilename, DWORD, DWORD) @@ -106,7 +103,6 @@ LWM(GetClassModule, DWORDLONG, DWORDLONG) LWM(GetModuleAssembly, DWORDLONG, DWORDLONG) LWM(GetAssemblyName, DWORDLONG, DWORD) LWM(GetMethodClass, DWORDLONG, DWORDLONG) -LWM(GetMethodModule, DWORDLONG, DWORDLONG) LWM(GetMethodDefFromMethod, DWORDLONG, DWORD) LWM(GetMethodHash, DWORDLONG, DWORD) LWM(GetMethodInfo, DWORDLONG, Agnostic_GetMethodInfo) @@ -144,29 +140,23 @@ LWM(GetObjectType, DWORDLONG, DWORDLONG) LWM(GetVarArgsHandle, GetVarArgsHandleValue, DLDL) LWM(GetVars, DWORDLONG, Agnostic_GetVars) LWM(InitClass, Agnostic_InitClass, DWORD) -LWM(IsCompatibleDelegate, Agnostic_IsCompatibleDelegate, DD) LWM(IsDelegateCreationAllowed, DLDL, DWORD) LWM(IsFieldStatic, DWORDLONG, DWORD) LWM(GetArrayOrStringLength, DWORDLONG, DWORD) LWM(ExpandRawHandleIntrinsic, Agnostic_CORINFO_RESOLVED_TOKENin, Agnostic_CORINFO_GENERICHANDLE_RESULT) LWM(IsIntrinsicType, DWORDLONG, DWORD) LWM(IsSDArray, DWORDLONG, DWORD) -LWM(IsValidStringRef, DLD, DWORD) LWM(GetStringLiteral, DLDDD, DD) LWM(PrintObjectDescription, DWORDLONG, Agnostic_PrintResult) LWM(PrintClassName, DWORDLONG, Agnostic_PrintResult) LWM(PrintFieldName, DWORDLONG, Agnostic_PrintResult) LWM(PrintMethodName, DWORDLONG, Agnostic_PrintResult) -LWM(IsValidToken, DLD, DWORD) LWM(IsValueClass, DWORDLONG, DWORD) -LWM(MergeClasses, DLDL, DWORDLONG) LWM(IsMoreSpecificType, DLDL, DWORD) LWM(IsEnum, DWORDLONG, DLD) LWM(PInvokeMarshalingRequired, MethodOrSigInfoValue, DWORD) LWM(ResolveToken, Agnostic_CORINFO_RESOLVED_TOKENin, ResolveTokenValue) LWM(ResolveVirtualMethod, Agnostic_ResolveVirtualMethodKey, Agnostic_ResolveVirtualMethodResult) -LWM(TryResolveToken, Agnostic_CORINFO_RESOLVED_TOKENin, TryResolveTokenValue) -LWM(SatisfiesClassConstraints, DWORDLONG, DWORD) LWM(SatisfiesMethodConstraints, DLDL, DWORD) LWM(GetUnmanagedCallConv, MethodOrSigInfoValue, DD) LWM(DoesFieldBelongToClass, DLDL, DWORD) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 70378310e449a..8f11b2cb71c96 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -726,29 +726,6 @@ CORINFO_CLASS_HANDLE MethodContext::repGetMethodClass(CORINFO_METHOD_HANDLE meth return result; } -void MethodContext::recGetMethodModule(CORINFO_METHOD_HANDLE methodHandle, CORINFO_MODULE_HANDLE moduleHandle) -{ - if (GetMethodModule == nullptr) - GetMethodModule = new LightWeightMap(); - - DWORDLONG key = CastHandle(methodHandle); - DWORDLONG value = CastHandle(moduleHandle); - GetMethodModule->Add(key, value); - DEBUG_REC(dmpGetMethodModule(key, value)); -} -void MethodContext::dmpGetMethodModule(DWORDLONG key, DWORDLONG value) -{ - printf("GetMethodModule key %016" PRIX64 ", value %016" PRIX64 "", key, value); -} -CORINFO_MODULE_HANDLE MethodContext::repGetMethodModule(CORINFO_METHOD_HANDLE methodHandle) -{ - DWORDLONG key = CastHandle(methodHandle); - DWORDLONG value = LookupByKeyOrMiss(GetMethodModule, key, ": key %016" PRIX64 "", key); - DEBUG_REP(dmpGetMethodModule(key, value)); - CORINFO_MODULE_HANDLE result = (CORINFO_MODULE_HANDLE)value; - return result; -} - void MethodContext::recGetClassAttribs(CORINFO_CLASS_HANDLE classHandle, DWORD attribs) { if (GetClassAttribs == nullptr) @@ -1181,14 +1158,6 @@ const char* CorJitFlagToString(CORJIT_FLAGS::CorJitFlag flag) return "CORJIT_FLAG_MIN_OPT"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_ENABLE_CFG: return "CORJIT_FLAG_ENABLE_CFG"; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_MCJIT_BACKGROUND: - return "CORJIT_FLAG_MCJIT_BACKGROUND"; - -#if defined(TARGET_X86) - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PINVOKE_RESTORE_ESP: - return "CORJIT_FLAG_PINVOKE_RESTORE_ESP"; -#endif // defined(TARGET_X86) - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_OSR: return "CORJIT_FLAG_OSR"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_ALT_JIT: @@ -1213,12 +1182,12 @@ const char* CorJitFlagToString(CORJIT_FLAGS::CorJitFlag flag) return "CORJIT_FLAG_PROCSPLIT"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBINSTR: return "CORJIT_FLAG_BBINSTR"; + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBINSTR_IF_LOOPS: + return "CORJIT_FLAG_BBINSTR_IF_LOOPS"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBOPT: return "CORJIT_FLAG_BBOPT"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_FRAMED: return "CORJIT_FLAG_FRAMED"; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_BBINSTR_IF_LOOPS: - return "CORJIT_FLAG_BBINSTR_IF_LOOPS"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PUBLISH_SECRET_PARAM: return "CORJIT_FLAG_PUBLISH_SECRET_PARAM"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_USE_PINVOKE_HELPERS: @@ -1231,20 +1200,21 @@ const char* CorJitFlagToString(CORJIT_FLAGS::CorJitFlag flag) return "CORJIT_FLAG_TIER0"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_TIER1: return "CORJIT_FLAG_TIER1"; - -#if defined(TARGET_ARM) - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_RELATIVE_CODE_RELOCS: - return "CORJIT_FLAG_RELATIVE_CODE_RELOCS"; -#endif // defined(TARGET_ARM) - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_NO_INLINING: return "CORJIT_FLAG_NO_INLINING"; #if defined(TARGET_ARM) + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_RELATIVE_CODE_RELOCS: + return "CORJIT_FLAG_RELATIVE_CODE_RELOCS"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SOFTFP_ABI: return "CORJIT_FLAG_SOFTFP_ABI"; #endif // defined(TARGET_ARM) +#if defined(TARGET_X86) || defined(TARGET_AMD64) + case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_VECTOR512_THROTTLING: + return "CORJIT_FLAG_VECTOR512_THROTTLING"; +#endif // defined(TARGET_XARCH) + default: return ""; } @@ -1432,42 +1402,6 @@ void MethodContext::repResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, DWOR *exceptionCode = (DWORD)value.exceptionCode; } -void MethodContext::recTryResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool success) -{ - if (TryResolveToken == nullptr) - TryResolveToken = new LightWeightMap(); - - Agnostic_CORINFO_RESOLVED_TOKENin key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken); - - TryResolveTokenValue value; - - value.tokenOut = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKENout(pResolvedToken, ResolveToken); - value.success = success ? 0 : 1; - - TryResolveToken->Add(key, value); - DEBUG_REC(dmpTryResolveToken(key, value)); -} -void MethodContext::dmpTryResolveToken(const Agnostic_CORINFO_RESOLVED_TOKENin& key, const TryResolveTokenValue& value) -{ - printf("TryResolveToken key: %s\n", SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKENin(key).c_str()); - printf(", value: %s failed-%u", SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKENout(value.tokenOut).c_str(), - value.success); -} -bool MethodContext::repTryResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken) -{ - Agnostic_CORINFO_RESOLVED_TOKENin key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken); - - TryResolveTokenValue value = LookupByKeyOrMiss(TryResolveToken, key, ": token %x", pResolvedToken->token); - DEBUG_REP(dmpTryResolveToken(key, value)); - - SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKENout(pResolvedToken, value.tokenOut, ResolveToken); - return (DWORD)value.success == 0; // recTryResolveToken encodes success as 0 -} - void MethodContext::recGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_HANDLE callerHandle, @@ -4349,7 +4283,7 @@ void MethodContext::repGetEEInfo(CORINFO_EE_INFO* pEEInfoOut) pEEInfoOut->sizeOfReversePInvokeFrame = (unsigned)0x8; pEEInfoOut->osPageSize = (size_t)0x1000; pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)((32 * 1024) - 1); - pEEInfoOut->targetAbi = CORINFO_DESKTOP_ABI; + pEEInfoOut->targetAbi = CORINFO_CORECLR_ABI; #ifdef TARGET_OSX pEEInfoOut->osType = CORINFO_MACOS; #elif defined(TARGET_UNIX) @@ -4590,36 +4524,6 @@ DWORD MethodContext::repGetThreadTLSIndex(void** ppIndirection) return (DWORD)value.B; } -void MethodContext::recGetInlinedCallFrameVptr(void** ppIndirection, const void* result) -{ - if (GetInlinedCallFrameVptr == nullptr) - GetInlinedCallFrameVptr = new LightWeightMap(); - - DLDL value; - - if (ppIndirection != nullptr) - value.A = CastPointer(*ppIndirection); - else - value.A = 0; - value.B = CastPointer(result); - - GetInlinedCallFrameVptr->Add(0, value); -} -void MethodContext::dmpGetInlinedCallFrameVptr(DWORD key, DLDL value) -{ - printf("GetInlinedCallFrameVptr key 0, value ppIndirection-%016" PRIX64 " result-%016" PRIX64 "", value.A, value.B); -} -const void* MethodContext::repGetInlinedCallFrameVptr(void** ppIndirection) -{ - DLDL value = LookupByKeyOrMissNoMessage(GetInlinedCallFrameVptr, 0); - - DEBUG_REP(dmpGetInlinedCallFrameVptr(0, value)); - - if (ppIndirection != nullptr) - *ppIndirection = (void*)value.A; - return (const void*)value.B; -} - void MethodContext::recGetAddrOfCaptureThreadGlobal(void** ppIndirection, int32_t* result) { if (GetAddrOfCaptureThreadGlobal == nullptr) @@ -4959,37 +4863,6 @@ bool MethodContext::repSatisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, C return value != 0; } -void MethodContext::recIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool result) -{ - if (IsValidStringRef == nullptr) - IsValidStringRef = new LightWeightMap(); - - DLD key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(module); - key.B = (DWORD)metaTOK; - - DWORD value = result ? 1 : 0; - IsValidStringRef->Add(key, value); - DEBUG_REC(dmpIsValidStringRef(key, value)); -} -void MethodContext::dmpIsValidStringRef(DLD key, DWORD value) -{ - printf("IsValidStringRef key mod-%016" PRIX64 " tok-%08X, value res-%u", key.A, key.B, value); -} -bool MethodContext::repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK) -{ - DLD key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(module); - key.B = (DWORD)metaTOK; - - DWORD value = LookupByKeyOrMissNoMessage(IsValidStringRef, key); - - DEBUG_REP(dmpIsValidStringRef(key, value)); - return value != 0; -} - void MethodContext::recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex, int length) { if (GetStringLiteral == nullptr) @@ -5165,28 +5038,6 @@ void MethodContext::repGetAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, C pLookup->accessType = (InfoAccessType)value.B; } -void MethodContext::recSatisfiesClassConstraints(CORINFO_CLASS_HANDLE cls, bool result) -{ - if (SatisfiesClassConstraints == nullptr) - SatisfiesClassConstraints = new LightWeightMap(); - - DWORDLONG key = CastHandle(cls); - DWORD value = result ? 1 : 0; - SatisfiesClassConstraints->Add(key, value); - DEBUG_REC(dmpSatisfiesClassConstraints(key, value)); -} -void MethodContext::dmpSatisfiesClassConstraints(DWORDLONG key, DWORD value) -{ - printf("SatisfiesClassConstraints key cls-%016" PRIX64 ", value res-%u", key, value); -} -bool MethodContext::repSatisfiesClassConstraints(CORINFO_CLASS_HANDLE cls) -{ - DWORDLONG key = CastHandle(cls); - DWORD value = LookupByKeyOrMiss(SatisfiesClassConstraints, key, ": key %016" PRIX64 "", key); - DEBUG_REP(dmpSatisfiesClassConstraints(key, value)); - return value != 0; -} - void MethodContext::recGetMethodHash(CORINFO_METHOD_HANDLE ftn, unsigned result) { if (GetMethodHash == nullptr) @@ -5255,57 +5106,6 @@ bool MethodContext::repCanTailCall(CORINFO_METHOD_HANDLE callerHnd, return value != 0; } -void MethodContext::recIsCompatibleDelegate(CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate, - bool result) -{ - if (IsCompatibleDelegate == nullptr) - IsCompatibleDelegate = new LightWeightMap(); - - Agnostic_IsCompatibleDelegate key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.objCls = CastHandle(objCls); - key.methodParentCls = CastHandle(methodParentCls); - key.method = CastHandle(method); - key.delegateCls = CastHandle(delegateCls); - - DD value; - value.A = (DWORD)*pfIsOpenDelegate; - value.B = (DWORD)result; - - IsCompatibleDelegate->Add(key, value); - DEBUG_REC(dmpIsCompatibleDelegate(key, value)); -} -void MethodContext::dmpIsCompatibleDelegate(const Agnostic_IsCompatibleDelegate& key, DD value) -{ - printf("IsCompatibleDelegate key objCls-%016" PRIX64 " methodParentCls-%016" PRIX64 " method-%016" PRIX64 " delegateCls-%016" PRIX64 ", value " - "pfIsOpenDelegate-%08X result-%08X", - key.objCls, key.methodParentCls, key.method, key.delegateCls, value.A, value.B); -} -bool MethodContext::repIsCompatibleDelegate(CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - Agnostic_IsCompatibleDelegate key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.objCls = CastHandle(objCls); - key.methodParentCls = CastHandle(methodParentCls); - key.method = CastHandle(method); - key.delegateCls = CastHandle(delegateCls); - - DD value = LookupByKeyOrMissNoMessage(IsCompatibleDelegate, key); - - DEBUG_REP(dmpIsCompatibleDelegate(key, value)); - - *pfIsOpenDelegate = value.A != 0; - return value.B != 0; -} - void MethodContext::recIsDelegateCreationAllowed(CORINFO_CLASS_HANDLE delegateHnd, CORINFO_METHOD_HANDLE calleeHnd, bool result) @@ -5869,37 +5669,6 @@ HRESULT MethodContext::repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftn return result; } -void MethodContext::recMergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, CORINFO_CLASS_HANDLE result) -{ - if (MergeClasses == nullptr) - MergeClasses = new LightWeightMap(); - - DLDL key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(cls1); - key.B = CastHandle(cls2); - - DWORDLONG value = CastHandle(result); - MergeClasses->Add(key, value); - DEBUG_REC(dmpMergeClasses(key, value)); -} -void MethodContext::dmpMergeClasses(DLDL key, DWORDLONG value) -{ - printf("MergeClasses NYI"); -} -CORINFO_CLASS_HANDLE MethodContext::repMergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) -{ - DLDL key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(cls1); - key.B = CastHandle(cls2); - - DWORDLONG value = LookupByKeyOrMiss(MergeClasses, key, ": key %016" PRIX64 " %016" PRIX64 "", key.A, key.B); - - DEBUG_REP(dmpMergeClasses(key, value)); - return (CORINFO_CLASS_HANDLE)value; -} - void MethodContext::recIsMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, bool result) { if (IsMoreSpecificType == nullptr) @@ -6038,37 +5807,6 @@ bool MethodContext::repCanGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSi return value != 0; } -void MethodContext::recCanAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType, bool result) -{ - if (CanAccessFamily == nullptr) - CanAccessFamily = new LightWeightMap(); - - DLDL key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(hCaller); - key.B = CastHandle(hInstanceType); - - DWORD value = result ? 1 : 0; - CanAccessFamily->Add(key, value); - DEBUG_REC(dmpCanAccessFamily(key, value)); -} -void MethodContext::dmpCanAccessFamily(DLDL key, DWORD value) -{ - printf("CanAccessFamily key cal-%016" PRIX64 " inst-%016" PRIX64 ", value %u", key.A, key.B, value); -} -bool MethodContext::repCanAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType) -{ - DLDL key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(hCaller); - key.B = CastHandle(hInstanceType); - - DWORD value = LookupByKeyOrMissNoMessage(CanAccessFamily, key); - - DEBUG_REP(dmpCanAccessFamily(key, value)); - return value != 0; -} - void MethodContext::recErrorList(const char* error) { if (ErrorList == nullptr) @@ -6215,58 +5953,6 @@ TypeCompareState MethodContext::repCompareTypesForEquality(CORINFO_CLASS_HANDLE return result; } -void MethodContext::recFindNameOfToken( - CORINFO_MODULE_HANDLE module, mdToken metaTOK, char* szFQName, size_t FQNameCapacity, size_t result) -{ - if (FindNameOfToken == nullptr) - FindNameOfToken = new LightWeightMap(); - - DLD key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(module); - key.B = (DWORD)metaTOK; - - DLD value; - value.A = result; - value.B = FindNameOfToken->AddBuffer((unsigned char*)szFQName, (unsigned int)result); - - FindNameOfToken->Add(key, value); - DEBUG_REC(dmpFindNameOfToken(key, value)); -} -void MethodContext::dmpFindNameOfToken(DLD key, DLD value) -{ - // practically the name of a token wont be bigger than 4gb... - unsigned char* buff = new unsigned char[(unsigned int)value.A + 1]; - ZeroMemory(buff, (unsigned int)value.A + 1); - memcpy(buff, FindNameOfToken->GetBuffer(value.B), (unsigned int)value.A); - FindNameOfToken->Unlock(); - printf("FindNameOfToken key mod-%016" PRIX64 " tok-%08X, value '%s'", key.A, key.B, buff); - delete[] buff; -} -size_t MethodContext::repFindNameOfToken(CORINFO_MODULE_HANDLE module, - mdToken metaTOK, - char* szFQName, - size_t FQNameCapacity) -{ - DLD key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(module); - key.B = (DWORD)metaTOK; - - DLD value = LookupByKeyOrMiss(FindNameOfToken, key, ": key %016" PRIX64 "", key.A); - - DEBUG_REP(dmpFindNameOfToken(key, value)); - - unsigned char* temp = nullptr; - if (value.B != (DWORD)-1) - { - temp = FindNameOfToken->GetBuffer(value.B); - memcpy(szFQName, temp, (size_t)value.A); - } - - return (size_t)value.A; -} - void MethodContext::recGetSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr, @@ -6503,37 +6189,6 @@ bool MethodContext::repDoesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_ return value != 0; } -void MethodContext::recIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool result) -{ - if (IsValidToken == nullptr) - IsValidToken = new LightWeightMap(); - - DLD key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(module); - key.B = (DWORD)metaTOK; - - DWORD value = result ? 1 : 0; - IsValidToken->Add(key, value); - DEBUG_REC(dmpIsValidToken(key, value)); -} -void MethodContext::dmpIsValidToken(DLD key, DWORD value) -{ - printf("IsValidToken key mod-%016" PRIX64 " tok-%08X, value res-%u", key.A, key.B, value); -} -bool MethodContext::repIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK) -{ - DLD key; - ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding - key.A = CastHandle(module); - key.B = (DWORD)metaTOK; - - DWORD value = LookupByKeyOrMiss(IsValidToken, key, ": key %016" PRIX64 "", key.A); - - DEBUG_REP(dmpIsValidToken(key, value)); - return value != 0; -} - void MethodContext::recGetClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, char* className, const char** namespaceName) { if (GetClassNameFromMetadata == nullptr) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index e6dacd31f2a3c..1300451268026 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -59,17 +59,6 @@ enum EXTRA_JIT_FLAGS HAS_LIKELY_METHOD = 56, }; -// Asserts to catch changes in corjit flags definitions. - -static_assert((int)EXTRA_JIT_FLAGS::HAS_PGO == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED36, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_EDGE_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED35, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_CLASS_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED34, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_LIKELY_CLASS == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED33, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_STATIC_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED32, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_DYNAMIC_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED31, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_METHOD_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED30, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_LIKELY_METHOD == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED29, "Jit Flags Mismatch"); - class MethodContext { friend class CompileResult; @@ -125,10 +114,6 @@ class MethodContext void dmpGetMethodClass(DWORDLONG key, DWORDLONG value); CORINFO_CLASS_HANDLE repGetMethodClass(CORINFO_METHOD_HANDLE methodHandle); - void recGetMethodModule(CORINFO_METHOD_HANDLE methodHandle, CORINFO_MODULE_HANDLE moduleHandle); - void dmpGetMethodModule(DWORDLONG key, DWORDLONG value); - CORINFO_MODULE_HANDLE repGetMethodModule(CORINFO_METHOD_HANDLE methodHandle); - void recGetClassAttribs(CORINFO_CLASS_HANDLE classHandle, DWORD attribs); void dmpGetClassAttribs(DWORDLONG key, DWORD value); DWORD repGetClassAttribs(CORINFO_CLASS_HANDLE classHandle); @@ -208,10 +193,6 @@ class MethodContext void dmpResolveToken(const Agnostic_CORINFO_RESOLVED_TOKENin& key, const ResolveTokenValue& value); void repResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, DWORD* exceptionCode); - void recTryResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool success); - void dmpTryResolveToken(const Agnostic_CORINFO_RESOLVED_TOKENin& key, const TryResolveTokenValue& value); - bool repTryResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken); - void recGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_HANDLE callerHandle, @@ -589,10 +570,6 @@ class MethodContext void dmpGetThreadTLSIndex(DWORD key, DLD value); DWORD repGetThreadTLSIndex(void** ppIndirection); - void recGetInlinedCallFrameVptr(void** ppIndirection, const void* result); - void dmpGetInlinedCallFrameVptr(DWORD key, DLDL value); - const void* repGetInlinedCallFrameVptr(void** ppIndirection); - void recGetAddrOfCaptureThreadGlobal(void** ppIndirection, int32_t* result); void dmpGetAddrOfCaptureThreadGlobal(DWORD key, DLDL value); int32_t* repGetAddrOfCaptureThreadGlobal(void** ppIndirection); @@ -667,10 +644,6 @@ class MethodContext void dmpGetAddressOfPInvokeTarget(DWORDLONG key, DLD value); void repGetAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP* pLookup); - void recSatisfiesClassConstraints(CORINFO_CLASS_HANDLE cls, bool result); - void dmpSatisfiesClassConstraints(DWORDLONG key, DWORD value); - bool repSatisfiesClassConstraints(CORINFO_CLASS_HANDLE cls); - void recGetMethodHash(CORINFO_METHOD_HANDLE ftn, unsigned result); void dmpGetMethodHash(DWORDLONG key, DWORD value); unsigned repGetMethodHash(CORINFO_METHOD_HANDLE ftn); @@ -686,19 +659,6 @@ class MethodContext CORINFO_METHOD_HANDLE exactCalleeHnd, bool fIsTailPrefix); - void recIsCompatibleDelegate(CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate, - bool result); - void dmpIsCompatibleDelegate(const Agnostic_IsCompatibleDelegate& key, DD value); - bool repIsCompatibleDelegate(CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate); - void recIsDelegateCreationAllowed(CORINFO_CLASS_HANDLE delegateHnd, CORINFO_METHOD_HANDLE calleeHnd, bool result); void dmpIsDelegateCreationAllowed(DLDL key, DWORD value); bool repIsDelegateCreationAllowed(CORINFO_CLASS_HANDLE delegateHnd, CORINFO_METHOD_HANDLE calleeHnd); @@ -738,10 +698,6 @@ class MethodContext void dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnostic_GetPgoInstrumentationResults& value); HRESULT repGetPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource); - void recMergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, CORINFO_CLASS_HANDLE result); - void dmpMergeClasses(DLDL key, DWORDLONG value); - CORINFO_CLASS_HANDLE repMergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); - void recIsMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, bool result); void dmpIsMoreSpecificType(DLDL key, DWORD value); bool repIsMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); @@ -758,10 +714,6 @@ class MethodContext void dmpCanGetCookieForPInvokeCalliSig(const CanGetCookieForPInvokeCalliSigValue& key, DWORD value); bool repCanGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig); - void recCanAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType, bool result); - void dmpCanAccessFamily(DLDL key, DWORD value); - bool repCanAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType); - void recErrorList(const char* error); void dmpErrorList(DWORD key, DWORD value); @@ -781,11 +733,6 @@ class MethodContext void dmpCompareTypesForEquality(DLDL key, DWORD value); TypeCompareState repCompareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); - void recFindNameOfToken( - CORINFO_MODULE_HANDLE module, mdToken metaTOK, char* szFQName, size_t FQNameCapacity, size_t result); - void dmpFindNameOfToken(DLD key, DLD value); - size_t repFindNameOfToken(CORINFO_MODULE_HANDLE module, mdToken metaTOK, char* szFQName, size_t FQNameCapacity); - void recGetSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr, @@ -815,10 +762,6 @@ class MethodContext void dmpDoesFieldBelongToClass(DLDL key, bool value); bool repDoesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_CLASS_HANDLE cls); - void recIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool result); - void dmpIsValidToken(DLD key, DWORD value); - bool repIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK); - void recGetClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, char* className, const char** namespaceName); void dmpGetClassNameFromMetadata(DLD key, DD value); const char* repGetClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName); @@ -981,7 +924,7 @@ enum mcPackets //Packet_AreTypesEquivalent = 1, Packet_AsCorInfoType = 2, Packet_CanAccessClass = 3, - Packet_CanAccessFamily = 4, + //Packet_CanAccessFamily = 4, Packet_CanCast = 5, Packet_PrintMethodName = 6, Packet_CanGetCookieForPInvokeCalliSig = 7, @@ -1040,7 +983,7 @@ enum mcPackets Packet_GetFunctionFixedEntryPoint = 61, Packet_GetGSCookie = 62, Packet_GetHelperFtn = 63, - Packet_GetInlinedCallFrameVptr = 65, + //Packet_GetInlinedCallFrameVptr = 65, Packet_GetArrayIntrinsicID = 66, Packet_GetJitTimeLogFilename = 67, Packet_GetJustMyCodeHandle = 68, @@ -1072,7 +1015,7 @@ enum mcPackets Packet_GetVars = 96, Packet_InitClass = 97, //Packet_InitConstraintsForVerification = 98, - Packet_IsCompatibleDelegate = 99, + //Packet_IsCompatibleDelegate = 99, //Packet_IsInstantiationOfVerifiedGeneric = 100, Packet_IsSDArray = 101, //Packet_IsStructRequiringStackAllocRetBuf = 102, @@ -1080,10 +1023,10 @@ enum mcPackets //Retired6 = 104, Packet_IsValueClass = 105, //Packet_IsWriteBarrierHelperRequired = 106, - Packet_MergeClasses = 107, + //Packet_MergeClasses = 107, Packet_PInvokeMarshalingRequired = 108, Packet_ResolveToken = 109, - Packet_SatisfiesClassConstraints = 110, + //Packet_SatisfiesClassConstraints = 110, Packet_SatisfiesMethodConstraints = 111, Packet_DoesFieldBelongToClass = 112, PacketCR_AddressMap = 113, @@ -1117,8 +1060,8 @@ enum mcPackets //Retired5 = 141, Packet_CheckMethodModifier = 142, Packet_CompileMethod = 143, - Packet_IsValidToken = 144, - Packet_FindNameOfToken = 145, + //Packet_IsValidToken = 144, + //Packet_FindNameOfToken = 145, //PacketCR_RecordCallSite = 146, Packet_GetLazyStringLiteralHelper = 147, Packet_IsIntrinsicType = 148, @@ -1131,7 +1074,7 @@ enum mcPackets Packet_IsDelegateCreationAllowed = 155, Packet_GetSystemVAmd64PassStructInRegisterDescriptor = 156, Packet_GetReadyToRunDelegateCtorHelper = 157, - Packet_TryResolveToken = 158, + //Packet_TryResolveToken = 158, Packet_GetHFAType = 159, Packet_ResolveVirtualMethod = 160, Packet_GetMethodNameFromMetadata = 161, @@ -1154,7 +1097,7 @@ enum mcPackets Packet_GetTailCallHelpers = 178, PacketCR_RecordCallSiteWithSignature = 179, PacketCR_RecordCallSiteWithoutSignature = 180, - Packet_GetMethodModule = 181, + //Packet_GetMethodModule = 181, //Retired10 = 182, Packet_GetExpectedTargetArchitecture = 183, Packet_SigInstHandleMap = 184, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp index 0ce0a4ccb39d1..9595d88ba68e6 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp @@ -234,55 +234,37 @@ std::string SpmiDumpHelper::DumpJitFlags(unsigned long long flags) AddFlag(DEBUG_INFO); AddFlag(MIN_OPT); AddFlag(ENABLE_CFG); - AddFlag(MCJIT_BACKGROUND); - - // x86 only - // - AddFlagNumeric(PINVOKE_RESTORE_ESP, 8); - - // UNUSED = 9 - // UNUSED = 10 - // UNUSED = 11 - // UNUSED = 12 - AddFlag(OSR); AddFlag(ALT_JIT); AddFlag(FROZEN_ALLOC_ALLOWED); - // UNUSED = 16 - // UNUSED = 17 AddFlag(MAKEFINALCODE); AddFlag(READYTORUN); AddFlag(PROF_ENTERLEAVE); - // UNUSED = 21 AddFlag(PROF_NO_PINVOKE_INLINE); - // UNUSED = 23 AddFlag(PREJIT); AddFlag(RELOC); - // UNUSED = 26 AddFlag(IL_STUB); AddFlag(PROCSPLIT); AddFlag(BBINSTR); + AddFlag(BBINSTR_IF_LOOPS); AddFlag(BBOPT); AddFlag(FRAMED); - AddFlag(BBINSTR_IF_LOOPS); AddFlag(PUBLISH_SECRET_PARAM); - // UNUSED = 34 - // UNUSED = 35 AddFlag(USE_PINVOKE_HELPERS); AddFlag(REVERSE_PINVOKE); AddFlag(TRACK_TRANSITIONS); AddFlag(TIER0); AddFlag(TIER1); + AddFlag(NO_INLINING); // arm32 only // - AddFlagNumeric(RELATIVE_CODE_RELOCS, 41); - - AddFlag(NO_INLINING); + AddFlagNumeric(RELATIVE_CODE_RELOCS, 29); + AddFlagNumeric(SOFTFP_ABI, 30); - // x86/x64 only + // xarch only // - AddFlagNumeric(VECTOR512_THROTTLING, 43); + AddFlagNumeric(VECTOR512_THROTTLING, 31); // "Extra jit flag" support // diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index c746be1fe5bd6..145b7ee9fce3f 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -184,15 +184,6 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getMethodClass(CORINFO_METHOD_HANDLE meth return temp; } -// return module it belongs to -CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule(CORINFO_METHOD_HANDLE method) -{ - mc->cr->AddCall("getMethodModule"); - CORINFO_MODULE_HANDLE temp = original_ICorJitInfo->getMethodModule(method); - mc->recGetMethodModule(method, temp); - return temp; -} - // This function returns the offset of the specified method in the // vtable of it's owning class or interface. void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */ @@ -288,7 +279,6 @@ bool interceptor_ICJI::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, C } // Check constraints on method type arguments (only). -// The parent class should be checked separately using satisfiesClassConstraints(parent). bool interceptor_ICJI::satisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, // the exact parent of the method CORINFO_METHOD_HANDLE method) { @@ -298,24 +288,6 @@ bool interceptor_ICJI::satisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, return temp; } -// Given a delegate target class, a target method parent class, a target method, -// a delegate class, check if the method signature is compatible with the Invoke method of the delegate -// (under the typical instantiation of any free type variables in the memberref signatures). -bool interceptor_ICJI::isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */ - CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */ - CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */ - CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */ - bool* pfIsOpenDelegate /* is the delegate open */ - ) -{ - mc->cr->AddCall("isCompatibleDelegate"); - bool temp = - original_ICorJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); - mc->recIsCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate, temp); - return temp; -} - // load and restore the method void interceptor_ICJI::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE method) { @@ -378,14 +350,6 @@ void interceptor_ICJI::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResol }); } -bool interceptor_ICJI::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResolvedToken) -{ - mc->cr->AddCall("tryResolveToken"); - bool success = original_ICorJitInfo->tryResolveToken(pResolvedToken); - mc->recResolveToken(pResolvedToken, success); - return success; -} - // Signature information about the call sig void interceptor_ICJI::findSig(CORINFO_MODULE_HANDLE module, /* IN */ unsigned sigTOK, /* IN */ @@ -420,28 +384,6 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getTokenTypeAsHandle(CORINFO_RESOLVED_TOK return temp; } -// Checks if the given metadata token is valid -bool interceptor_ICJI::isValidToken(CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK /* IN */ - ) -{ - mc->cr->AddCall("isValidToken"); - bool result = original_ICorJitInfo->isValidToken(module, metaTOK); - mc->recIsValidToken(module, metaTOK, result); - return result; -} - -// Checks if the given metadata token is valid StringRef -bool interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK /* IN */ - ) -{ - mc->cr->AddCall("isValidStringRef"); - bool temp = original_ICorJitInfo->isValidStringRef(module, metaTOK); - mc->recIsValidStringRef(module, metaTOK, temp); - return temp; -} - int interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */ unsigned metaTOK, /* IN */ char16_t* buffer, /* OUT */ @@ -918,15 +860,6 @@ TypeCompareState interceptor_ICJI::compareTypesForEquality(CORINFO_CLASS_HANDLE return temp; } -// returns the intersection of cls1 and cls2. -CORINFO_CLASS_HANDLE interceptor_ICJI::mergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) -{ - mc->cr->AddCall("mergeClasses"); - CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->mergeClasses(cls1, cls2); - mc->recMergeClasses(cls1, cls2, temp); - return temp; -} - // Returns true if cls2 is known to be a more specific type than cls1. bool interceptor_ICJI::isMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) { @@ -977,15 +910,6 @@ CorInfoType interceptor_ICJI::getChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_ return temp; } -// Check constraints on type arguments of this class and parent classes -bool interceptor_ICJI::satisfiesClassConstraints(CORINFO_CLASS_HANDLE cls) -{ - mc->cr->AddCall("satisfiesClassConstraints"); - bool temp = original_ICorJitInfo->satisfiesClassConstraints(cls); - mc->recSatisfiesClassConstraints(cls, temp); - return temp; -} - // Check if this is a single dimensional array type bool interceptor_ICJI::isSDArray(CORINFO_CLASS_HANDLE cls) { @@ -1401,19 +1325,6 @@ unsigned interceptor_ICJI::getMethodHash(CORINFO_METHOD_HANDLE ftn /* IN */ return temp; } -// this function is for debugging only. -size_t interceptor_ICJI::findNameOfToken(CORINFO_MODULE_HANDLE module, /* IN */ - mdToken metaTOK, /* IN */ - _Out_writes_(FQNameCapacity) char* szFQName, /* OUT */ - size_t FQNameCapacity /* IN */ - ) -{ - mc->cr->AddCall("findNameOfToken"); - size_t result = original_ICorJitInfo->findNameOfToken(module, metaTOK, szFQName, FQNameCapacity); - mc->recFindNameOfToken(module, metaTOK, szFQName, FQNameCapacity, result); - return result; -} - bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor( /* IN */ CORINFO_CLASS_HANDLE structHnd, /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) @@ -1450,14 +1361,6 @@ uint32_t interceptor_ICJI::getThreadTLSIndex(void** ppIndirection) return temp; } -const void* interceptor_ICJI::getInlinedCallFrameVptr(void** ppIndirection) -{ - mc->cr->AddCall("getInlinedCallFrameVptr"); - const void* temp = original_ICorJitInfo->getInlinedCallFrameVptr(ppIndirection); - mc->recGetInlinedCallFrameVptr(ppIndirection, temp); - return temp; -} - int32_t* interceptor_ICJI::getAddrOfCaptureThreadGlobal(void** ppIndirection) { mc->cr->AddCall("getAddrOfCaptureThreadGlobal"); @@ -1662,22 +1565,6 @@ void interceptor_ICJI::getCallInfo( }); } -bool interceptor_ICJI::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType) -{ - mc->cr->AddCall("canAccessFamily"); - bool temp = original_ICorJitInfo->canAccessFamily(hCaller, hInstanceType); - mc->recCanAccessFamily(hCaller, hInstanceType, temp); - return temp; -} - -// Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class -// except reflection emitted classes and generics) -bool interceptor_ICJI::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls) -{ - mc->cr->AddCall("isRIDClassDomainID"); - return original_ICorJitInfo->isRIDClassDomainID(cls); -} - // returns the class's domain ID for accessing shared statics unsigned interceptor_ICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection) { @@ -2013,13 +1900,12 @@ void interceptor_ICJI::recordRelocation(void* location, /* IN */ void* locationRW, /* IN */ void* target, /* IN */ uint16_t fRelocType, /* IN */ - uint16_t slotNum, /* IN */ int32_t addlDelta /* IN */ ) { mc->cr->AddCall("recordRelocation"); - original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); - mc->cr->recRecordRelocation(location, target, fRelocType, slotNum, addlDelta); + original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, addlDelta); + mc->cr->recRecordRelocation(location, target, fRelocType, addlDelta); } uint16_t interceptor_ICJI::getRelocTypeHint(void* target) diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 6d301f516f60b..70f64123a4790 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -114,13 +114,6 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getMethodClass( return original_ICorJitInfo->getMethodClass(method); } -CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule( - CORINFO_METHOD_HANDLE method) -{ - mcs->AddCall("getMethodModule"); - return original_ICorJitInfo->getMethodModule(method); -} - void interceptor_ICJI::getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, @@ -200,17 +193,6 @@ bool interceptor_ICJI::satisfiesMethodConstraints( return original_ICorJitInfo->satisfiesMethodConstraints(parent, method); } -bool interceptor_ICJI::isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - mcs->AddCall("isCompatibleDelegate"); - return original_ICorJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); -} - void interceptor_ICJI::methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method) { @@ -254,13 +236,6 @@ void interceptor_ICJI::resolveToken( original_ICorJitInfo->resolveToken(pResolvedToken); } -bool interceptor_ICJI::tryResolveToken( - CORINFO_RESOLVED_TOKEN* pResolvedToken) -{ - mcs->AddCall("tryResolveToken"); - return original_ICorJitInfo->tryResolveToken(pResolvedToken); -} - void interceptor_ICJI::findSig( CORINFO_MODULE_HANDLE module, unsigned sigTOK, @@ -288,22 +263,6 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getTokenTypeAsHandle( return original_ICorJitInfo->getTokenTypeAsHandle(pResolvedToken); } -bool interceptor_ICJI::isValidToken( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - mcs->AddCall("isValidToken"); - return original_ICorJitInfo->isValidToken(module, metaTOK); -} - -bool interceptor_ICJI::isValidStringRef( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - mcs->AddCall("isValidStringRef"); - return original_ICorJitInfo->isValidStringRef(module, metaTOK); -} - int interceptor_ICJI::getStringLiteral( CORINFO_MODULE_HANDLE module, unsigned metaTOK, @@ -666,14 +625,6 @@ TypeCompareState interceptor_ICJI::compareTypesForEquality( return original_ICorJitInfo->compareTypesForEquality(cls1, cls2); } -CORINFO_CLASS_HANDLE interceptor_ICJI::mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - mcs->AddCall("mergeClasses"); - return original_ICorJitInfo->mergeClasses(cls1, cls2); -} - bool interceptor_ICJI::isMoreSpecificType( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) @@ -705,13 +656,6 @@ CorInfoType interceptor_ICJI::getChildType( return original_ICorJitInfo->getChildType(clsHnd, clsRet); } -bool interceptor_ICJI::satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls) -{ - mcs->AddCall("satisfiesClassConstraints"); - return original_ICorJitInfo->satisfiesClassConstraints(cls); -} - bool interceptor_ICJI::isSDArray( CORINFO_CLASS_HANDLE cls) { @@ -988,16 +932,6 @@ unsigned interceptor_ICJI::getMethodHash( return original_ICorJitInfo->getMethodHash(ftn); } -size_t interceptor_ICJI::findNameOfToken( - CORINFO_MODULE_HANDLE moduleHandle, - mdToken token, - char* szFQName, - size_t FQNameCapacity) -{ - mcs->AddCall("findNameOfToken"); - return original_ICorJitInfo->findNameOfToken(moduleHandle, token, szFQName, FQNameCapacity); -} - bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) @@ -1027,13 +961,6 @@ uint32_t interceptor_ICJI::getThreadTLSIndex( return original_ICorJitInfo->getThreadTLSIndex(ppIndirection); } -const void* interceptor_ICJI::getInlinedCallFrameVptr( - void** ppIndirection) -{ - mcs->AddCall("getInlinedCallFrameVptr"); - return original_ICorJitInfo->getInlinedCallFrameVptr(ppIndirection); -} - int32_t* interceptor_ICJI::getAddrOfCaptureThreadGlobal( void** ppIndirection) { @@ -1182,21 +1109,6 @@ void interceptor_ICJI::getCallInfo( original_ICorJitInfo->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult); } -bool interceptor_ICJI::canAccessFamily( - CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) -{ - mcs->AddCall("canAccessFamily"); - return original_ICorJitInfo->canAccessFamily(hCaller, hInstanceType); -} - -bool interceptor_ICJI::isRIDClassDomainID( - CORINFO_CLASS_HANDLE cls) -{ - mcs->AddCall("isRIDClassDomainID"); - return original_ICorJitInfo->isRIDClassDomainID(cls); -} - unsigned interceptor_ICJI::getClassDomainID( CORINFO_CLASS_HANDLE cls, void** ppIndirection) @@ -1434,11 +1346,10 @@ void interceptor_ICJI::recordRelocation( void* locationRW, void* target, uint16_t fRelocType, - uint16_t slotNum, int32_t addlDelta) { mcs->AddCall("recordRelocation"); - original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); + original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, addlDelta); } uint16_t interceptor_ICJI::getRelocTypeHint( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 7dd611b5283dc..fb2d3246a9689 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -102,12 +102,6 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getMethodClass( return original_ICorJitInfo->getMethodClass(method); } -CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule( - CORINFO_METHOD_HANDLE method) -{ - return original_ICorJitInfo->getMethodModule(method); -} - void interceptor_ICJI::getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, @@ -177,16 +171,6 @@ bool interceptor_ICJI::satisfiesMethodConstraints( return original_ICorJitInfo->satisfiesMethodConstraints(parent, method); } -bool interceptor_ICJI::isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - return original_ICorJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); -} - void interceptor_ICJI::methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method) { @@ -224,12 +208,6 @@ void interceptor_ICJI::resolveToken( original_ICorJitInfo->resolveToken(pResolvedToken); } -bool interceptor_ICJI::tryResolveToken( - CORINFO_RESOLVED_TOKEN* pResolvedToken) -{ - return original_ICorJitInfo->tryResolveToken(pResolvedToken); -} - void interceptor_ICJI::findSig( CORINFO_MODULE_HANDLE module, unsigned sigTOK, @@ -254,20 +232,6 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getTokenTypeAsHandle( return original_ICorJitInfo->getTokenTypeAsHandle(pResolvedToken); } -bool interceptor_ICJI::isValidToken( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - return original_ICorJitInfo->isValidToken(module, metaTOK); -} - -bool interceptor_ICJI::isValidStringRef( - CORINFO_MODULE_HANDLE module, - unsigned metaTOK) -{ - return original_ICorJitInfo->isValidStringRef(module, metaTOK); -} - int interceptor_ICJI::getStringLiteral( CORINFO_MODULE_HANDLE module, unsigned metaTOK, @@ -584,13 +548,6 @@ TypeCompareState interceptor_ICJI::compareTypesForEquality( return original_ICorJitInfo->compareTypesForEquality(cls1, cls2); } -CORINFO_CLASS_HANDLE interceptor_ICJI::mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - return original_ICorJitInfo->mergeClasses(cls1, cls2); -} - bool interceptor_ICJI::isMoreSpecificType( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) @@ -618,12 +575,6 @@ CorInfoType interceptor_ICJI::getChildType( return original_ICorJitInfo->getChildType(clsHnd, clsRet); } -bool interceptor_ICJI::satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls) -{ - return original_ICorJitInfo->satisfiesClassConstraints(cls); -} - bool interceptor_ICJI::isSDArray( CORINFO_CLASS_HANDLE cls) { @@ -866,15 +817,6 @@ unsigned interceptor_ICJI::getMethodHash( return original_ICorJitInfo->getMethodHash(ftn); } -size_t interceptor_ICJI::findNameOfToken( - CORINFO_MODULE_HANDLE moduleHandle, - mdToken token, - char* szFQName, - size_t FQNameCapacity) -{ - return original_ICorJitInfo->findNameOfToken(moduleHandle, token, szFQName, FQNameCapacity); -} - bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) @@ -900,12 +842,6 @@ uint32_t interceptor_ICJI::getThreadTLSIndex( return original_ICorJitInfo->getThreadTLSIndex(ppIndirection); } -const void* interceptor_ICJI::getInlinedCallFrameVptr( - void** ppIndirection) -{ - return original_ICorJitInfo->getInlinedCallFrameVptr(ppIndirection); -} - int32_t* interceptor_ICJI::getAddrOfCaptureThreadGlobal( void** ppIndirection) { @@ -1036,19 +972,6 @@ void interceptor_ICJI::getCallInfo( original_ICorJitInfo->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult); } -bool interceptor_ICJI::canAccessFamily( - CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) -{ - return original_ICorJitInfo->canAccessFamily(hCaller, hInstanceType); -} - -bool interceptor_ICJI::isRIDClassDomainID( - CORINFO_CLASS_HANDLE cls) -{ - return original_ICorJitInfo->isRIDClassDomainID(cls); -} - unsigned interceptor_ICJI::getClassDomainID( CORINFO_CLASS_HANDLE cls, void** ppIndirection) @@ -1259,10 +1182,9 @@ void interceptor_ICJI::recordRelocation( void* locationRW, void* target, uint16_t fRelocType, - uint16_t slotNum, int32_t addlDelta) { - original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, slotNum, addlDelta); + original_ICorJitInfo->recordRelocation(location, locationRW, target, fRelocType, addlDelta); } uint16_t interceptor_ICJI::getRelocTypeHint( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 16d52438b6c40..756443dce9399 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -160,13 +160,6 @@ CORINFO_CLASS_HANDLE MyICJI::getMethodClass(CORINFO_METHOD_HANDLE method) return jitInstance->mc->repGetMethodClass(method); } -// return module it belongs to -CORINFO_MODULE_HANDLE MyICJI::getMethodModule(CORINFO_METHOD_HANDLE method) -{ - jitInstance->mc->cr->AddCall("getMethodModule"); - return jitInstance->mc->repGetMethodModule(method); -} - // This function returns the offset of the specified method in the // vtable of it's owning class or interface. void MyICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */ @@ -244,7 +237,6 @@ bool MyICJI::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SIG } // Check constraints on method type arguments (only). -// The parent class should be checked separately using satisfiesClassConstraints(parent). bool MyICJI::satisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, // the exact parent of the method CORINFO_METHOD_HANDLE method) { @@ -252,20 +244,6 @@ bool MyICJI::satisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, // the exa return jitInstance->mc->repSatisfiesMethodConstraints(parent, method); } -// Given a delegate target class, a target method parent class, a target method, -// a delegate class, check if the method signature is compatible with the Invoke method of the delegate -// (under the typical instantiation of any free type variables in the memberref signatures). -bool MyICJI::isCompatibleDelegate(CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */ - CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */ - CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */ - CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */ - bool* pfIsOpenDelegate /* is the delegate open */ - ) -{ - jitInstance->mc->cr->AddCall("isCompatibleDelegate"); - return jitInstance->mc->repIsCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); -} - // load and restore the method void MyICJI::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE method) { @@ -322,13 +300,6 @@ void MyICJI::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResolvedToken) ThrowException(exceptionCode); } -// Resolve metadata token into runtime method handles. -bool MyICJI::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResolvedToken) -{ - jitInstance->mc->cr->AddCall("tryResolveToken"); - return jitInstance->mc->repTryResolveToken(pResolvedToken); -} - // Signature information about the call sig void MyICJI::findSig(CORINFO_MODULE_HANDLE module, /* IN */ unsigned sigTOK, /* IN */ @@ -359,24 +330,6 @@ CORINFO_CLASS_HANDLE MyICJI::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResol return jitInstance->mc->repGetTokenTypeAsHandle(pResolvedToken); } -// Checks if the given metadata token is valid -bool MyICJI::isValidToken(CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK /* IN */ - ) -{ - jitInstance->mc->cr->AddCall("isValidToken"); - return jitInstance->mc->repIsValidToken(module, metaTOK); -} - -// Checks if the given metadata token is valid StringRef -bool MyICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK /* IN */ - ) -{ - jitInstance->mc->cr->AddCall("isValidStringRef"); - return jitInstance->mc->repIsValidStringRef(module, metaTOK); -} - int MyICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */ unsigned metaTOK, /* IN */ char16_t* buffer, /* OUT */ @@ -775,13 +728,6 @@ TypeCompareState MyICJI::compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORI return jitInstance->mc->repCompareTypesForEquality(cls1, cls2); } -// returns the intersection of cls1 and cls2. -CORINFO_CLASS_HANDLE MyICJI::mergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) -{ - jitInstance->mc->cr->AddCall("mergeClasses"); - return jitInstance->mc->repMergeClasses(cls1, cls2); -} - // Returns true if cls2 is known to be a more specific type than cls1 bool MyICJI::isMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) { @@ -819,13 +765,6 @@ CorInfoType MyICJI::getChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HAND return jitInstance->mc->repGetChildType(clsHnd, clsRet); } -// Check constraints on type arguments of this class and parent classes -bool MyICJI::satisfiesClassConstraints(CORINFO_CLASS_HANDLE cls) -{ - jitInstance->mc->cr->AddCall("satisfiesClassConstraints"); - return jitInstance->mc->repSatisfiesClassConstraints(cls); -} - // Check if this is a single dimensional array type bool MyICJI::isSDArray(CORINFO_CLASS_HANDLE cls) { @@ -1214,17 +1153,6 @@ unsigned MyICJI::getMethodHash(CORINFO_METHOD_HANDLE ftn /* IN */ return jitInstance->mc->repGetMethodHash(ftn); } -// this function is for debugging only. -size_t MyICJI::findNameOfToken(CORINFO_MODULE_HANDLE module, /* IN */ - mdToken metaTOK, /* IN */ - _Out_writes_(FQNameCapacity) char* szFQName, /* OUT */ - size_t FQNameCapacity /* IN */ - ) -{ - jitInstance->mc->cr->AddCall("findNameOfToken"); - return jitInstance->mc->repFindNameOfToken(module, metaTOK, szFQName, FQNameCapacity); -} - bool MyICJI::getSystemVAmd64PassStructInRegisterDescriptor( /* IN */ CORINFO_CLASS_HANDLE structHnd, /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) @@ -1252,12 +1180,6 @@ uint32_t MyICJI::getThreadTLSIndex(void** ppIndirection) return jitInstance->mc->repGetThreadTLSIndex(ppIndirection); } -const void* MyICJI::getInlinedCallFrameVptr(void** ppIndirection) -{ - jitInstance->mc->cr->AddCall("getInlinedCallFrameVptr"); - return jitInstance->mc->repGetInlinedCallFrameVptr(ppIndirection); -} - int32_t* MyICJI::getAddrOfCaptureThreadGlobal(void** ppIndirection) { jitInstance->mc->cr->AddCall("getAddrOfCaptureThreadGlobal"); @@ -1431,22 +1353,6 @@ void MyICJI::getCallInfo( ThrowException(exceptionCode); } -bool MyICJI::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType) - -{ - jitInstance->mc->cr->AddCall("canAccessFamily"); - return jitInstance->mc->repCanAccessFamily(hCaller, hInstanceType); -} -// Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class -// except reflection emitted classes and generics) -bool MyICJI::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls) -{ - jitInstance->mc->cr->AddCall("isRIDClassDomainID"); - LogError("Hit unimplemented isRIDClassDomainID"); - DebugBreakorAV(107); - return false; -} - // returns the class's domain ID for accessing shared statics unsigned MyICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection) { @@ -1846,12 +1752,11 @@ void MyICJI::recordRelocation(void* location, /* IN */ void* locationRW, /* IN */ void* target, /* IN */ uint16_t fRelocType, /* IN */ - uint16_t slotNum, /* IN */ int32_t addlDelta /* IN */ ) { jitInstance->mc->cr->AddCall("recordRelocation"); - jitInstance->mc->cr->repRecordRelocation(location, target, fRelocType, slotNum, addlDelta); + jitInstance->mc->cr->repRecordRelocation(location, target, fRelocType, addlDelta); } uint16_t MyICJI::getRelocTypeHint(void* target) diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 3655045215d3c..244ec5dc09adb 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -1537,37 +1537,6 @@ BOOL Module::IsRuntimeMarshallingEnabled() return hr != S_OK; } -BOOL Module::IsPreV4Assembly() -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - } - CONTRACTL_END - - if (!(m_dwPersistedFlags & COMPUTED_IS_PRE_V4_ASSEMBLY)) - { - IMDInternalImport *pImport = GetAssembly()->GetMDImport(); - _ASSERTE(pImport); - - BOOL fIsPreV4Assembly = FALSE; - LPCSTR szVersion = NULL; - if (SUCCEEDED(pImport->GetVersionString(&szVersion))) - { - if (szVersion != NULL && strlen(szVersion) > 2) - { - fIsPreV4Assembly = (szVersion[0] == 'v' || szVersion[0] == 'V') && - (szVersion[1] == '1' || szVersion[1] == '2'); - } - } - - InterlockedOr((LONG*)&m_dwPersistedFlags, COMPUTED_IS_PRE_V4_ASSEMBLY | - (fIsPreV4Assembly ? IS_PRE_V4_ASSEMBLY : 0)); - } - - return !!(m_dwPersistedFlags & IS_PRE_V4_ASSEMBLY); -} DWORD Module::AllocateDynamicEntry(MethodTable *pMT) { @@ -2844,18 +2813,6 @@ OBJECTHANDLE ModuleBase::ResolveStringRef(DWORD token, void** ppPinnedString) return string; } -// -// Used by the verifier. Returns whether this stringref is valid. -// -CHECK Module::CheckStringRef(DWORD token) -{ - LIMITED_METHOD_CONTRACT; - CHECK(TypeFromToken(token)==mdtString); - CHECK(!IsNilToken(token)); - CHECK(GetMDImport()->IsValidToken(token)); - CHECK_OK; -} - mdToken Module::GetEntryPointToken() { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 56dd2a4d25a6a..77ef721e7711d 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -679,10 +679,6 @@ class Module : public ModuleBase // This flag applies to assembly, but is also stored here so that it can be cached in ngen image COLLECTIBLE_MODULE = 0x00000080, - // Caches metadata version - COMPUTED_IS_PRE_V4_ASSEMBLY = 0x00000100, - IS_PRE_V4_ASSEMBLY = 0x00000200, - //If attribute value has been cached before DEFAULT_DLL_IMPORT_SEARCH_PATHS_IS_CACHED = 0x00000400, @@ -1183,8 +1179,6 @@ class Module : public ModuleBase // the class load, which avoids the need for a 'being loaded' list MethodTable* CreateArrayMethodTable(TypeHandle elemType, CorElementType kind, unsigned rank, class AllocMemTracker *pamTracker); - CHECK CheckStringRef(RVA rva); - // Module/Assembly traversal Assembly * GetAssemblyIfLoaded( mdAssemblyRef kAssemblyRef, @@ -1711,21 +1705,11 @@ class Module : public ModuleBase return (m_DefaultDllImportSearchPathsAttributeValue & 0x2) != 0; } - //----------------------------------------------------------------------------------------- - // True iff metadata version string is 1.* or 2.*. - // @TODO (post-Dev10): All places that need this information should call this function - // instead of parsing the version themselves. - //----------------------------------------------------------------------------------------- - BOOL IsPreV4Assembly(); - protected: - // initialize Crst controlling the Dynamic IL hashtables void InitializeDynamicILCrst(); -public: - private: // This struct stores the data used by the managed debugging infrastructure. If it turns out that diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index 792e640accaf5..06775e004629d 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -4971,168 +4971,6 @@ BOOL ClassLoader::CanAccessFamily( return FALSE; } -//If instance is an inner class, this also succeeds if the outer class conforms to 8.5.3.2. A nested class -//is enclosed inside of the enclosing class' open type. So we need to ignore generic variables. That also -//helps us with: -/* -class Base { - protected int m_family; -} -class Derived : Base { - class Inner { - public int function(Derived d) { - return d.m_family; - } - } -} -*/ - -//Since the inner T is not the same T as the enclosing T (since accessing generic variables is a CLS rule, -//not a CLI rule), we see that as a comparison between Derived and Derived. CanCastTo rejects that. -//Instead we just check against the typedef of the two types. This ignores all generic parameters (formal -//or not). - -BOOL CanAccessFamilyVerificationEnclosingHelper(MethodTable * pMTCurrentEnclosingClass, - TypeHandle thInstanceClass) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END - - _ASSERTE(pMTCurrentEnclosingClass); - - if (thInstanceClass.IsGenericVariable()) - { - //In this case it is a TypeVarTypeDesc (i.e. T). If this access would be legal due to a - //constraint: - // - /* - public class My - { - public class Inner where U : My - { - public int foo(U u) - { - return u.field; - } - } - protected int field; - } - */ - //We need to find the generic class constraint. (The above is legal because U must be a My which makes this - //legal by 8.5.3.2) - // There may only be 1 class constraint on a generic parameter - - // Get the constraints on this generic variable - // At most 1 of them is a class constraint. - // That class constraint methodtable can go through the normal search for matching typedef logic below - TypeVarTypeDesc *tyvar = thInstanceClass.AsGenericVariable(); - DWORD numConstraints; - TypeHandle *constraints = tyvar->GetConstraints(&numConstraints, CLASS_DEPENDENCIES_LOADED); - if (constraints == NULL) - { - // If we did not find a class constraint, we cannot generate a methodtable to search for - return FALSE; - } - else - { - for (DWORD i = 0; i < numConstraints; i++) - { - if (!constraints[i].IsInterface()) - { - // We have found the class constraint on this TypeVarTypeDesc - // Recurse on the found class constraint. It is possible that this constraint may also be a TypeVarTypeDesc -//class Outer4 -//{ -// protected int field; -// -// public class Inner where V:U where U : Outer4 -// { -// public int Method(V param) { return (++param.field); } -// } -//} - return CanAccessFamilyVerificationEnclosingHelper(pMTCurrentEnclosingClass, constraints[i]); - } - } - // If we did not find a class constraint, we cannot generate a methodtable to search for - return FALSE; - } - } - do - { - MethodTable * pAccessor = pMTCurrentEnclosingClass; - //If thInstanceClass is a MethodTable, we should only be doing the TypeDef comparison (see - //above). - if (!thInstanceClass.IsTypeDesc()) - { - MethodTable *pInstanceMT = thInstanceClass.AsMethodTable(); - - // This is a CanCastTo implementation for classes, assuming we should ignore generic instantiation parameters. - do - { - if (pAccessor->HasSameTypeDefAs(pInstanceMT)) - return TRUE; - pInstanceMT = pInstanceMT->GetParentMethodTable(); - }while(pInstanceMT); - } - else - { - // Leave this logic in place for now, as I'm not fully confident it can't happen, and we are very close to RTM - // This logic was originally written to handle TypeVarTypeDescs, but those are now handled above. - _ASSERTE(FALSE); - if (thInstanceClass.CanCastTo(TypeHandle(pAccessor))) - return TRUE; - } - - pMTCurrentEnclosingClass = GetEnclosingMethodTable(pMTCurrentEnclosingClass); - }while(pMTCurrentEnclosingClass); - return FALSE; -} - - -//This checks the verification only part of the rule above. -//From the example above: -// GrandChild::function2(Child * o) { -// o->protectedField; //This access is illegal. -// } -// pCurrentClass is GrandChild and pTargetClass is Child. This check is completely unnecessary for statics, -// but by legacy convention you can use GrandChild for pTargetClass in that case. - -BOOL ClassLoader::CanAccessFamilyVerification(TypeHandle thCurrentClass, - TypeHandle thInstanceClass) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - INJECT_FAULT(COMPlusThrowOM();); - MODE_ANY; - PRECONDITION(!thCurrentClass.IsNull()); - PRECONDITION(!thCurrentClass.IsTypeDesc()); - } - CONTRACTL_END - - //Check to see if Instance is equal to or derived from pCurrentClass. - // - //In some cases the type we have for the instance type is actually a TypeVarTypeDesc. In those cases we - //need to check against the constraints (You're accessing a member through a 'T' with a type constraint - //that makes this legal). For those cases, CanCastTo does what I want. - MethodTable * pAccessor = thCurrentClass.GetMethodTable(); - if (thInstanceClass.CanCastTo(TypeHandle(pAccessor))) - return TRUE; - - //TypeDescs don't have methods so only run this on MethodTables. - if (!thInstanceClass.IsNull()) - { - return CanAccessFamilyVerificationEnclosingHelper(pAccessor, thInstanceClass); - } - return FALSE; -} - #endif // #ifndef DACCESS_COMPILE #ifdef DACCESS_COMPILE diff --git a/src/coreclr/vm/clsload.hpp b/src/coreclr/vm/clsload.hpp index 6016e88d2cea7..fd2aabe3801ed 100644 --- a/src/coreclr/vm/clsload.hpp +++ b/src/coreclr/vm/clsload.hpp @@ -847,10 +847,6 @@ class ClassLoader FieldDesc* pOptionalTargetField, const AccessCheckOptions & accessCheckOptions = *AccessCheckOptions::s_pNormalAccessChecks); - static BOOL CanAccessFamilyVerification( - TypeHandle thCurrentClass, - TypeHandle thInstanceClass); - private: // Access check helpers static BOOL CanAccessMethodInstantiation( diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 32b5af3d0238f..a98268aa8f453 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -3020,68 +3020,6 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT } -/*@GENERICSVER: new (works for generics too) - Does a static validation of parameters passed into a delegate constructor. - - - For "new Delegate(obj.method)" where method is statically typed as "C::m" and - the static type of obj is D (some subclass of C)... - - Params: - instHnd : Static type of the instance, from which pFtn is obtained. Ignored if pFtn - is static (i.e. D) - ftnParentHnd: Parent of the MethodDesc, pFtn, used to create the delegate (i.e. type C) - pFtn : (possibly shared) MethodDesc of the function pointer used to create the delegate (i.e. C::m) - pDlgt : The delegate type (i.e. Delegate) - module: The module scoping methodMemberRef and delegateConstructorMemberRef - methodMemberRef: the MemberRef, MemberDef or MemberSpec of the target method (i.e. a mdToken for C::m) - delegateConstructorMemberRef: the MemberRef, MemberDef or MemberSpec of the delegate constructor (i.e. a mdToken for Delegate::.ctor) - - Validates the following conditions: - 1. If the function (pFtn) is not static, pInst should be equal to the type where - pFtn is defined or pInst should be a parent of pFtn's type. - 2. The signature of the function should be compatible with the signature - of the Invoke method of the delegate type. - The signature is retrieved from module, methodMemberRef and delegateConstructorMemberRef - - NB: Although some of these arguments are redundant, we pass them in to avoid looking up - information that should already be available. - Instead of comparing type handles modulo some context, the method directly compares metadata to avoid - loading classes referenced in the method signatures (hence the need for the module and member refs). - Also, because this method works directly on metadata, without allowing any additional instantiation of the - free type variables in the signature of the method or delegate constructor, this code - will *only* verify a constructor application at the typical (ie. formal) instantiation. -*/ -/* static */ -bool COMDelegate::ValidateCtor(TypeHandle instHnd, - TypeHandle ftnParentHnd, - MethodDesc *pFtn, - TypeHandle dlgtHnd, - bool *pfIsOpenDelegate) - -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - - PRECONDITION(CheckPointer(pFtn)); - PRECONDITION(!dlgtHnd.IsNull()); - PRECONDITION(!ftnParentHnd.IsNull()); - - INJECT_FAULT(COMPlusThrowOM()); // from MetaSig::CompareElementType - } - CONTRACTL_END; - - DelegateEEClass *pdlgEEClass = (DelegateEEClass*)dlgtHnd.AsMethodTable()->GetClass(); - PREFIX_ASSUME(pdlgEEClass != NULL); - MethodDesc *pDlgtInvoke = pdlgEEClass->GetInvokeMethod(); - if (pDlgtInvoke == NULL) - return false; - return IsMethodDescCompatible(instHnd, ftnParentHnd, pFtn, dlgtHnd, pDlgtInvoke, DBF_RelaxedSignature, pfIsOpenDelegate); -} - BOOL COMDelegate::IsWrapperDelegate(DELEGATEREF dRef) { CONTRACTL diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index 0b280afc914ba..4f693ccae8274 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -132,9 +132,6 @@ class COMDelegate int flags, bool *pfIsOpenDelegate); static MethodDesc* GetDelegateCtor(TypeHandle delegateType, MethodDesc *pTargetMethod, DelegateCtorArgs *pCtorData); - //@GENERICSVER: new (suitable for generics) - // Method to do static validation of delegate .ctor - static bool ValidateCtor(TypeHandle objHnd, TypeHandle ftnParentHnd, MethodDesc *pFtn, TypeHandle dlgtHnd, bool *pfIsOpenDelegate); private: static void BindToMethod(DELEGATEREF *pRefThis, diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 90cf7a9241d91..ddd3bb66c98b6 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -813,6 +813,7 @@ DEFINE_FIELD_U(iFrameCount, StackFrameHelper, iFrameCount) DEFINE_CLASS(STARTUP_HOOK_PROVIDER, System, StartupHookProvider) DEFINE_METHOD(STARTUP_HOOK_PROVIDER, MANAGED_STARTUP, ManagedStartup, SM_PtrChar_RetVoid) +DEFINE_METHOD(STARTUP_HOOK_PROVIDER, CALL_STARTUP_HOOK, CallStartupHook, SM_PtrChar_RetVoid) DEFINE_CLASS(STREAM, IO, Stream) DEFINE_METHOD(STREAM, BEGIN_READ, BeginRead, IM_ArrByte_Int_Int_AsyncCallback_Object_RetIAsyncResult) diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index a860846d5f50d..fafb5213b6046 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -335,13 +335,33 @@ static uint32_t ds_rt_apply_startup_hook (const ep_char16_t *startup_hook_path) { + if (NULL == startup_hook_path) + return DS_IPC_E_INVALIDARG; + HRESULT hr = S_OK; // This is set to true when the EE has initialized, which occurs after // the diagnostic suspension point has completed. if (g_fEEStarted) { - // TODO: Support loading and executing startup hook after EE has completely initialized. - return DS_IPC_E_INVALIDARG; + // This is not actually starting the EE (the above already checked that), + // but waits for the EE to be started so that the startup hook can be loaded + // and executed. + IfFailRet(EnsureEEStarted()); + + EX_TRY { + GCX_COOP(); + + // Load and call startup hook since managed execution is already running. + MethodDescCallSite callStartupHook(METHOD__STARTUP_HOOK_PROVIDER__CALL_STARTUP_HOOK); + + ARG_SLOT args[1]; + args[0] = PtrToArgSlot(startup_hook_path); + + callStartupHook.Call(args); + } + EX_CATCH_HRESULT (hr); + + IfFailRet(hr); } else { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 6727949fea6d5..388b5156f4fba 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -611,107 +611,6 @@ CORINFO_CLASS_HANDLE CEEInfo::getTokenTypeAsHandle (CORINFO_RESOLVED_TOKEN * pRe return tokenType; } -/*********************************************************************/ -size_t CEEInfo::findNameOfToken ( - CORINFO_MODULE_HANDLE scopeHnd, - mdToken metaTOK, - _Out_writes_ (FQNameCapacity) char * szFQName, - size_t FQNameCapacity) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - size_t NameLen = 0; - - JIT_TO_EE_TRANSITION(); - - if (IsDynamicScope(scopeHnd)) - { - strncpy_s (szFQName, FQNameCapacity, "DynamicToken", FQNameCapacity - 1); - NameLen = strlen (szFQName); - } - else - { - Module* module = (Module *)scopeHnd; - NameLen = findNameOfToken(module, metaTOK, szFQName, FQNameCapacity); - } - - EE_TO_JIT_TRANSITION(); - - return NameLen; -} - -/*********************************************************************/ -// Checks if the given metadata token is valid -bool CEEInfo::isValidToken ( - CORINFO_MODULE_HANDLE module, - mdToken metaTOK) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - bool result = false; - - JIT_TO_EE_TRANSITION_LEAF(); - - if (IsDynamicScope(module)) - { - // No explicit token validation for dynamic code. Validation is - // side-effect of token resolution. - result = true; - } - else - { - result = ((Module *)module)->GetMDImport()->IsValidToken(metaTOK); - } - - EE_TO_JIT_TRANSITION_LEAF(); - - return result; -} - -/*********************************************************************/ -// Checks if the given metadata token is valid StringRef -bool CEEInfo::isValidStringRef ( - CORINFO_MODULE_HANDLE module, - mdToken metaTOK) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - bool result = true; - - JIT_TO_EE_TRANSITION(); - - if (IsDynamicScope(module)) - { - result = GetDynamicResolver(module)->IsValidStringRef(metaTOK); - } - else - { - result = ((Module *)module)->CheckStringRef(metaTOK); - if (result) - { - DWORD dwCharCount; - LPCWSTR pString; - result = (!FAILED(((Module *)module)->GetMDImport()->GetUserString(metaTOK, &dwCharCount, NULL, &pString)) && - pString != NULL); - } - } - - EE_TO_JIT_TRANSITION(); - - return result; -} int CEEInfo::getStringLiteral ( CORINFO_MODULE_HANDLE moduleHnd, @@ -1230,117 +1129,6 @@ void CEEInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken EE_TO_JIT_TRANSITION(); } -/*********************************************************************/ -struct TryResolveTokenFilterParam -{ - CEEInfo* m_this; - CORINFO_RESOLVED_TOKEN* m_resolvedToken; - EXCEPTION_POINTERS m_exceptionPointers; - bool m_success; -}; - -bool isValidTokenForTryResolveToken(CEEInfo* info, CORINFO_RESOLVED_TOKEN* resolvedToken) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - if (!info->isValidToken(resolvedToken->tokenScope, resolvedToken->token)) - { - return false; - } - - CorInfoTokenKind tokenType = resolvedToken->tokenType; - switch (TypeFromToken(resolvedToken->token)) - { - case mdtModuleRef: - case mdtTypeDef: - case mdtTypeRef: - case mdtTypeSpec: - if ((tokenType & CORINFO_TOKENKIND_Class) == 0) - return false; - break; - - case mdtMethodDef: - case mdtMethodSpec: - if ((tokenType & CORINFO_TOKENKIND_Method) == 0) - return false; - break; - - case mdtFieldDef: - if ((tokenType & CORINFO_TOKENKIND_Field) == 0) - return false; - break; - - case mdtMemberRef: - if ((tokenType & (CORINFO_TOKENKIND_Method | CORINFO_TOKENKIND_Field)) == 0) - return false; - break; - - default: - return false; - } - - return true; -} - -LONG EEFilterException(struct _EXCEPTION_POINTERS* exceptionPointers, void* unused); - -LONG TryResolveTokenFilter(struct _EXCEPTION_POINTERS* exceptionPointers, void* theParam) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - // Backward compatibility: Convert bad image format exceptions thrown while resolving tokens - // to simple true/false successes. This is done for backward compatibility only. Ideally, - // we would always treat bad tokens in the IL stream as fatal errors. - if (exceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS) - { - auto* param = reinterpret_cast(theParam); - if (!isValidTokenForTryResolveToken(param->m_this, param->m_resolvedToken)) - { - param->m_exceptionPointers = *exceptionPointers; - return EEFilterException(exceptionPointers, nullptr); - } - } - - return EXCEPTION_CONTINUE_SEARCH; -} - -bool CEEInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken) -{ - // No dynamic contract here because SEH is used - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_TRIGGERS; - STATIC_CONTRACT_MODE_PREEMPTIVE; - - TryResolveTokenFilterParam param; - param.m_this = this; - param.m_resolvedToken = resolvedToken; - param.m_success = true; - - PAL_TRY(TryResolveTokenFilterParam*, pParam, ¶m) - { - pParam->m_this->resolveToken(pParam->m_resolvedToken); - } - PAL_EXCEPT_FILTER(TryResolveTokenFilter) - { - if (param.m_exceptionPointers.ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS) - { - HandleException(¶m.m_exceptionPointers); - } - - param.m_success = false; - } - PAL_ENDTRY - - return param.m_success; -} /*********************************************************************/ // We have a few frequently used constants in CoreLib that are defined as @@ -4464,74 +4252,6 @@ TypeCompareState CEEInfo::compareTypesForEquality( return result; } -/*********************************************************************/ -// returns the intersection of cls1 and cls2. -CORINFO_CLASS_HANDLE CEEInfo::mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - CORINFO_CLASS_HANDLE result = NULL; - - JIT_TO_EE_TRANSITION(); - - TypeHandle merged = TypeHandle::MergeTypeHandlesToCommonParent(TypeHandle(cls1), TypeHandle(cls2)); -#ifdef _DEBUG - { - //Make sure the merge is reflexive in the cases we "support". - TypeHandle hnd1 = TypeHandle(cls1); - TypeHandle hnd2 = TypeHandle(cls2); - TypeHandle reflexive = TypeHandle::MergeTypeHandlesToCommonParent(hnd2, hnd1); - - //If both sides are classes than either they have a common non-interface parent (in which case it is - //reflexive) - //OR they share a common interface, and it can be order dependent (if they share multiple interfaces - //in common) - if (!hnd1.IsInterface() && !hnd2.IsInterface()) - { - if (merged.IsInterface()) - { - _ASSERTE(reflexive.IsInterface()); - } - else - { - _ASSERTE(merged == reflexive); - } - } - //Both results must either be interfaces or classes. They cannot be mixed. - _ASSERTE((!!merged.IsInterface()) == (!!reflexive.IsInterface())); - - //If the result of the merge was a class, then the result of the reflexive merge was the same class. - if (!merged.IsInterface()) - { - _ASSERTE(merged == reflexive); - } - - // If both sides are arrays, then the result is either an array or g_pArrayClass. The above is - // actually true for reference types as well, but it is a little excessive to deal with. - if (hnd1.IsArray() && hnd2.IsArray()) - { - _ASSERTE((merged.IsArray() && reflexive.IsArray()) - || ((merged == g_pArrayClass) && (reflexive == g_pArrayClass))); - } - - //Can I assert anything about generic variables? - - //The results must always be assignable - _ASSERTE(hnd1.CanCastTo(merged) && hnd2.CanCastTo(merged) && hnd1.CanCastTo(reflexive) - && hnd2.CanCastTo(reflexive)); - } -#endif - result = CORINFO_CLASS_HANDLE(merged.AsPtr()); - - EE_TO_JIT_TRANSITION(); - return result; -} /*********************************************************************/ static BOOL isMoreSpecificTypeHelper( @@ -4734,28 +4454,6 @@ CorInfoType CEEInfo::getChildType ( return ret; } -/*********************************************************************/ -// Check any constraints on class type arguments -bool CEEInfo::satisfiesClassConstraints(CORINFO_CLASS_HANDLE cls) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - bool result = false; - - JIT_TO_EE_TRANSITION(); - - _ASSERTE(cls != NULL); - result = TypeHandle(cls).SatisfiesClassConstraints(); - - EE_TO_JIT_TRANSITION(); - - return result; -} - /*********************************************************************/ // Check if this is a single dimensional array type bool CEEInfo::isSDArray(CORINFO_CLASS_HANDLE cls) @@ -5695,74 +5393,6 @@ void CEEInfo::getCallInfo( EE_TO_JIT_TRANSITION(); } -bool CEEInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) -{ - WRAPPER_NO_CONTRACT; - - bool ret = false; - - //Since this is only for verification, I don't need to do the demand. - JIT_TO_EE_TRANSITION(); - - TypeHandle targetType = TypeHandle(hInstanceType); - TypeHandle accessingType = TypeHandle(GetMethod(hCaller)->GetMethodTable()); - AccessCheckOptions::AccessCheckType accessCheckOptions = AccessCheckOptions::kNormalAccessibilityChecks; - DynamicResolver* pIgnored; - BOOL doCheck = TRUE; - if (GetMethod(hCaller)->IsDynamicMethod()) - { - //If this is a DynamicMethod, perform the check from the type to which the DynamicMethod was - //attached. - // - //If this is a dynamic method, don't do this check. If they specified SkipVisibilityChecks - //(ModifyCheckForDynamicMethod returned false), we should obviously skip the check for the C++ - //protected rule (since we skipped all the other visibility checks). If they specified - //RestrictedSkipVisibilityChecks, then they're a "free" DynamicMethod. This check is meaningless - //(i.e. it would always fail). We've already done a demand for access to the member. Let that be - //enough. - doCheck = ModifyCheckForDynamicMethod(GetMethod(hCaller)->AsDynamicMethodDesc()->GetResolver(), - &accessingType, &accessCheckOptions, &pIgnored); - if (accessCheckOptions == AccessCheckOptions::kRestrictedMemberAccess - || accessCheckOptions == AccessCheckOptions::kRestrictedMemberAccessNoTransparency - ) - doCheck = FALSE; - } - - if (doCheck) - { - ret = !!ClassLoader::CanAccessFamilyVerification(accessingType, targetType); - } - else - { - ret = true; - } - - EE_TO_JIT_TRANSITION(); - return ret; -} - -bool CEEInfo::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - bool result = FALSE; - - JIT_TO_EE_TRANSITION(); - - TypeHandle VMClsHnd(cls); - - result = !VMClsHnd.AsMethodTable()->IsDynamicStatics(); - - EE_TO_JIT_TRANSITION(); - - return result; -} - /***********************************************************************/ unsigned CEEInfo::getClassDomainID (CORINFO_CLASS_HANDLE clsHnd, @@ -8703,37 +8333,6 @@ CEEInfo::getMethodClass( return result; } -/***********************************************************************/ -CORINFO_MODULE_HANDLE CEEInfo::getMethodModule (CORINFO_METHOD_HANDLE methodHnd) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - CORINFO_MODULE_HANDLE result = NULL; - - JIT_TO_EE_TRANSITION_LEAF(); - - MethodDesc* method = GetMethod(methodHnd); - - if (method->IsDynamicMethod()) - { - // this should never be called, thus the assert, I don't know if the (non existent) caller - // expects the Module or the scope - UNREACHABLE(); - } - else - { - result = (CORINFO_MODULE_HANDLE) method->GetModule(); - } - - EE_TO_JIT_TRANSITION_LEAF(); - - return result; -} - /*********************************************************************/ bool CEEInfo::isIntrinsicType(CORINFO_CLASS_HANDLE classHnd) { @@ -10127,56 +9726,6 @@ bool CEEInfo::satisfiesMethodConstraints( } - -/*********************************************************************/ -// Given a delegate target class, a target method parent class, a target method, -// a delegate class, check if the method signature is compatible with the Invoke method of the delegate -// (under the typical instantiation of any free type variables in the memberref signatures). -// -// objCls should be NULL if the target object is NULL -//@GENERICSVER: new (suitable for generics) -bool CEEInfo::isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - bool result = false; - - JIT_TO_EE_TRANSITION(); - - _ASSERTE(method != NULL); - _ASSERTE(delegateCls != NULL); - - TypeHandle delegateClsHnd = (TypeHandle) delegateCls; - - _ASSERTE(delegateClsHnd.GetMethodTable()->IsDelegate()); - - TypeHandle methodParentHnd = (TypeHandle) (methodParentCls); - MethodDesc* pMDFtn = GetMethod(method); - TypeHandle objClsHnd(objCls); - - EX_TRY - { - result = COMDelegate::ValidateCtor(objClsHnd, methodParentHnd, pMDFtn, delegateClsHnd, pfIsOpenDelegate); - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions) - - EE_TO_JIT_TRANSITION(); - - return result; -} - /*********************************************************************/ // return address of fixup area for late-bound N/Direct calls. void CEEInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, @@ -10360,27 +9909,6 @@ uint32_t CEEInfo::getThreadTLSIndex(void **ppIndirection) return result; } -const void * CEEInfo::getInlinedCallFrameVptr(void **ppIndirection) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - void * result = NULL; - - if (ppIndirection != NULL) - *ppIndirection = NULL; - - JIT_TO_EE_TRANSITION_LEAF(); - - result = (void*)InlinedCallFrame::GetMethodFrameVPtr(); - - EE_TO_JIT_TRANSITION_LEAF(); - - return result; -} int32_t * CEEInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection) { @@ -11534,7 +11062,6 @@ void CEEJitInfo::recordRelocation(void * location, void * locationRW, void * target, WORD fRelocType, - WORD slot, INT32 addlDelta) { CONTRACTL { @@ -11552,7 +11079,7 @@ void CEEJitInfo::recordRelocation(void * location, { case IMAGE_REL_BASED_DIR64: // Write 64-bits into location - *((UINT64 *) ((BYTE *) locationRW + slot)) = (UINT64) target; + *((UINT64 *) locationRW) = (UINT64) target; break; #ifdef TARGET_AMD64 @@ -11560,8 +11087,8 @@ void CEEJitInfo::recordRelocation(void * location, { target = (BYTE *)target + addlDelta; - INT32 * fixupLocation = (INT32 *) ((BYTE *) location + slot); - INT32 * fixupLocationRW = (INT32 *) ((BYTE *) locationRW + slot); + INT32 * fixupLocation = (INT32 *) location; + INT32 * fixupLocationRW = (INT32 *) locationRW; BYTE * baseAddr = (BYTE *)fixupLocation + sizeof(INT32); delta = (INT64)((BYTE *)target - baseAddr); @@ -11615,7 +11142,6 @@ void CEEJitInfo::recordRelocation(void * location, #ifdef TARGET_ARM64 case IMAGE_REL_ARM64_BRANCH26: // 26 bit offset << 2 & sign ext, for B and BL { - _ASSERTE(slot == 0); _ASSERTE(addlDelta == 0); PCODE branchTarget = (PCODE) target; @@ -11692,7 +11218,6 @@ void CEEJitInfo::recordRelocation(void * location, case IMAGE_REL_ARM64_PAGEBASE_REL21: { - _ASSERTE(slot == 0); _ASSERTE(addlDelta == 0); // Write the 21 bits pc-relative page address into location. @@ -11706,7 +11231,6 @@ void CEEJitInfo::recordRelocation(void * location, case IMAGE_REL_ARM64_PAGEOFFSET_12A: { - _ASSERTE(slot == 0); _ASSERTE(addlDelta == 0); // Write the 12 bits page offset into location. @@ -12771,10 +12295,6 @@ CorJitResult invokeCompileMethod(EEJitManager *jitMgr, CORJIT_FLAGS flags; if (g_pConfig->JitFramed()) flags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); -#ifdef TARGET_X86 - if (g_pConfig->PInvokeRestoreEsp(ftn->GetModule()->IsPreV4Assembly())) - flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PINVOKE_RESTORE_ESP); -#endif // TARGET_X86 // Set flags based on method's ImplFlags. if (!ftn->IsNoMetadata()) @@ -13237,17 +12757,14 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, { jitInfo.WriteCode(jitMgr); #if defined(DEBUGGING_SUPPORTED) - if (!pJitFlags->IsSet(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND)) + // + // Notify the debugger that we have successfully jitted the function + // + if (g_pDebugInterface) { - // - // Notify the debugger that we have successfully jitted the function - // - if (g_pDebugInterface) + if (!jitInfo.JitAgain()) { - if (!jitInfo.JitAgain()) - { - g_pDebugInterface->JITComplete(nativeCodeVersion, (TADDR)nativeEntry); - } + g_pDebugInterface->JITComplete(nativeCodeVersion, (TADDR)nativeEntry); } } #endif // DEBUGGING_SUPPORTED @@ -14557,7 +14074,6 @@ void CEEInfo::recordRelocation( void * locationRW, /* IN */ void * target, /* IN */ WORD fRelocType, /* IN */ - WORD slotNum, /* IN */ INT32 addlDelta /* IN */ ) { diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 862b363dbe772..26837eb6622c3 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -653,7 +653,6 @@ class CEEJitInfo : public CEEInfo void *locationRW, void *target, uint16_t fRelocType, - uint16_t slot, int32_t addlDelta) override final; uint16_t getRelocTypeHint(void * target) override final; diff --git a/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs b/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs index 9285def9f15d8..4233fc4094cb1 100644 --- a/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs +++ b/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs @@ -5,7 +5,6 @@ using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; -using System.Runtime.Versioning; using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; @@ -16,25 +15,59 @@ namespace System.Threading /// internal sealed class AsyncOverSyncWithIoCancellation { - /// A thread handle for the current OS thread. - /// This is lazily-initialized for the current OS thread. We rely on finalization to clean up after it when the thread goes away. + /// The for the current thread. + /// + /// The safety of caching this on the current thread is based on the fact that all work performed + /// is synchronous on this thread. If a cancellation callback occurs on a different thread, that + /// could be using this instance, but only between the time that the operation is initiated on this + /// thread and disposal completes on this thread. + /// [ThreadStatic] - private static SafeThreadHandle? t_currentThreadHandle; + private static AsyncOverSyncWithIoCancellation? t_instance; /// The OS handle of the thread performing the I/O. - private SafeThreadHandle? ThreadHandle; + /// This is stored as part of the object's construction because the objects are thread affinitized. + private readonly SafeThreadHandle? _threadHandle; + /// Whether the call to CancellationToken.UnsafeRegister completed. - private volatile bool FinishedCancellationRegistration; + private bool _finishedCancellationRegistration; /// Whether the I/O operation has finished (successfully or unsuccessfully) and is requesting cancellation attempts stop. - private volatile bool ContinueTryingToCancel = true; + private bool _continueTryingToCancel; /// /// A task that may be checked after the has been disposed. If it's null at that point, /// the callback wasn't and will never be invoked. If it's non-null, its completion represents the completion of the asynchronous callback. /// - private volatile Task? CallbackCompleted; + private Task? _callbackCompleted; + + /// Initialize the instance. This should be done once per thread. + private AsyncOverSyncWithIoCancellation() + { + // Get a handle for the current thread. This is stored and used to cancel the I/O on this thread + // in response to the cancellation token having cancellation requested. If the handle is invalid, + // which could happen if OpenThread fails, skip attempts at cancellation. The handle needs to be + // opened with THREAD_TERMINATE in order to be able to call CancelSynchronousIo. + SafeThreadHandle handle = Interop.Kernel32.OpenThread(Interop.Kernel32.THREAD_TERMINATE, bInheritHandle: false, Interop.Kernel32.GetCurrentThreadId()); + if (!handle.IsInvalid) + { + _threadHandle = handle; + } + else + { +#if DEBUG + int lastError = Marshal.GetLastPInvokeError(); + Debug.Fail($"{nameof(Interop.Kernel32.OpenThread)} unexpectedly failed with 0x{lastError:X8}: {Marshal.GetPInvokeErrorMessage(lastError)}"); +#endif + handle.Dispose(); + } + } - /// Prevent external instantiation. - private AsyncOverSyncWithIoCancellation() { } + /// Resets this instance's state to be ready for another use on this thread. + private void Reset() + { + _finishedCancellationRegistration = false; + _continueTryingToCancel = true; + _callbackCompleted = null; + } /// Queues the invocation of to the thread pool. /// The type of the state passed to . @@ -51,12 +84,13 @@ private AsyncOverSyncWithIoCancellation() { } [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))] public static async ValueTask InvokeAsync(Action action, TState state, CancellationToken cancellationToken) { - // Queue the work to complete asynchronously. + // Queue the work to complete asynchronously. Logically, this is just queueing a work item to the thread pool. + // We use a ForceYielding awaiter in combination with the PoolingAsyncValueTaskMethodBuilder to reduce allocation. await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); - // Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used inside - // the using block, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. The func - // _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work. + // Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used + // after this point, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. + // The func _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work. SyncAsyncWorkItemRegistration reg = RegisterCancellation(cancellationToken); try { @@ -68,7 +102,7 @@ public static async ValueTask InvokeAsync(Action action, TState } finally { - await reg.DisposeAsync().ConfigureAwait(false); + reg.Dispose(); } } @@ -88,12 +122,13 @@ public static async ValueTask InvokeAsync(Action action, TState [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))] public static async ValueTask InvokeAsync(Func func, TState state, CancellationToken cancellationToken) { - // Queue the work to complete asynchronously. + // Queue the work to complete asynchronously. Logically, this is just queueing a work item to the thread pool. + // We use a ForceYielding awaiter in combination with the PoolingAsyncValueTaskMethodBuilder to reduce allocation. await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); - // Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used inside - // the using block, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. The func - // _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work. + // Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used + // after this point, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. + // The func _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work. SyncAsyncWorkItemRegistration reg = RegisterCancellation(cancellationToken); try { @@ -105,7 +140,7 @@ public static async ValueTask InvokeAsync(FuncThe struct IDisposable returned from RegisterCancellation in order to clean up after the registration. - private struct SyncAsyncWorkItemRegistration : IDisposable, IAsyncDisposable + /// + /// This does not implement IAsyncDisposable, even though async disposal could await both cancellation registration disposal + /// and the callback completion. By only supporting synchronous disposal, we can ensure that all relevant work happens + /// on the calling thread, which in turn allows us to use a per-thread singleton that avoids allocation in the most + /// common case (an operation being performed with a cancelable token). The benefit of async disposal would be that _if_ + /// cancellation occurred while the operation was in progress, we could avoid blocking the disposing thread until the + /// cancellation request completes. However, this is a rare case, and even when it occurs, it's expected to be very fast, + /// and in general should be completed by the time we even get to the disposal itself. + /// + private struct SyncAsyncWorkItemRegistration : IDisposable { public AsyncOverSyncWithIoCancellation WorkItem; public CancellationTokenRegistration CancellationRegistration; @@ -141,7 +185,7 @@ public void Dispose() // Prior to calling Dispose on the CancellationTokenRegistration, we need to tell // the registration callback to exit if it's currently running; otherwise, we could deadlock. - WorkItem.ContinueTryingToCancel = false; + Volatile.Write(ref WorkItem._continueTryingToCancel, false); // Then we need to dispose of the registration. Upon Dispose returning, we know that // either the synchronous invocation of the callback completed or that the callback @@ -150,64 +194,33 @@ public void Dispose() // Now that we know the synchronous callback has quiesced, check to see whether it scheduled // asynchronous work. If it did, wait for that work to complete. - WorkItem.CallbackCompleted?.GetAwaiter().GetResult(); - } - - /// Asynchronously waits for any pending cancellation callback to complete and cleans up resources. - public async ValueTask DisposeAsync() - { - if (WorkItem is null) - { - return; - } - - // Prior to calling Dispose on the CancellationTokenRegistration, we need to tell - // the registration callback to exit if it's currently running; otherwise, we could deadlock. - WorkItem.ContinueTryingToCancel = false; - - // Then we need to dispose of the registration. Upon Dispose returning, we know that - // either the synchronous invocation of the callback completed or that the callback - // will never be invoked. - await CancellationRegistration.DisposeAsync().ConfigureAwait(false); - - // Now that we know the synchronous callback has quiesced, check to see whether it scheduled - // asynchronous work. If it did, wait for that work to complete. - if (WorkItem.CallbackCompleted is Task t) - { - await t.ConfigureAwait(false); - } + WorkItem._callbackCompleted?.GetAwaiter().GetResult(); } } /// Registers for cancellation with the specified token. /// Upon cancellation being requested, the implementation will attempt to CancelSynchronousIo for the thread calling RegisterCancellation. - private static SyncAsyncWorkItemRegistration RegisterCancellation(CancellationToken cancellationToken) => - cancellationToken.CanBeCanceled ? RegisterCancellation(new AsyncOverSyncWithIoCancellation(), cancellationToken) : - default; // If the token can't be canceled, there's nothing to register. - - /// Registers for cancellation with the specified token. - /// Upon cancellation being requested, the implementation will attempt to CancelSynchronousIo for the thread calling RegisterCancellation. - private static SyncAsyncWorkItemRegistration RegisterCancellation(AsyncOverSyncWithIoCancellation instance, CancellationToken cancellationToken) + private static SyncAsyncWorkItemRegistration RegisterCancellation(CancellationToken cancellationToken) { - // Get a handle for the current thread. This is stored and used to cancel the I/O on this thread - // in response to the cancellation token having cancellation requested. If the handle is invalid, - // which could happen if OpenThread fails, skip attempts at cancellation. The handle needs to be - // opened with THREAD_TERMINATE in order to be able to call CancelSynchronousIo. - instance.ThreadHandle = t_currentThreadHandle; - if (instance.ThreadHandle is null) + if (!cancellationToken.CanBeCanceled) { - instance.ThreadHandle = Interop.Kernel32.OpenThread(Interop.Kernel32.THREAD_TERMINATE, bInheritHandle: false, Interop.Kernel32.GetCurrentThreadId()); - if (instance.ThreadHandle.IsInvalid) - { - int lastError = Marshal.GetLastPInvokeError(); - Debug.Fail($"{nameof(Interop.Kernel32.OpenThread)} unexpectedly failed with 0x{lastError:X8}: {Marshal.GetPInvokeErrorMessage(lastError)}"); - return default; - } + return default; + } - t_currentThreadHandle = instance.ThreadHandle; + cancellationToken.ThrowIfCancellationRequested(); + + // Get the instance for this thread. If the instance doesn't have a thread handle, that + // means we were unable to obtain one previously, and we shouldn't try to cancel I/O. + AsyncOverSyncWithIoCancellation instance = t_instance ??= new AsyncOverSyncWithIoCancellation(); + if (instance._threadHandle is null) + { + return default; } - // Register with the token. + // Reset the instance's state so we can use it again. + instance.Reset(); + + // Register with the caller's cancellation token. SyncAsyncWorkItemRegistration reg = default; reg.WorkItem = instance; reg.CancellationRegistration = cancellationToken.UnsafeRegister(static s => @@ -218,7 +231,7 @@ private static SyncAsyncWorkItemRegistration RegisterCancellation(AsyncOverSyncW // the callback immediately. If we allowed that to loop until cancellation was successful, // we'd deadlock, as we'd never perform the very I/O it was waiting for. As such, if // the callback is invoked prior to be ready for it, we ignore the callback. - if (!instance.FinishedCancellationRegistration) + if (!Volatile.Read(ref instance._finishedCancellationRegistration)) { return; } @@ -230,7 +243,7 @@ private static SyncAsyncWorkItemRegistration RegisterCancellation(AsyncOverSyncW // this looping synchronously, we instead queue the invocation of the looping so that it // runs asynchronously from the Cancel call. Then in order to be able to track its completion, // we store the Task representing that asynchronous work, such that cleanup can wait for the Task. - instance.CallbackCompleted = Task.Factory.StartNew(static s => + instance._callbackCompleted = Task.Factory.StartNew(static s => { var instance = (AsyncOverSyncWithIoCancellation)s!; @@ -238,9 +251,9 @@ private static SyncAsyncWorkItemRegistration RegisterCancellation(AsyncOverSyncW // the synchronous operation, CancelSynchronousIo will fail with ERROR_NOT_FOUND, and // we'll loop to try again. SpinWait sw = default; - while (instance.ContinueTryingToCancel) + while (Volatile.Read(ref instance._continueTryingToCancel)) { - if (Interop.Kernel32.CancelSynchronousIo(instance.ThreadHandle!)) + if (Interop.Kernel32.CancelSynchronousIo(instance._threadHandle!)) { // Successfully canceled I/O. break; @@ -261,7 +274,7 @@ private static SyncAsyncWorkItemRegistration RegisterCancellation(AsyncOverSyncW // Now that we've registered with the token, tell the callback it's safe to enter // its cancellation loop if the callback is invoked. - instance.FinishedCancellationRegistration = true; + Volatile.Write(ref instance._finishedCancellationRegistration, true); // And now since cancellation may have been requested and we may have suppressed it // until the previous line, check to see if cancellation has now been requested, and diff --git a/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/Microsoft.Bcl.AsyncInterfaces.csproj b/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/Microsoft.Bcl.AsyncInterfaces.csproj index 313bc2ab4868d..43af9e134a213 100644 --- a/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/Microsoft.Bcl.AsyncInterfaces.csproj +++ b/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/Microsoft.Bcl.AsyncInterfaces.csproj @@ -1,6 +1,8 @@ netstandard2.0;$(NetFrameworkMinimum);netstandard2.1 + + $(NoWarn);1591 true Provides the IAsyncEnumerable<T> and IAsyncDisposable interfaces and helper types for .NET Standard 2.0. This package is not required starting with .NET Standard 2.1 and .NET Core 3.0. diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs index 7a13cdf999acb..e4f2e66b7006c 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/ref/Microsoft.Extensions.Caching.Memory.cs @@ -42,6 +42,9 @@ public partial class MemoryCacheOptions : Microsoft.Extensions.Options.IOptions< public MemoryCacheOptions() { } public Microsoft.Extensions.Internal.ISystemClock? Clock { get { throw null; } set { } } public double CompactionPercentage { get { throw null; } set { } } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.Obsolete("This property is retained only for compatibility. Remove use and instead call MemoryCache.Compact as needed.", error: true)] + public bool CompactOnMemoryPressure { get; set; } public System.TimeSpan ExpirationScanFrequency { get { throw null; } set { } } Microsoft.Extensions.Caching.Memory.MemoryCacheOptions Microsoft.Extensions.Options.IOptions.Value { get { throw null; } } public long? SizeLimit { get { throw null; } set { } } diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs index efb5b197d9378..15a4eaf220e52 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCacheOptions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Options; @@ -42,6 +43,10 @@ public long? SizeLimit } } + [EditorBrowsableAttribute(EditorBrowsableState.Never)] + [Obsolete("This property is retained only for compatibility. Remove use and instead call MemoryCache.Compact as needed.", error: true)] + public bool CompactOnMemoryPressure { get; set; } + /// /// Gets or sets the amount to compact the cache by when the maximum size is exceeded. /// diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj index 8a167e3eab128..af88313e6c130 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj @@ -9,6 +9,8 @@ false false $(NoWarn);CA1852 + + $(NoWarn);1591 true Suite of xUnit.net tests to check for container compatibility with Microsoft.Extensions.DependencyInjection. diff --git a/src/libraries/Microsoft.Extensions.Diagnostics/ref/Microsoft.Extensions.Diagnostics.cs b/src/libraries/Microsoft.Extensions.Diagnostics/ref/Microsoft.Extensions.Diagnostics.cs index 52fa2fcf89e11..9c1afafdd2fb5 100644 --- a/src/libraries/Microsoft.Extensions.Diagnostics/ref/Microsoft.Extensions.Diagnostics.cs +++ b/src/libraries/Microsoft.Extensions.Diagnostics/ref/Microsoft.Extensions.Diagnostics.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.Extensions.Diagnostics.Metrics +namespace Microsoft.Extensions.DependencyInjection { public static class MetricsServiceExtensions { - public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) { return null!; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) { throw null; } } } \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Diagnostics/src/Metrics/MetricsServiceExtensions.cs b/src/libraries/Microsoft.Extensions.Diagnostics/src/Metrics/MetricsServiceExtensions.cs index 08435c29ea335..0bbbbb9089e2e 100644 --- a/src/libraries/Microsoft.Extensions.Diagnostics/src/Metrics/MetricsServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Diagnostics/src/Metrics/MetricsServiceExtensions.cs @@ -1,11 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.Metrics; using Microsoft.Extensions.DependencyInjection.Extensions; using System; -namespace Microsoft.Extensions.Diagnostics.Metrics +namespace Microsoft.Extensions.DependencyInjection { /// /// Extension methods for setting up metrics services in an . diff --git a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs index 4069eee62b84f..f14fb7a69588b 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdHelpers.cs @@ -21,7 +21,9 @@ public static partial class SystemdHelpers /// /// Check if the current process is hosted as a systemd Service. /// - /// True if the current process is hosted as a systemd Service, otherwise false. + /// + /// if the current process is hosted as a systemd Service; otherwise, . + /// public static bool IsSystemdService() => _isSystemdService ??= GetIsSystemdService(); diff --git a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdLifetime.cs b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdLifetime.cs index e1b196fb2a6f5..94addfe256f9d 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdLifetime.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdLifetime.cs @@ -46,11 +46,29 @@ public SystemdLifetime(IHostEnvironment environment, IHostApplicationLifetime ap private ILogger Logger { get; } private ISystemdNotifier SystemdNotifier { get; } + /// + /// Asynchronously stops and shuts down the host. This method is called from . + /// + /// + /// A cancellation token that indicates when stop should no longer be graceful. + /// + /// + /// A task that represents the asynchronous stop operation. + /// public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } + /// + /// Asynchronously waits until the start operation is complete before continuing. This method is called at the beginning of . This can be used to delay startup until signaled by an external event. + /// + /// + /// A cancellation token that indicates when stop should no longer be graceful. + /// + /// + /// A task that represents the waiting for start operation. + /// public Task WaitForStartAsync(CancellationToken cancellationToken) { _applicationStartedRegistration = ApplicationLifetime.ApplicationStarted.Register(state => @@ -86,6 +104,9 @@ private void OnApplicationStopping() SystemdNotifier.Notify(ServiceState.Stopping); } + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// public void Dispose() { UnregisterShutdownHandlers(); diff --git a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdNotifier.cs b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdNotifier.cs index bfde5fe73df6a..2bc1865423f88 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdNotifier.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.Systemd/src/SystemdNotifier.cs @@ -7,6 +7,9 @@ namespace Microsoft.Extensions.Hosting.Systemd { + /// + /// Provides support to notify systemd about the service status. + /// [UnsupportedOSPlatform("browser")] public class SystemdNotifier : ISystemdNotifier { diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs index 883be7b40f2d1..1f182bc223d14 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceHelpers.cs @@ -15,7 +15,9 @@ public static class WindowsServiceHelpers /// /// Check if the current process is hosted as a Windows Service. /// - /// True if the current process is hosted as a Windows Service, otherwise false. + /// + /// if the current process is hosted as a Windows Service; otherwise, . + /// [SupportedOSPlatformGuard("windows")] public static bool IsWindowsService() { diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs index 7edd3ea3d35c3..69e0fd1a06731 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetime.cs @@ -62,6 +62,15 @@ public WindowsServiceLifetime(IHostEnvironment environment, IHostApplicationLife private IHostEnvironment Environment { get; } private ILogger Logger { get; } + /// + /// Asynchronously waits until start is complete before continuing. This method is called at the beginning of . This can be used to delay startup until signaled by an external event. + /// + /// + /// A cancellation token that indicates when stop should no longer be graceful. + /// + /// + /// A task that represents the asynchronous waiting for start operation. + /// public Task WaitForStartAsync(CancellationToken cancellationToken) { cancellationToken.Register(() => _delayStart.TrySetCanceled()); @@ -99,9 +108,14 @@ private void Run() } /// - /// Called from to stop the service if not already stopped, and wait for the service dispatcher to exit. - /// Once this method returns the service is stopped and the process can be terminated at any time. + /// Asynchronously stops and shuts down the host. This method is called from . /// + /// + /// A cancellation token that indicates when stop should no longer be graceful. + /// + /// + /// A task that represents the asynchronous stop operation. + /// public async Task StopAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetimeOptions.cs b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetimeOptions.cs index 53a8dc0eb4807..c1858dbe0c7fb 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetimeOptions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetimeOptions.cs @@ -5,6 +5,9 @@ namespace Microsoft.Extensions.Hosting { + /// + /// Options to configure the lifetime of a windows service. + /// public class WindowsServiceLifetimeOptions { /// diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs index 02cde025bf0c5..24d70caf79114 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs @@ -144,11 +144,43 @@ public IReadOnlyList GetLogClasses(IEnumerable items = attributeData.ConstructorArguments; - Debug.Assert(items.Length == 3); - eventId = items[0].IsNull ? -1 : (int)GetItem(items[0]); - level = items[1].IsNull ? null : (int?)GetItem(items[1]); - message = items[2].IsNull ? string.Empty : (string)GetItem(items[2]); + switch (items.Length) + { + case 1: + // LoggerMessageAttribute(LogLevel level) + // LoggerMessageAttribute(string message) + if (items[0].Type.SpecialType == SpecialType.System_String) + { + message = (string)GetItem(items[0]); + level = null; + } + else + { + message = string.Empty; + level = items[0].IsNull ? null : (int?)GetItem(items[0]); + } + eventId = -1; + break; + + case 2: + // LoggerMessageAttribute(LogLevel level, string message) + eventId = -1; + level = items[0].IsNull ? null : (int?)GetItem(items[0]); + message = items[1].IsNull ? string.Empty : (string)GetItem(items[1]); + break; + + case 3: + // LoggerMessageAttribute(int eventId, LogLevel level, string message) + eventId = items[0].IsNull ? -1 : (int)GetItem(items[0]); + level = items[1].IsNull ? null : (int?)GetItem(items[1]); + message = items[2].IsNull ? string.Empty : (string)GetItem(items[2]); + break; + + default: + Debug.Assert(false, "Unexpected number of arguments in attribute constructor."); + break; + } } // argument syntax takes parameters. e.g. EventId = 0 @@ -266,7 +298,8 @@ public IReadOnlyList GetLogClasses(IEnumerable + /// Initializes a new instance of the class + /// which is used to guide the production of a strongly-typed logging method. + /// + /// The log level. + /// Format string of the log message. + public LoggerMessageAttribute(LogLevel level, string message) + { + Level = level; + Message = message; + } + + /// + /// Initializes a new instance of the class + /// which is used to guide the production of a strongly-typed logging method. + /// + /// The log level. + public LoggerMessageAttribute(LogLevel level) + { + Level = level; + } + + /// + /// Initializes a new instance of the class + /// which is used to guide the production of a strongly-typed logging method. + /// + /// Format string of the log message. + public LoggerMessageAttribute(string message) + { + Message = message; + } + /// /// Gets the logging event id for the logging method. /// diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs index f3419669a361f..8d6eafe7ec91a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs @@ -282,6 +282,27 @@ public void InstanceTests() Assert.Equal("M1 Foo", logger.LastFormattedString); Assert.Equal(LogLevel.Trace, logger.LastLogLevel); Assert.Equal(1, logger.CallCount); + + logger.Reset(); + o.M2("Bar"); + Assert.Null(logger.LastException); + Assert.Equal("M2 Bar", logger.LastFormattedString); + Assert.Equal(LogLevel.Information, logger.LastLogLevel); + Assert.Equal(-1, logger.LastEventId.Id); + + logger.Reset(); + o.M3(LogLevel.Critical, "Foo Bar"); + Assert.Null(logger.LastException); + Assert.Equal("M3 Foo Bar", logger.LastFormattedString); + Assert.Equal(LogLevel.Critical, logger.LastLogLevel); + Assert.Equal(-1, logger.LastEventId.Id); + + logger.Reset(); + o.M4(); + Assert.Null(logger.LastException); + Assert.Equal("", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(-1, logger.LastEventId.Id); } [Fact] diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/TestInstances.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/TestInstances.cs index 13ed72bbc8276..d9e043116cd2c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/TestInstances.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/TestInstances.cs @@ -17,5 +17,16 @@ public TestInstances(ILogger logger) [LoggerMessage(EventId = 1, Level = LogLevel.Trace, Message = "M1 {p1}")] public partial void M1(string p1); + + // Test LoggerMessage Constructor's overloads + + [LoggerMessage(LogLevel.Information, "M2 {p1}")] + public partial void M2(string p1); + + [LoggerMessage("M3 {p1}")] + public partial void M3(LogLevel level, string p1); + + [LoggerMessage(LogLevel.Debug)] + public partial void M4(); } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs index 0941865d6e3db..ebdce4441e286 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.cs @@ -9,6 +9,30 @@ namespace Microsoft.Extensions.Logging [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] public static partial class ConsoleLoggerExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Configuration.IConfiguration configuration) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings settings) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel, bool includeScopes) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, bool includeScopes) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Func filter) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddConsole(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Func filter, bool includeScopes) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("Binding TOptions to configuration values may require generating dynamic code at runtime.")] @@ -27,6 +51,16 @@ public static partial class ConsoleLoggerExtensions } namespace Microsoft.Extensions.Logging.Console { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.")] + public partial class ConfigurationConsoleLoggerSettings : Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings + { + public ConfigurationConsoleLoggerSettings(Microsoft.Extensions.Configuration.IConfiguration configuration) { } + public Microsoft.Extensions.Primitives.IChangeToken? ChangeToken { get { throw null; } } + public bool IncludeScopes { get { throw null; } } + public Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings Reload() { throw null; } + public bool TryGetSwitch(string name, out Microsoft.Extensions.Logging.LogLevel level) { throw null; } + } public abstract partial class ConsoleFormatter { protected ConsoleFormatter(string name) { } @@ -86,6 +120,27 @@ public enum ConsoleLoggerQueueFullMode Wait = 0, DropWrite = 1, } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public partial class ConsoleLoggerSettings : Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings + { + public ConsoleLoggerSettings() { } + public Microsoft.Extensions.Primitives.IChangeToken? ChangeToken { get { throw null; } set { } } + public bool DisableColors { get { throw null; } set { } } + public bool IncludeScopes { get { throw null; } set { } } + public System.Collections.Generic.IDictionary Switches { get { throw null; } set { } } + public Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings Reload() { throw null; } + public bool TryGetSwitch(string name, out Microsoft.Extensions.Logging.LogLevel level) { throw null; } + } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public partial interface IConsoleLoggerSettings + { + Microsoft.Extensions.Primitives.IChangeToken? ChangeToken { get; } + bool IncludeScopes { get; } + Microsoft.Extensions.Logging.Console.IConsoleLoggerSettings Reload(); + bool TryGetSwitch(string name, out Microsoft.Extensions.Logging.LogLevel level); + } public partial class JsonConsoleFormatterOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { public JsonConsoleFormatterOptions() { } diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj index 532e6fe9f79a4..6ac2f32359d4c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Console/ref/Microsoft.Extensions.Logging.Console.csproj @@ -21,6 +21,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConfigurationConsoleLoggerSettings.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConfigurationConsoleLoggerSettings.cs new file mode 100644 index 0000000000000..9ac19144b737b --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConfigurationConsoleLoggerSettings.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.")] + public class ConfigurationConsoleLoggerSettings : IConsoleLoggerSettings + { + internal readonly IConfiguration _configuration; + + public ConfigurationConsoleLoggerSettings(IConfiguration configuration) + { + _configuration = configuration; + ChangeToken = configuration.GetReloadToken(); + } + + public IChangeToken? ChangeToken { get; private set; } + + public bool IncludeScopes + { + get + { + bool includeScopes; + var value = _configuration["IncludeScopes"]; + if (string.IsNullOrEmpty(value)) + { + return false; + } + else if (bool.TryParse(value, out includeScopes)) + { + return includeScopes; + } + else + { + var message = $"Configuration value '{value}' for setting '{nameof(IncludeScopes)}' is not supported."; + throw new InvalidOperationException(message); + } + } + } + + public IConsoleLoggerSettings Reload() + { + ChangeToken = null!; + return new ConfigurationConsoleLoggerSettings(_configuration); + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + var switches = _configuration.GetSection("LogLevel"); + if (switches == null) + { + level = LogLevel.None; + return false; + } + + var value = switches[name]; + if (string.IsNullOrEmpty(value)) + { + level = LogLevel.None; + return false; + } + else if (Enum.TryParse(value, true, out level)) + { + return true; + } + else + { + var message = $"Configuration value '{value}' for category '{name}' is not supported."; + throw new InvalidOperationException(message); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.Obsolete.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.Obsolete.cs new file mode 100644 index 0000000000000..3ddc4586e9833 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.Obsolete.cs @@ -0,0 +1,126 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging.Configuration; +using Microsoft.Extensions.Logging.Console; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging +{ + public static partial class ConsoleLoggerExtensions + { + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Extensions.Configuration.IConfiguration configuration) + { + var settings = new ConfigurationConsoleLoggerSettings(configuration); + return factory.AddConsole(settings); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Console.IConsoleLoggerSettings settings) + { + factory.AddProvider(new ConsoleLoggerProvider(ConsoleLoggerSettingsAdapter.GetOptionsMonitor(settings))); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Logging.LogLevel minLevel, bool includeScopes) + { + factory.AddConsole((n, l) => l >= LogLevel.Information, includeScopes); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, Logging.LogLevel minLevel) + { + factory.AddConsole(minLevel, includeScopes: false); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, bool includeScopes) + { + factory.AddConsole((n, l) => l >= LogLevel.Information, includeScopes); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, System.Func filter, bool includeScopes) + { + factory.AddConsole(new ConsoleLoggerSettings() { IncludeScopes = includeScopes }); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory, System.Func filter) + { + factory.AddConsole(filter, includeScopes: false); + return factory; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddConsole(this ILoggingBuilder builder).", error: true)] + public static Logging.ILoggerFactory AddConsole(this Logging.ILoggerFactory factory) + { + return factory.AddConsole(includeScopes: false); + } + + [Obsolete] + private sealed class ConsoleLoggerSettingsAdapter : IConfigureOptions, IOptionsChangeTokenSource + { + private IConsoleLoggerSettings _settings; + private ConsoleLoggerSettingsAdapter(IConsoleLoggerSettings settings) + { + _settings = settings; + } + + IChangeToken IOptionsChangeTokenSource.GetChangeToken() => _settings.ChangeToken ?? NullChangeToken.Instance; + + string IOptionsChangeTokenSource.Name => Microsoft.Extensions.Options.Options.DefaultName; + + void IConfigureOptions.Configure(ConsoleLoggerOptions options) + { + options.IncludeScopes = _settings.IncludeScopes; + if (_settings is ConfigurationConsoleLoggerSettings configSettings) + { + options.Configure(configSettings._configuration); + } + else if (_settings is ConsoleLoggerSettings consoleSettings) + { + options.DisableColors = consoleSettings.DisableColors; + } + } + + internal static OptionsMonitor GetOptionsMonitor(IConsoleLoggerSettings settings) + { + ConsoleLoggerSettingsAdapter adapter = new(settings); + OptionsFactory factory = new( new IConfigureOptions[] { adapter }, Array.Empty>()); + IOptionsChangeTokenSource[] sources = new IOptionsChangeTokenSource[] { adapter }; + OptionsCache cache = new(); + + return new OptionsMonitor(factory, sources, cache); + } + } + + private sealed class NullChangeToken : IChangeToken, IDisposable + { + internal static NullChangeToken Instance { get; } = new NullChangeToken(); + private NullChangeToken() { } + public bool HasChanged => false; + public bool ActiveChangeCallbacks => false; + public IDisposable RegisterChangeCallback(Action callback, object? state) => this; + public void Dispose() { } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs index f4ffbe9309f30..9a7d5998afd4c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.cs @@ -15,7 +15,7 @@ namespace Microsoft.Extensions.Logging { [UnsupportedOSPlatform("browser")] - public static class ConsoleLoggerExtensions + public static partial class ConsoleLoggerExtensions { internal const string RequiresDynamicCodeMessage = "Binding TOptions to configuration values may require generating dynamic code at runtime."; internal const string TrimmingRequiresUnreferencedCodeMessage = "TOptions's dependent types may have their members trimmed. Ensure all required members are preserved."; diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs index f1f96fd661142..97d8538f925ce 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs @@ -16,7 +16,7 @@ namespace Microsoft.Extensions.Logging.Console /// [UnsupportedOSPlatform("browser")] [ProviderAlias("Console")] - public class ConsoleLoggerProvider : ILoggerProvider, ISupportExternalScope + public partial class ConsoleLoggerProvider : ILoggerProvider, ISupportExternalScope { private readonly IOptionsMonitor _options; private readonly ConcurrentDictionary _loggers; diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerSettings.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerSettings.cs new file mode 100644 index 0000000000000..77bd183cef358 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerSettings.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public class ConsoleLoggerSettings : IConsoleLoggerSettings + { + public IChangeToken? ChangeToken { get; set; } + + public bool IncludeScopes { get; set; } + + public bool DisableColors { get; set; } + + public IDictionary Switches { get; set; } = new Dictionary(); + + public IConsoleLoggerSettings Reload() + { + return this; + } + + public bool TryGetSwitch(string name, out LogLevel level) + { + return Switches.TryGetValue(name, out level); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/IConsoleLoggerSettings.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/IConsoleLoggerSettings.cs new file mode 100644 index 0000000000000..81c2b846c5e3e --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/IConsoleLoggerSettings.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.Extensions.Logging.Console +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is ConsoleLoggerOptions.", error: true)] + public interface IConsoleLoggerSettings + { + bool IncludeScopes { get; } + + IChangeToken? ChangeToken { get; } + + bool TryGetSwitch(string name, out LogLevel level); + + IConsoleLoggerSettings Reload(); + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs b/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs index 4e4fb2d98df06..6b0feb5254e92 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Debug/ref/Microsoft.Extensions.Logging.Debug.cs @@ -8,6 +8,15 @@ namespace Microsoft.Extensions.Logging { public static partial class DebugLoggerFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddDebug(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddDebug(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddDebug(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Func filter) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddDebug(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs index f84e641ace3dd..eda4262a465d8 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLogger.cs @@ -31,8 +31,7 @@ public IDisposable BeginScope(TState state) where TState : notnull /// public bool IsEnabled(LogLevel logLevel) { - // If the filter is null, everything is enabled - // unless the debugger is not attached + // Everything is enabled unless the debugger is not attached return Debugger.IsAttached && logLevel != LogLevel.None; } diff --git a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs index bf426222c4594..179c27ed80586 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Debug/src/DebugLoggerFactoryExtensions.cs @@ -4,6 +4,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging.Debug; +using System; +using System.ComponentModel; namespace Microsoft.Extensions.Logging { @@ -12,6 +14,36 @@ namespace Microsoft.Extensions.Logging /// public static class DebugLoggerFactoryExtensions { + /// + /// Adds a debug logger that is enabled for .Information or higher. + /// + /// The extension method argument. + /// The minimum to be logged. This parameter is no longer honored and will be ignored. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddDebug(this ILoggerFactory factory, LogLevel minLevel) => AddDebug(factory); + + /// + /// Adds a debug logger that is enabled as defined by the filter function. + /// + /// The extension method argument. + /// The function used to filter events based on the log level. This parameter is no longer honored and will be ignored. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddDebug(this ILoggerFactory factory, Func filter) => AddDebug(factory); + + /// + /// Adds a debug logger that is enabled for s of minLevel or higher. + /// + /// The extension method argument. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddDebug(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddDebug(this ILoggerFactory factory) + { + factory.AddProvider(new DebugLoggerProvider()); + return factory; + } + /// /// Adds a debug logger named 'Debug' to the factory. /// diff --git a/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs b/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs index 523a34dc137dc..659188403840d 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventLog/ref/Microsoft.Extensions.Logging.EventLog.cs @@ -8,6 +8,15 @@ namespace Microsoft.Extensions.Logging { public static partial class EventLoggerFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventLog(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventLog(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.EventLog.EventLogSettings settings) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventLog(this Microsoft.Extensions.Logging.ILoggerFactory factory, Microsoft.Extensions.Logging.LogLevel minLevel) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventLog(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventLog(this Microsoft.Extensions.Logging.ILoggingBuilder builder, Microsoft.Extensions.Logging.EventLog.EventLogSettings settings) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventLog(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Action configure) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs index 8ac843c859af0..1ff31e4e1586a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventLog/src/EventLoggerFactoryExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging.EventLog; @@ -13,6 +14,40 @@ namespace Microsoft.Extensions.Logging /// public static class EventLoggerFactoryExtensions { + /// + /// Adds an event logger. Use to enable logging for specific s. + /// + /// The extension method argument. + /// The . + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventLog(this ILoggerFactory factory, EventLog.EventLogSettings settings) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(settings); + + factory.AddProvider(new EventLogLoggerProvider(settings)); + return factory; + } + + /// + /// Adds an event logger that is enabled for s of minLevel or higher. + /// + /// The extension method argument. + /// The minimum to be logged + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventLog(this ILoggerFactory factory, LogLevel minLevel) => + AddEventLog(factory, new EventLogSettings() { Filter = (_, logLevel) => logLevel >= minLevel }); + + /// + /// Adds an event logger that is enabled for .Information or higher. + /// + /// The extension method argument. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventLog(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventLog(this ILoggerFactory factory) => AddEventLog(factory, LogLevel.Information); + /// /// Adds an event logger named 'EventLog' to the factory. /// diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs index 023c42d936c49..0adcc2b6f3490 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/ref/Microsoft.Extensions.Logging.EventSource.cs @@ -8,6 +8,9 @@ namespace Microsoft.Extensions.Logging { public static partial class EventSourceLoggerFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddEventSourceLogger(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddEventSourceLogger(this Microsoft.Extensions.Logging.ILoggerFactory factory) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventSourceLogger(this Microsoft.Extensions.Logging.ILoggingBuilder builder) { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs index 7f247bd6caec9..cd92ca6b2aee4 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/EventSourceLoggerFactoryExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging.EventSource; @@ -15,7 +16,23 @@ namespace Microsoft.Extensions.Logging public static class EventSourceLoggerFactoryExtensions { /// - /// Adds an event logger named 'EventSource' to the factory. + /// Adds an logger that writes messages to the instance. + /// + /// The extension method argument. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddEventSourceLogger(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddEventSourceLogger(this ILoggerFactory factory) + { + ThrowHelper.ThrowIfNull(factory); + + factory.AddProvider(new EventSourceLoggerProvider(LoggingEventSource.Instance)); + + return factory; + } + + /// + /// Adds an logger that writes messages to the instance. /// /// The extension method argument. /// The so that additional calls can be chained. diff --git a/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs b/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs index 66396cb62448a..cb8d69261e334 100644 --- a/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.TraceSource/ref/Microsoft.Extensions.Logging.TraceSource.cs @@ -8,6 +8,18 @@ namespace Microsoft.Extensions.Logging { public static partial class TraceSourceFactoryExtensions { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch, System.Diagnostics.TraceListener listener) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, string switchName) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static Microsoft.Extensions.Logging.ILoggerFactory AddTraceSource(this Microsoft.Extensions.Logging.ILoggerFactory factory, string switchName, System.Diagnostics.TraceListener listener) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddTraceSource(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Diagnostics.SourceSwitch sourceSwitch) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddTraceSource(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Diagnostics.SourceSwitch sourceSwitch, System.Diagnostics.TraceListener listener) { throw null; } public static Microsoft.Extensions.Logging.ILoggingBuilder AddTraceSource(this Microsoft.Extensions.Logging.ILoggingBuilder builder, string switchName) { throw null; } diff --git a/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs index e8d2bba55a0b1..863a069d50366 100644 --- a/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.TraceSource/src/TraceSourceFactoryExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.ComponentModel; using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.TraceSource; @@ -14,7 +15,83 @@ namespace Microsoft.Extensions.Logging public static class TraceSourceFactoryExtensions { /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . + /// + /// The to use. + /// The to use. + /// The to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch, System.Diagnostics.TraceListener listener) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(sourceSwitch); + ThrowHelper.ThrowIfNull(listener); + + factory.AddProvider(new TraceSourceLoggerProvider(sourceSwitch, listener)); + + return factory; + } + + /// + /// Adds a logger that writes to . + /// + /// The to use. + /// The to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, System.Diagnostics.SourceSwitch sourceSwitch) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(sourceSwitch); + + factory.AddProvider(new TraceSourceLoggerProvider(sourceSwitch)); + + return factory; + } + + /// + /// Adds a logger that writes to . + /// + /// The to use. + /// The name of the to use. + /// The to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, string switchName, System.Diagnostics.TraceListener listener) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(switchName); + ThrowHelper.ThrowIfNull(listener); + + factory.AddProvider(new TraceSourceLoggerProvider(new SourceSwitch(switchName), listener)); + + return factory; + } + + /// + /// Adds a logger that writes to . + /// + /// The to use. + /// The name of the to use. + /// The so that additional calls can be chained. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is retained only for compatibility. The recommended alternative is AddTraceSource(this ILoggingBuilder builder).", error: true)] + public static ILoggerFactory AddTraceSource(this ILoggerFactory factory, string switchName) + { + ThrowHelper.ThrowIfNull(factory); + ThrowHelper.ThrowIfNull(switchName); + + factory.AddProvider(new TraceSourceLoggerProvider(new SourceSwitch(switchName))); + + return factory; + } + + /// + /// Adds a logger that writes to . /// /// The to use. /// The name of the to use. @@ -30,7 +107,7 @@ public static ILoggingBuilder AddTraceSource( } /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . /// /// The to use. /// The name of the to use. @@ -49,7 +126,7 @@ public static ILoggingBuilder AddTraceSource( } /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . /// /// The to use. /// The to use. @@ -67,9 +144,9 @@ public static ILoggingBuilder AddTraceSource( } /// - /// Adds a TraceSource logger named 'TraceSource' to the factory. + /// Adds a logger that writes to . /// - /// The to use. + /// The to use. /// The to use. /// The to use. /// The so that additional calls can be chained. diff --git a/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs b/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs index 5811822286a00..a5f5f188981cd 100644 --- a/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs +++ b/src/libraries/Microsoft.Extensions.Primitives/ref/Microsoft.Extensions.Primitives.cs @@ -36,6 +36,20 @@ public partial interface IChangeToken bool HasChanged { get; } System.IDisposable RegisterChangeCallback(System.Action callback, object? state); } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [System.ObsoleteAttribute("This type is retained only for compatibility. The recommended alternative is string.Create (int length, TState state, System.Buffers.SpanAction action).", error: true)] + public partial struct InplaceStringBuilder + { + private object _dummy; + private int _dummyPrimitive; + public InplaceStringBuilder(int capacity) { throw null; } + public int Capacity { get { throw null; } set { } } + public void Append(Microsoft.Extensions.Primitives.StringSegment segment) { } + public void Append(char c) { } + public void Append(string? value) { } + public void Append(string? value, int offset, int count) { } + public override string? ToString() { throw null; } + } public readonly partial struct StringSegment : System.IEquatable, System.IEquatable { private readonly object _dummy; diff --git a/src/libraries/Microsoft.Extensions.Primitives/src/InplaceStringBuilder.cs b/src/libraries/Microsoft.Extensions.Primitives/src/InplaceStringBuilder.cs new file mode 100644 index 0000000000000..063de6effb241 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Primitives/src/InplaceStringBuilder.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Microsoft.Extensions.Primitives +{ + [DebuggerDisplay("Value = {_value}")] + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This type is retained only for compatibility. The recommended alternative is string.Create (int length, TState state, System.Buffers.SpanAction action).", error: true)] + public struct InplaceStringBuilder + { + private int _offset; + private int _capacity; + private string? _value; + + public InplaceStringBuilder(int capacity) : this() + { + if (capacity < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); + } + + _capacity = capacity; + } + + public int Capacity + { + get => _capacity; + set + { + if (value < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value); + } + + // _offset > 0 indicates writing state + if (_offset > 0) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_CannotChangeAfterWriteStarted); + } + + _capacity = value; + } + } + + public void Append(string? value) + { + if (value == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); + } + + Append(value, 0, value.Length); + } + + public void Append(StringSegment segment) + { + Append(segment.Buffer, segment.Offset, segment.Length); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe void Append(string? value, int offset, int count) + { + EnsureValueIsInitialized(); + + if (value == null + || offset < 0 + || value.Length - offset < count + || Capacity - _offset < count) + { + ThrowValidationError(value, offset, count); + } + + fixed (char* destination = _value) + fixed (char* source = value) + { + Unsafe.CopyBlockUnaligned(destination + _offset, source + offset, (uint)count * 2); + _offset += count; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe void Append(char c) + { + EnsureValueIsInitialized(); + + if (_offset >= Capacity) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_NotEnough, 1, Capacity - _offset); + } + + fixed (char* destination = _value) + { + destination[_offset++] = c; + } + } + + public override string? ToString() + { + if (Capacity != _offset) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_NotUsedEntirely, Capacity, _offset); + } + + return _value; + } + + private void EnsureValueIsInitialized() + { + _value ??= new string('\0', _capacity); + } + + private void ThrowValidationError(string? value, int offset, int count) + { + if (value == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); + } + + if (offset < 0 || value.Length - offset < count) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset); + } + + if (Capacity - _offset < count) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Capacity_NotEnough, value.Length, Capacity - _offset); + } + } + } +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 1df89338842fd..1b22030ff3d96 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -1,13 +1,16 @@ $(NetCoreAppToolCurrent);$(NetFrameworkToolCurrent) + Microsoft.NETCore.Platforms.BuildTasks + + disable false false - Microsoft.NETCore.Platforms.BuildTasks false false + false true $(MSBuildProjectName) diff --git a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs index c001a7446525d..f8292c4de0f99 100644 --- a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs +++ b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs @@ -60,6 +60,7 @@ public void CurrencyNegativePattern_Get_ReturnsExpected_ByLocale(string locale) [InlineData(0)] [InlineData(1)] [InlineData(15)] + [InlineData(16)] public void CurrencyNegativePattern_Set_GetReturnsExpected(int newCurrencyNegativePattern) { NumberFormatInfo format = new NumberFormatInfo(); @@ -69,7 +70,7 @@ public void CurrencyNegativePattern_Set_GetReturnsExpected(int newCurrencyNegati [Theory] [InlineData(-1)] - [InlineData(16)] + [InlineData(17)] public void CurrencyNegativePattern_SetInvalid_ThrowsArgumentOutOfRangeException(int value) { var format = new NumberFormatInfo(); diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.Windows.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.Windows.cs index e612c16e78019..6763a7218eca4 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.Windows.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.Windows.cs @@ -35,7 +35,7 @@ protected override async Task CreateConnectedStreamsAsync() protected override Type UnsupportedConcurrentExceptionType => null; protected override bool UsableAfterCanceledReads => false; - protected override bool FullyCancelableOperations => false; + protected override bool FullyCancelableOperations => OperatingSystem.IsWindows(); protected override bool BlocksOnZeroByteReads => OperatingSystem.IsWindows(); protected override bool SupportsConcurrentBidirectionalUse => false; } diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs index c93d520b55b07..812bb775f6968 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs @@ -241,7 +241,7 @@ protected override Task CreateConnectedStreamsAsync() protected override Type UnsupportedConcurrentExceptionType => null; protected override bool UsableAfterCanceledReads => false; - protected override bool FullyCancelableOperations => false; + protected override bool FullyCancelableOperations => OperatingSystem.IsWindows(); protected override bool BlocksOnZeroByteReads => OperatingSystem.IsWindows(); protected override bool SupportsConcurrentBidirectionalUse => false; } @@ -268,7 +268,7 @@ protected override async Task CreateConnectedStreamsAsync() protected override Type UnsupportedConcurrentExceptionType => null; protected override bool UsableAfterCanceledReads => false; - protected override bool FullyCancelableOperations => false; + protected override bool FullyCancelableOperations => OperatingSystem.IsWindows(); protected override bool BlocksOnZeroByteReads => OperatingSystem.IsWindows(); protected override bool SupportsConcurrentBidirectionalUse => false; } diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs index 268224ab9b9f7..d31149d297c5e 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs @@ -95,8 +95,6 @@ public async Task ReadAsyncCanceledFile(int bufferSize, bool isAsync) // Ideally we'd be doing an Assert.Throws // but since cancellation is a race condition we accept either outcome Assert.Equal(cts.Token, oce.CancellationToken); - - Assert.Equal(0, fs.Position); // if read was cancelled, the Position should remain unchanged } } } diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs index c654ed010b6f3..13f872909ab6c 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs @@ -123,9 +123,6 @@ public async Task WriteAsyncCancelledFile(int bufferSize, bool isAsync) // Ideally we'd be doing an Assert.Throws // but since cancellation is a race condition we accept either outcome Assert.Equal(cts.Token, oce.CancellationToken); - - Assert.Equal(0, fs.Length); // if write was cancelled, the file should be empty - Assert.Equal(0, fs.Position); // if write was cancelled, the Position should remain unchanged } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj index 50559202a984e..521f8055a4fa6 100644 --- a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj @@ -2,6 +2,8 @@ $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true + + $(NoWarn);1591 true Tensor class which represents and extends multi-dimensional arrays. diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml index 278ed933f0704..2533b4b59e1ab 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml @@ -15,6 +15,13 @@ M:Internal.Runtime.InteropServices.ComponentActivator.GetFunctionPointer(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr) This warning is left in the product so developers get an ILLink warning when trimming an app with Internal.Runtime.InteropServices.ComponentActivator.IsSupported=true. + + ILLink + IL2026 + member + M:System.StartupHookProvider.CallStartupHook(System.Char*) + This warning is left in the product so developers get an ILLink warning when trimming an app with System.StartupHookProvider.IsSupported=true. + ILLink IL2026 diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index a5126b8367527..0912d9b45989e 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -75,7 +75,6 @@ - @@ -1586,6 +1585,9 @@ Common\Interop\Windows\Kernel32\Interop.CancelIoEx.cs + + Interop\Windows\Kernel32\Interop.CancelSynchronousIo.cs + Common\Interop\Windows\Kernel32\Interop.CompletionPort.cs @@ -1721,6 +1723,9 @@ Common\Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs + + Interop\Windows\Kernel32\Interop.GetCurrentThreadId.cs + Common\Interop\Windows\Kernel32\Interop.GetFileAttributesEx.cs @@ -1820,6 +1825,9 @@ Common\Interop\Windows\Kernel32\Interop.MoveFileEx.cs + + Interop\Windows\Kernel32\Interop.OpenThread.cs + Common\Interop\Windows\Kernel32\Interop.OSVERSIONINFOEX.cs @@ -2021,6 +2029,9 @@ Common\Microsoft\Win32\SafeHandles\SafeTokenHandle.cs + + Common\Microsoft\Win32\SafeHandles\SafeThreadHandle.cs + Common\System\IO\FileSystem.Attributes.Windows.cs @@ -2030,6 +2041,9 @@ Common\System\IO\PathInternal.Windows.cs + + Common\System\Threading\AsyncOverSyncWithIoCancellation.cs + @@ -2350,6 +2364,7 @@ Common\Interop\Android\Interop.Libraries.cs + diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs index 9f4c2f7eb1c19..3d01c21c800c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -244,10 +244,7 @@ public int CurrencyDecimalDigits { if (value < 0 || value > 99) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 99)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 99); } VerifyWritable(); @@ -441,12 +438,9 @@ public int CurrencyNegativePattern get => _currencyNegativePattern; set { - if (value < 0 || value > 15) + if (value < 0 || value > 16) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 15)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 16); } VerifyWritable(); @@ -462,10 +456,7 @@ public int NumberNegativePattern // NOTENOTE: the range of value should correspond to negNumberFormats[] in vm\COMNumber.cpp. if (value < 0 || value > 4) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 4)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 4); } VerifyWritable(); @@ -481,10 +472,7 @@ public int PercentPositivePattern // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp. if (value < 0 || value > 3) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 3)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 3); } VerifyWritable(); @@ -500,10 +488,7 @@ public int PercentNegativePattern // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp. if (value < 0 || value > 11) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 11)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 11); } VerifyWritable(); @@ -563,10 +548,7 @@ public int NumberDecimalDigits { if (value < 0 || value > 99) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 99)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 99); } VerifyWritable(); @@ -623,10 +605,7 @@ public int CurrencyPositivePattern { if (value < 0 || value > 3) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 3)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 3); } VerifyWritable(); @@ -686,10 +665,7 @@ public int PercentDecimalDigits { if (value < 0 || value > 99) { - throw new ArgumentOutOfRangeException( - nameof(value), - value, - SR.Format(SR.ArgumentOutOfRange_Range, 0, 99)); + ThrowHelper.ThrowArgumentOutOfRange_Range(nameof(value), value, 0, 99); } VerifyWritable(); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs index fcbf862ec91c4..e06187b5a3de5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs @@ -92,11 +92,10 @@ internal static unsafe long ReadScatterAtOffset(SafeFileHandle handle, IReadOnly } internal static ValueTask ReadAtOffsetAsync(SafeFileHandle handle, Memory buffer, long fileOffset, CancellationToken cancellationToken, OSFileStreamStrategy? strategy = null) - => ScheduleSyncReadAtOffsetAsync(handle, buffer, fileOffset, cancellationToken, strategy); + => handle.GetThreadPoolValueTaskSource().QueueRead(buffer, fileOffset, cancellationToken, strategy); - private static ValueTask ReadScatterAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, - long fileOffset, CancellationToken cancellationToken) - => ScheduleSyncReadScatterAtOffsetAsync(handle, buffers, fileOffset, cancellationToken); + private static ValueTask ReadScatterAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, CancellationToken cancellationToken) + => handle.GetThreadPoolValueTaskSource().QueueReadScatter(buffers, fileOffset, cancellationToken); internal static unsafe void WriteAtOffset(SafeFileHandle handle, ReadOnlySpan buffer, long fileOffset) { @@ -240,10 +239,9 @@ internal static unsafe void WriteGatherAtOffset(SafeFileHandle handle, IReadOnly } internal static ValueTask WriteAtOffsetAsync(SafeFileHandle handle, ReadOnlyMemory buffer, long fileOffset, CancellationToken cancellationToken, OSFileStreamStrategy? strategy = null) - => ScheduleSyncWriteAtOffsetAsync(handle, buffer, fileOffset, cancellationToken, strategy); + => handle.GetThreadPoolValueTaskSource().QueueWrite(buffer, fileOffset, cancellationToken, strategy); - private static ValueTask WriteGatherAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, - long fileOffset, CancellationToken cancellationToken) - => ScheduleSyncWriteGatherAtOffsetAsync(handle, buffers, fileOffset, cancellationToken); + private static ValueTask WriteGatherAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, CancellationToken cancellationToken) + => handle.GetThreadPoolValueTaskSource().QueueWriteGather(buffers, fileOffset, cancellationToken); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs index 7806747972372..e5c8e17da23e9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs @@ -250,7 +250,23 @@ internal static ValueTask ReadAtOffsetAsync(SafeFileHandle handle, Memory(Win32Marshal.GetExceptionForWin32Error(errorCode, handle.Path)); } - return ScheduleSyncReadAtOffsetAsync(handle, buffer, fileOffset, cancellationToken, strategy); + return AsyncOverSyncWithIoCancellation.InvokeAsync(static state => + { + try + { + int result = ReadAtOffset(state.handle, state.buffer.Span, state.fileOffset); + if (result != state.buffer.Length) + { + state.strategy?.OnIncompleteOperation(state.buffer.Length, result); + } + return result; + } + catch (Exception) when (state.strategy is not null) + { + state.strategy.OnIncompleteOperation(state.buffer.Length, 0); + throw; + } + }, (handle, buffer, fileOffset, strategy), cancellationToken); } private static unsafe (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) QueueAsyncReadFile(SafeFileHandle handle, Memory buffer, long fileOffset, @@ -332,7 +348,18 @@ internal static ValueTask WriteAtOffsetAsync(SafeFileHandle handle, ReadOnlyMemo return ValueTask.FromException(Win32Marshal.GetExceptionForWin32Error(errorCode, handle.Path)); } - return ScheduleSyncWriteAtOffsetAsync(handle, buffer, fileOffset, cancellationToken, strategy); + return AsyncOverSyncWithIoCancellation.InvokeAsync(static state => + { + try + { + WriteAtOffset(state.handle, state.buffer.Span, state.fileOffset); + } + catch (Exception) when (state.strategy is not null) + { + state.strategy.OnIncompleteOperation(state.buffer.Length, 0); + throw; + } + }, (handle, buffer, fileOffset, strategy), cancellationToken); } private static unsafe (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) QueueAsyncWriteFile(SafeFileHandle handle, ReadOnlyMemory buffer, long fileOffset, @@ -527,7 +554,7 @@ private static ValueTask ReadScatterAtOffsetAsync(SafeFileHandle handle, I { if (!handle.IsAsync) { - return ScheduleSyncReadScatterAtOffsetAsync(handle, buffers, fileOffset, cancellationToken); + return AsyncOverSyncWithIoCancellation.InvokeAsync(static state => ReadScatterAtOffset(state.handle, state.buffers, state.fileOffset), (handle, buffers, fileOffset), cancellationToken); } if (CanUseScatterGatherWindowsAPIs(handle) @@ -624,7 +651,7 @@ private static ValueTask WriteGatherAtOffsetAsync(SafeFileHandle handle, IReadOn { if (!handle.IsAsync) { - return ScheduleSyncWriteGatherAtOffsetAsync(handle, buffers, fileOffset, cancellationToken); + return AsyncOverSyncWithIoCancellation.InvokeAsync(static state => WriteGatherAtOffset(state.handle, state.buffers, state.fileOffset), (handle, buffers, fileOffset), cancellationToken); } if (CanUseScatterGatherWindowsAPIs(handle) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs index 7aaaace1e3e47..e30acc5e1160a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.IO.Strategies; using System.Threading; using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; @@ -284,29 +283,5 @@ private static void ValidateBuffers(IReadOnlyList buffers) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.buffers); } } - - private static ValueTask ScheduleSyncReadAtOffsetAsync(SafeFileHandle handle, Memory buffer, - long fileOffset, CancellationToken cancellationToken, OSFileStreamStrategy? strategy) - { - return handle.GetThreadPoolValueTaskSource().QueueRead(buffer, fileOffset, cancellationToken, strategy); - } - - private static ValueTask ScheduleSyncReadScatterAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, - long fileOffset, CancellationToken cancellationToken) - { - return handle.GetThreadPoolValueTaskSource().QueueReadScatter(buffers, fileOffset, cancellationToken); - } - - private static ValueTask ScheduleSyncWriteAtOffsetAsync(SafeFileHandle handle, ReadOnlyMemory buffer, - long fileOffset, CancellationToken cancellationToken, OSFileStreamStrategy? strategy) - { - return handle.GetThreadPoolValueTaskSource().QueueWrite(buffer, fileOffset, cancellationToken, strategy); - } - - private static ValueTask ScheduleSyncWriteGatherAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, - long fileOffset, CancellationToken cancellationToken) - { - return handle.GetThreadPoolValueTaskSource().QueueWriteGather(buffers, fileOffset, cancellationToken); - } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs b/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs index 72232ba42d3ad..c25c080586eaf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs @@ -49,6 +49,40 @@ private static void ProcessStartupHooks(string diagnosticStartupHooks) startupHookParts.AddRange(startupHooksVariable.Split(Path.PathSeparator)); } + // Parse startup hooks variable + StartupHookNameOrPath[] startupHooks = new StartupHookNameOrPath[startupHookParts.Count]; + for (int i = 0; i < startupHookParts.Count; i++) + { + ParseStartupHook(ref startupHooks[i], startupHookParts[i]); + } + + // Call each startup hook + for (int i = 0; i < startupHooks.Length; i++) + { +#pragma warning disable IL2026 // suppressed in ILLink.Suppressions.LibraryBuild.xml + CallStartupHook(startupHooks[i]); +#pragma warning restore IL2026 + } + } + + // Parse a string specifying a single entry containing a startup hook, + // and call the hook. + private static unsafe void CallStartupHook(char* pStartupHookPart) + { + if (!IsSupported) + return; + + StartupHookNameOrPath startupHook = default(StartupHookNameOrPath); + + ParseStartupHook(ref startupHook, new string(pStartupHookPart)); + +#pragma warning disable IL2026 // suppressed in ILLink.Suppressions.LibraryBuild.xml + CallStartupHook(startupHook); +#pragma warning restore IL2026 + } + + private static void ParseStartupHook(ref StartupHookNameOrPath startupHook, string startupHookPart) + { ReadOnlySpan disallowedSimpleAssemblyNameChars = stackalloc char[4] { Path.DirectorySeparatorChar, @@ -57,57 +91,42 @@ private static void ProcessStartupHooks(string diagnosticStartupHooks) ',' }; - // Parse startup hooks variable - StartupHookNameOrPath[] startupHooks = new StartupHookNameOrPath[startupHookParts.Count]; - for (int i = 0; i < startupHookParts.Count; i++) + if (string.IsNullOrEmpty(startupHookPart)) { - string startupHookPart = startupHookParts[i]; - if (string.IsNullOrEmpty(startupHookPart)) - { - // Leave the slot in startupHooks empty (nulls for everything). This is simpler than shifting and resizing the array. - continue; - } + return; + } - if (Path.IsPathFullyQualified(startupHookPart)) - { - startupHooks[i].Path = startupHookPart; - } - else + if (Path.IsPathFullyQualified(startupHookPart)) + { + startupHook.Path = startupHookPart; + } + else + { + // The intent here is to only support simple assembly names, but AssemblyName .ctor accepts + // lot of other forms (fully qualified assembly name, strings which look like relative paths and so on). + // So add a check on top which will disallow any directory separator, space or comma in the assembly name. + for (int j = 0; j < disallowedSimpleAssemblyNameChars.Length; j++) { - // The intent here is to only support simple assembly names, but AssemblyName .ctor accepts - // lot of other forms (fully qualified assembly name, strings which look like relative paths and so on). - // So add a check on top which will disallow any directory separator, space or comma in the assembly name. - for (int j = 0; j < disallowedSimpleAssemblyNameChars.Length; j++) - { - if (startupHookPart.Contains(disallowedSimpleAssemblyNameChars[j])) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidStartupHookSimpleAssemblyName, startupHookPart)); - } - } - - if (startupHookPart.EndsWith(DisallowedSimpleAssemblyNameSuffix, StringComparison.OrdinalIgnoreCase)) + if (startupHookPart.Contains(disallowedSimpleAssemblyNameChars[j])) { throw new ArgumentException(SR.Format(SR.Argument_InvalidStartupHookSimpleAssemblyName, startupHookPart)); } + } - try - { - // This will throw if the string is not a valid assembly name. - startupHooks[i].AssemblyName = new AssemblyName(startupHookPart); - } - catch (Exception assemblyNameException) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidStartupHookSimpleAssemblyName, startupHookPart), assemblyNameException); - } + if (startupHookPart.EndsWith(DisallowedSimpleAssemblyNameSuffix, StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidStartupHookSimpleAssemblyName, startupHookPart)); } - } - // Call each hook in turn - foreach (StartupHookNameOrPath startupHook in startupHooks) - { -#pragma warning disable IL2026 // suppressed in ILLink.Suppressions.LibraryBuild.xml - CallStartupHook(startupHook); -#pragma warning restore IL2026 + try + { + // This will throw if the string is not a valid assembly name. + startupHook.AssemblyName = new AssemblyName(startupHookPart); + } + catch (Exception assemblyNameException) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidStartupHookSimpleAssemblyName, startupHookPart), assemblyNameException); + } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs index 331f9c545ed14..72dcb670f5b9f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs @@ -103,7 +103,7 @@ private GeneratedMethodContextBase CreateUnmanagedToManagedStub() private MethodDeclarationSyntax CreateUnreachableExceptionStub() { - // DeclarationCopiedFromBaseDeclaration() => throw new UnreachableException("This method should not be reached"); + // DeclarationCopiedFromBaseDeclaration() => throw new UnreachableException(); return MethodInfo.Syntax .WithReturnType(GenerationContext.SignatureContext.StubReturnType) .WithModifiers(TokenList()) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf index f990f848fc740..1f2c366aee9b2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf @@ -169,32 +169,32 @@ Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. - Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. + Události nejsou konceptem COM, takže pro události instance na rozhraních COM generovaných zdrojem nebude vygenerován žádný kód spolupráce. The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + Událost instance {0} je deklarována v rozhraní {1}, ve kterém se používá GeneratedComInterfaceAttribute. Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported + Deklarace události instance v typu s GeneratedComInterfaceAttribute se nepodporuje. Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. - Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. + Vlastnosti nejsou konceptem COM, takže pro vlastnosti instance na rozhraních COM generovaných zdrojem nebude vygenerován žádný kód spolupráce. The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + Vlastnost instance {0} je deklarována v rozhraní {1}, ve kterém je použit atribut GeneratedComInterfaceAttribute. Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported + Deklarace vlastnosti instance v typu s GeneratedComInterfaceAttribute se nepodporuje. @@ -269,7 +269,7 @@ Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. - Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. + Rozhraní s atributem GeneratedComInterfaceAttribute musí mít přístupnost public nebo internal a musí být částečná, neobecná a musí určovat identifikátor GUID s atributem System.Runtime.InteropServices.GuidAttribute. @@ -279,7 +279,7 @@ Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} - Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} + Rozhraní „{0}“ má atribut „GeneratedComInterfaceAttribute“, ale není přístupný přes generovaný kód. Rozhraní a všechny obsahující typy musí mít přístupnost „internal“ nebo „public“, aby k němu vygenerovaný kód mohl přistupovat. {1} {1} is details about which type/containing type is not accessible @@ -389,7 +389,7 @@ The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} - The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} + Typ „{0}“ zadaný jako „GeneratedComInterfaceAttribute.StringMarswebingCustomType“ není přístupný přes generovaný kód. Typ musí mít přístupnost alespoň „internal“. {1} {1} is details about which type/containing type is not accessible diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf index 90992e554372c..04c1fab80866d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf @@ -169,32 +169,32 @@ Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. - Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. + Les événements ne sont pas un concept dans COM. Par conséquent, aucun code d’interopérabilité n’est généré à la source pour les événements d’instance sur les interfaces COM générées par la source. The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + L’événement d’instance « {0} » est déclaré dans l’interface « {1} », à laquelle « GeneratedComInterfaceAttribute » est appliqué Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported + La déclaration d’un événement d’instance dans un type avec « GeneratedComInterfaceAttribute » n’est pas prise en charge Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. - Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. + Les propriétés ne sont pas un concept dans COM. Par conséquent, aucun code d’interopérabilité n’est généré à la source pour les propriétés d’instance sur les interfaces COM générées par la source. The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + La propriété d’instance « {0} » est déclarée dans l’interface « {1} », à laquelle « GeneratedComInterfaceAttribute » est appliqué Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported + La déclaration d’une propriété d’instance dans un type avec « GeneratedComInterfaceAttribute » n’est pas prise en charge @@ -269,7 +269,7 @@ Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. - Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. + Les interfaces attribuées avec 'GeneratedComInterfaceAttribute' doivent avoir une accessibilité 'publique' ou "interne" et être partielles, non génériques, et doivent spécifier un GUID avec 'System.Runtime.InteropServices.GuidAttribute'. @@ -279,7 +279,7 @@ Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} - Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} + L’interface '{0}' est attribuée à 'GeneratedComInterfaceAttribute' mais n’est pas accessible par le code généré. L’interface et tous les types contenants doivent avoir l’accessibilité 'interne' ou 'publique' pour que le code généré y accède. {1} {1} is details about which type/containing type is not accessible @@ -389,7 +389,7 @@ The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} - The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} + Le type '{0}' spécifié en tant que 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' n’est pas accessible par le code généré. Le type doit avoir au moins l’accessibilité 'interne'. {1} {1} is details about which type/containing type is not accessible diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf index c88b701b57840..35a7dac9c428a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf @@ -74,12 +74,12 @@ A class with 'GeneratedComClassAttribute' must implement at least one interface with 'GeneratedComInterfaceAttribute' or else the generated code with not have an effect. - A class with 'GeneratedComClassAttribute' must implement at least one interface with 'GeneratedComInterfaceAttribute' or else the generated code with not have an effect. + Una classe con 'GeneratedComClassAttribute' deve implementare almeno un'interfaccia con 'GeneratedComInterfaceAttribute' oppure il codice generato senza alcun effetto. Class '{0}' with 'GeneratedComClassAttribute' does not implement any interfaces with 'GeneratedComInterfaceAttribute'. Source will not be generated for '{0}'. - Class '{0}' with 'GeneratedComClassAttribute' does not implement any interfaces with 'GeneratedComInterfaceAttribute'. Source will not be generated for '{0}'. + La classe '{0}' con 'GeneratedComClassAttribute' non implementa interfacce con 'GeneratedComInterfaceAttribute'. L'origine non verrà generata per '{0}'. @@ -259,7 +259,7 @@ Class '{0}' with 'GeneratedComClassAttribute' or one of its containing types is not marked 'partial'. - Class '{0}' with 'GeneratedComClassAttribute' or one of its containing types is not marked 'partial'. + La classe '{0}' con 'GeneratedComClassAttribute' o uno dei tipi che lo contengono non è contrassegnata come 'partial'. @@ -359,17 +359,17 @@ 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. - 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + GeneratedComInterfaceAttribute e 'GeneratedComClassAttribute' richiedono codice non gestito. Il progetto deve essere aggiornato con '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. - 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + GeneratedComInterfaceAttribute e 'GeneratedComClassAttribute' richiedono codice non gestito. Il progetto deve essere aggiornato con '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. - 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. + 'GeneratedComInterfaceAttribute' e 'GeneratedComClassAttribute' richiedono codice non sicuro. diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf index 1bbc4a3ac05c8..2c7c7bf8e8701 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf @@ -169,32 +169,32 @@ Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. - Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. + イベントは COM の概念ではないため、ソース生成 COM インターフェイス上のインスタンス イベントに対して相互運用コードはソース生成されません。 The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + インスタンス イベント '{0}' は、'GeneratedComInterfaceAttribute' が適用されているインターフェイス '{1}' で宣言されています Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported + 'GeneratedComInterfaceAttribute' を含む型のインスタンス イベントの宣言はサポートされていません Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. - Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. + プロパティは COM の概念ではないため、ソース生成 COM インターフェイス上のインスタンス プロパティに対して相互運用コードはソース生成されません。 The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + インスタンス プロパティ '{0}' は、'GeneratedComInterfaceAttribute' が適用されているインターフェイス '{1}' で宣言されています Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported + 'GeneratedComInterfaceAttribute' を含む型のインスタンス プロパティの宣言はサポートされていません diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf index 7f70f9271fc69..691b3bdf787c5 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf @@ -169,32 +169,32 @@ Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. - Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. + 이벤트는 COM의 개념이 아니므로 소스 생성 COM 인터페이스의 인스턴스 이벤트에 대해 interop 코드가 생성되지 않습니다. The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + 'GeneratedComInterfaceAttribute'가 적용된 '{1}' 인터페이스에서 '{0}' 인스턴스 이벤트가 선언되었습니다. Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported + 'GeneratedComInterfaceAttribute'를 사용하는 형식의 인스턴스 이벤트 선언은 지원되지 않습니다. Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. - Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. + 속성은 COM의 개념이 아니므로 소스 생성 COM 인터페이스의 인스턴스 속성에 대해 interop 코드가 생성되지 않습니다. The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + 'GeneratedComInterfaceAttribute'가 적용된 '{1}' 인터페이스에서 '{0}' 인스턴스 속성이 선언되었습니다. Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported + 'GeneratedComInterfaceAttribute'를 사용하는 형식의 인스턴스 속성 선언은 지원되지 않습니다. @@ -269,7 +269,7 @@ Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. - Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. + 'GeneratedComInterfaceAttribute'로 특성이 지정된 인터페이스에는 'public' 또는 'internal' 접근성이 있어야 하며 부분적이고 제네릭이 아니어야 하며 'System.Runtime.InteropServices.GuidAttribute'를 사용하여 GUID를 지정해야 합니다. @@ -279,7 +279,7 @@ Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} - Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} + 인터페이스 '{0}'은(는) 'GeneratedComInterfaceAttribute'로 특성이 지정되었지만 생성된 코드에서 액세스할 수 없습니다. 인터페이스와 포함된 모든 형식에는 액세스하기 위해 생성된 코드에 대한 접근성 'internal' 또는 'public'이 있어야 합니다. {1} {1} is details about which type/containing type is not accessible @@ -389,7 +389,7 @@ The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} - The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} + 생성된 코드에서 'GeneratedComInterfaceAttribute.StringMarscingingCustomType'으로 지정된 '{0}' 형식에 액세스할 수 없습니다. 형식에는 최소한 'internal' 접근성이 있어야 합니다. {1} {1} is details about which type/containing type is not accessible diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf index 80e29931c5ab8..15c6aac84e87e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf @@ -269,7 +269,7 @@ Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. - Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. + Interfejsy z atrybutem „GeneratedComInterfaceAttribute” muszą mieć ułatwienia dostępu „publiczny” lub „wewnętrzny”, muszą być częściowe, nie być ogóle, i muszą określać identyfikator GUID z atrybutem „System.Runtime.InteropServices.GuidAttribute”. @@ -279,7 +279,7 @@ Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} - Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} + Interfejs „{0}” ma atrybut „GeneratedComInterfaceAttribute”, ale nie jest dostępny za pomocą wygenerowanego kodu. Interfejs i wszystkie zawierające go typy muszą mieć ułatwienia dostępu „wewnętrzny” lub „publiczny”, aby wygenerowany kod mógł uzyskać do niego dostęp. {1} {1} is details about which type/containing type is not accessible @@ -389,7 +389,7 @@ The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} - The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} + Typ „{0}” określony jako „GeneratedComInterfaceAttribute.StringMarshallingCustomType” jest niedostępny za pomocą wygenerowanego kodu. Typ musi mieć co najmniej ułatwienia dostępu „wewnętrzny”. {1} {1} is details about which type/containing type is not accessible diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf index 18a9a670a0825..bc06648e32e23 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf @@ -74,12 +74,12 @@ A class with 'GeneratedComClassAttribute' must implement at least one interface with 'GeneratedComInterfaceAttribute' or else the generated code with not have an effect. - A class with 'GeneratedComClassAttribute' must implement at least one interface with 'GeneratedComInterfaceAttribute' or else the generated code with not have an effect. + Класс с "GeneratedComClassAttribute" должен реализовывать по крайней мере один интерфейс с "GeneratedComInterfaceAttribute", иначе сгенерированный код не будет иметь эффекта. Class '{0}' with 'GeneratedComClassAttribute' does not implement any interfaces with 'GeneratedComInterfaceAttribute'. Source will not be generated for '{0}'. - Class '{0}' with 'GeneratedComClassAttribute' does not implement any interfaces with 'GeneratedComInterfaceAttribute'. Source will not be generated for '{0}'. + Класс "{0}" с "GeneratedComClassAttribute" не реализует интерфейсы с "GeneratedComInterfaceAttribute". Источник не будет создан для "{0}". @@ -259,7 +259,7 @@ Class '{0}' with 'GeneratedComClassAttribute' or one of its containing types is not marked 'partial'. - Class '{0}' with 'GeneratedComClassAttribute' or one of its containing types is not marked 'partial'. + Класс "{0}" с "GeneratedComClassAttribute" или один из его содержащих типов не помечен как "частичный". @@ -359,17 +359,17 @@ 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. - 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + Для "GeneratedComInterfaceAttribute" и "GeneratedComClassAttribute" требуется небезопасный код. Проект необходимо обновить с использованием значения "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>". 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. - 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. Project must be updated with '<AllowUnsafeBlocks>true</AllowUnsafeBlocks>'. + Для "GeneratedComInterfaceAttribute" и "GeneratedComClassAttribute" требуется небезопасный код. Проект необходимо обновить с использованием значения "<AllowUnsafeBlocks>true</AllowUnsafeBlocks>". 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. - 'GeneratedComInterfaceAttribute' and 'GeneratedComClassAttribute' require unsafe code. + Для "GeneratedComInterfaceAttribute" и "GeneratedComClassAttribute" требуется небезопасный код. diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf index 9a5ca77751164..c32ad990e6ec1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf @@ -269,7 +269,7 @@ Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. - Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. + 'GeneratedComInterfaceAttribute' özniteliğine sahip arabirimler 'public' veya 'internal' erişilebilirlik özelliğine sahip olmalı, kısmi olmalı, genel olmamalı ve 'System.Runtime.InteropServices.GuidAttribute' ile bir GUID belirtmelidir. @@ -279,7 +279,7 @@ Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} - Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} + '{0}' arabirimi 'GeneratedComInterfaceAttribute' özniteliğine sahip ancak oluşturulan kod ile bu arabirime erişilemiyor. Arabirim ve tüm kapsayan türler, oluşturulan kodun bu arabirime erişebilmesi için 'internal' veya 'public' erişilebilirlik özelliğine sahip olmalıdır. {1} {1} is details about which type/containing type is not accessible @@ -389,7 +389,7 @@ The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} - The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} + 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' olarak belirtilen '{0}' türüne, oluşturulan kod ile erişilemiyor. Tür, en azından 'internal' erişilebilirlik özelliğine sahip olmalıdır. {1} {1} is details about which type/containing type is not accessible diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf index 8129c3f1d7776..d9dc9875fc57c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf @@ -269,7 +269,7 @@ Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. - Interfaces attributed with 'GeneratedComInterfaceAttribute' must have 'public' or 'internal' accessibility and be partial, non-generic, and must specify a GUID with 'System.Runtime.InteropServices.GuidAttribute'. + 通过 "GeneratedComInterfaceAttribute" 特性化的接口必须具有 "public" 或 "internal" 可访问性,必须是部分的、非泛型的,并且必须使用 "System.Runtime.InteropServices.GuidAttribute" 指定 GUID。 @@ -279,7 +279,7 @@ Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} - Interface '{0}' is attributed with 'GeneratedComInterfaceAttribute' but is not accessible by generated code. The interface and all containing types must have accessibility 'internal' or 'public' for generated code to access it. {1} + 接口 "GeneratedComInterfaceAttribute" 通过“{0}”进行特性化,但生成的代码无法访问它。该接口和所有包含类型必须具有 "internal" 或 "public" 可访问下,生成的代码才能访问它。{1} {1} is details about which type/containing type is not accessible @@ -389,7 +389,7 @@ The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} - The type '{0}' specified as 'GeneratedComInterfaceAttribute.StringMarshallingCustomType' is not accessible by generated code. The type must have at least 'internal' accessibility. {1} + 生成的代码无法访问指定为 "GeneratedComInterfaceAttribute.StringMarshallingCustomType" 的“{0}”类型。该类型必须至少具有 "internal" 可访问性。{1} {1} is details about which type/containing type is not accessible diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf index cab753796a459..a3d4669040643 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf @@ -169,32 +169,32 @@ Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. - Events are not a concept in COM, so no interop code will be source generated for instance events on source-generated COM interfaces. + 事件不是 COM 中的概念,因此不會為來源產生的 COM 介面上的執行個體事件來源產生 Interop 程式碼。 The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance event '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + 執行個體事件 '{0}' 是在套用了 'GeneratedComInterfaceAttribute' 的介面 '{1}' 中宣告的 Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance event in a type with the 'GeneratedComInterfaceAttribute' is not supported + 不支援在具有 'GeneratedComInterfaceAttribute' 的類型中宣告執行個體事件 Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. - Properties are not a concept in COM, so no interop code will be source generated for instance properties on source-generated COM interfaces. + 屬性不是 COM 中的概念,因此不會為來源產生的 COM 介面上的執行個體屬性來源產生 Interop 程式碼。 The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied - The instance property '{0}' is declared in the interface '{1}', which has the 'GeneratedComInterfaceAttribute' applied + 執行個體屬性 '{0}' 是在套用了 'GeneratedComInterfaceAttribute' 的介面 '{1}' 中宣告的 Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported - Declaring an instance property in a type with the 'GeneratedComInterfaceAttribute' is not supported + 不支援在具有 'GeneratedComInterfaceAttribute' 的類型中宣告執行個體屬性 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf index 65c9d12a2eaa1..ea18fe04b64ef 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf @@ -24,7 +24,7 @@ Containing type '{0}' has accessibility '{1}'. - Containing type '{0}' has accessibility '{1}'. + Obsahující typ „{0}“má přístupnost „{1}“. @@ -119,7 +119,7 @@ '{0}' has accessibility '{1}'. - '{0}' has accessibility '{1}'. + „{0}“ má přístupnost „{1}“. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf index 6803cca7e5795..1aa3d47900e8a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf @@ -24,7 +24,7 @@ Containing type '{0}' has accessibility '{1}'. - Containing type '{0}' has accessibility '{1}'. + Le type conteneur '{0}' a une accessibilité '{1}'. @@ -119,7 +119,7 @@ '{0}' has accessibility '{1}'. - '{0}' has accessibility '{1}'. + '{0}' a une accessibilité '{1}'. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf index 31f918cff9b7f..c1091feae70da 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf @@ -24,7 +24,7 @@ Containing type '{0}' has accessibility '{1}'. - Containing type '{0}' has accessibility '{1}'. + '{0}' 형식을 포함하는 경우 접근성 '{1}'이(가) 있습니다. @@ -119,7 +119,7 @@ '{0}' has accessibility '{1}'. - '{0}' has accessibility '{1}'. + '{0}'에는 접근성 '{1}'이(가) 있습니다. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf index c6e1a1e0e4e86..8be8cdf02e954 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf @@ -24,7 +24,7 @@ Containing type '{0}' has accessibility '{1}'. - Containing type '{0}' has accessibility '{1}'. + Zawierający typ „{0}” ma ułatwienia dostępu „{1}”. @@ -119,7 +119,7 @@ '{0}' has accessibility '{1}'. - '{0}' has accessibility '{1}'. + „{0}” ma ułatwienia dostępu „{1}”. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf index db08826a7868d..f98b8630033fc 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf @@ -24,7 +24,7 @@ Containing type '{0}' has accessibility '{1}'. - Containing type '{0}' has accessibility '{1}'. + '{0}' kapsayan türü '{1}' erişilebilirlik özelliğine sahip. @@ -119,7 +119,7 @@ '{0}' has accessibility '{1}'. - '{0}' has accessibility '{1}'. + '{0}', '{1}' erişilebilirlik özelliğine sahip. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf index a3304f8a91843..606fcf26d2b94 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf @@ -24,7 +24,7 @@ Containing type '{0}' has accessibility '{1}'. - Containing type '{0}' has accessibility '{1}'. + 包含类型“{0}”具有可访问性“{1}”。 @@ -119,7 +119,7 @@ '{0}' has accessibility '{1}'. - '{0}' has accessibility '{1}'. + “{0}”具有可访问性“{1}”。 diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index 28ec1aca68f20..62325c1626921 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -285,6 +285,33 @@ partial interface {|#0:IComInterface2|} : IComInterface, IOtherComInterface } """; + public string DerivedWithParametersDeclaredInOtherNamespace => $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + using OtherNS; + + namespace OtherNS + { + public struct NewType; + } + + namespace Test + { + {{GeneratedComInterface()}} + partial interface IComInterface + { + NewType Method(NewType p); + } + + {{GeneratedComInterface()}} + partial interface IComInterface2 : IComInterface + { + NewType Method2(NewType p); + } + } + """; + public string DerivedWithStringMarshalling(params (StringMarshalling StringMarshalling, Type? StringMarshallingCustomType)[] attributeArguments) { diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index c866713b9d402..3590d17524558 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -8,9 +8,8 @@ using System.Threading.Tasks; using Microsoft.Interop.UnitTests; using Xunit; - -using VerifyVTableGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; +using VerifyVTableGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier; namespace ComInterfaceGenerator.Unit.Tests { @@ -334,6 +333,7 @@ public static IEnumerable ComInterfaceSnippetsToCompile() { CodeSnippets codeSnippets = new(new GeneratedComInterfaceAttributeProvider()); yield return new object[] { ID(), codeSnippets.DerivedComInterfaceType }; + yield return new object[] { ID(), codeSnippets.DerivedWithParametersDeclaredInOtherNamespace }; yield return new object[] { ID(), codeSnippets.ComInterfaceParameters }; } diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntegerToStringTests.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntegerToStringTests.cs index 533d3c623df4d..a3df88edaa2cd 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntegerToStringTests.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntegerToStringTests.cs @@ -718,6 +718,9 @@ private static string CurrencyFormatter(string input, int precision, NumberForma pre = "("; post = " " + nfi.CurrencySymbol + ")"; break; + case 16: + pre = nfi.CurrencySymbol + nfi.NegativeSign + " "; + break; } } else diff --git a/src/libraries/System.Speech/src/System.Speech.csproj b/src/libraries/System.Speech/src/System.Speech.csproj index 128a12cf6048a..a06ca783311a3 100644 --- a/src/libraries/System.Speech/src/System.Speech.csproj +++ b/src/libraries/System.Speech/src/System.Speech.csproj @@ -7,6 +7,8 @@ $(NoWarn);CS0649;SA1129;IDE0059;IDE0060;CA1822;CA1852 annotations false + + $(NoWarn);1591 true true true diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs index f76fa204a2ca8..e0b04f3014279 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverterFactory.cs @@ -40,18 +40,11 @@ public override bool CanConvert(Type typeToConvert) Justification = "The ctor is marked RequiresUnreferencedCode.")] public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { - ConstructorInfo? constructor; JsonConverter converter; Type converterType; - if (typeToConvert.IsKeyValuePair()) - { - // browser-wasm compat -- ensure the linker doesn't trim away constructor parameter names from KVP. - Type[] genericArguments = typeToConvert.GetGenericArguments(); - Type keyValuePairType = typeof(KeyValuePair<,>).MakeGenericType(genericArguments); - constructor = keyValuePairType.GetConstructor(genericArguments); - } - else if (!typeToConvert.TryGetDeserializationConstructor(_useDefaultConstructorInUnannotatedStructs, out constructor)) + bool useDefaultConstructorInUnannotatedStructs = _useDefaultConstructorInUnannotatedStructs && !typeToConvert.IsKeyValuePair(); + if (!typeToConvert.TryGetDeserializationConstructor(useDefaultConstructorInUnannotatedStructs, out ConstructorInfo? constructor)) { ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateTypeAttribute(typeToConvert); } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs index 6a59bf1ab1547..d3531970a8e76 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.CompilerServices; using System.Text.Json.Nodes; @@ -13,6 +15,13 @@ namespace System.Text.Json.Serialization.Tests { public abstract partial class JsonSerializerWrapper { + // Ensure that the reflection-based serializer testing abstraction roots KeyValuePair<,> + // which is required by many tests in the reflection test suite. + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties, typeof(KeyValuePair<,>))] + protected JsonSerializerWrapper() + { + } + public static JsonSerializerWrapper SpanSerializer { get; } = new SpanSerializerWrapper(); public static JsonSerializerWrapper StringSerializer { get; } = new StringSerializerWrapper(); public static StreamingJsonSerializerWrapper AsyncStreamSerializer { get; } = new AsyncStreamSerializerWrapper(); diff --git a/src/libraries/System.Threading.RateLimiting/src/System.Threading.RateLimiting.csproj b/src/libraries/System.Threading.RateLimiting/src/System.Threading.RateLimiting.csproj index d1400f97ec8b6..00c1eadc2486b 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System.Threading.RateLimiting.csproj +++ b/src/libraries/System.Threading.RateLimiting/src/System.Threading.RateLimiting.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml index cc02039de6739..5286108f99594 100644 --- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml +++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml @@ -648,6 +648,8 @@ + + diff --git a/src/tests/JIT/Directed/physicalpromotion/fuzzlyn2.cs b/src/tests/JIT/Directed/physicalpromotion/fuzzlyn2.cs new file mode 100644 index 0000000000000..ad41b1c8b7974 --- /dev/null +++ b/src/tests/JIT/Directed/physicalpromotion/fuzzlyn2.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +// Generated by Fuzzlyn v1.5 on 2023-06-15 11:50:35 +// Run on X64 Windows +// Seed: 1595496264005900603 +// Reduced from 20.9 KiB to 0.9 KiB in 00:00:18 +// Debug: Outputs 0 +// Release: Outputs 1 +public struct S0 +{ + public bool F0; + public short F1; + public byte F2; + public uint F3; + public uint F4; + public short F5; + public sbyte F6; + public bool F7; + public S0(bool f0, short f1, byte f2, uint f3, uint f4, short f5, sbyte f6, bool f7) + { + F0 = f0; + F1 = f1; + F2 = f2; + F3 = f3; + F4 = f4; + F5 = f5; + F6 = f6; + F7 = f7; + } +} + +public struct S1 +{ + public S0 F1; + public S0 F2; +} + +public class Runtime_87614 +{ + [Fact] + public static int TestEntryPoint() + { + var vr1 = new S1(); + int result = M3(vr1); + if (result != 0) + { + Console.WriteLine("FAIL: result is {0}", result); + } + return result == 0 ? 100 : 101; + } + + public static int M3(S1 arg0) + { + arg0.F1 = new S0(arg0.F2.F0, 1, 0, arg0.F1.F4, arg0.F1.F4, arg0.F1.F1, 0, true); + Consume(arg0.F1.F0); + Consume(arg0.F1.F1); + Consume(arg0.F1.F4); + return arg0.F1.F5; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Consume(T value) + { + } +} diff --git a/src/tests/JIT/Directed/physicalpromotion/fuzzlyn2.csproj b/src/tests/JIT/Directed/physicalpromotion/fuzzlyn2.csproj new file mode 100644 index 0000000000000..13d1f0b7f65d4 --- /dev/null +++ b/src/tests/JIT/Directed/physicalpromotion/fuzzlyn2.csproj @@ -0,0 +1,9 @@ + + + True + + + + + + \ No newline at end of file diff --git a/src/tests/JIT/opt/Compares/conditionalNegates.cs b/src/tests/JIT/opt/Compares/conditionalNegates.cs index 8366f1b9b9db6..b612756576010 100644 --- a/src/tests/JIT/opt/Compares/conditionalNegates.cs +++ b/src/tests/JIT/opt/Compares/conditionalNegates.cs @@ -129,4 +129,23 @@ public static void cneg_shifted_true_oper(int op1, int op2, int expected) int result = op1 < 51 ? -(op1 >> 3) : op2; Assert.Equal(expected, result); } + + [Theory] + [InlineData(1, -1)] + [InlineData(55, ~55)] + [MethodImpl(MethodImplOptions.NoInlining)] + public static void cneg_mixed_not_and_neg_oper(int op1, int expected) + { + //ARM64-FULL-LINE: cmp {{w[0-9]+}}, #52 + //ARM64-FULL-LINE-NEXT: csneg {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}}, {{gt|le}} + if (op1 <= 52) + { + op1 = -op1; + } + else + { + op1 = ~op1; + } + Assert.Equal(expected, op1); + } } diff --git a/src/tests/tracing/eventpipe/applystartuphook/ApplyStartupHookValidation.cs b/src/tests/tracing/eventpipe/applystartuphook/ApplyStartupHookValidation.cs index c62579fbdd379..87f968f22509e 100644 --- a/src/tests/tracing/eventpipe/applystartuphook/ApplyStartupHookValidation.cs +++ b/src/tests/tracing/eventpipe/applystartuphook/ApplyStartupHookValidation.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using Microsoft.Diagnostics.Tools.RuntimeClient; using Microsoft.Diagnostics.Tracing; +using Microsoft.Diagnostics.Tracing.Parsers; using Tracing.Tests.Common; using DiagnosticsClient = Microsoft.Diagnostics.NETCore.Client.DiagnosticsClient; @@ -48,6 +49,7 @@ public static async Task TEST_ApplyStartupHookAtStartupSuspension() Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"Received: {response.ToString()}"); + fSuccess &= CheckResponse(response); } Logger.logger.Log("Waiting to accept diagnostic connection."); @@ -64,6 +66,90 @@ public static async Task TEST_ApplyStartupHookAtStartupSuspension() Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"Received: {response.ToString()}"); + fSuccess &= CheckResponse(response); + } + } + ); + + fSuccess &= await subprocessTask; + + return fSuccess; + } + + public static async Task TEST_ApplyStartupHookDuringExecution() + { + bool fSuccess = true; + string serverName = ReverseServer.MakeServerAddress(); + Logger.logger.Log($"Server name is '{serverName}'"); + Task subprocessTask = Utils.RunSubprocess( + currentAssembly: Assembly.GetExecutingAssembly(), + environment: new Dictionary + { + { Utils.DiagnosticPortsEnvKey, serverName } + }, + duringExecution: async (pid) => + { + ReverseServer server = new ReverseServer(serverName); + Logger.logger.Log("Waiting to accept diagnostic connection."); + using (Stream stream = await server.AcceptAsync()) + { + Logger.logger.Log("Accepted diagnostic connection."); + + IpcAdvertise advertise = IpcAdvertise.Parse(stream); + Logger.logger.Log($"IpcAdvertise: {advertise}"); + + SessionConfiguration config = new( + circularBufferSizeMB: 1000, + format: EventPipeSerializationFormat.NetTrace, + providers: new List { + new Provider(AppEventSource.SourceName, 0, EventLevel.Verbose) + }); + + Logger.logger.Log("Starting EventPipeSession over standard connection"); + using Stream eventStream = EventPipeClient.CollectTracing(pid, config, out ulong sessionId); + Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:X}"); + + using EventPipeEventSource source = new(eventStream); + TaskCompletionSource completionSource = new(TaskCreationOptions.RunContinuationsAsynchronously); + + source.Dynamic.All += (TraceEvent traceEvent) => + { + if (AppEventSource.SourceName.Equals(traceEvent.ProviderName) && nameof(AppEventSource.Running).Equals(traceEvent.EventName)) + completionSource.TrySetResult(); + }; + + _ = Task.Run(() => source.Process()); + + Logger.logger.Log($"Send ResumeRuntime Diagnostics IPC Command"); + // send ResumeRuntime command (0x04=ProcessCommandSet, 0x01=ResumeRuntime commandid) + var message = new IpcMessage(0x04,0x01); + Logger.logger.Log($"Sent: {message.ToString()}"); + IpcMessage response = IpcClient.SendMessage(stream, message); + Logger.logger.Log($"received: {response.ToString()}"); + fSuccess &= CheckResponse(response); + + Logger.logger.Log("Start waiting for any event that indicates managed code is running."); + await completionSource.Task.ConfigureAwait(false); + + Logger.logger.Log("Stopping trace."); + EventPipeClient.StopTracing(pid, sessionId); + } + + Logger.logger.Log("Waiting to accept diagnostic connection."); + using (Stream stream = await server.AcceptAsync()) + { + Logger.logger.Log("Accepted diagnostic connection."); + + IpcAdvertise advertise = IpcAdvertise.Parse(stream); + Logger.logger.Log($"IpcAdvertise: {advertise}"); + + string startupHookPath = Hook.Basic.AssemblyPath; + Logger.logger.Log($"Send ApplyStartupHook Diagnostic IPC: {startupHookPath}"); + IpcMessage message = CreateApplyStartupHookMessage(startupHookPath); + Logger.logger.Log($"Sent: {message.ToString()}"); + IpcMessage response = IpcClient.SendMessage(stream, message); + Logger.logger.Log($"Received: {response.ToString()}"); + fSuccess &= CheckResponse(response); } } ); @@ -82,10 +168,19 @@ private static IpcMessage CreateApplyStartupHookMessage(string startupHookPath) return new IpcMessage(0x04, 0x07, serializedConfiguration); } + private static bool CheckResponse(IpcMessage response) + { + Logger.logger.Log($"Response CommandId: {response.Header.CommandId}"); + return response.Header.CommandId == (byte)0; // DiagnosticsServerResponseId.OK; + } + public static async Task Main(string[] args) { if (args.Length >= 1) { + AppEventSource source = new(); + source.Running(); + Console.Out.WriteLine("Subprocess started! Waiting for input..."); var input = Console.In.ReadLine(); // will block until data is sent across stdin Console.Out.WriteLine($"Received '{input}'"); @@ -120,5 +215,20 @@ public static async Task Main(string[] args) } return fSuccess ? 100 : -1; } + + [EventSource(Name = AppEventSource.SourceName)] + private class AppEventSource : EventSource + { + public const string SourceName = nameof(AppEventSource); + public const int RunningEventId = 1; + + public AppEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { } + + [Event(RunningEventId)] + public void Running() + { + WriteEvent(RunningEventId); + } + } } } diff --git a/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs b/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs index 53533e252c5df..39c8f8e71dad3 100644 --- a/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs +++ b/src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs @@ -64,6 +64,8 @@ void AddRange (DiagnosticId first, DiagnosticId last) public override ImmutableArray SupportedDiagnostics => GetSupportedDiagnostics (); + static Location GetPrimaryLocation (ImmutableArray locations) => locations.Length > 0 ? locations[0] : Location.None; + public override void Initialize (AnalysisContext context) { if (!System.Diagnostics.Debugger.IsAttached) @@ -87,6 +89,7 @@ public override void Initialize (AnalysisContext context) // Examine generic instantiations in base types and interface list context.RegisterSymbolAction (context => { var type = (INamedTypeSymbol) context.Symbol; + var location = GetPrimaryLocation (type.Locations); // RUC on type doesn't silence DAM warnings about generic base/interface types. // This knowledge lives in IsInRequiresUnreferencedCodeAttributeScope, // which we still call for consistency here, but it is expected to return false. @@ -94,12 +97,12 @@ public override void Initialize (AnalysisContext context) return; if (type.BaseType is INamedTypeSymbol baseType) { - foreach (var diagnostic in ProcessGenericParameters (baseType, type.Locations[0])) + foreach (var diagnostic in ProcessGenericParameters (baseType, location)) context.ReportDiagnostic (diagnostic); } foreach (var interfaceType in type.Interfaces) { - foreach (var diagnostic in ProcessGenericParameters (interfaceType, type.Locations[0])) + foreach (var diagnostic in ProcessGenericParameters (interfaceType, location)) context.ReportDiagnostic (diagnostic); } }, SymbolKind.NamedType); @@ -111,11 +114,11 @@ public override void Initialize (AnalysisContext context) return; var returnType = method.ReturnType; - foreach (var diagnostic in ProcessGenericParameters (returnType, method.Locations[0])) + foreach (var diagnostic in ProcessGenericParameters (returnType, GetPrimaryLocation (method.Locations))) context.ReportDiagnostic (diagnostic); foreach (var parameter in method.Parameters) { - foreach (var diagnostic in ProcessGenericParameters (parameter.Type, parameter.Locations[0])) + foreach (var diagnostic in ProcessGenericParameters (parameter.Type, GetPrimaryLocation (parameter.Locations))) context.ReportDiagnostic (diagnostic); } }, SymbolKind.Method); @@ -125,7 +128,7 @@ public override void Initialize (AnalysisContext context) if (field.IsInRequiresUnreferencedCodeAttributeScope (out _)) return; - foreach (var diagnostic in ProcessGenericParameters (field.Type, field.Locations[0])) + foreach (var diagnostic in ProcessGenericParameters (field.Type, GetPrimaryLocation (field.Locations))) context.ReportDiagnostic (diagnostic); }, SymbolKind.Field); // Examine generic instantiations in invocations of generically instantiated methods, @@ -244,19 +247,20 @@ static List GetDynamicallyAccessedMembersDiagnostics (SingleValue so static void VerifyMemberOnlyApplyToTypesOrStrings (SymbolAnalysisContext context, ISymbol member) { + var location = GetPrimaryLocation (member.Locations); if (member is IFieldSymbol field && field.GetDynamicallyAccessedMemberTypes () != DynamicallyAccessedMemberTypes.None && !field.Type.IsTypeInterestingForDataflow ()) - context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnFieldCanOnlyApplyToTypesOrStrings), member.Locations[0], member.GetDisplayName ())); + context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnFieldCanOnlyApplyToTypesOrStrings), location, member.GetDisplayName ())); else if (member is IMethodSymbol method) { if (method.GetDynamicallyAccessedMemberTypesOnReturnType () != DynamicallyAccessedMemberTypes.None && !method.ReturnType.IsTypeInterestingForDataflow ()) - context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings), member.Locations[0], member.GetDisplayName ())); + context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings), location, member.GetDisplayName ())); if (method.GetDynamicallyAccessedMemberTypes () != DynamicallyAccessedMemberTypes.None && !method.ContainingType.IsTypeInterestingForDataflow ()) - context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersIsNotAllowedOnMethods), member.Locations[0])); + context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersIsNotAllowedOnMethods), location)); foreach (var parameter in method.Parameters) { if (parameter.GetDynamicallyAccessedMemberTypes () != DynamicallyAccessedMemberTypes.None && !parameter.Type.IsTypeInterestingForDataflow ()) - context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnMethodParameterCanOnlyApplyToTypesOrStrings), member.Locations[0], parameter.GetDisplayName (), member.GetDisplayName ())); + context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnMethodParameterCanOnlyApplyToTypesOrStrings), location, parameter.GetDisplayName (), member.GetDisplayName ())); } } else if (member is IPropertySymbol property && property.GetDynamicallyAccessedMemberTypes () != DynamicallyAccessedMemberTypes.None && !property.Type.IsTypeInterestingForDataflow ()) { - context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnPropertyCanOnlyApplyToTypesOrStrings), member.Locations[0], member.GetDisplayName ())); + context.ReportDiagnostic (Diagnostic.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersOnPropertyCanOnlyApplyToTypesOrStrings), location, member.GetDisplayName ())); } } @@ -277,7 +281,7 @@ static void VerifyDamOnMethodsMatch (SymbolAnalysisContext context, IMethodSymbo (IMethodSymbol attributableMethod, DynamicallyAccessedMemberTypes missingAttribute) = GetTargetAndRequirements (overrideMethod, baseMethod, overrideMethodReturnAnnotation, baseMethodReturnAnnotation); - Location attributableSymbolLocation = attributableMethod.Locations[0]; + Location attributableSymbolLocation = GetPrimaryLocation (attributableMethod.Locations); // code fix does not support merging multiple attributes. If an attribute is present or the method is not in source, do not provide args for code fix. (Location[]? sourceLocation, Dictionary? DAMArgs) = (!attributableSymbolLocation.IsInSource @@ -287,7 +291,7 @@ static void VerifyDamOnMethodsMatch (SymbolAnalysisContext context, IMethodSymbo context.ReportDiagnostic (Diagnostic.Create ( DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides), - overrideMethod.Locations[0], sourceLocation, DAMArgs?.ToImmutableDictionary (), overrideMethod.GetDisplayName (), baseMethod.GetDisplayName ())); + GetPrimaryLocation (overrideMethod.Locations), sourceLocation, DAMArgs?.ToImmutableDictionary (), overrideMethod.GetDisplayName (), baseMethod.GetDisplayName ())); } foreach (var overrideParam in overrideMethod.GetMetadataParameters ()) { @@ -320,7 +324,8 @@ static void VerifyDamOnMethodsMatch (SymbolAnalysisContext context, IMethodSymbo (IMethodSymbol attributableMethod, DynamicallyAccessedMemberTypes missingAttribute) = GetTargetAndRequirements (overrideMethod, baseMethod, methodTypeParameterAnnotation, overriddenMethodTypeParameterAnnotation); - Location attributableSymbolLocation = attributableMethod.TypeParameters[i].Locations[0]; + var attributableSymbol = attributableMethod.TypeParameters[i]; + Location attributableSymbolLocation = GetPrimaryLocation (attributableSymbol.Locations); // code fix does not support merging multiple attributes. If an attribute is present or the method is not in source, do not provide args for code fix. (Location[]? sourceLocation, Dictionary? DAMArgs) = (!attributableSymbolLocation.IsInSource @@ -330,7 +335,7 @@ static void VerifyDamOnMethodsMatch (SymbolAnalysisContext context, IMethodSymbo context.ReportDiagnostic (Diagnostic.Create ( DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnGenericParameterBetweenOverrides), - overrideMethod.TypeParameters[i].Locations[0], sourceLocation, DAMArgs?.ToImmutableDictionary (), + GetPrimaryLocation (overrideMethod.TypeParameters[i].Locations), sourceLocation, DAMArgs?.ToImmutableDictionary (), overrideMethod.TypeParameters[i].GetDisplayName (), overrideMethod.GetDisplayName (), baseMethod.TypeParameters[i].GetDisplayName (), baseMethod.GetDisplayName ())); } @@ -339,7 +344,7 @@ static void VerifyDamOnMethodsMatch (SymbolAnalysisContext context, IMethodSymbo if (!overrideMethod.IsStatic && overrideMethod.GetDynamicallyAccessedMemberTypes () != baseMethod.GetDynamicallyAccessedMemberTypes ()) context.ReportDiagnostic (Diagnostic.Create ( DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersMismatchOnImplicitThisBetweenOverrides), - overrideMethod.Locations[0], + GetPrimaryLocation (overrideMethod.Locations), overrideMethod.GetDisplayName (), baseMethod.GetDisplayName ())); } @@ -364,10 +369,11 @@ static void VerifyDamOnPropertyAndAccessorMatch (SymbolAnalysisContext context, // None on parameter of 'set' matches unannotated || methodSymbol.MethodKind == MethodKind.PropertySet && methodSymbol.Parameters[methodSymbol.Parameters.Length - 1].GetDynamicallyAccessedMemberTypes () != DynamicallyAccessedMemberTypes.None) { + var associatedSymbol = methodSymbol.AssociatedSymbol!; context.ReportDiagnostic (Diagnostic.Create ( DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor), - methodSymbol.AssociatedSymbol!.Locations[0], - methodSymbol.AssociatedSymbol!.GetDisplayName (), + GetPrimaryLocation (associatedSymbol.Locations), + associatedSymbol.GetDisplayName (), methodSymbol.GetDisplayName () )); return; diff --git a/src/tools/illink/src/ILLink.Shared/DataFlow/ValueSet.cs b/src/tools/illink/src/ILLink.Shared/DataFlow/ValueSet.cs index 199a2761f95f2..2fb1fc3f21746 100644 --- a/src/tools/illink/src/ILLink.Shared/DataFlow/ValueSet.cs +++ b/src/tools/illink/src/ILLink.Shared/DataFlow/ValueSet.cs @@ -15,6 +15,8 @@ namespace ILLink.Shared.DataFlow public readonly struct ValueSet : IEquatable>, IEnumerable, IDeepCopyValue> where TValue : notnull { + const int MaxValuesInSet = 256; + // Since we're going to do lot of type checks for this class a lot, it is much more efficient // if the class is sealed (as then the runtime can do a simple method table pointer comparison) private sealed class EnumerableValues : HashSet @@ -194,6 +196,10 @@ internal static ValueSet Meet (ValueSet left, ValueSet r var values = new EnumerableValues (left.DeepCopy ()); values.UnionWith (right.DeepCopy ()); + // Limit the number of values we track, to prevent hangs in case of patterns that + // create exponentially many possible values. This will result in analysis holes. + if (values.Count > MaxValuesInSet) + return default; return new ValueSet (values); } diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index b6376efeef6f5..ab3619c5958d1 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -1452,7 +1452,7 @@ sealed class TypeReferenceMarker : TypeReferenceWalker readonly MarkingHelpers markingHelpers; TypeReferenceMarker (AssemblyDefinition assembly, MarkingHelpers markingHelpers) - : base (assembly) + : base (assembly, walkSymbols: false) { this.markingHelpers = markingHelpers; } diff --git a/src/tools/illink/src/linker/Linker.Steps/SweepStep.cs b/src/tools/illink/src/linker/Linker.Steps/SweepStep.cs index 9e179e92a79a2..794ef60ea19a7 100644 --- a/src/tools/illink/src/linker/Linker.Steps/SweepStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/SweepStep.cs @@ -58,7 +58,7 @@ protected override void Process () foreach (var assembly in assemblies) RemoveUnmarkedAssembly (assembly); - // Look for references (included to previously unresolved assemblies) marked for deletion + // Look for references (including to previously unresolved assemblies) marked for deletion foreach (var assembly in assemblies) UpdateAssemblyReferencesToRemovedAssemblies (assembly); @@ -69,7 +69,7 @@ protected override void Process () case AssemblyAction.CopyUsed: case AssemblyAction.Link: case AssemblyAction.Save: - bool changed = AssemblyReferencesCorrector.SweepAssemblyReferences (assembly); + bool changed = SweepAssemblyReferences (assembly); if (changed && action == AssemblyAction.CopyUsed) Annotations.SetAction (assembly, AssemblyAction.Save); break; @@ -174,7 +174,7 @@ protected void ProcessAssemblyAction (AssemblyDefinition assembly) AssemblyAction assemblyAction = AssemblyAction.Copy; if (SweepTypeForwarders (assembly)) { // Need to sweep references, in case sweeping type forwarders removed any - AssemblyReferencesCorrector.SweepAssemblyReferences (assembly); + SweepAssemblyReferences (assembly); assemblyAction = AssemblyAction.Save; } @@ -194,7 +194,7 @@ protected void ProcessAssemblyAction (AssemblyDefinition assembly) case AssemblyAction.Save: if (SweepTypeForwarders (assembly)) { // Need to sweep references, in case sweeping type forwarders removed any - AssemblyReferencesCorrector.SweepAssemblyReferences (assembly); + SweepAssemblyReferences (assembly); } break; } @@ -242,7 +242,7 @@ protected virtual void SweepAssembly (AssemblyDefinition assembly) } if (SweepTypeForwarders (assembly) || updateScopes) - AssemblyReferencesCorrector.SweepAssemblyReferences (assembly); + SweepAssemblyReferences (assembly); } bool IsMarkedAssembly (AssemblyDefinition assembly) @@ -568,32 +568,32 @@ protected virtual void CustomAttributeUsageRemoved (ICustomAttributeProvider pro { } + bool SweepAssemblyReferences (AssemblyDefinition assembly) + { + // + // We used to run over list returned by GetTypeReferences but + // that returns typeref(s) of original assembly and we don't track + // which types are needed for which assembly which left us + // with dangling assembly references + // + assembly.MainModule.AssemblyReferences.Clear (); + + var arc = new AssemblyReferencesCorrector (assembly, walkSymbols: Context.LinkSymbols); + arc.Process (); + + return arc.ChangedAnyScopes; + } + sealed class AssemblyReferencesCorrector : TypeReferenceWalker { readonly DefaultMetadataImporter importer; - bool changedAnyScopes; + public bool ChangedAnyScopes { get; private set; } - AssemblyReferencesCorrector (AssemblyDefinition assembly) : base (assembly) + public AssemblyReferencesCorrector (AssemblyDefinition assembly, bool walkSymbols) : base (assembly, walkSymbols) { this.importer = new DefaultMetadataImporter (assembly.MainModule); - changedAnyScopes = false; - } - - public static bool SweepAssemblyReferences (AssemblyDefinition assembly) - { - // - // We used to run over list returned by GetTypeReferences but - // that returns typeref(s) of original assembly and we don't track - // which types are needed for which assembly which left us - // with dangling assembly references - // - assembly.MainModule.AssemblyReferences.Clear (); - - var arc = new AssemblyReferencesCorrector (assembly); - arc.Process (); - - return arc.changedAnyScopes; + ChangedAnyScopes = false; } protected override void ProcessTypeReference (TypeReference type) @@ -626,7 +626,7 @@ protected override void ProcessTypeReference (TypeReference type) return; type.Scope = tr.Scope; - changedAnyScopes = true; + ChangedAnyScopes = true; } protected override void ProcessExportedType (ExportedType exportedType) @@ -647,7 +647,7 @@ protected override void ProcessExportedType (ExportedType exportedType) return; exportedType.Scope = tr.Scope; - changedAnyScopes = true; + ChangedAnyScopes = true; } } } diff --git a/src/tools/illink/src/linker/Linker/TypeReferenceWalker.cs b/src/tools/illink/src/linker/Linker/TypeReferenceWalker.cs index 7ae2584732686..7b372891203d5 100644 --- a/src/tools/illink/src/linker/Linker/TypeReferenceWalker.cs +++ b/src/tools/illink/src/linker/Linker/TypeReferenceWalker.cs @@ -15,15 +15,18 @@ abstract class TypeReferenceWalker protected HashSet Visited { get; } = new HashSet (); - public TypeReferenceWalker (AssemblyDefinition assembly) + readonly bool walkSymbols; + + public TypeReferenceWalker (AssemblyDefinition assembly, bool walkSymbols) { this.assembly = assembly; + this.walkSymbols = walkSymbols; } // Traverse the assembly and mark the scopes of discovered type references (but not exported types). // This includes scopes referenced by Cecil TypeReference objects that don't represent rows in the typeref table, // such as references to built-in types, or attribute arguments which encode type references as strings. - protected virtual void Process () + public virtual void Process () { if (Visited.Count > 0) throw new InvalidOperationException (); @@ -103,6 +106,9 @@ void WalkScopes (TypeDefinition typeDefinition) if (m.HasBody) WalkTypeScope (m.Body); + + if (walkSymbols && m.DebugInformation?.Scope?.Import is ImportDebugInformation import) + WalkDebugInfoImportScope (import); } } @@ -315,6 +321,17 @@ void WalkForwardedTypesScope (CustomAttributeArgument attributeArgument) } } + void WalkDebugInfoImportScope (ImportDebugInformation import) + { + if (import.HasTargets) { + foreach (var target in import.Targets) + WalkScopeOfTypeReference (target.Type); + } + + if (import.Parent is ImportDebugInformation parent) + WalkDebugInfoImportScope (parent); + } + void WalkScopeOfTypeReference (TypeReference type) { if (type == null) diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs index 2a1f1e713281f..0b7f9e5d1c8ba 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DynamicallyAccessedMembersAnalyzerTests.cs @@ -13,9 +13,14 @@ namespace ILLink.RoslynAnalyzer.Tests { public class DynamicallyAccessedMembersAnalyzerTests { - static Task VerifyDynamicallyAccessedMembersAnalyzer (string source, params DiagnosticResult[] expected) - { - return VerifyCS.VerifyAnalyzerAsync (source, + static Task VerifyDynamicallyAccessedMembersAnalyzer ( + string source, + bool consoleApplication, + params DiagnosticResult[] expected) + { + return VerifyCS.VerifyAnalyzerAsync ( + source, + consoleApplication, TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer), expected: expected); } @@ -49,7 +54,7 @@ private static void M(Type type) } } """; - return VerifyCS.VerifyAnalyzerAsync (TargetParameterWithAnnotations); + return VerifyCS.VerifyAnalyzerAsync (TargetParameterWithAnnotations, consoleApplication: false); } #region SourceParameter @@ -84,7 +89,7 @@ private static void M(Type type) // (21,3): warning IL2067: 'parameter' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethodsOnParameter(Type)'. // The parameter 'type' of method 'C.M(Type)' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsParameter) .WithSpan (21, 3, 21, 38) .WithSpan (19, 24, 19, 33) @@ -124,7 +129,7 @@ private static Type M(Type type) // (18,10): warning IL2068: 'C.M(Type)' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The parameter 'type' of method 'C.M(Type)' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType) .WithSpan (18, 10, 18, 14) .WithSpan (16, 24, 16, 33) @@ -165,7 +170,7 @@ private static void M(Type type) // (17,3): warning IL2069: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The parameter 'type' of method 'C.M(Type)' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsField) .WithSpan (17, 3, 17, 11) .WithSpan (15, 24, 15, 33) @@ -203,7 +208,7 @@ private static void M(Type type) // (16,3): warning IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'. // The parameter 'type' of method 'C.M(Type)' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchParameterTargetsThisParameter) .WithSpan (16, 3, 16, 24) .WithSpan (14, 24, 14, 33) @@ -248,7 +253,7 @@ private static Type GetT() // (12,3): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethodsOnParameter(Type)'. // The return value of method 'C.GetT()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter) .WithSpan (12, 3, 12, 40) .WithSpan (20, 2, 23, 3) @@ -289,7 +294,7 @@ private static Type GetFoo() // (18,10): warning IL2073: 'C.M()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The return value of method 'C.GetT()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsMethodReturnType) .WithSpan (18, 10, 18, 18) .WithSpan (21, 2, 24, 3) @@ -327,7 +332,7 @@ private static Type M() // (12,3): warning IL2074: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The return value of method 'C.M()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsField) .WithSpan (12, 3, 12, 10) .WithSpan (15, 2, 18, 3) @@ -365,7 +370,7 @@ private static Type GetFoo () // (11,3): warning IL2075: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'. // The return value of method 'C.GetT()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsThisParameter) .WithSpan (11, 3, 11, 28) .WithSpan (15, 2, 18, 3) @@ -404,7 +409,7 @@ private static void NeedsPublicMethods( // (14,3): warning IL2077: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.NeedsPublicMethods(Type)'. // The field 'C.f' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsParameter) .WithSpan (14, 3, 14, 24) .WithSpan (10, 22, 10, 37) @@ -445,7 +450,7 @@ private static Type M() // (20,10): warning IL2078: 'C.M()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The field 'C.f' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsMethodReturnType) .WithSpan (20, 10, 20, 11) .WithSpan (10, 22, 10, 37) @@ -480,7 +485,7 @@ public static void Main() // (17,3): warning IL2079: value stored in field 'C.f2' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The field 'C.f1' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsField) .WithSpan (17, 3, 17, 10) .WithSpan (10, 22, 10, 38) @@ -514,7 +519,7 @@ public static void Main() // (13,3): warning IL2080: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethod(String)'. // The field 'C.f' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchFieldTargetsThisParameter) .WithSpan (13, 3, 13, 21) .WithSpan (9, 22, 9, 37) @@ -749,7 +754,7 @@ private static void M2( // (198,4): warning IL2082: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'. // The implicit 'this' argument of method 'System.C.M1()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetParameterWithAnnotations), + return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetParameterWithAnnotations), consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsParameter) .WithSpan (198, 4, 198, 12) .WithSpan (196, 3, 199, 4) @@ -788,7 +793,7 @@ private static void M2( } """; - return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), ConversionOperation), + return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), ConversionOperation), consoleApplication: false, // (203,4): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'. The return value of method 'System.ConvertsToType.implicit operator Type(ConvertsToType)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter) .WithSpan (203, 4, 203, 28) @@ -831,7 +836,7 @@ private static void M2( } """; - return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), AnnotatedConversionOperation), + return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), AnnotatedConversionOperation), consoleApplication: false, // (205,4): warning IL2072: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.C.M2(Type)'. The return value of method 'System.ConvertsToType.implicit operator Type(ConvertsToType)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchMethodReturnTypeTargetsParameter) .WithSpan (205, 4, 205, 28) @@ -872,7 +877,7 @@ private static void M2( } """; - return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), AnnotatedConversionOperation)); + return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), AnnotatedConversionOperation), consoleApplication: false); } @@ -902,7 +907,7 @@ private Type M() // (200,11): warning IL2083: 'System.C.M()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The implicit 'this' argument of method 'System.C.M()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetMethodReturnTypeWithAnnotations), + return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetMethodReturnTypeWithAnnotations), consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsMethodReturnType) .WithSpan (200, 11, 200, 15) .WithSpan (196, 3, 201, 4) @@ -937,7 +942,7 @@ private void M() // (198,4): warning IL2084: value stored in field 'System.C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The implicit 'this' argument of method 'System.C.M()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetFieldWithAnnotations), + return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetFieldWithAnnotations), consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsField) .WithSpan (198, 4, 198, 12) .WithSpan (196, 3, 199, 4) @@ -970,7 +975,7 @@ private void M() // (198,4): warning IL2085: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'System.Type.GetMethods()'. // The implicit 'this' argument of method 'System.C.M()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetMethodWithAnnotations), + return VerifyDynamicallyAccessedMembersAnalyzer (string.Concat (GetSystemTypeBase (), TargetMethodWithAnnotations), consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchThisParameterTargetsThisParameter) .WithSpan (198, 4, 198, 21) .WithSpan (196, 3, 199, 4) @@ -1007,7 +1012,7 @@ private static void M2() // (18,3): warning IL2087: 'type' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in call to 'C.M1(Type)'. // The generic parameter 'T' of 'C.M2()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsParameter) .WithSpan (18, 3, 18, 16) .WithSpan (16, 25, 16, 26) @@ -1039,7 +1044,7 @@ private static Type M() // (14,10): warning IL2088: 'C.M()' method return value does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' requirements. // The generic parameter 'T' of 'C.M()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsMethodReturnType) .WithSpan (14, 10, 14, 19) .WithSpan (12, 24, 12, 25) @@ -1073,7 +1078,7 @@ private static void M() // (16,3): warning IL2089: value stored in field 'C.f' does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' requirements. // The generic parameter 'T' of 'C.M()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsField) .WithSpan (16, 3, 16, 16) .WithSpan (14, 24, 14, 25) @@ -1110,7 +1115,7 @@ private static void M2() // (16,3): warning IL2091: 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' // in 'C.M1()'. The generic parameter 'S' of 'C.M2()' does not have matching annotations. // The source value must declare at least the same requirements as those declared on the target location it is assigned to. - return VerifyDynamicallyAccessedMembersAnalyzer (TargetGenericParameterWithAnnotations, + return VerifyDynamicallyAccessedMembersAnalyzer (TargetGenericParameterWithAnnotations, consoleApplication: false, VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter) .WithSpan (16, 3, 16, 10) .WithSpan (14, 25, 14, 26) @@ -1140,7 +1145,7 @@ private static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes } } """; - return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations); + return VerifyDynamicallyAccessedMembersAnalyzer (TargetParameterWithAnnotations, consoleApplication: false); } [Fact] @@ -1169,7 +1174,7 @@ private static Type M() } """; - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations); + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, consoleApplication: false); } [Fact] @@ -1198,7 +1203,7 @@ private static Type M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes } """; - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations); + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodReturnTypeWithAnnotations, consoleApplication: false); } [Fact] @@ -1229,7 +1234,7 @@ private static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes } """; - return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations); + return VerifyDynamicallyAccessedMembersAnalyzer (TargetFieldWithAnnotations, consoleApplication: false); } [Fact] @@ -1257,7 +1262,7 @@ private static void M([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes } """; - return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations); + return VerifyDynamicallyAccessedMembersAnalyzer (TargetMethodWithAnnotations, consoleApplication: false); } [Fact] @@ -1278,7 +1283,7 @@ static void RequireAll([DynamicallyAccessedMembers(DynamicallyAccessedMemberType } """; - return VerifyDynamicallyAccessedMembersAnalyzer (Source, + return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (8,14): error CS0103: The name 'type' does not exist in the current context DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 14, 8, 18).WithArguments ("type")); } @@ -1302,7 +1307,7 @@ public static void Main() } """; - return VerifyDynamicallyAccessedMembersAnalyzer (Source, + return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (12,34): error CS0103: The name 'type' does not exist in the current context DiagnosticResult.CompilerError ("CS0103").WithSpan (12, 34, 12, 38).WithArguments ("type")); } @@ -1326,7 +1331,7 @@ public static void Main() } """; - return VerifyDynamicallyAccessedMembersAnalyzer (Source, + return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (8,22): error CS0103: The name 'type' does not exist in the current context DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 22, 8, 26).WithArguments ("type")); } @@ -1350,7 +1355,7 @@ public static void Main() } """; - return VerifyDynamicallyAccessedMembersAnalyzer (Source, + return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (8,9): error CS0103: The name 'type' does not exist in the current context DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 3, 8, 7).WithArguments ("type")); } @@ -1374,7 +1379,7 @@ public static void Main() } """; - return VerifyDynamicallyAccessedMembersAnalyzer (Source, + return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (8,3): error CS0103: The name 'type' does not exist in the current context DiagnosticResult.CompilerError ("CS0103").WithSpan (8, 3, 8, 7).WithArguments ("type")); } @@ -1400,9 +1405,22 @@ class CRequires<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Publi """; // The actual usage (return value) should warn, about missing annotation, but the cref should not. - return VerifyDynamicallyAccessedMembersAnalyzer (Source, + return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: false, // (11,9): warning IL2091: 'TInner' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicMethods' in 'CRequires'. The generic parameter 'TOuter' of 'C' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. VerifyCS.Diagnostic (DiagnosticId.DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter).WithSpan (11, 36, 11, 57).WithSpan (4, 9, 4, 15).WithArguments ("TInner", "CRequires", "TOuter", "C", "'DynamicallyAccessedMemberTypes.PublicMethods'")); } + + [Fact] + public Task MethodParameterWithoutLocationAnalysis () + { + // The implicit main method has parameters + var Source = """ + using System; + foreach (var arg in args) + Console.WriteLine (arg); + """; + + return VerifyDynamicallyAccessedMembersAnalyzer (Source, consoleApplication: true); + } } } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs index ecea646eb5696..7b5e1e923bb47 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresAssemblyFilesAnalyzerTests.cs @@ -22,10 +22,15 @@ static Task VerifyRequiresAssemblyFilesAnalyzer (string source, params Diagnosti return VerifyRequiresAssemblyFilesAnalyzer (source, null, expected); } - static async Task VerifyRequiresAssemblyFilesAnalyzer (string source, IEnumerable? additionalReferences, params DiagnosticResult[] expected) + static async Task VerifyRequiresAssemblyFilesAnalyzer ( + string source, + IEnumerable? additionalReferences, + params DiagnosticResult[] expected) { - await VerifyCS.VerifyAnalyzerAsync (source, + await VerifyCS.VerifyAnalyzerAsync ( + source, + consoleApplication: false, TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.EnableSingleFileAnalyzer), additionalReferences ?? Array.Empty (), expected); @@ -338,7 +343,7 @@ public void M() """; // If 'PublishSingleFile' is not set to true, no diagnostics should be produced by the analyzer. This will // effectively verify that the number of produced diagnostics matches the number of expected ones (zero). - return VerifyCS.VerifyAnalyzerAsync (src); + return VerifyCS.VerifyAnalyzerAsync (src, consoleApplication: false); } [Fact] diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs index 12f839003297d..77497b9b398d5 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/RequiresUnreferencedCodeAnalyzerTests.cs @@ -23,7 +23,9 @@ static Task VerifyRequiresUnreferencedCodeAnalyzer (string source, params Diagno VerifyRequiresUnreferencedCodeAnalyzer (source, null, expected); static async Task VerifyRequiresUnreferencedCodeAnalyzer (string source, IEnumerable? additionalReferences, params DiagnosticResult[] expected) => - await VerifyCS.VerifyAnalyzerAsync (source, + await VerifyCS.VerifyAnalyzerAsync ( + source, + consoleApplication: false, TestCaseUtils.UseMSBuildProperties (MSBuildPropertyOptionNames.EnableTrimAnalyzer), additionalReferences ?? Array.Empty (), expected); diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs index e45d10a010754..8b4473d8be10f 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseCompilation.cs @@ -24,14 +24,16 @@ internal static class TestCaseCompilation public static Task<(CompilationWithAnalyzers Compilation, SemanticModel SemanticModel, List ExceptionDiagnostics)> CreateCompilation ( string src, + bool consoleApplication, (string, string)[]? globalAnalyzerOptions = null, IEnumerable? additionalReferences = null, IEnumerable? additionalSources = null, IEnumerable? additionalFiles = null) - => CreateCompilation (CSharpSyntaxTree.ParseText (src), globalAnalyzerOptions, additionalReferences, additionalSources, additionalFiles); + => CreateCompilation (CSharpSyntaxTree.ParseText (src), consoleApplication, globalAnalyzerOptions, additionalReferences, additionalSources, additionalFiles); public static async Task<(CompilationWithAnalyzers Compilation, SemanticModel SemanticModel, List ExceptionDiagnostics)> CreateCompilation ( SyntaxTree src, + bool consoleApplication, (string, string)[]? globalAnalyzerOptions = null, IEnumerable? additionalReferences = null, IEnumerable? additionalSources = null, @@ -45,7 +47,7 @@ internal static class TestCaseCompilation assemblyName: Guid.NewGuid ().ToString ("N"), syntaxTrees: sources, references: (await TestCaseUtils.GetNet6References ()).Add (mdRef).AddRange (additionalReferences), - new CSharpCompilationOptions (OutputKind.DynamicallyLinkedLibrary)); + new CSharpCompilationOptions (consoleApplication ? OutputKind.ConsoleApplication : OutputKind.DynamicallyLinkedLibrary)); var analyzerOptions = new AnalyzerOptions ( additionalFiles: additionalFiles?.ToImmutableArray () ?? ImmutableArray.Empty, new SimpleAnalyzerOptions (globalAnalyzerOptions)); diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs index 76da0406184c6..c36c864545739 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs @@ -74,6 +74,7 @@ public static async Task RunTestFile (string suiteName, string testName, bool al var (comp, model, exceptionDiagnostics) = await TestCaseCompilation.CreateCompilation ( tree, + consoleApplication: false, msbuildProperties, additionalSources: testDependenciesSource, additionalFiles: additionalFiles); diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs index 32f60660d3fd7..3256e8da7fbd5 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpAnalyzerVerifier`1.cs @@ -39,9 +39,14 @@ public static DiagnosticResult Diagnostic (DiagnosticId diagnosticId) => CSharpAnalyzerVerifier.Diagnostic (DiagnosticDescriptors.GetDiagnosticDescriptor (diagnosticId)); /// - public static async Task VerifyAnalyzerAsync (string src, (string, string)[]? analyzerOptions = null, IEnumerable? additionalReferences = null, params DiagnosticResult[] expected) + public static async Task VerifyAnalyzerAsync ( + string src, + bool consoleApplication, + (string, string)[]? analyzerOptions = null, + IEnumerable? additionalReferences = null, + params DiagnosticResult[] expected) { - var (comp, _, exceptionDiagnostics) = await TestCaseCompilation.CreateCompilation (src, analyzerOptions, additionalReferences); + var (comp, _, exceptionDiagnostics) = await TestCaseCompilation.CreateCompilation (src, consoleApplication, analyzerOptions, additionalReferences); var diags = (await comp.GetAllDiagnosticsAsync ()).AddRange (exceptionDiagnostics); var analyzers = ImmutableArray.Create (new TAnalyzer ()); VerifyDiagnosticResults (diags, analyzers, expected, DefaultVerifier); diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs index d163a30ae44df..33c9d178c699d 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/Verifiers/CSharpCodeFixVerifier`2.cs @@ -54,8 +54,13 @@ public static DiagnosticResult Diagnostic (DiagnosticDescriptor descriptor) => CSharpAnalyzerVerifier.Diagnostic (descriptor); /// - public static Task VerifyAnalyzerAsync (string source, (string, string)[]? analyzerOptions = null, IEnumerable? additionalReferences = null, params DiagnosticResult[] expected) - => CSharpAnalyzerVerifier.VerifyAnalyzerAsync (source, analyzerOptions, additionalReferences, expected); + public static Task VerifyAnalyzerAsync ( + string source, + bool consoleApplication, + (string, string)[]? analyzerOptions = null, + IEnumerable? additionalReferences = null, + params DiagnosticResult[] expected) + => CSharpAnalyzerVerifier.VerifyAnalyzerAsync (source, consoleApplication, analyzerOptions, additionalReferences, expected); /// /// Verifies the analyzer provides diagnostics which, in combination with the code fix, produce the expected diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs index a9d51cb1fa073..7963bf379491b 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/DataFlowTests.g.cs @@ -7,6 +7,12 @@ namespace ILLink.RoslynAnalyzer.Tests public sealed partial class DataFlowTests : LinkerTestBase { + [Fact] + public Task ExponentialDataFlow () + { + return RunTest (allowMissingWarnings: true); + } + [Fact] public Task GenericParameterDataFlowMarking () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs index 73e5c69c20ca0..50ddfa7b36067 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs @@ -11,7 +11,7 @@ namespace Mono.Linker.Tests.Cases.Expectations.Metadata [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] public class SetupCompileBeforeAttribute : BaseMetadataAttribute { - public SetupCompileBeforeAttribute (string outputName, string[] sourceFiles, string[] references = null, string[] defines = null, object[] resources = null, string additionalArguments = null, string compilerToUse = null, bool addAsReference = true, bool removeFromLinkerInput = false, string outputSubFolder = null) + public SetupCompileBeforeAttribute (string outputName, string[] sourceFiles, string[] references = null, string[] defines = null, object[] resources = null, string[] additionalArguments = null, string compilerToUse = null, bool addAsReference = true, bool removeFromLinkerInput = false, string outputSubFolder = null) { ArgumentNullException.ThrowIfNull (sourceFiles); diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs new file mode 100644 index 0000000000000..240a0e9ab0892 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ExponentialDataFlow.cs @@ -0,0 +1,168 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; + +namespace Mono.Linker.Tests.Cases.DataFlow +{ + [ExpectedNoWarnings] + [SkipKeptItemsValidation] + public class ExponentialDataFlow + { + public static void Main () + { + ExponentialArrayStates.Test (); + ExponentialArrayStatesDataFlow.Test (); + ArrayStatesDataFlow.Test (); + } + + class ExponentialArrayStates + { + public static void Test () + { + object[] data = new object[20]; + if (true) data[0] = new object (); + if (true) data[1] = new object (); + if (true) data[2] = new object (); + if (true) data[3] = new object (); + if (true) data[4] = new object (); + if (true) data[5] = new object (); + if (true) data[6] = new object (); + if (true) data[7] = new object (); + if (true) data[8] = new object (); + if (true) data[9] = new object (); + if (true) data[10] = new object (); + if (true) data[11] = new object (); + if (true) data[12] = new object (); + if (true) data[13] = new object (); + if (true) data[14] = new object (); + if (true) data[15] = new object (); + if (true) data[16] = new object (); + if (true) data[17] = new object (); + if (true) data[18] = new object (); + if (true) data[19] = new object (); + } + } + + class ArrayStatesDataFlow + { + class GenericTypeWithRequires<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T> + { + } + + [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'")] + public static void Test () + { + Type[] types = new Type[1] { typeof (int) }; + if (true) types[0] = typeof (T); + typeof (GenericTypeWithRequires<>).MakeGenericType (types); + } + } + + class ExponentialArrayStatesDataFlow + { + class GenericTypeWithRequires< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T0, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T1, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T2, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T3, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T4, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T5, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T6, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T7, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T8, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T9, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T10, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T11, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T12, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T13, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T14, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T15, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T16, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T17, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T18, + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] T19> + { + } + + [ExpectedWarning ("IL3050", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + // The way we track arrays causes the analyzer to track exponentially many + // ArrayValues in the ValueSet for the pattern in this method, hitting the limit. + // When this happens, we replace the ValueSet wit a TopValue, which doesn't + // produce a warning in this case. + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL2090", "'T'", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + public static void Test () + { + Type[] types = new Type[20] { + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int), + typeof (int) + }; + if (Condition) types[0] = typeof (T); + if (Condition) types[1] = typeof (T); + if (Condition) types[2] = typeof (T); + if (Condition) types[3] = typeof (T); + if (Condition) types[4] = typeof (T); + if (Condition) types[5] = typeof (T); + if (Condition) types[6] = typeof (T); + if (Condition) types[7] = typeof (T); + if (Condition) types[8] = typeof (T); + if (Condition) types[9] = typeof (T); + if (Condition) types[10] = typeof (T); + if (Condition) types[11] = typeof (T); + if (Condition) types[12] = typeof (T); + if (Condition) types[13] = typeof (T); + if (Condition) types[14] = typeof (T); + if (Condition) types[15] = typeof (T); + if (Condition) types[16] = typeof (T); + if (Condition) types[17] = typeof (T); + if (Condition) types[18] = typeof (T); + if (Condition) types[19] = typeof (T); + + typeof (GenericTypeWithRequires<,,,,,,,,,,,,,,,,,,,>).MakeGenericType (types); + } + + static bool Condition => Random.Shared.Next (2) == 0; + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj b/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj index 08943354e19ce..453c2d2d26593 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj @@ -16,6 +16,7 @@ + diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveAction.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveAction.cs new file mode 100644 index 0000000000000..ad98b500a4eb3 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveAction.cs @@ -0,0 +1,42 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.References.Dependencies; + +namespace Mono.Linker.Tests.Cases.References +{ + /// + /// We can't detect the using usage in the assembly. As a result, nothing in `library` is going to be marked and that assembly will be deleted. + /// With the assembly action of `save`, we remove unused assembly references from the assembly and rewrite it. + /// When cecil writes the assembly, the unused typeref is not written out. + /// + + // Add a custom step which sets the assembly action of the test to "save" + [SetupCompileBefore ("SetSaveAction.dll", new[] { "Dependencies/CustomMarkHandlerSaveAssembly.cs" }, + new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "CustomMarkHandlerSaveAssembly,SetSaveAction.dll")] + + // When csc is used, `saved.dll` will have a reference to `library.dll` + [SetupCompileBefore ("library.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_Lib.cs" })] + [SetupCompileBefore ("saved.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs" }, + // Even though this testcase doesn't link symbols, tell the compiler to produce symbols to confirm that the behavior + // isn't affected by the presence of symbols when not passing '-b'. + new[] { "library.dll" }, additionalArguments: new string[] { "/debug:portable" }, compilerToUse: "csc")] + + // Here to assert that the test is setup correctly to preserve unused code in the saved assembly. This is an important aspect of the bug + [KeptMemberInAssembly ("saved.dll", typeof (AssemblyOnlyUsedByUsing_UnusedUsing), "Unused()")] + + // The library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked + [RemovedAssembly ("library.dll")] + // The `save` action results in the reference to System.Runtime being resolved into a reference directly to System.Private.CoreLib. + // The reference to `library` is removed. + [KeptReferencesInAssembly ("saved.dll", new[] { "System.Private.CoreLib" })] + public class AssemblyOnlyUsedByUsingSaveAction + { + public static void Main () + { + // Use something to keep the reference at compile time + AssemblyOnlyUsedByUsing_UnusedUsing.UsedToKeepReference (); + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveActionWithSymbols.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveActionWithSymbols.cs new file mode 100644 index 0000000000000..f4a8479647dcc --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingSaveActionWithSymbols.cs @@ -0,0 +1,45 @@ +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.References.Dependencies; + +namespace Mono.Linker.Tests.Cases.References +{ + /// + /// We can't detect the using usage in the assembly. As a result, nothing in `library` is going to be marked and that assembly will be deleted. + /// With the assembly action of `save`, we remove unused assembly references from the assembly and rewrite it, preserving all methods. + /// When debug symbols are present for the `save` assembly, we do not trim debug symbols, so cecil keeps all type references in the + /// save assembly that are referenced by the debug info. This includes the unused typeref, so the assemblyref referenced by the typeref + /// must also be preserved. + /// + + // Add a custom step which sets the assembly action of the test to "save" + [SetupCompileBefore ("SetSaveAction_Symbols.dll", new[] { "Dependencies/CustomMarkHandlerSaveAssembly.cs" }, + new[] { "illink.dll", "Mono.Cecil.dll", "netstandard.dll" })] + [SetupLinkerArgument ("--custom-step", "CustomMarkHandlerSaveAssembly,SetSaveAction_Symbols.dll")] + + // When csc is used, `saved.dll` will have a reference to `library.dll` + [SetupCompileBefore ("library.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_Lib.cs" })] + [SetupCompileBefore ("saved.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs" }, + new[] { "library.dll" }, additionalArguments: new string[] { "/debug:portable" }, compilerToUse: "csc")] + + // Here to assert that the test is setup correctly to preserve unused code in the saved assembly. This is an important aspect of the bug + [KeptMemberInAssembly ("saved.dll", typeof (AssemblyOnlyUsedByUsing_UnusedUsing), "Unused()")] + + // The library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked + [RemovedAssembly ("library.dll")] + // The `save` action results in the reference to System.Runtime being resolved into a reference directly to System.Private.CoreLib. + // The reference to `library` is kept, because it is referenced from a typeref that is referenced from the debug info. + [KeptReferencesInAssembly ("saved.dll", new[] { "System.Private.CoreLib", "library" })] + + // Linking debug symbols is required for cecil not to remove the typeref from the assembly, because it is only referenced from the debug info. + [SetupLinkerLinkSymbols ("true")] + public class AssemblyOnlyUsedByUsingSaveActionWithSymbols + { + public static void Main () + { + // Use something to keep the reference at compile time + AssemblyOnlyUsedByUsing_UnusedUsing.UsedToKeepReference (); + } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs index bc607d4419164..9171863d1da3f 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs @@ -7,18 +7,18 @@ namespace Mono.Linker.Tests.Cases.References { /// /// We can't detect the using usage in the assembly. As a result, nothing in `library` is going to be marked and that assembly will be deleted. - /// Because of that, `copied` needs to have it's reference to `library` removed even though we specified an assembly action of `copy` + /// However, because we specified an assembly action of `copy`, we do not rewrite `copied`, and it ends up with an unused reference to the removed `library`. /// [SetupLinkerAction ("copy", "copied")] - [SetupCompileBefore ("library.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_Lib.cs" })] // When csc is used, `copied.dll` will have a reference to `library.dll` - [SetupCompileBefore ("copied.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_Copied.cs" }, new[] { "library.dll" }, compilerToUse: "csc")] + [SetupCompileBefore ("library.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_Lib.cs" })] + [SetupCompileBefore ("copied.dll", new[] { "Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs" }, new[] { "library.dll" }, compilerToUse: "csc")] // Here to assert that the test is setup correctly to copy the copied assembly. This is an important aspect of the bug - [KeptMemberInAssembly ("copied.dll", typeof (AssemblyOnlyUsedByUsing_Copied), "Unused()")] + [KeptMemberInAssembly ("copied.dll", typeof (AssemblyOnlyUsedByUsing_UnusedUsing), "Unused()")] - // We library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked + // The library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked [RemovedAssembly ("library.dll")] [KeptReferencesInAssembly ("copied.dll", new[] { "System.Runtime", "library" })] public class AssemblyOnlyUsedByUsingWithCsc @@ -26,7 +26,7 @@ public class AssemblyOnlyUsedByUsingWithCsc public static void Main () { // Use something to keep the reference at compile time - AssemblyOnlyUsedByUsing_Copied.UsedToKeepReference (); + AssemblyOnlyUsedByUsing_UnusedUsing.UsedToKeepReference (); } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Copied.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs similarity index 89% rename from src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Copied.cs rename to src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs index caa846e827e56..006c6b0ce4a84 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Copied.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_UnusedUsing.cs @@ -1,11 +1,10 @@ - // This is what triggers the behavior difference between Roslyn and mcs. Roslyn will keep the reference // to this assembly because of this whereas mcs will not using ImportantForBug = Mono.Linker.Tests.Cases.References.Dependencies.AssemblyOnlyUsedByUsing_Lib; namespace Mono.Linker.Tests.Cases.References.Dependencies { - public class AssemblyOnlyUsedByUsing_Copied + public class AssemblyOnlyUsedByUsing_UnusedUsing { public static void UsedToKeepReference () { @@ -15,4 +14,4 @@ private static void Unused () { } } -} \ No newline at end of file +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/CustomMarkHandlerSaveAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/CustomMarkHandlerSaveAssembly.cs new file mode 100644 index 0000000000000..c95bd8b54ba84 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/References/Dependencies/CustomMarkHandlerSaveAssembly.cs @@ -0,0 +1,15 @@ +using System; +using Mono.Cecil; +using Mono.Linker; +using Mono.Linker.Steps; + +public class CustomMarkHandlerSaveAssembly : IMarkHandler +{ + public void Initialize (LinkContext context, MarkContext markContext) + { + markContext.RegisterMarkAssemblyAction (assembly => { + if (assembly.Name.Name == "saved") + context.Annotations.SetAction (assembly, AssemblyAction.Save); + }); + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs index 8eb4836ce67af..f1f81fbabe183 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("false")] [RemovedSymbols ("LibraryWithEmbeddedPdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs index 1265d927ef8fd..45b23a5b96a62 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [KeptSymbols ("LibraryWithEmbeddedPdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndDeterministicMvid.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndDeterministicMvid.cs index 3de804ae5b746..2f21be5a6212b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndDeterministicMvid.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndDeterministicMvid.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [SetupLinkerArgument ("--deterministic", "true")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndNewMvid.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndNewMvid.cs index 637d598b9a8c1..6ec3277b92d0f 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndNewMvid.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabledAndNewMvid.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [SetupLinkerArgument ("--deterministic", "true")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs index 3be34790d05e5..bb8c4f4cd08ed 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("false")] [SetupLinkerAction ("copy", "LibraryWithEmbeddedPdbSymbols")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs index 5e202274623db..b61d450d2ff03 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [SetupLinkerAction ("copy", "LibraryWithEmbeddedPdbSymbols")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs index 31a47f88cbb3a..e436bffc0a3de 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("false")] [RemovedAssembly ("LibraryWithEmbeddedPdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs index c570ec4800991..4cbfe74923be6 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [RemovedAssembly ("LibraryWithEmbeddedPdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs index 7fa2733ad7ad6..5d23cc5640517 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("false")] [RemovedSymbols ("LibraryWithPortablePdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs index 291ec6bdd5a39..430d9abca42f0 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs @@ -5,7 +5,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [KeptSymbols ("LibraryWithPortablePdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndDeterministicMvid.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndDeterministicMvid.cs index 6de9854946a24..7ea5441e024ac 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndDeterministicMvid.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndDeterministicMvid.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [SetupLinkerArgument ("--deterministic", "true")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndNewMvid.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndNewMvid.cs index a63248b8ab4ec..7f1ce479fb163 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndNewMvid.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabledAndNewMvid.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [SetupLinkerArgument ("--new-mvid", "true")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs index de06cb99daeb7..81716cdb97672 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("false")] [SetupLinkerAction ("copy", "LibraryWithPortablePdbSymbols")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs index 42813cc990434..ae77b9e4340e4 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [SetupLinkerAction ("copy", "LibraryWithPortablePdbSymbols")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs index 9b0b44377af09..d60e7858ff1b9 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("false")] [RemovedAssembly ("LibraryWithPortablePdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs index 70d5f1c0fb270..01e2b61827329 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs @@ -4,7 +4,7 @@ namespace Mono.Linker.Tests.Cases.Symbols { - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] [SetupLinkerLinkSymbols ("true")] [RemovedAssembly ("LibraryWithPortablePdbSymbols.dll")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs index d4d004129fcd8..bca76ff9f5597 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs @@ -13,9 +13,9 @@ namespace Mono.Linker.Tests.Cases.Symbols [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")] [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")] - [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: "/debug:full")] - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: new[] { "/debug:full" })] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupCompileArgument ("/debug:full")] [SetupLinkerLinkSymbols ("false")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs index 5f829acb37a2e..0e1c493d637dc 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs @@ -10,9 +10,9 @@ namespace Mono.Linker.Tests.Cases.Symbols [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")] [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")] - [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: "/debug:full")] - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: new[] { "/debug:full" })] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupCompileArgument ("/debug:full")] [SetupLinkerLinkSymbols ("true")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesWithMdbAndSymbolLinkingEnabled.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesWithMdbAndSymbolLinkingEnabled.cs index 323e1ff9fe45a..7ab84855a7f2c 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesWithMdbAndSymbolLinkingEnabled.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesWithMdbAndSymbolLinkingEnabled.cs @@ -16,9 +16,9 @@ namespace Mono.Linker.Tests.Cases.Symbols [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")] [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")] - [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: "/debug:full")] - [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")] - [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: new[] { "/debug:full" })] + [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: new[] { "/debug:portable" }, compilerToUse: "csc")] + [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: new[] { "/debug:embedded" }, compilerToUse: "csc")] [SetupCompileArgument ("/debug:full")] [SetupLinkerLinkSymbols ("true")] diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/WorksWithDynamicAssembly.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/WorksWithDynamicAssembly.cs index 2b33fd2d37885..3b9ef03188436 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/WorksWithDynamicAssembly.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/UnreachableBlock/WorksWithDynamicAssembly.cs @@ -8,7 +8,7 @@ namespace Mono.Linker.Tests.Cases.UnreachableBlock [SetupCompileArgument ("/optimize+")] [SetupLinkerArgument ("--enable-opt", "ipconstprop")] [SetupCompileBefore ("library.dll", new string[] { "Dependencies/ReferencedAssemblyWithUnreachableBlocks.cs" }, - addAsReference: false, additionalArguments: "/optimize+", compilerToUse: "csc")] + addAsReference: false, additionalArguments: new[] { "/optimize+" }, compilerToUse: "csc")] [RemovedMemberInAssembly ("library.dll", "Mono.Linker.Tests.Cases.UnreachableBlock.Dependencies.AssemblyWithUnreachableBlocks", new string[] { "NeverReached()" })] [ExpectedInstructionSequenceOnMemberInAssembly ("library.dll", diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs index d9d4b8a432348..8ef1b7906d36b 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ILVerifier.cs @@ -46,7 +46,7 @@ public ILVerifier (NPath assemblyPath) var allResults = _verifier.Verify (Resolve (assemblyName)) ?? Enumerable.Empty (); - Results = allResults.Where (r => r.Code switch { + Results = allResults.Where (r => r.Code is not ( ILVerify.VerifierError.None // Static interface methods cause this warning or ILVerify.VerifierError.CallAbstract @@ -57,10 +57,7 @@ or ILVerify.VerifierError.Unverifiable // ref returning a ref local causes this warning but is okay or VerifierError.ReturnPtrToStack // Span indexing with indexer (ex. span[^4]) causes this warning - or VerifierError.InitOnly - => false, - _ => true - }); + or VerifierError.InitOnly)); } PEReader LoadAssembly (string assemblyName) diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs index 963c6a4795605..c47c5e8a062bf 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs @@ -24,11 +24,11 @@ protected override LinkContext GetDefaultContext (Pipeline pipeline, ILogger log } } - public virtual void Link (string[] args, LinkerCustomizations customizations, ILogger logger) + public virtual int Link (string[] args, LinkerCustomizations customizations, ILogger logger) { Driver.ProcessResponseFile (args, out var queue); using (var driver = new TestDriver (queue, customizations)) { - driver.Run (logger); + return driver.Run (logger); } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index 816bff646401c..acdcc29668363 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -49,13 +49,42 @@ public ResultChecker (BaseAssemblyResolver originalsResolver, BaseAssemblyResolv _linkedReaderParameters = linkedReaderParameters; } - static void VerifyIL (NPath pathToAssembly) + static void VerifyIL (NPath pathToAssembly, AssemblyDefinition linked) { var verifier = new ILVerifier (pathToAssembly); - foreach (var result in verifier.Results) { - if (result.Code == ILVerify.VerifierError.None) - continue; + foreach (var result in verifier.Results) Assert.Fail (ILVerifier.GetErrorMessage (result)); + } + + static void ValidateTypeRefsHaveValidAssemblyRefs (AssemblyDefinition linked) + { + foreach (var typeRef in linked.MainModule.GetTypeReferences ()) { + switch (typeRef.Scope) { + case null: + // There should be an ExportedType row for this typeref + var exportedType = linked.MainModule.ExportedTypes.SingleOrDefault (et => et.FullName == typeRef.FullName); + Assert.IsNotNull (exportedType, $"Type reference '{typeRef.FullName}' with null scope has no ExportedType row"); + // The exported type's Implementation must be an index into the File/ExportedType/AssemblyRef table + switch (exportedType.Scope) { + case AssemblyNameReference: + // There should be an AssemblyRef row for this assembly + var assemblyRef = linked.MainModule.AssemblyReferences.Single (ar => ar.Name == exportedType.Scope.Name); + Assert.IsNotNull (assemblyRef, $"Exported type '{exportedType.FullName}' has a reference to assembly '{exportedType.Scope.Name}' which is not a reference of '{linked.FullName}'"); + break; + default: + throw new NotImplementedException ($"Unexpected scope type '{exportedType.Scope.GetType ()}' for exported type '{exportedType.FullName}'"); + } + continue; + case AssemblyNameReference: + { + // There should be an AssemblyRef row for this assembly + var assemblyRef = linked.MainModule.AssemblyReferences.Single (ar => ar.Name == typeRef.Scope.Name); + Assert.IsNotNull (assemblyRef, $"Type reference '{typeRef.FullName}' has a reference to assembly '{typeRef.Scope.Name}' which is not a reference of '{linked.FullName}'"); + continue; + } + default: + throw new NotImplementedException ($"Unexpected scope type '{typeRef.Scope.GetType ()}' for type reference '{typeRef.FullName}'"); + } } } @@ -85,8 +114,10 @@ public virtual void Check (LinkedTestCaseResult linkResult) Assert.IsTrue (linkResult.OutputAssemblyPath.FileExists (), $"The linked output assembly was not found. Expected at {linkResult.OutputAssemblyPath}"); var linked = ResolveLinkedAssembly (linkResult.OutputAssemblyPath.FileNameWithoutExtension); - if (ShouldValidateIL (original)) - VerifyIL (linkResult.OutputAssemblyPath); + if (ShouldValidateIL (original)) { + VerifyIL (linkResult.OutputAssemblyPath, linked); + ValidateTypeRefsHaveValidAssemblyRefs (linked); + } InitialChecking (linkResult, original, linked); @@ -99,6 +130,7 @@ public virtual void Check (LinkedTestCaseResult linkResult) } VerifyLinkingOfOtherAssemblies (original); + VerifyILOfOtherAssemblies (linkResult); AdditionalChecking (linkResult, original); } finally { _originalsResolver.Dispose (); @@ -116,6 +148,17 @@ bool HasActiveSkipKeptItemsValidationAttribute (ICustomAttributeProvider provide } } + void VerifyILOfOtherAssemblies (LinkedTestCaseResult linkResult) + { + foreach (var linkedAssemblyPath in linkResult.Sandbox.OutputDirectory.Files ("*.dll")) { + if (linkedAssemblyPath == linkResult.OutputAssemblyPath) + continue; + + var linked = ResolveLinkedAssembly (linkedAssemblyPath.FileNameWithoutExtension); + ValidateTypeRefsHaveValidAssemblyRefs (linked); + } + } + protected virtual AssemblyChecker CreateAssemblyChecker (AssemblyDefinition original, AssemblyDefinition linked, LinkedTestCaseResult linkedTestCase) { return new AssemblyChecker (original, linked, linkedTestCase); diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs index 7a01221e2959c..b6cf9a4fca006 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs @@ -12,7 +12,7 @@ public class SetupCompileInfo public string[] Defines; public string[] References; public SourceAndDestinationPair[] Resources; - public string AdditionalArguments; + public string[] AdditionalArguments; public string CompilerToUse; public bool AddAsReference; public bool RemoveFromLinkerInput; diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs index 4b7f22134ea50..15a4ac56de0ba 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs @@ -227,7 +227,7 @@ private SetupCompileInfo CreateSetupCompileAssemblyInfo (CustomAttribute attribu References = ((CustomAttributeArgument[]) ctorArguments[2].Value)?.Select (arg => arg.Value.ToString ()).ToArray (), Defines = ((CustomAttributeArgument[]) ctorArguments[3].Value)?.Select (arg => arg.Value.ToString ()).ToArray (), Resources = ResourcesForAttributeArgument (ctorArguments[4]), - AdditionalArguments = (string) ctorArguments[5].Value, + AdditionalArguments = ((CustomAttributeArgument[]) ctorArguments[5].Value)?.Select (arg => arg.Value.ToString ()).ToArray (), CompilerToUse = (string) ctorArguments[6].Value, AddAsReference = ctorArguments.Count >= 8 ? (bool) ctorArguments[7].Value : true, RemoveFromLinkerInput = ctorArguments.Count >= 9 ? (bool) ctorArguments[8].Value : false, diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs index 504e1e6b2c59a..aba20b96f3b15 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs @@ -94,7 +94,7 @@ protected virtual CompilerOptions CreateOptionsForSupportingAssembly (SetupCompi { var allDefines = defines.Concat (setupCompileInfo.Defines ?? Array.Empty ()).ToArray (); var allReferences = references.Concat (setupCompileInfo.References?.Select (p => MakeSupportingAssemblyReferencePathAbsolute (outputDirectory, p)) ?? Array.Empty ()).ToArray (); - string[] additionalArguments = string.IsNullOrEmpty (setupCompileInfo.AdditionalArguments) ? null : new[] { setupCompileInfo.AdditionalArguments }; + string[] additionalArguments = setupCompileInfo.AdditionalArguments; return new CompilerOptions { OutputPath = outputDirectory.Combine (setupCompileInfo.OutputName), SourceFiles = sourceFiles,